aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/.jscsrc3
-rw-r--r--web/.jshintignore1
-rw-r--r--web/app/Application.js12
-rw-r--r--web/app/DeviceImages.js9
-rw-r--r--web/app/GeofenceConverter.js22
-rw-r--r--web/app/Style.js6
-rw-r--r--web/app/controller/Root.js183
-rw-r--r--web/app/model/Calendar.js34
-rw-r--r--web/app/model/Geofence.js3
-rw-r--r--web/app/model/Notification.js8
-rw-r--r--web/app/store/AllCalendars.js30
-rw-r--r--web/app/store/Calendars.js30
-rw-r--r--web/app/store/GeofenceTypes.js3
-rw-r--r--web/app/store/Notifications.js4
-rw-r--r--web/app/store/Positions.js5
-rw-r--r--web/app/view/CalendarDialog.js58
-rw-r--r--web/app/view/CalendarDialogController.js37
-rw-r--r--web/app/view/Calendars.js52
-rw-r--r--web/app/view/CalendarsController.js74
-rw-r--r--web/app/view/GeofenceDialog.js8
-rw-r--r--web/app/view/GeofencesController.js1
-rw-r--r--web/app/view/Login.js14
-rw-r--r--web/app/view/MapController.js323
-rw-r--r--web/app/view/MapMarkerController.js387
-rw-r--r--web/app/view/Notifications.js19
-rw-r--r--web/app/view/NotificationsController.js44
-rw-r--r--web/app/view/ReportConfigController.js6
-rw-r--r--web/app/view/ReportController.js96
-rw-r--r--web/app/view/ServerDialog.js8
-rw-r--r--web/app/view/SettingsMenu.js6
-rw-r--r--web/app/view/SettingsMenuController.js13
-rw-r--r--web/app/view/State.js5
-rw-r--r--web/app/view/UserCalendars.js49
-rw-r--r--web/app/view/UserDialog.js16
-rw-r--r--web/app/view/UserDialogController.js10
-rw-r--r--web/app/view/Users.js10
-rw-r--r--web/app/view/UsersController.js21
-rw-r--r--web/debug.html1
-rw-r--r--web/l10n/ar.json5
-rw-r--r--web/l10n/bg.json5
-rw-r--r--web/l10n/cs.json5
-rw-r--r--web/l10n/da.json5
-rw-r--r--web/l10n/de.json11
-rw-r--r--web/l10n/el.json5
-rw-r--r--web/l10n/en.json10
-rw-r--r--web/l10n/es.json5
-rw-r--r--web/l10n/fa.json5
-rw-r--r--web/l10n/fi.json5
-rw-r--r--web/l10n/fr.json5
-rw-r--r--web/l10n/he.json5
-rw-r--r--web/l10n/hi.json5
-rw-r--r--web/l10n/hu.json5
-rw-r--r--web/l10n/id.json5
-rw-r--r--web/l10n/it.json5
-rw-r--r--web/l10n/ka.json5
-rw-r--r--web/l10n/lo.json5
-rw-r--r--web/l10n/lt.json5
-rw-r--r--web/l10n/ml.json5
-rw-r--r--web/l10n/ms.json5
-rw-r--r--web/l10n/nb.json5
-rw-r--r--web/l10n/ne.json5
-rw-r--r--web/l10n/nl.json5
-rw-r--r--web/l10n/nn.json5
-rw-r--r--web/l10n/pl.json5
-rw-r--r--web/l10n/pt.json291
-rw-r--r--web/l10n/pt_BR.json5
-rw-r--r--web/l10n/ro.json5
-rw-r--r--web/l10n/ru.json13
-rw-r--r--web/l10n/si.json5
-rw-r--r--web/l10n/sk.json5
-rw-r--r--web/l10n/sl.json5
-rw-r--r--web/l10n/sq.json5
-rw-r--r--web/l10n/sr.json7
-rw-r--r--web/l10n/ta.json5
-rw-r--r--web/l10n/th.json5
-rw-r--r--web/l10n/tr.json5
-rw-r--r--web/l10n/uk.json5
-rw-r--r--web/l10n/vi.json5
-rw-r--r--web/l10n/zh.json5
-rw-r--r--web/load.js4
-rw-r--r--web/logo.svg166
-rw-r--r--web/release.html1
-rw-r--r--web/simple/app.js97
-rw-r--r--web/simple/index.html14
84 files changed, 1756 insertions, 649 deletions
diff --git a/web/.jscsrc b/web/.jscsrc
index 7d924ab9..70c9dc48 100644
--- a/web/.jscsrc
+++ b/web/.jscsrc
@@ -1,4 +1,5 @@
{
"preset": "crockford",
- "maxErrors": 100
+ "maxErrors": 100,
+ "excludeFiles": ["simple/app.js"]
}
diff --git a/web/.jshintignore b/web/.jshintignore
index 52da2c02..0a20d51b 100644
--- a/web/.jshintignore
+++ b/web/.jshintignore
@@ -1 +1,2 @@
locale.js
+simple/app.js
diff --git a/web/app/Application.js b/web/app/Application.js
index 6f4cb1dd..daa25b85 100644
--- a/web/app/Application.js
+++ b/web/app/Application.js
@@ -37,7 +37,8 @@ Ext.define('Traccar.Application', {
'Notification',
'AttributeAlias',
'ReportSummary',
- 'ReportTrip'
+ 'ReportTrip',
+ 'Calendar'
],
stores: [
@@ -70,7 +71,9 @@ Ext.define('Traccar.Application', {
'ReportTypes',
'ReportEventTypes',
'Statistics',
- 'DeviceImages'
+ 'DeviceImages',
+ 'Calendars',
+ 'AllCalendars'
],
controllers: [
@@ -81,6 +84,11 @@ Ext.define('Traccar.Application', {
return window.matchMedia && window.matchMedia('(max-width: 768px)').matches;
},
+ getEventString: function (eventType) {
+ var key = 'event' + eventType.charAt(0).toUpperCase() + eventType.slice(1);
+ return Strings[key] || key;
+ },
+
showReports: function (show) {
var rootPanel = Ext.getCmp('rootPanel');
if (rootPanel) {
diff --git a/web/app/DeviceImages.js b/web/app/DeviceImages.js
index a05a8153..b31f3ed3 100644
--- a/web/app/DeviceImages.js
+++ b/web/app/DeviceImages.js
@@ -98,15 +98,8 @@ Ext.define('Traccar.DeviceImages', {
},
rotateImageIcon: function (image, angle) {
- var svg = Traccar.DeviceImages.getImageSvg(image.fill, image.zoom, angle, image.category);
+ var svg = this.getImageSvg(image.fill, image.zoom, angle, image.category);
image.getImage().src = this.formatSrc(svg);
image.angle = angle;
- },
-
- changeImageColor: function (image, color, category) {
- var svg = Traccar.DeviceImages.getImageSvg(color, image.zoom, image.angle, category);
- image.getImage().src = this.formatSrc(svg);
- image.fill = color;
- image.category = category;
}
});
diff --git a/web/app/GeofenceConverter.js b/web/app/GeofenceConverter.js
index f0e28b3f..9e3c1327 100644
--- a/web/app/GeofenceConverter.js
+++ b/web/app/GeofenceConverter.js
@@ -49,6 +49,20 @@ Ext.define('Traccar.GeofenceConverter', {
geometry = new ol.geom.Circle(center, radius);
}
}
+ } else if (wkt.lastIndexOf('LINESTRING', 0) === 0) {
+ content = wkt.match(/\([^\(\)]+\)/);
+ if (content !== null) {
+ coordinates = content[0].match(/-?\d+\.?\d*/g);
+ if (coordinates !== null) {
+ projection = mapView.getProjection();
+ for (i = 0; i < coordinates.length; i += 2) {
+ lat = Number(coordinates[i]);
+ lon = Number(coordinates[i + 1]);
+ points.push(ol.proj.transform([lon, lat], 'EPSG:4326', projection));
+ }
+ geometry = new ol.geom.LineString(points);
+ }
+ }
}
return geometry;
},
@@ -74,6 +88,14 @@ Ext.define('Traccar.GeofenceConverter', {
result += points[0][i][1] + ' ' + points[0][i][0] + ', ';
}
result = result.substring(0, result.length - 2) + '))';
+ } else if (geometry instanceof ol.geom.LineString) {
+ geometry.transform(projection, 'EPSG:4326');
+ points = geometry.getCoordinates();
+ result = 'LINESTRING (';
+ for (i = 0; i < points.length; i += 1) {
+ result += points[i][1] + ' ' + points[i][0] + ', ';
+ }
+ result = result.substring(0, result.length - 2) + ')';
}
return result;
}
diff --git a/web/app/Style.js b/web/app/Style.js
index 4960aefa..c5fce9b6 100644
--- a/web/app/Style.js
+++ b/web/app/Style.js
@@ -18,6 +18,8 @@
Ext.define('Traccar.Style', {
singleton: true,
+ reconnectTimeout: 60 * 1000,
+
normalPadding: 10,
windowWidth: 640,
@@ -76,7 +78,5 @@ Ext.define('Traccar.Style', {
coordinatePrecision: 6,
numberPrecision: 2,
- reportTagfieldWidth: 375,
-
- headerButtonsMargin: '0 5'
+ reportTagfieldWidth: 375
});
diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js
index e30446c9..0cc2a148 100644
--- a/web/app/controller/Root.js
+++ b/web/app/controller/Root.js
@@ -75,7 +75,7 @@ Ext.define('Traccar.controller.Root', {
},
loadApp: function () {
- var attribution;
+ var attribution, eventId;
Ext.getStore('Groups').load();
Ext.getStore('Geofences').load();
Ext.getStore('AttributeAliases').load();
@@ -94,6 +94,11 @@ Ext.define('Traccar.controller.Root', {
} else {
Ext.create('widget.main');
}
+ eventId = Ext.Object.fromQueryString(window.location.search).eventId;
+ if (eventId) {
+ this.fireEvent('showsingleevent', eventId);
+ this.removeUrlParameter('eventId');
+ }
},
beep: function () {
@@ -108,103 +113,117 @@ Ext.define('Traccar.controller.Root', {
return muteButton && !muteButton.pressed;
},
+ removeUrlParameter: function (param) {
+ var params = Ext.Object.fromQueryString(window.location.search);
+ delete params[param];
+ if (Ext.Object.isEmpty(params)) {
+ window.history.pushState(null, null, window.location.pathname);
+ } else {
+ window.history.pushState(null, null, window.location.pathname + '?' + Ext.Object.toQueryString(params));
+ }
+ },
+
asyncUpdate: function (first) {
- var protocol, pathname, socket, self = this;
+ var self = this, protocol, pathname, socket;
protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
pathname = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/') + 1);
socket = new WebSocket(protocol + '//' + window.location.host + pathname + 'api/socket');
socket.onclose = function (event) {
- self.asyncUpdate(false);
+ Ext.toast(Strings.errorSocket, Strings.errorTitle, 'br');
+
+ Ext.Ajax.request({
+ url: 'api/devices',
+ success: function(response) {
+ self.updateDevices(Ext.decode(response.responseText));
+ }
+ });
+
+ Ext.Ajax.request({
+ url: 'api/positions',
+ headers: {
+ Accept: 'application/json'
+ },
+ success: function(response) {
+ self.updatePositions(Ext.decode(response.responseText));
+ }
+ });
+
+ setTimeout(function() {
+ self.asyncUpdate(false);
+ }, Traccar.Style.reconnectTimeout);
};
socket.onmessage = function (event) {
- var i, j, store, data, array, entity, device, typeKey, alarmKey, text, geofence;
-
- data = Ext.decode(event.data);
+ var data = Ext.decode(event.data);
if (data.devices) {
- array = data.devices;
- store = Ext.getStore('Devices');
- for (i = 0; i < array.length; i++) {
- entity = store.getById(array[i].id);
- if (entity) {
- entity.set({
- status: array[i].status,
- lastUpdate: array[i].lastUpdate
- }, {
- dirty: false
- });
- }
- }
+ self.updateDevices(data.devices);
+ }
+ if (data.positions) {
+ self.updatePositions(data.positions);
}
+ if (data.events) {
+ self.updateEvents(data.events);
+ }
+ };
+ },
- if (data.positions && !data.events) {
- array = data.positions;
- store = Ext.getStore('LatestPositions');
- for (i = 0; i < array.length; i++) {
- entity = store.findRecord('deviceId', array[i].deviceId, 0, false, false, true);
- if (entity) {
- entity.set(array[i]);
- } else {
- store.add(Ext.create('Traccar.model.Position', array[i]));
- }
- }
+ updateDevices: function (array) {
+ var i, store, entity;
+ store = Ext.getStore('Devices');
+ for (i = 0; i < array.length; i++) {
+ entity = store.getById(array[i].id);
+ if (entity) {
+ entity.set({
+ status: array[i].status,
+ lastUpdate: array[i].lastUpdate
+ }, {
+ dirty: false
+ });
}
+ }
+ },
- if (data.events) {
- array = data.events;
- store = Ext.getStore('Events');
- for (i = 0; i < array.length; i++) {
- store.add(array[i]);
- if (array[i].type === 'commandResult' && data.positions) {
- for (j = 0; j < data.positions.length; j++) {
- if (data.positions[j].id === array[i].positionId) {
- text = data.positions[j].attributes.result;
- break;
- }
- }
- text = Strings.eventCommandResult + ': ' + text;
- } else if (array[i].type === 'alarm' && data.positions) {
- alarmKey = 'alarm';
- text = Strings[alarmKey];
- if (!text) {
- text = alarmKey;
- }
- for (j = 0; j < data.positions.length; j++) {
- if (data.positions[j].id === array[i].positionId && data.positions[j].attributes.alarm !== null) {
- if (typeof data.positions[j].attributes.alarm === 'string' && data.positions[j].attributes.alarm.length >= 2) {
- alarmKey = 'alarm' + data.positions[j].attributes.alarm.charAt(0).toUpperCase() + data.positions[j].attributes.alarm.slice(1);
- text = Strings[alarmKey];
- if (!text) {
- text = alarmKey;
- }
- }
- break;
- }
- }
- } else {
- typeKey = 'event' + array[i].type.charAt(0).toUpperCase() + array[i].type.slice(1);
- text = Strings[typeKey];
- if (!text) {
- text = typeKey;
- }
- }
- if (array[i].geofenceId !== 0) {
- geofence = Ext.getStore('Geofences').getById(array[i].geofenceId);
- if (typeof geofence !== 'undefined') {
- text += ' \"' + geofence.get('name') + '"';
- }
- }
- device = Ext.getStore('Devices').getById(array[i].deviceId);
- if (typeof device !== 'undefined') {
- if (self.mutePressed()) {
- self.beep();
- }
- Ext.toast(text, device.get('name'));
- }
+ updatePositions: function (array) {
+ var i, store, data, entity;
+ store = Ext.getStore('LatestPositions');
+ for (i = 0; i < array.length; i++) {
+ entity = store.findRecord('deviceId', array[i].deviceId, 0, false, false, true);
+ if (entity) {
+ entity.set(array[i]);
+ } else {
+ store.add(Ext.create('Traccar.model.Position', array[i]));
+ }
+ }
+ },
+
+ updateEvents: function (array) {
+ var i, store, device, alarmKey, text, geofence;
+ store = Ext.getStore('Events');
+ for (i = 0; i < array.length; i++) {
+ store.add(array[i]);
+ if (array[i].type === 'commandResult') {
+ text = Strings.eventCommandResult + ': ' + array[i].attributes.result;
+ } else if (array[i].type === 'alarm') {
+ alarmKey = 'alarm' + array[i].attributes.alarm.charAt(0).toUpperCase() + array[i].attributes.alarm.slice(1);
+ text = Strings[alarmKey] || alarmKey;
+ } else {
+ text = Traccar.app.getEventString(array[i].type);
+ }
+ if (array[i].geofenceId !== 0) {
+ geofence = Ext.getStore('Geofences').getById(array[i].geofenceId);
+ if (geofence) {
+ text += ' \"' + geofence.get('name') + '"';
}
}
- };
+ device = Ext.getStore('Devices').getById(array[i].deviceId);
+ if (device) {
+ if (this.mutePressed()) {
+ this.beep();
+ }
+ Ext.toast(text, device.get('name'), 'br');
+ }
+ }
}
});
diff --git a/web/app/model/Calendar.js b/web/app/model/Calendar.js
new file mode 100644
index 00000000..00b076b3
--- /dev/null
+++ b/web/app/model/Calendar.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.model.Calendar', {
+ extend: 'Ext.data.Model',
+ identifier: 'negative',
+
+ fields: [{
+ name: 'id',
+ type: 'int'
+ }, {
+ name: 'name',
+ type: 'string'
+ }, {
+ name: 'calendarData'
+ }, {
+ name: 'attributes'
+ }]
+});
diff --git a/web/app/model/Geofence.js b/web/app/model/Geofence.js
index 63c8e8e2..12a9f878 100644
--- a/web/app/model/Geofence.js
+++ b/web/app/model/Geofence.js
@@ -32,6 +32,9 @@ Ext.define('Traccar.model.Geofence', {
name: 'area',
type: 'string'
}, {
+ name: 'calendarId',
+ type: 'int'
+ }, {
name: 'attributes'
}]
});
diff --git a/web/app/model/Notification.js b/web/app/model/Notification.js
index 1e6c36c5..54f6674c 100644
--- a/web/app/model/Notification.js
+++ b/web/app/model/Notification.js
@@ -17,7 +17,7 @@
Ext.define('Traccar.model.Notification', {
extend: 'Ext.data.Model',
- identifier: 'negative',
+ idProperty: 'type',
fields: [{
name: 'id',
@@ -30,5 +30,11 @@ Ext.define('Traccar.model.Notification', {
type: 'int'
}, {
name: 'attributes'
+ }, {
+ name: 'web',
+ type: 'bool'
+ }, {
+ name: 'mail',
+ type: 'bool'
}]
});
diff --git a/web/app/store/AllCalendars.js b/web/app/store/AllCalendars.js
new file mode 100644
index 00000000..26557287
--- /dev/null
+++ b/web/app/store/AllCalendars.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.store.AllCalendars', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.Calendar',
+
+ proxy: {
+ type: 'rest',
+ url: 'api/calendars',
+ extraParams: {
+ all: true
+ }
+ }
+});
diff --git a/web/app/store/Calendars.js b/web/app/store/Calendars.js
new file mode 100644
index 00000000..fa8e5c66
--- /dev/null
+++ b/web/app/store/Calendars.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.store.Calendars', {
+ extend: 'Ext.data.Store',
+ model: 'Traccar.model.Calendar',
+
+ proxy: {
+ type: 'rest',
+ url: 'api/calendars',
+ writer: {
+ writeAllFields: true
+ }
+ }
+});
diff --git a/web/app/store/GeofenceTypes.js b/web/app/store/GeofenceTypes.js
index c102de69..45b79897 100644
--- a/web/app/store/GeofenceTypes.js
+++ b/web/app/store/GeofenceTypes.js
@@ -25,5 +25,8 @@ Ext.define('Traccar.store.GeofenceTypes', {
}, {
key: 'Circle',
name: Strings.mapShapeCircle
+ }, {
+ key: 'LineString',
+ name: Strings.mapShapePolyline
}]
});
diff --git a/web/app/store/Notifications.js b/web/app/store/Notifications.js
index e4d2991a..d79702fc 100644
--- a/web/app/store/Notifications.js
+++ b/web/app/store/Notifications.js
@@ -22,5 +22,7 @@ Ext.define('Traccar.store.Notifications', {
proxy: {
type: 'rest',
url: 'api/users/notifications'
- }
+ },
+ sortOnLoad: true,
+ sorters: { property: 'type', direction : 'ASC' }
});
diff --git a/web/app/store/Positions.js b/web/app/store/Positions.js
index 8f185af1..388a3320 100644
--- a/web/app/store/Positions.js
+++ b/web/app/store/Positions.js
@@ -21,6 +21,9 @@ Ext.define('Traccar.store.Positions', {
proxy: {
type: 'rest',
- url: 'api/positions'
+ url: 'api/positions',
+ headers: {
+ 'Accept': 'application/json'
+ }
}
});
diff --git a/web/app/view/CalendarDialog.js b/web/app/view/CalendarDialog.js
new file mode 100644
index 00000000..2609a6da
--- /dev/null
+++ b/web/app/view/CalendarDialog.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.CalendarDialog', {
+ extend: 'Traccar.view.BaseEditDialog',
+
+ requires: [
+ 'Traccar.view.CalendarDialogController'
+ ],
+
+ controller: 'calendarDialog',
+ title: Strings.sharedCalendar,
+
+ items: {
+ xtype: 'form',
+ items: [{
+ xtype: 'textfield',
+ name: 'name',
+ fieldLabel: Strings.sharedName,
+ allowBlank: false
+ }, {
+ xtype: 'filefield',
+ name: 'file',
+ fieldLabel: Strings.sharedFile,
+ allowBlank: false,
+ buttonConfig: {
+ glyph: 'xf093@FontAwesome',
+ text: '',
+ tooltip: Strings.sharedSelectFile,
+ tooltipType: 'title',
+ minWidth: 0
+ },
+ listeners: {
+ change: 'onFileChange'
+ }
+ }, {
+ xtype: 'hiddenfield',
+ name: 'calendarData',
+ allowBlank: false,
+ reference: 'calendarDataField'
+ }]
+ }
+});
diff --git a/web/app/view/CalendarDialogController.js b/web/app/view/CalendarDialogController.js
new file mode 100644
index 00000000..48400bc5
--- /dev/null
+++ b/web/app/view/CalendarDialogController.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.CalendarDialogController', {
+ extend: 'Traccar.view.BaseEditDialogController',
+ alias: 'controller.calendarDialog',
+
+ onFileChange: function (fileField) {
+ var reader;
+ if (fileField.fileInputEl.dom.files.length > 0) {
+ reader = new FileReader();
+ reader.onload = function (event) {
+ fileField.up('window').lookupReference('calendarDataField').setValue(
+ btoa(String.fromCharCode.apply(null, new Uint8Array(event.target.result))));
+ };
+ reader.onerror = function (event) {
+ Traccar.app.showError(event.target.error);
+ };
+ reader.readAsArrayBuffer(fileField.fileInputEl.dom.files[0]);
+ }
+ }
+});
diff --git a/web/app/view/Calendars.js b/web/app/view/Calendars.js
new file mode 100644
index 00000000..a905a5ba
--- /dev/null
+++ b/web/app/view/Calendars.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.Calendars', {
+ extend: 'Ext.grid.Panel',
+ xtype: 'calendarsView',
+
+ requires: [
+ 'Traccar.view.CalendarsController',
+ 'Traccar.view.EditToolbar'
+ ],
+
+ controller: 'calendars',
+ store: 'Calendars',
+
+ selType: 'rowmodel',
+
+ tbar: {
+ xtype: 'editToolbar'
+ },
+
+ listeners: {
+ selectionchange: 'onSelectionChange'
+ },
+
+ forceFit: true,
+
+ columns: {
+ defaults: {
+ minWidth: Traccar.Style.columnWidthNormal
+ },
+ items: [{
+ text: Strings.sharedName,
+ dataIndex: 'name'
+ }]
+ }
+});
diff --git a/web/app/view/CalendarsController.js b/web/app/view/CalendarsController.js
new file mode 100644
index 00000000..d5ab57a5
--- /dev/null
+++ b/web/app/view/CalendarsController.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.CalendarsController', {
+ extend: 'Ext.app.ViewController',
+ alias: 'controller.calendars',
+
+ requires: [
+ 'Traccar.view.CalendarDialog',
+ 'Traccar.model.Calendar'
+ ],
+
+ init: function () {
+ Ext.getStore('Calendars').load();
+ },
+
+ onAddClick: function () {
+ var calendar, dialog;
+ calendar = Ext.create('Traccar.model.Calendar');
+ calendar.store = this.getView().getStore();
+ dialog = Ext.create('Traccar.view.CalendarDialog');
+ dialog.down('form').loadRecord(calendar);
+ dialog.show();
+ },
+
+ onEditClick: function () {
+ var calendar, dialog;
+ calendar = this.getView().getSelectionModel().getSelection()[0];
+ dialog = Ext.create('Traccar.view.CalendarDialog');
+ dialog.down('form').loadRecord(calendar);
+ dialog.show();
+ },
+
+ onRemoveClick: function () {
+ var calendar = this.getView().getSelectionModel().getSelection()[0];
+ Ext.Msg.show({
+ title: Strings.sharedCalendar,
+ message: Strings.sharedRemoveConfirm,
+ buttons: Ext.Msg.YESNO,
+ buttonText: {
+ yes: Strings.sharedRemove,
+ no: Strings.sharedCancel
+ },
+ fn: function (btn) {
+ var store = Ext.getStore('Calendars');
+ if (btn === 'yes') {
+ store.remove(calendar);
+ store.sync();
+ }
+ }
+ });
+ },
+
+ onSelectionChange: function (selected) {
+ var disabled = selected.length > 0;
+ this.lookupReference('toolbarEditButton').setDisabled(disabled);
+ this.lookupReference('toolbarRemoveButton').setDisabled(disabled);
+ }
+});
diff --git a/web/app/view/GeofenceDialog.js b/web/app/view/GeofenceDialog.js
index 9f5bdbf7..7b2112b3 100644
--- a/web/app/view/GeofenceDialog.js
+++ b/web/app/view/GeofenceDialog.js
@@ -36,6 +36,14 @@ Ext.define('Traccar.view.GeofenceDialog', {
name: 'description',
fieldLabel: Strings.sharedDescription
}, {
+ xtype: 'combobox',
+ name: 'calendarId',
+ store: 'Calendars',
+ queryMode: 'local',
+ displayField: 'name',
+ valueField: 'id',
+ fieldLabel: Strings.sharedCalendar
+ }, {
xtype: 'hiddenfield',
name: 'area',
allowBlank: false,
diff --git a/web/app/view/GeofencesController.js b/web/app/view/GeofencesController.js
index 032ba7fa..78389066 100644
--- a/web/app/view/GeofencesController.js
+++ b/web/app/view/GeofencesController.js
@@ -26,6 +26,7 @@ Ext.define('Traccar.view.GeofencesController', {
init: function () {
Ext.getStore('Geofences').load();
+ Ext.getStore('Calendars').load();
},
onAddClick: function () {
diff --git a/web/app/view/Login.js b/web/app/view/Login.js
index d71fed8b..5d0da0f5 100644
--- a/web/app/view/Login.js
+++ b/web/app/view/Login.js
@@ -25,7 +25,7 @@ Ext.define('Traccar.view.Login', {
controller: 'login',
- title: Strings.loginTitle,
+ header: false,
closable: false,
modal: false,
@@ -41,6 +41,16 @@ Ext.define('Traccar.view.Login', {
},
items: [{
+ xtype: 'image',
+ src: 'logo.svg',
+ alt: Strings.loginLogo,
+ width: 180,
+ height: 48,
+ style: {
+ display: 'block',
+ margin: '10px auto 25px'
+ }
+ }, {
xtype: 'combobox',
name: 'language',
fieldLabel: Strings.loginLanguage,
@@ -79,6 +89,8 @@ Ext.define('Traccar.view.Login', {
inputAttrTpl: ['autocomplete="on"']
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
reference: 'rememberField',
fieldLabel: Strings.userRemember
}, {
diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js
index 9fcd4939..c52fdd5f 100644
--- a/web/app/view/MapController.js
+++ b/web/app/view/MapController.js
@@ -16,59 +16,33 @@
*/
Ext.define('Traccar.view.MapController', {
- extend: 'Ext.app.ViewController',
+ extend: 'Traccar.view.MapMarkerController',
alias: 'controller.map',
requires: [
- 'Traccar.model.Position',
- 'Traccar.model.Device',
- 'Traccar.GeofenceConverter',
- 'Traccar.DeviceImages'
+ 'Traccar.GeofenceConverter'
],
config: {
listen: {
controller: {
'*': {
- selectdevice: 'selectDevice',
- selectreport: 'selectReport',
mapstaterequest: 'getMapState'
}
},
store: {
- '#Devices': {
- add: 'updateDevice',
- update: 'updateDevice',
- remove: 'removeDevice'
- },
- '#LatestPositions': {
- add: 'updateLatest',
- update: 'updateLatest'
- },
- '#ReportRoute': {
- load: 'loadReport',
- clear: 'clearReport'
- },
'#Geofences': {
load: 'showGeofences',
add: 'updateGeofences',
update: 'updateGeofences',
remove: 'updateGeofences'
}
- },
- component: {
- '#': {
- selectfeature: 'selectFeature'
- }
}
}
},
init: function () {
- this.latestMarkers = {};
- this.reportMarkers = {};
- this.liveRoutes = {};
- this.liveRouteLength = Traccar.app.getAttributePreference('web.liveRouteLength', 10);
+ this.callParent();
this.lookupReference('showReportsButton').setVisible(Traccar.app.isMobile());
},
@@ -76,58 +50,6 @@ Ext.define('Traccar.view.MapController', {
Traccar.app.showReports(true);
},
- getDeviceColor: function (device) {
- switch (device.get('status')) {
- case 'online':
- return Traccar.Style.mapColorOnline;
- case 'offline':
- return Traccar.Style.mapColorOffline;
- default:
- return Traccar.Style.mapColorUnknown;
- }
- },
-
- updateDevice: function (store, data) {
- var i, device, deviceId, marker, style;
-
- if (!Ext.isArray(data)) {
- data = [data];
- }
-
- for (i = 0; i < data.length; i++) {
- device = data[i];
- deviceId = device.get('id');
-
- if (deviceId in this.latestMarkers) {
- marker = this.latestMarkers[deviceId];
- style = marker.getStyle();
- if (style.getImage().fill !== this.getDeviceColor(device) ||
- style.getImage().category !== device.get('category')) {
- Traccar.DeviceImages.changeImageColor(style.getImage(),
- this.getDeviceColor(device), device.get('category'));
- marker.changed();
- }
- if (style.getText().getText() !== device.get('name')) {
- style.getText().setText(device.get('name'));
- marker.changed();
- }
- }
- }
- },
-
- removeDevice: function (store, data) {
- var i, deviceId;
- if (!Ext.isArray(data)) {
- data = [data];
- }
- for (i = 0; i < data.length; i++) {
- deviceId = data[i].get('id');
- if (this.latestMarkers[deviceId]) {
- this.getView().getLatestSource().removeFeature(this.latestMarkers[deviceId]);
- }
- }
- },
-
onFollowClick: function (button, pressed) {
if (pressed && this.selectedMarker) {
this.getView().getMapView().setCenter(this.selectedMarker.getGeometry().getCoordinates());
@@ -138,245 +60,6 @@ Ext.define('Traccar.view.MapController', {
this.getView().getLiveRouteLayer().setVisible(button.pressed);
},
- updateLatest: function (store, data) {
- var i, position, device;
-
- if (!Ext.isArray(data)) {
- data = [data];
- }
-
- for (i = 0; i < data.length; i++) {
- position = data[i];
- device = Ext.getStore('Devices').findRecord('id', position.get('deviceId'), 0, false, false, true);
-
- if (device) {
- this.updateLatestMarker(position, device);
- this.updateLiveRoute(position);
- }
- }
- },
-
- updateLatestMarker: function (position, device) {
- var geometry, deviceId, marker, style;
- geometry = new ol.geom.Point(ol.proj.fromLonLat([
- position.get('longitude'),
- position.get('latitude')
- ]));
- deviceId = position.get('deviceId');
- if (deviceId in this.latestMarkers) {
- marker = this.latestMarkers[deviceId];
- style = marker.getStyle();
- if (style.getImage().angle !== position.get('course')) {
- Traccar.DeviceImages.rotateImageIcon(style.getImage(), position.get('course'));
- }
- marker.setGeometry(geometry);
- } else {
- marker = new ol.Feature(geometry);
- marker.set('record', device);
-
- style = this.getLatestMarker(this.getDeviceColor(device),
- position.get('course'),
- device.get('category'));
- style.getText().setText(device.get('name'));
- marker.setStyle(style);
- this.latestMarkers[deviceId] = marker;
- this.getView().getLatestSource().addFeature(marker);
-
- }
-
- if (marker === this.selectedMarker && this.lookupReference('deviceFollowButton').pressed) {
- this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
- }
- },
-
- updateLiveRoute: function (position) {
- var deviceId, liveLine, liveCoordinates, lastLiveCoordinates, newCoordinates;
- deviceId = position.get('deviceId');
- if (deviceId in this.liveRoutes) {
- liveCoordinates = this.liveRoutes[deviceId].getGeometry().getCoordinates();
- lastLiveCoordinates = liveCoordinates[liveCoordinates.length - 1];
- newCoordinates = ol.proj.fromLonLat([position.get('longitude'), position.get('latitude')]);
- if (lastLiveCoordinates[0] === newCoordinates[0] &&
- lastLiveCoordinates[1] === newCoordinates[1]) {
- return;
- }
- if (liveCoordinates.length >= this.liveRouteLength) {
- liveCoordinates.shift();
- }
- liveCoordinates.push(newCoordinates);
- this.liveRoutes[deviceId].getGeometry().setCoordinates(liveCoordinates);
- } else {
- liveLine = new ol.Feature({
- geometry: new ol.geom.LineString([
- ol.proj.fromLonLat([
- position.get('longitude'),
- position.get('latitude')
- ])
- ])
- });
- liveLine.setStyle(this.getRouteStyle(deviceId));
- this.liveRoutes[deviceId] = liveLine;
- this.getView().getLiveRouteSource().addFeature(liveLine);
- }
- },
-
- loadReport: function (store, data) {
- var i, position, point, geometry, marker, style;
-
- this.clearReport(store);
-
- if (data.length > 0) {
- this.reportRoute = [];
- for (i = 0; i < data.length; i++) {
- if (i === 0 || data[i].get('deviceId') !== data[i - 1].get('deviceId')) {
- this.reportRoute.push(new ol.Feature({
- geometry: new ol.geom.LineString([])
- }));
- this.reportRoute[this.reportRoute.length - 1].setStyle(this.getRouteStyle(data[i].get('deviceId')));
- this.getView().getRouteSource().addFeature(this.reportRoute[this.reportRoute.length - 1]);
- }
- position = data[i];
-
- point = ol.proj.fromLonLat([
- position.get('longitude'),
- position.get('latitude')
- ]);
- geometry = new ol.geom.Point(point);
-
- marker = new ol.Feature(geometry);
- marker.set('record', position);
- this.reportMarkers[position.get('id')] = marker;
- this.getView().getReportSource().addFeature(marker);
-
- style = this.getReportMarker(position.get('deviceId'), position.get('course'));
- /*style.getText().setText(
- Ext.Date.format(position.get('fixTime'), Traccar.Style.dateTimeFormat24));*/
-
- marker.setStyle(style);
-
- this.reportRoute[this.reportRoute.length - 1].getGeometry().appendCoordinate(point);
- }
-
- this.getView().getMapView().fit(this.reportRoute[0].getGeometry(), this.getView().getMap().getSize());
- }
- },
-
- clearReport: function (store) {
- var key, i;
-
- if (this.reportRoute) {
- for (i = 0; i < this.reportRoute.length; i++) {
- this.getView().getRouteSource().removeFeature(this.reportRoute[i]);
- }
- this.reportRoute = null;
- }
-
- if (this.reportMarkers) {
- for (key in this.reportMarkers) {
- if (this.reportMarkers.hasOwnProperty(key)) {
- this.getView().getReportSource().removeFeature(this.reportMarkers[key]);
- }
- }
- this.reportMarkers = {};
- }
- },
-
- getRouteStyle: function (deviceId) {
- var index = 0;
- if (deviceId !== undefined) {
- index = deviceId % Traccar.Style.mapRouteColor.length;
- }
- return new ol.style.Style({
- stroke: new ol.style.Stroke({
- color: Traccar.Style.mapRouteColor[index],
- width: Traccar.Style.mapRouteWidth
- })
- });
- },
-
- getMarkerStyle: function (zoom, color, angle, category) {
- var image = Traccar.DeviceImages.getImageIcon(color, zoom, angle, category);
- return new ol.style.Style({
- image: image,
- text: new ol.style.Text({
- textBaseline: 'bottom',
- fill: new ol.style.Fill({
- color: Traccar.Style.mapTextColor
- }),
- stroke: new ol.style.Stroke({
- color: Traccar.Style.mapTextStrokeColor,
- width: Traccar.Style.mapTextStrokeWidth
- }),
- offsetY: -image.getSize()[1] / 2 - Traccar.Style.mapTextOffset,
- font : Traccar.Style.mapTextFont
- })
- });
- },
-
- getLatestMarker: function (color, angle, category) {
- return this.getMarkerStyle(false, color, angle, category);
- },
-
- getReportMarker: function (deviceId, angle) {
- var index = 0;
- if (deviceId !== undefined) {
- index = deviceId % Traccar.Style.mapRouteColor.length;
- }
- return this.getMarkerStyle(false, Traccar.Style.mapRouteColor[index], angle, 'arrow');
- },
-
- resizeMarker: function (style, zoom) {
- var image, text;
- image = Traccar.DeviceImages.getImageIcon(style.getImage().fill,
- zoom,
- style.getImage().angle,
- style.getImage().category);
- text = style.getText();
- text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset);
- return new ol.style.Style({
- image: image,
- text: text
- });
- },
-
- selectMarker: function (marker, center) {
- if (this.selectedMarker) {
- this.selectedMarker.setStyle(
- this.resizeMarker(this.selectedMarker.getStyle(), false));
- }
-
- if (marker) {
- marker.setStyle(
- this.resizeMarker(marker.getStyle(), true));
- if (center) {
- this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
- }
- }
-
- this.selectedMarker = marker;
- },
-
- selectDevice: function (device, center) {
- this.selectMarker(this.latestMarkers[device.get('id')], center);
- },
-
- selectReport: function (position, center) {
- if (position instanceof Traccar.model.Position) {
- this.selectMarker(this.reportMarkers[position.get('id')], center);
- }
- },
-
- selectFeature: function (feature) {
- var record = feature.get('record');
- if (record) {
- if (record instanceof Traccar.model.Device) {
- this.fireEvent('selectdevice', record, false);
- } else {
- this.fireEvent('selectreport', record, false);
- }
- }
- },
-
getMapState: function () {
var zoom, center, projection;
projection = this.getView().getMapView().getProjection();
diff --git a/web/app/view/MapMarkerController.js b/web/app/view/MapMarkerController.js
new file mode 100644
index 00000000..5fa9f4ca
--- /dev/null
+++ b/web/app/view/MapMarkerController.js
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.MapMarkerController', {
+ extend: 'Ext.app.ViewController',
+ alias: 'controller.mapMarker',
+
+ requires: [
+ 'Traccar.model.Position',
+ 'Traccar.model.Device',
+ 'Traccar.DeviceImages'
+ ],
+
+ config: {
+ listen: {
+ controller: {
+ '*': {
+ selectdevice: 'selectDevice',
+ selectreport: 'selectReport'
+ }
+ },
+ store: {
+ '#Devices': {
+ add: 'updateDevice',
+ update: 'updateDevice',
+ remove: 'removeDevice'
+ },
+ '#LatestPositions': {
+ add: 'updateLatest',
+ update: 'updateLatest'
+ },
+ '#ReportRoute': {
+ add: 'addReportMarkers',
+ load: 'loadReport',
+ clear: 'clearReport'
+ }
+ },
+ component: {
+ '#': {
+ selectfeature: 'selectFeature'
+ }
+ }
+ }
+ },
+
+ init: function () {
+ this.latestMarkers = {};
+ this.reportMarkers = {};
+ this.liveRoutes = {};
+ this.liveRouteLength = Traccar.app.getAttributePreference('web.liveRouteLength', 10);
+ },
+
+ getDeviceColor: function (device) {
+ switch (device.get('status')) {
+ case 'online':
+ return Traccar.Style.mapColorOnline;
+ case 'offline':
+ return Traccar.Style.mapColorOffline;
+ default:
+ return Traccar.Style.mapColorUnknown;
+ }
+ },
+
+ updateDevice: function (store, data) {
+ var i, device, deviceId, marker, style;
+
+ if (!Ext.isArray(data)) {
+ data = [data];
+ }
+
+ for (i = 0; i < data.length; i++) {
+ device = data[i];
+ deviceId = device.get('id');
+
+ if (deviceId in this.latestMarkers) {
+ marker = this.latestMarkers[deviceId];
+ style = marker.getStyle();
+ if (style.getImage().fill !== this.getDeviceColor(device) ||
+ style.getImage().category !== device.get('category')) {
+ marker.setStyle(this.updateDeviceMarker(style, this.getDeviceColor(device), device.get('category')));
+ }
+ if (style.getText().getText() !== device.get('name')) {
+ style.getText().setText(device.get('name'));
+ marker.changed();
+ }
+ }
+ }
+ },
+
+ removeDevice: function (store, data) {
+ var i, deviceId;
+ if (!Ext.isArray(data)) {
+ data = [data];
+ }
+ for (i = 0; i < data.length; i++) {
+ deviceId = data[i].get('id');
+ if (this.latestMarkers[deviceId]) {
+ this.getView().getLatestSource().removeFeature(this.latestMarkers[deviceId]);
+ }
+ }
+ },
+
+ updateLatest: function (store, data) {
+ var i, position, device;
+
+ if (!Ext.isArray(data)) {
+ data = [data];
+ }
+
+ for (i = 0; i < data.length; i++) {
+ position = data[i];
+ device = Ext.getStore('Devices').findRecord('id', position.get('deviceId'), 0, false, false, true);
+
+ if (device) {
+ this.updateLatestMarker(position, device);
+ this.updateLiveRoute(position);
+ }
+ }
+ },
+
+ updateLatestMarker: function (position, device) {
+ var geometry, deviceId, marker, style;
+ geometry = new ol.geom.Point(ol.proj.fromLonLat([
+ position.get('longitude'),
+ position.get('latitude')
+ ]));
+ deviceId = position.get('deviceId');
+ if (deviceId in this.latestMarkers) {
+ marker = this.latestMarkers[deviceId];
+ style = marker.getStyle();
+ if (style.getImage().angle !== position.get('course')) {
+ Traccar.DeviceImages.rotateImageIcon(style.getImage(), position.get('course'));
+ }
+ marker.setGeometry(geometry);
+ } else {
+ marker = new ol.Feature(geometry);
+ marker.set('record', device);
+
+ style = this.getLatestMarker(this.getDeviceColor(device),
+ position.get('course'),
+ device.get('category'));
+ style.getText().setText(device.get('name'));
+ marker.setStyle(style);
+ this.latestMarkers[deviceId] = marker;
+ this.getView().getLatestSource().addFeature(marker);
+
+ }
+
+ if (marker === this.selectedMarker && this.lookupReference('deviceFollowButton').pressed) {
+ this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
+ }
+ },
+
+ updateLiveRoute: function (position) {
+ var deviceId, liveLine, liveCoordinates, lastLiveCoordinates, newCoordinates;
+ deviceId = position.get('deviceId');
+ if (deviceId in this.liveRoutes) {
+ liveCoordinates = this.liveRoutes[deviceId].getGeometry().getCoordinates();
+ lastLiveCoordinates = liveCoordinates[liveCoordinates.length - 1];
+ newCoordinates = ol.proj.fromLonLat([position.get('longitude'), position.get('latitude')]);
+ if (lastLiveCoordinates[0] === newCoordinates[0] &&
+ lastLiveCoordinates[1] === newCoordinates[1]) {
+ return;
+ }
+ if (liveCoordinates.length >= this.liveRouteLength) {
+ liveCoordinates.shift();
+ }
+ liveCoordinates.push(newCoordinates);
+ this.liveRoutes[deviceId].getGeometry().setCoordinates(liveCoordinates);
+ } else {
+ liveLine = new ol.Feature({
+ geometry: new ol.geom.LineString([
+ ol.proj.fromLonLat([
+ position.get('longitude'),
+ position.get('latitude')
+ ])
+ ])
+ });
+ liveLine.setStyle(this.getRouteStyle(deviceId));
+ this.liveRoutes[deviceId] = liveLine;
+ this.getView().getLiveRouteSource().addFeature(liveLine);
+ }
+ },
+
+ loadReport: function (store, data) {
+ var i, position, point;
+
+ this.addReportMarkers(store, data);
+
+ this.reportRoute = [];
+ for (i = 0; i < data.length; i++) {
+ position = data[i];
+ point = ol.proj.fromLonLat([
+ position.get('longitude'),
+ position.get('latitude')
+ ]);
+ if (i === 0 || data[i].get('deviceId') !== data[i - 1].get('deviceId')) {
+ this.reportRoute.push(new ol.Feature({
+ geometry: new ol.geom.LineString([])
+ }));
+ this.reportRoute[this.reportRoute.length - 1].setStyle(this.getRouteStyle(data[i].get('deviceId')));
+ this.getView().getRouteSource().addFeature(this.reportRoute[this.reportRoute.length - 1]);
+ }
+ this.reportRoute[this.reportRoute.length - 1].getGeometry().appendCoordinate(point);
+ }
+ },
+
+ addReportMarkers: function (store, data) {
+ var i, position, point, geometry, marker, style, minx, miny, maxx, maxy;
+ this.clearReport();
+ for (i = 0; i < data.length; i++) {
+ position = data[i];
+ point = ol.proj.fromLonLat([
+ position.get('longitude'),
+ position.get('latitude')
+ ]);
+ if (i === 0) {
+ minx = maxx = point[0];
+ miny = maxy = point[1];
+ } else {
+ minx = Math.min(point[0], minx);
+ miny = Math.min(point[1], miny);
+ maxx = Math.max(point[0], maxx);
+ maxy = Math.max(point[1], maxy);
+ }
+ geometry = new ol.geom.Point(point);
+ marker = new ol.Feature(geometry);
+ marker.set('record', position);
+ style = this.getReportMarker(position.get('deviceId'), position.get('course'));
+ /*style.getText().setText(
+ Ext.Date.format(position.get('fixTime'), Traccar.Style.dateTimeFormat24));*/
+ marker.setStyle(style);
+ this.reportMarkers[position.get('id')] = marker;
+ this.getView().getReportSource().addFeature(marker);
+ }
+ if (minx !== maxx || miny !== maxy) {
+ this.getView().getMapView().fit([minx, miny, maxx, maxy], this.getView().getMap().getSize());
+ } else if (geometry) {
+ this.getView().getMapView().fit(geometry, this.getView().getMap().getSize());
+ }
+ },
+
+ clearReport: function () {
+ var key, i;
+
+ if (this.reportRoute) {
+ for (i = 0; i < this.reportRoute.length; i++) {
+ this.getView().getRouteSource().removeFeature(this.reportRoute[i]);
+ }
+ this.reportRoute = null;
+ }
+
+ if (this.reportMarkers) {
+ for (key in this.reportMarkers) {
+ if (this.reportMarkers.hasOwnProperty(key)) {
+ this.getView().getReportSource().removeFeature(this.reportMarkers[key]);
+ }
+ }
+ this.reportMarkers = {};
+ }
+ },
+
+ getRouteStyle: function (deviceId) {
+ var index = 0;
+ if (deviceId !== undefined) {
+ index = deviceId % Traccar.Style.mapRouteColor.length;
+ }
+ return new ol.style.Style({
+ stroke: new ol.style.Stroke({
+ color: Traccar.Style.mapRouteColor[index],
+ width: Traccar.Style.mapRouteWidth
+ })
+ });
+ },
+
+ getMarkerStyle: function (zoom, color, angle, category) {
+ var image = Traccar.DeviceImages.getImageIcon(color, zoom, angle, category);
+ return new ol.style.Style({
+ image: image,
+ text: new ol.style.Text({
+ textBaseline: 'bottom',
+ fill: new ol.style.Fill({
+ color: Traccar.Style.mapTextColor
+ }),
+ stroke: new ol.style.Stroke({
+ color: Traccar.Style.mapTextStrokeColor,
+ width: Traccar.Style.mapTextStrokeWidth
+ }),
+ offsetY: -image.getSize()[1] / 2 - Traccar.Style.mapTextOffset,
+ font : Traccar.Style.mapTextFont
+ })
+ });
+ },
+
+ getLatestMarker: function (color, angle, category) {
+ return this.getMarkerStyle(false, color, angle, category);
+ },
+
+ getReportMarker: function (deviceId, angle) {
+ var index = 0;
+ if (deviceId !== undefined) {
+ index = deviceId % Traccar.Style.mapRouteColor.length;
+ }
+ return this.getMarkerStyle(false, Traccar.Style.mapRouteColor[index], angle, 'arrow');
+ },
+
+ resizeMarker: function (style, zoom) {
+ var image, text;
+ image = Traccar.DeviceImages.getImageIcon(style.getImage().fill,
+ zoom,
+ style.getImage().angle,
+ style.getImage().category);
+ text = style.getText();
+ text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset);
+ return new ol.style.Style({
+ image: image,
+ text: text
+ });
+ },
+
+ updateDeviceMarker: function (style, color, category) {
+ var image, text;
+ image = Traccar.DeviceImages.getImageIcon(color,
+ style.getImage().zoom,
+ style.getImage().angle,
+ category);
+ text = style.getText();
+ text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset);
+ return new ol.style.Style({
+ image: image,
+ text: text
+ });
+ },
+
+ selectMarker: function (marker, center) {
+ if (this.selectedMarker) {
+ this.selectedMarker.setStyle(
+ this.resizeMarker(this.selectedMarker.getStyle(), false));
+ }
+
+ if (marker) {
+ marker.setStyle(
+ this.resizeMarker(marker.getStyle(), true));
+ if (center) {
+ this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
+ }
+ }
+
+ this.selectedMarker = marker;
+ },
+
+ selectDevice: function (device, center) {
+ this.selectMarker(this.latestMarkers[device.get('id')], center);
+ },
+
+ selectReport: function (position, center) {
+ if (position instanceof Traccar.model.Position) {
+ this.selectMarker(this.reportMarkers[position.get('id')], center);
+ }
+ },
+
+ selectFeature: function (feature) {
+ var record = feature.get('record');
+ if (record) {
+ if (record instanceof Traccar.model.Device) {
+ this.fireEvent('selectdevice', record, false);
+ } else {
+ this.fireEvent('selectreport', record, false);
+ }
+ }
+ }
+});
diff --git a/web/app/view/Notifications.js b/web/app/view/Notifications.js
index 900ebe3f..419d9616 100644
--- a/web/app/view/Notifications.js
+++ b/web/app/view/Notifications.js
@@ -24,7 +24,7 @@ Ext.define('Traccar.view.Notifications', {
],
controller: 'notificationsController',
- store: 'AllNotifications',
+ store: 'Notifications',
selModel: {
selType: 'cellmodel'
@@ -44,32 +44,21 @@ Ext.define('Traccar.view.Notifications', {
text: Strings.notificationType,
dataIndex: 'type',
renderer: function (value) {
- var typeKey = 'event' + value.charAt(0).toUpperCase() + value.slice(1);
- return Strings[typeKey];
+ return Traccar.app.getEventString(value);
}
}, {
text: Strings.notificationWeb,
- dataIndex: 'attributes.web',
+ dataIndex: 'web',
xtype: 'checkcolumn',
listeners: {
- beforeCheckChange: 'onBeforeCheckChange',
checkChange: 'onCheckChange'
- },
- renderer: function (value, metaData, record) {
- var fields = this.dataIndex.split('\.', 2);
- return (new Ext.ux.CheckColumn()).renderer(record.get(fields[0])[fields[1]], metaData);
}
}, {
text: Strings.notificationMail,
- dataIndex: 'attributes.mail',
+ dataIndex: 'mail',
xtype: 'checkcolumn',
listeners: {
- beforeCheckChange: 'onBeforeCheckChange',
checkChange: 'onCheckChange'
- },
- renderer: function (value, metaData, record) {
- var fields = this.dataIndex.split('\.', 2);
- return (new Ext.ux.CheckColumn()).renderer(record.get(fields[0])[fields[1]], metaData);
}
}]
}
diff --git a/web/app/view/NotificationsController.js b/web/app/view/NotificationsController.js
index 70b99f1b..4c83b145 100644
--- a/web/app/view/NotificationsController.js
+++ b/web/app/view/NotificationsController.js
@@ -24,57 +24,19 @@ Ext.define('Traccar.view.NotificationsController', {
],
init: function () {
- this.userId = this.getView().user.getId();
this.getView().getStore().load({
- scope: this,
- callback: function (records, operation, success) {
- var notificationsStore = Ext.create('Traccar.store.Notifications');
- notificationsStore.load({
- params: {
- userId: this.userId
- },
- scope: this,
- callback: function (records, operation, success) {
- var i, index, attributes, storeRecord;
- if (success) {
- for (i = 0; i < records.length; i++) {
- index = this.getView().getStore().findExact('type', records[i].get('type'));
- attributes = records[i].get('attributes');
- storeRecord = this.getView().getStore().getAt(index);
- storeRecord.set('attributes', attributes);
- storeRecord.commit();
- }
- }
- }
- });
+ params: {
+ userId: this.getView().user.getId()
}
});
},
- onBeforeCheckChange: function (column, rowIndex, checked, eOpts) {
- var fields, record, data;
- fields = column.dataIndex.split('\.', 2);
- record = this.getView().getStore().getAt(rowIndex);
- data = record.get(fields[0]);
- if (!data[fields[1]]) {
- data[fields[1]] = 'true';
- } else {
- delete data[fields[1]];
- }
- record.set(fields[0], data);
- record.commit();
- },
-
onCheckChange: function (column, rowIndex, checked, eOpts) {
var record = this.getView().getStore().getAt(rowIndex);
Ext.Ajax.request({
scope: this,
url: 'api/users/notifications',
- jsonData: {
- userId: this.userId,
- type: record.get('type'),
- attributes: record.get('attributes')
- },
+ jsonData: record.data,
callback: function (options, success, response) {
if (!success) {
Traccar.app.showError(response);
diff --git a/web/app/view/ReportConfigController.js b/web/app/view/ReportConfigController.js
index c121c654..0ae7c0a4 100644
--- a/web/app/view/ReportConfigController.js
+++ b/web/app/view/ReportConfigController.js
@@ -35,13 +35,11 @@ Ext.define('Traccar.view.ReportConfigController', {
Ext.create('Traccar.store.AllNotifications').load({
scope: this,
callback: function (records, operation, success) {
- var i, value, name, typeKey;
+ var i, value;
if (success) {
for (i = 0; i < records.length; i++) {
value = records[i].get('type');
- typeKey = 'event' + value.charAt(0).toUpperCase() + value.slice(1);
- name = Strings[typeKey];
- store.add({type: value, name: name});
+ store.add({type: value, name: Traccar.app.getEventString(value)});
}
}
}
diff --git a/web/app/view/ReportController.js b/web/app/view/ReportController.js
index 775394d0..1f3f3a2a 100644
--- a/web/app/view/ReportController.js
+++ b/web/app/view/ReportController.js
@@ -32,11 +32,18 @@ Ext.define('Traccar.view.ReportController', {
listen: {
controller: {
'*': {
- selectdevice: 'selectDevice'
+ selectdevice: 'selectDevice',
+ showsingleevent: 'showSingleEvent'
},
'map': {
selectreport: 'selectReport'
}
+ },
+ store: {
+ '#ReportEvents': {
+ add: 'loadEvents',
+ load: 'loadEvents'
+ }
}
}
},
@@ -112,8 +119,8 @@ Ext.define('Traccar.view.ReportController', {
deviceId: this.deviceId,
groupId: this.groupId,
type: this.eventType,
- from: from.toISOString(),
- to: to.toISOString()
+ from: Ext.Date.format(from, 'c'),
+ to: Ext.Date.format(to, 'c')
});
}
}
@@ -126,7 +133,7 @@ Ext.define('Traccar.view.ReportController', {
clearReport: function (reportType) {
this.getView().getStore().removeAll();
- if (reportType === 'trips') {
+ if (reportType === 'trips' || reportType === 'events') {
Ext.getStore('ReportRoute').removeAll();
}
},
@@ -139,6 +146,9 @@ Ext.define('Traccar.view.ReportController', {
if (report instanceof Traccar.model.ReportTrip) {
this.selectTrip(report);
}
+ if (report instanceof Traccar.model.Event) {
+ this.selectEvent(report);
+ }
}
},
@@ -149,10 +159,16 @@ Ext.define('Traccar.view.ReportController', {
},
selectReport: function (object, center) {
- var reportType = this.lookupReference('reportTypeField').getValue();
- if (object instanceof Traccar.model.Position && reportType === 'route') {
- this.getView().getSelectionModel().select([object], false, true);
- this.getView().getView().focusRow(object);
+ var positionEvent, reportType = this.lookupReference('reportTypeField').getValue();
+ if (object instanceof Traccar.model.Position) {
+ if (reportType === 'route') {
+ this.getView().getSelectionModel().select([object], false, true);
+ this.getView().getView().focusRow(object);
+ } else if (reportType === 'events') {
+ positionEvent = this.getView().getStore().findRecord('positionId', object.get('id'), 0, false, true, true);
+ this.getView().getSelectionModel().select([positionEvent], false, true);
+ this.getView().getView().focusRow(positionEvent);
+ }
}
},
@@ -170,6 +186,67 @@ Ext.define('Traccar.view.ReportController', {
});
},
+ selectEvent: function (event) {
+ var position;
+ if (event.get('positionId')) {
+ position = Ext.getStore('ReportRoute').getById(event.get('positionId'));
+ if (position) {
+ this.fireEvent('selectreport', position, true);
+ }
+ }
+ },
+
+ loadEvents: function (store, data) {
+ var i, eventObject, positionIds = [];
+ Ext.getStore('ReportRoute').removeAll();
+ for (i = 0; i < data.length; i++) {
+ eventObject = data[i];
+ if (eventObject.get('positionId')) {
+ positionIds.push(eventObject.get('positionId'));
+ }
+ }
+ if (positionIds.length > 0) {
+ Ext.getStore('Positions').load({
+ params: {
+ id: positionIds
+ },
+ scope: this,
+ callback: function (records, operation, success) {
+ if (success) {
+ Ext.getStore('ReportRoute').add(records);
+ if (records.length === 1) {
+ this.fireEvent('selectreport', records[0], false);
+ }
+ }
+ }
+ });
+ }
+ },
+
+ showSingleEvent: function (eventId) {
+ this.lookupReference('reportTypeField').setValue('events');
+ Ext.getStore('Events').load({
+ id: eventId,
+ scope: this,
+ callback: function (records, operation, success) {
+ if (success) {
+ Ext.getStore('ReportEvents').add(records);
+ if (records.length > 0) {
+ if (!records[0].get('positionId')) {
+ if (Traccar.app.isMobile()) {
+ Traccar.app.showReports(true);
+ } else {
+ this.getView().expand();
+ }
+ }
+ this.getView().getSelectionModel().select([records[0]], false, true);
+ this.getView().getView().focusRow(records[0]);
+ }
+ }
+ }
+ });
+ },
+
downloadFile: function (requestUrl, requestParams) {
Ext.Ajax.request({
url: requestUrl,
@@ -272,8 +349,7 @@ Ext.define('Traccar.view.ReportController', {
text: Strings.sharedType,
dataIndex: 'type',
renderer: function (value) {
- var typeKey = 'event' + value.charAt(0).toUpperCase() + value.slice(1);
- return Strings[typeKey];
+ return Traccar.app.getEventString(value);
}
}, {
text: Strings.sharedGeofence,
diff --git a/web/app/view/ServerDialog.js b/web/app/view/ServerDialog.js
index 0f965885..0a05876e 100644
--- a/web/app/view/ServerDialog.js
+++ b/web/app/view/ServerDialog.js
@@ -29,11 +29,15 @@ Ext.define('Traccar.view.ServerDialog', {
xtype: 'form',
items: [{
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'registration',
fieldLabel: Strings.serverRegistration,
allowBlank: false
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'readonly',
fieldLabel: Strings.serverReadonly,
allowBlank: false
@@ -88,11 +92,15 @@ Ext.define('Traccar.view.ServerDialog', {
fieldLabel: Strings.serverZoom
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'twelveHourFormat',
fieldLabel: Strings.settingsTwelveHourFormat,
allowBlank: false
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'forceSettings',
fieldLabel: Strings.serverForceSettings,
allowBlank: false
diff --git a/web/app/view/SettingsMenu.js b/web/app/view/SettingsMenu.js
index db436b33..c71c8372 100644
--- a/web/app/view/SettingsMenu.js
+++ b/web/app/view/SettingsMenu.js
@@ -82,6 +82,12 @@ Ext.define('Traccar.view.SettingsMenu', {
handler: 'onStatisticsClick',
reference: 'settingsStatisticsButton'
}, {
+ hidden: true,
+ text: Strings.sharedCalendars,
+ glyph: 'xf073@FontAwesome',
+ handler: 'onCalendarsClick',
+ reference: 'settingsCalendarsButton'
+ }, {
text: Strings.loginLogout,
glyph: 'xf08b@FontAwesome',
handler: 'onLogoutClick'
diff --git a/web/app/view/SettingsMenuController.js b/web/app/view/SettingsMenuController.js
index 0ec2a781..2f1685f0 100644
--- a/web/app/view/SettingsMenuController.js
+++ b/web/app/view/SettingsMenuController.js
@@ -30,6 +30,7 @@ Ext.define('Traccar.view.SettingsMenuController', {
'Traccar.view.AttributeAliases',
'Traccar.view.Statistics',
'Traccar.view.DeviceDistanceDialog',
+ 'Traccar.view.Calendars',
'Traccar.view.BaseWindow'
],
@@ -47,12 +48,14 @@ Ext.define('Traccar.view.SettingsMenuController', {
this.lookupReference('settingsGroupsButton').setHidden(false);
this.lookupReference('settingsGeofencesButton').setHidden(false);
this.lookupReference('settingsAttributeAliasesButton').setHidden(false);
+ this.lookupReference('settingsCalendarsButton').setHidden(false);
}
},
onUserClick: function () {
var dialog = Ext.create('Traccar.view.UserDialog');
dialog.down('form').loadRecord(Traccar.app.getUser());
+ dialog.lookupReference('testMailButton').setHidden(false);
dialog.show();
},
@@ -129,6 +132,16 @@ Ext.define('Traccar.view.SettingsMenuController', {
dialog.show();
},
+ onCalendarsClick: function () {
+ Ext.create('Traccar.view.BaseWindow', {
+ title: Strings.sharedCalendars,
+ modal: false,
+ items: {
+ xtype: 'calendarsView'
+ }
+ }).show();
+ },
+
onLogoutClick: function () {
Ext.create('Traccar.view.LoginController').logout();
}
diff --git a/web/app/view/State.js b/web/app/view/State.js
index 3356fd72..2dc466f1 100644
--- a/web/app/view/State.js
+++ b/web/app/view/State.js
@@ -49,11 +49,10 @@ Ext.define('Traccar.view.State', {
selectionchange: 'onSelectionChange'
},
- forceFit: true,
-
columns: {
defaults: {
- minWidth: Traccar.Style.columnWidthNormal
+ minWidth: Traccar.Style.columnWidthNormal,
+ flex: 1
},
items: [{
text: Strings.stateName,
diff --git a/web/app/view/UserCalendars.js b/web/app/view/UserCalendars.js
new file mode 100644
index 00000000..29bb99cb
--- /dev/null
+++ b/web/app/view/UserCalendars.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.view.UserCalendars', {
+ extend: 'Ext.grid.Panel',
+ xtype: 'userCalendarsView',
+
+ requires: [
+ 'Traccar.view.BasePermissionsController'
+ ],
+
+ controller: 'basePermissionsController',
+
+ selModel: {
+ selType: 'checkboxmodel',
+ checkOnly: true,
+ showHeaderCheckbox: false
+ },
+
+ listeners: {
+ beforedeselect: 'onBeforeDeselect',
+ beforeselect: 'onBeforeSelect'
+ },
+
+ forceFit: true,
+
+ columns: {
+ items: [{
+ text: Strings.sharedName,
+ minWidth: Traccar.Style.columnWidthNormal,
+ dataIndex: 'name'
+ }]
+ }
+});
diff --git a/web/app/view/UserDialog.js b/web/app/view/UserDialog.js
index 52ec933c..8ee12437 100644
--- a/web/app/view/UserDialog.js
+++ b/web/app/view/UserDialog.js
@@ -44,6 +44,8 @@ Ext.define('Traccar.view.UserDialog', {
allowBlank: false
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'readonly',
fieldLabel: Strings.serverReadonly,
allowBlank: false,
@@ -51,6 +53,8 @@ Ext.define('Traccar.view.UserDialog', {
reference: 'readonlyField'
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'admin',
fieldLabel: Strings.userAdmin,
allowBlank: false,
@@ -99,6 +103,8 @@ Ext.define('Traccar.view.UserDialog', {
fieldLabel: Strings.serverZoom
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'twelveHourFormat',
fieldLabel: Strings.settingsTwelveHourFormat,
allowBlank: false
@@ -112,6 +118,8 @@ Ext.define('Traccar.view.UserDialog', {
editable: false
}, {
xtype: 'checkboxfield',
+ inputValue: true,
+ uncheckedValue: false,
name: 'disabled',
fieldLabel: Strings.userDisabled,
hidden: true,
@@ -155,6 +163,14 @@ Ext.define('Traccar.view.UserDialog', {
tooltip: Strings.sharedGetMapState,
tooltipType: 'title'
}, {
+ glyph: 'xf003@FontAwesome',
+ minWidth: 0,
+ handler: 'testMail',
+ hidden: true,
+ reference: 'testMailButton',
+ tooltip: Strings.sharedTestMail,
+ tooltipType: 'title'
+ }, {
xtype: 'tbfill'
}, {
glyph: 'xf00c@FontAwesome',
diff --git a/web/app/view/UserDialogController.js b/web/app/view/UserDialogController.js
index 0f1c022b..f07031e3 100644
--- a/web/app/view/UserDialogController.js
+++ b/web/app/view/UserDialogController.js
@@ -42,6 +42,16 @@ Ext.define('Traccar.view.UserDialogController', {
this.lookupReference('tokenField').setValue(newToken);
},
+ testMail: function () {
+ Ext.Ajax.request({
+ url: 'api/users/notifications/test',
+ method: 'POST',
+ failure: function (response) {
+ Traccar.app.showError(response);
+ }
+ });
+ },
+
onSaveClick: function (button) {
var dialog, record, store;
dialog = button.up('window').down('form');
diff --git a/web/app/view/Users.js b/web/app/view/Users.js
index 4259c4c1..09a03cc2 100644
--- a/web/app/view/Users.js
+++ b/web/app/view/Users.js
@@ -1,5 +1,6 @@
/*
- * Copyright 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,6 +60,13 @@ Ext.define('Traccar.view.Users', {
glyph: 'xf003@FontAwesome',
tooltip: Strings.sharedNotifications,
tooltipType: 'title'
+ }, {
+ disabled: true,
+ handler: 'onCalendarsClick',
+ reference: 'userCalendarsButton',
+ glyph: 'xf073@FontAwesome',
+ tooltip: Strings.sharedCalendars,
+ tooltipType: 'title'
}]
},
diff --git a/web/app/view/UsersController.js b/web/app/view/UsersController.js
index 9b7076e6..af9d47b2 100644
--- a/web/app/view/UsersController.js
+++ b/web/app/view/UsersController.js
@@ -1,5 +1,6 @@
/*
- * Copyright 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +25,7 @@ Ext.define('Traccar.view.UsersController', {
'Traccar.view.UserDevices',
'Traccar.view.UserGroups',
'Traccar.view.UserGeofences',
+ 'Traccar.view.UserCalendars',
'Traccar.view.Notifications',
'Traccar.view.BaseWindow',
'Traccar.model.User'
@@ -129,6 +131,22 @@ Ext.define('Traccar.view.UsersController', {
}).show();
},
+ onCalendarsClick: function () {
+ var user = this.getView().getSelectionModel().getSelection()[0];
+ Ext.create('Traccar.view.BaseWindow', {
+ title: Strings.sharedCalendars,
+ items: {
+ xtype: 'userCalendarsView',
+ baseObjectName: 'userId',
+ linkObjectName: 'calendarId',
+ storeName: 'AllCalendars',
+ linkStoreName: 'Calendars',
+ urlApi: 'api/permissions/calendars',
+ baseObject: user.getId()
+ }
+ }).show();
+ },
+
onSelectionChange: function (selected) {
var disabled = selected.length > 0;
this.lookupReference('toolbarEditButton').setDisabled(disabled);
@@ -137,5 +155,6 @@ Ext.define('Traccar.view.UsersController', {
this.lookupReference('userGroupsButton').setDisabled(disabled);
this.lookupReference('userGeofencesButton').setDisabled(disabled);
this.lookupReference('userNotificationsButton').setDisabled(disabled);
+ this.lookupReference('userCalendarsButton').setDisabled(disabled);
}
});
diff --git a/web/debug.html b/web/debug.html
index bafdd3c4..5e47ee65 100644
--- a/web/debug.html
+++ b/web/debug.html
@@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Traccar</title>
+<link rel="stylesheet" href="app.css">
</head>
<body>
<div id="spinner"></div>
diff --git a/web/l10n/ar.json b/web/l10n/ar.json
index 0c72c8ee..f70fe04f 100644
--- a/web/l10n/ar.json
+++ b/web/l10n/ar.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "خطأ",
"errorUnknown": "خطأ غير معروف",
"errorConnection": "خطأ في الاتصال",
@@ -58,6 +59,7 @@
"loginFailed": "كلمة مرور او بريد خاطئ",
"loginCreated": "تم تسجيل مستخدم جديد",
"loginLogout": "خروج",
+ "loginLogo": "Logo",
"devicesAndState": "الأجهزة والحالة",
"deviceTitle": "أجهزة",
"deviceIdentifier": "المعرف",
@@ -111,6 +113,7 @@
"mapBingAerial": "خرائط جوية Bing",
"mapShapePolygon": "مضلع",
"mapShapeCircle": "دائرة",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "حالة",
"stateName": "عنصر",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "الجهاز متصل",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "الجهاز غير متصل",
"eventDeviceMoving": "الجهاز يتحرك",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/bg.json b/web/l10n/bg.json
index 7ccd4211..80d2d67e 100644
--- a/web/l10n/bg.json
+++ b/web/l10n/bg.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Грешка",
"errorUnknown": "Непозната Грешка",
"errorConnection": "Грешка във връзката",
@@ -58,6 +59,7 @@
"loginFailed": "Грешен потребител или парола",
"loginCreated": "Регистриран Нов Потребител",
"loginLogout": "Изход",
+ "loginLogo": "Logo",
"devicesAndState": "Устройства и състояние",
"deviceTitle": "Устройства",
"deviceIdentifier": "Идентификатор",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Многоъгълник",
"mapShapeCircle": "Кръг",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Състояние",
"stateName": "Параметър",
@@ -146,6 +149,7 @@
"commandMessage": "Съобщение",
"eventAll": "Всички събития",
"eventDeviceOnline": "Устройството е онлайн",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Устройството е офлайн",
"eventDeviceMoving": "Устройството е в движение",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Аларми",
"eventIgnitionOn": "Запалването е включено",
"eventIgnitionOff": "Запалването е изключено",
+ "eventMaintenance": "Maintenance required",
"alarm": "Аларма",
"alarmSos": "SOS Аларма",
"alarmVibration": "Аларма Вибрация",
diff --git a/web/l10n/cs.json b/web/l10n/cs.json
index 229febdb..8741fb97 100644
--- a/web/l10n/cs.json
+++ b/web/l10n/cs.json
@@ -40,6 +40,7 @@
"sharedAlias": "Přezdívka",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Chyba",
"errorUnknown": "Neznámá chyba",
"errorConnection": "Chyba spojení",
@@ -58,6 +59,7 @@
"loginFailed": "Nesprávný email nebo heslo",
"loginCreated": "Nový uživatel byl zaregistrován",
"loginLogout": "Odhlášení",
+ "loginLogo": "Logo",
"devicesAndState": "Zařízení a stav",
"deviceTitle": "Zařízení",
"deviceIdentifier": "Identifikace",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps anténa",
"mapShapePolygon": "Mnohoúhelník",
"mapShapeCircle": "Kruh",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Stav",
"stateName": "Atribut",
@@ -146,6 +149,7 @@
"commandMessage": "Zpráva",
"eventAll": "Všechny události",
"eventDeviceOnline": "Zařízení je online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Zařízení je offline",
"eventDeviceMoving": "Zařízení s pohybuje",
"eventDeviceStopped": "Zařízení se zastavilo",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmy",
"eventIgnitionOn": "Zažehnutí je ZAPNUTO",
"eventIgnitionOff": "Zažehnutí je VYPNUTO",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS alarm",
"alarmVibration": "Vibrační alarm",
diff --git a/web/l10n/da.json b/web/l10n/da.json
index ad61ff55..491b1374 100644
--- a/web/l10n/da.json
+++ b/web/l10n/da.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Fejl",
"errorUnknown": "Ukendt Fejl",
"errorConnection": "Tilslutning fejl",
@@ -58,6 +59,7 @@
"loginFailed": "Fejl i email adresse eller kodeord",
"loginCreated": "Ny bruger er registreret",
"loginLogout": "Log af",
+ "loginLogo": "Logo",
"devicesAndState": "Enheder og status",
"deviceTitle": "Enheder",
"deviceIdentifier": "Imei nr",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Cirkel",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Status",
"stateName": "Parameter",
@@ -146,6 +149,7 @@
"commandMessage": "Meddelelse",
"eventAll": "Alle begivenheder",
"eventDeviceOnline": "Enhed online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Enhed offline",
"eventDeviceMoving": "Enhed i bevægelse",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmer",
"eventIgnitionOn": "Tænding slået til",
"eventIgnitionOff": "Tænding slået fra",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS alarm",
"alarmVibration": "Vibrations alarm",
diff --git a/web/l10n/de.json b/web/l10n/de.json
index 1379c394..ba22a2f4 100644
--- a/web/l10n/de.json
+++ b/web/l10n/de.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Gerätedistanz",
"sharedDevice": "Gerät",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Fehler",
"errorUnknown": "Unbekannter Fehler",
"errorConnection": "Verbindungsfehler",
@@ -49,8 +50,8 @@
"userRemember": "Erinnern",
"userDisabled": "Deaktiviert",
"userExpirationTime": "Ablaufdatum",
- "userDeviceLimit": "Device Limit",
- "userToken": "Token",
+ "userDeviceLimit": "Gerätelimit",
+ "userToken": "Zeichen",
"loginTitle": "Anmeldung",
"loginLanguage": "Sprache",
"loginRegister": "Registrieren",
@@ -58,13 +59,14 @@
"loginFailed": "Falsche Emailadresse oder Passwort",
"loginCreated": "Neuer Benutzer wurde registriert",
"loginLogout": "Abmelden",
+ "loginLogo": "Logo",
"devicesAndState": "Geräte und Status",
"deviceTitle": "Geräte",
"deviceIdentifier": "Kennung",
"devicePhone": "Telefon",
"deviceModel": "Modell",
"deviceContact": "Kontakt",
- "deviceCategory": "Kategorie",
+ "deviceCategory": "Symbol",
"deviceLastUpdate": "Letzte Aktualisierung",
"deviceCommand": "Befehl",
"deviceFollow": "Folgen",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Luftbilder",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Kreis",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Route",
"stateTitle": "Status",
"stateName": "Parameter",
@@ -146,6 +149,7 @@
"commandMessage": "Nachricht",
"eventAll": "Alle Ereignisse",
"eventDeviceOnline": "Gerät ist online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Gerät ist offline",
"eventDeviceMoving": "Gerät ist in Bewegung",
"eventDeviceStopped": "Gerät hat angehalten",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarme",
"eventIgnitionOn": "Zünding an",
"eventIgnitionOff": "Zündung aus",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Erschütterungsalarm",
diff --git a/web/l10n/el.json b/web/l10n/el.json
index 0c7b8c69..1abac4dc 100644
--- a/web/l10n/el.json
+++ b/web/l10n/el.json
@@ -40,6 +40,7 @@
"sharedAlias": "Ψευδώνυμο",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Σφάλμα",
"errorUnknown": "Άγνωστο σφάλμα",
"errorConnection": "Σφάλμα σύνδεσης",
@@ -58,6 +59,7 @@
"loginFailed": "Εσφαλμένη διεύθυνση ή εσφαλμένο συνθηματικό",
"loginCreated": "Ο νέος χρήστης καταχωρήθηκε.",
"loginLogout": "Αποσύνδεση",
+ "loginLogo": "Logo",
"devicesAndState": "Κατάσταση συσκευών",
"deviceTitle": "Συσκευές",
"deviceIdentifier": "Αναγνωριστικό",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Πολύγωνο",
"mapShapeCircle": "Κύκλος",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Κατάσταση",
"stateName": "Παράμετρος",
@@ -146,6 +149,7 @@
"commandMessage": "Μήνυμα",
"eventAll": "Όλα τα γεγονότα",
"eventDeviceOnline": "Η συσκευή είναι συνδεδεμένη",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Η συσκευή είναι αποσυνδεδεμένη",
"eventDeviceMoving": "Η συσκευή βρίσκεται σε κίνηση",
"eventDeviceStopped": "Η συσκευή είναι σταματημένη",
@@ -156,6 +160,7 @@
"eventAlarm": "Προειδοποιήσεις",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Προειδοποίηση",
"alarmSos": "Προειδοποίηση SOS",
"alarmVibration": "Προειδοποίηση δόνησης",
diff --git a/web/l10n/en.json b/web/l10n/en.json
index 220c1d68..39376bea 100644
--- a/web/l10n/en.json
+++ b/web/l10n/en.json
@@ -40,9 +40,15 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
+ "sharedCalendar": "Calendar",
+ "sharedCalendars": "Calendars",
+ "sharedFile": "File",
+ "sharedSelectFile": "Select File",
"errorTitle": "Error",
"errorUnknown": "Unknown error",
"errorConnection": "Connection error",
+ "errorSocket": "Web socket connection error",
"userEmail": "Email",
"userPassword": "Password",
"userAdmin": "Admin",
@@ -58,6 +64,7 @@
"loginFailed": "Incorrect email address or password",
"loginCreated": "New user has been registered",
"loginLogout": "Logout",
+ "loginLogo": "Logo",
"devicesAndState": "Devices and State",
"deviceTitle": "Devices",
"deviceIdentifier": "Identifier",
@@ -111,6 +118,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "State",
"stateName": "Attribute",
@@ -148,6 +156,7 @@
"commandTimezone": "Timezone Offset",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -158,6 +167,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/es.json b/web/l10n/es.json
index e660c775..ce65fe49 100644
--- a/web/l10n/es.json
+++ b/web/l10n/es.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Error",
"errorUnknown": "Error Desconocido",
"errorConnection": "Error de Conexión",
@@ -58,6 +59,7 @@
"loginFailed": "Dirección de Correo o Contraseña Incorrecta",
"loginCreated": "Nuevo Usuario ha sido registrado",
"loginLogout": "Salir",
+ "loginLogo": "Logo",
"devicesAndState": "Dispositivos y Estado",
"deviceTitle": "Dispositivos",
"deviceIdentifier": "Identificador",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps - Aéreo",
"mapShapePolygon": "Polígono",
"mapShapeCircle": "Círculo",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Estado",
"stateName": "Parámetro",
@@ -146,6 +149,7 @@
"commandMessage": "Mensaje",
"eventAll": "Todos los Eventos",
"eventDeviceOnline": "El dispositivo está en linea",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "El dispositivo está fuera de linea",
"eventDeviceMoving": "El dispositivo se está moviendo",
"eventDeviceStopped": "El dispositivo se ha detenido",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmas",
"eventIgnitionOn": "Encendido ON",
"eventIgnitionOff": "Encendido OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarma",
"alarmSos": "Alarma de SOS",
"alarmVibration": "Alarma de vibración",
diff --git a/web/l10n/fa.json b/web/l10n/fa.json
index b3e68e94..0d7e0dab 100644
--- a/web/l10n/fa.json
+++ b/web/l10n/fa.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "خطا",
"errorUnknown": "خطا ناشناخته",
"errorConnection": "خطا در اتصال",
@@ -58,6 +59,7 @@
"loginFailed": "نام كاربرى يا گذرواژه اشتباه است",
"loginCreated": "ثبت نام با موفقيت انجام شد",
"loginLogout": "خروج",
+ "loginLogo": "Logo",
"devicesAndState": "دستگاه ها و وضعیت",
"deviceTitle": "دستگاه ها",
"deviceIdentifier": "سريال دستگاه",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "چند ضلعی",
"mapShapeCircle": "دایره ",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "وضعیت",
"stateName": "ویژگی",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "دستگاه آنلاین است ",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "دستگاه آفلاین است ",
"eventDeviceMoving": "خودرو در حال حرکت است",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "هشدار ها",
"eventIgnitionOn": "خودرو روشن هست ",
"eventIgnitionOff": "خودرو خاموش است ",
+ "eventMaintenance": "Maintenance required",
"alarm": "هشدار",
"alarmSos": "هشدار کمک اضطراری",
"alarmVibration": "هشدار ضربه",
diff --git a/web/l10n/fi.json b/web/l10n/fi.json
index 12691f0d..beccd687 100644
--- a/web/l10n/fi.json
+++ b/web/l10n/fi.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Virhe",
"errorUnknown": "Tuntematon virhe",
"errorConnection": "Yhteysvirhe",
@@ -58,6 +59,7 @@
"loginFailed": "Virheellinen email tai salasana",
"loginCreated": "Uusi käyttäjä on rekisteröitynyt",
"loginLogout": "Kirjaudu ulos",
+ "loginLogo": "Logo",
"devicesAndState": "Laitteet ja Tilat",
"deviceTitle": "Laitteet",
"deviceIdentifier": "Tunniste",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps ilmakuva",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Tila",
"stateName": "Ominaisuus",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/fr.json b/web/l10n/fr.json
index 85ed03f0..ec042e58 100644
--- a/web/l10n/fr.json
+++ b/web/l10n/fr.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Erreur",
"errorUnknown": "Erreur inconnue",
"errorConnection": "Erreur de connexion",
@@ -58,6 +59,7 @@
"loginFailed": "Adresse email ou mot de passe incorrect",
"loginCreated": "Nouvel utilisateur enregistré",
"loginLogout": "Déconnexion",
+ "loginLogo": "Logo",
"devicesAndState": "Dispositifs et Etat",
"deviceTitle": "Dispositifs",
"deviceIdentifier": "Identifiant",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygone",
"mapShapeCircle": "Cercle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Etat",
"stateName": "Paramètre",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "Tous les événements",
"eventDeviceOnline": "L'appareil est en ligne",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "L'appareil est hors-ligne",
"eventDeviceMoving": "L'appareil est en mouvement",
"eventDeviceStopped": "Le dispositif s'est arrêté",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmes",
"eventIgnitionOn": "Contact mis",
"eventIgnitionOff": "Contact coupé",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarme",
"alarmSos": "Alarme SOS",
"alarmVibration": "Alarme vibration",
diff --git a/web/l10n/he.json b/web/l10n/he.json
index 79712ef9..5bfa1160 100644
--- a/web/l10n/he.json
+++ b/web/l10n/he.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "שגיאה",
"errorUnknown": "שגיאה לא ידועה",
"errorConnection": "בעייה בחיבור",
@@ -58,6 +59,7 @@
"loginFailed": "אימייל או סיסמה שגויים",
"loginCreated": "משתמש חדש נרשם",
"loginLogout": "יציאה",
+ "loginLogo": "Logo",
"devicesAndState": "מכשירים וסטטוס",
"deviceTitle": "מכשירים",
"deviceIdentifier": "מזהה",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "פוליגון",
"mapShapeCircle": "מעגל",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "מצב",
"stateName": "תכונה",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "המכשיר און לין",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "המכשיר מנותק",
"eventDeviceMoving": "המכשיר בתזוזה",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "אזעקות",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "אזעקה",
"alarmSos": "אתרעת SOS",
"alarmVibration": "אזעקת רטט",
diff --git a/web/l10n/hi.json b/web/l10n/hi.json
index d8e10931..4ca52215 100644
--- a/web/l10n/hi.json
+++ b/web/l10n/hi.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "त्रुटि",
"errorUnknown": "अज्ञात त्रुटि",
"errorConnection": "कनेक्शन त्रुटि",
@@ -58,6 +59,7 @@
"loginFailed": "ई-मेल पता या पासवर्ड गलत है",
"loginCreated": "नया उपयोगकर्ता पंजीकृत हो गया है",
"loginLogout": "लॉगआउट / निष्कासन करें",
+ "loginLogo": "Logo",
"devicesAndState": "उपकरण एवम स्तिति",
"deviceTitle": "उपकरण",
"deviceIdentifier": "पहचानकर्ता",
@@ -111,6 +113,7 @@
"mapBingAerial": "बिंग मैप्स एरियल",
"mapShapePolygon": "बहुभुज",
"mapShapeCircle": "वृत्त",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "स्थिति / अवस्ता",
"stateName": "गुण",
@@ -146,6 +149,7 @@
"commandMessage": "संदेश / मेसेज",
"eventAll": "सभी घटनाएँ / इवेंट्स",
"eventDeviceOnline": "उपकरण / डिवाइस ऑनलाइन है",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "उपकरण / डिवाइस ऑफ़लाइन है",
"eventDeviceMoving": "उपकरण / डिवाइस गतिमान है",
"eventDeviceStopped": "उपकरण / डिवाइस रुक गया है",
@@ -156,6 +160,7 @@
"eventAlarm": " एक से अधिक अलार्म",
"eventIgnitionOn": "इग्निशन ऑन / चालू है",
"eventIgnitionOff": "इग्निशन ऑफ / बंद है",
+ "eventMaintenance": "Maintenance required",
"alarm": "अलार्म",
"alarmSos": "एसओएस / एमर्जेन्सी अलार्म",
"alarmVibration": "कंपन होने का अलार्म",
diff --git a/web/l10n/hu.json b/web/l10n/hu.json
index d1a5fcb4..a598be1a 100644
--- a/web/l10n/hu.json
+++ b/web/l10n/hu.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Hiba",
"errorUnknown": "Ismeretlen hiba",
"errorConnection": "Kapcsolódási hiba",
@@ -58,6 +59,7 @@
"loginFailed": "Hibás email vagy jelszó",
"loginCreated": "Az új felhasználó sikeresen létrehozva",
"loginLogout": "Kilépés",
+ "loginLogo": "Logo",
"devicesAndState": "Eszközök és állapotuk",
"deviceTitle": "Eszközök",
"deviceIdentifier": "Azonosító",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Poligon",
"mapShapeCircle": "Kör",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Helyzet",
"stateName": "Paraméter",
@@ -146,6 +149,7 @@
"commandMessage": "Üzenet",
"eventAll": "Minden esemény",
"eventDeviceOnline": "Eszköz online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Eszköz offline",
"eventDeviceMoving": "Eszköz mozog",
"eventDeviceStopped": "Eszköz megállt",
@@ -156,6 +160,7 @@
"eventAlarm": "Riasztások",
"eventIgnitionOn": "Gyújtás BE",
"eventIgnitionOff": "Gyújtás KI",
+ "eventMaintenance": "Maintenance required",
"alarm": "Riasztás",
"alarmSos": "SOS Riasztás",
"alarmVibration": "Rezgés riasztás",
diff --git a/web/l10n/id.json b/web/l10n/id.json
index 424f9796..03a3c3c7 100644
--- a/web/l10n/id.json
+++ b/web/l10n/id.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Error",
"errorUnknown": "Error tidak diketahui",
"errorConnection": "Koneksi error",
@@ -58,6 +59,7 @@
"loginFailed": "Email atau password salah",
"loginCreated": "Pengguna baru telah terdaftar",
"loginLogout": "Keluar",
+ "loginLogo": "Logo",
"devicesAndState": "Perangkat dan Status",
"deviceTitle": "Perangkat",
"deviceIdentifier": "Identifikasi",
@@ -111,6 +113,7 @@
"mapBingAerial": "Peta Udara Bing",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Status",
"stateName": "atribut",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/it.json b/web/l10n/it.json
index 2f83e0ed..a6ffe655 100644
--- a/web/l10n/it.json
+++ b/web/l10n/it.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Errore",
"errorUnknown": "Errore sconosciuto",
"errorConnection": "Errore di connessione",
@@ -58,6 +59,7 @@
"loginFailed": "Indirizzo email o password errati",
"loginCreated": "Un nuovo utente si e` registrato",
"loginLogout": "Logout",
+ "loginLogo": "Logo",
"devicesAndState": "Dispositivi e stato",
"deviceTitle": "Dispositivi",
"deviceIdentifier": "Identificativo",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Poligono",
"mapShapeCircle": "Cerchio",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Stato",
"stateName": "Attributo",
@@ -146,6 +149,7 @@
"commandMessage": "Messaggio",
"eventAll": "Tutti gli Eventi",
"eventDeviceOnline": "Dispositivo online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Dispositivo offline",
"eventDeviceMoving": "Dispositivo in movimento",
"eventDeviceStopped": "Il dispositivo si è feramto",
@@ -156,6 +160,7 @@
"eventAlarm": "Allarmi",
"eventIgnitionOn": "Accensione è inserita",
"eventIgnitionOff": "Accensione è disinserita",
+ "eventMaintenance": "Maintenance required",
"alarm": "Allarme",
"alarmSos": "Allarme SOS",
"alarmVibration": "Allarme Vibrazione",
diff --git a/web/l10n/ka.json b/web/l10n/ka.json
index 765c2a9e..da5f00d6 100644
--- a/web/l10n/ka.json
+++ b/web/l10n/ka.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "შეცდომა",
"errorUnknown": "უცნობი შეცდომა",
"errorConnection": "კავშირის შეცდომა",
@@ -58,6 +59,7 @@
"loginFailed": "არასწორი ელ-ფოსტა ან პაროლი",
"loginCreated": "ახალი მომხარებელი დარეგისტრირდა",
"loginLogout": "გამოსვლა",
+ "loginLogo": "Logo",
"devicesAndState": "მოწყობილობები და სტატუსი",
"deviceTitle": "მოწყობილობები",
"deviceIdentifier": "იდენტიფიკატორი",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "სტატუსი",
"stateName": "ატრიბუტი",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/lo.json b/web/l10n/lo.json
index 3d3e4b96..74c11a53 100644
--- a/web/l10n/lo.json
+++ b/web/l10n/lo.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "ຜິດພາດ",
"errorUnknown": "ຂໍ້ຜິດພາດທີ່ບໍ່ຮູ້ຈັກ",
"errorConnection": "ການເຊື່ອມຕໍ່ຜິດພາດ",
@@ -58,6 +59,7 @@
"loginFailed": "ທີ່ຢູ່ອີເມວຫລືລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ",
"loginCreated": "ຜູ້ໃຊ້ໃຫມ່ ໄດ້ຮັບການລົງທະບຽນ",
"loginLogout": "ອອກຈາກລະບົບ",
+ "loginLogo": "Logo",
"devicesAndState": "ອຸປະກອນແລະສະຖານະ",
"deviceTitle": "ເຄື່ອງ/ອຸປະກອນ",
"deviceIdentifier": "ລະບຸເລກອຸປະກອນ",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps ທາງອາກາດ",
"mapShapePolygon": "ໂພລີກອນ",
"mapShapeCircle": "ວົງກົມ",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "ສະຖານະ",
"stateName": "ຄຸນລັກສະນະ",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "ອຸປະກອນເຊື່ອມຕໍ່ແລ້ວ",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "ອຸປະກອນບໍ່ໄດ້ເຊື່ອມຕໍ່",
"eventDeviceMoving": "ອຸປະກອນກຳລັງເຄື່ອນທີ່",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "ລາຍການແຈ້ງເຕືອນ",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "ແຈ້ງເຕືອນ",
"alarmSos": "ແຈ້ງເຕືອນ SOS",
"alarmVibration": "ແຈ້ງເຕືອນແບບສັ່ນ",
diff --git a/web/l10n/lt.json b/web/l10n/lt.json
index 43c804a4..6d3da8fc 100644
--- a/web/l10n/lt.json
+++ b/web/l10n/lt.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Klaida",
"errorUnknown": "Nenumatyta klaida",
"errorConnection": "Ryšio klaida",
@@ -58,6 +59,7 @@
"loginFailed": "Neteisingas el.paštas ir/ar slaptažodis",
"loginCreated": "Registracija sėkminga",
"loginLogout": "Atsijungti",
+ "loginLogo": "Logo",
"devicesAndState": "Prietaisai ir Statusas",
"deviceTitle": "Prietaisai",
"deviceIdentifier": "Identifikacinis kodas",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Būklė",
"stateName": "Parametras",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/ml.json b/web/l10n/ml.json
index 0aedf6ca..ab4037e6 100644
--- a/web/l10n/ml.json
+++ b/web/l10n/ml.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "പിശക്‌",
"errorUnknown": "അജ്ഞാത പിശക്",
"errorConnection": "കണക്ഷൻ പിശക്",
@@ -58,6 +59,7 @@
"loginFailed": "തെറ്റായ ഇമെയിൽ വിലാസവും പാസ്വേഡും",
"loginCreated": "പുതിയ ഉപയോക്താവ് രജിസ്റ്റർ ചെയ്തു",
"loginLogout": "പുറത്തുകടക്കുക",
+ "loginLogo": "Logo",
"devicesAndState": "സാധനങ്ങളിന് നില ",
"deviceTitle": "സാധനങ്ങളിന് ",
"deviceIdentifier": "ഐഡന്റിഫയർ",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "State",
"stateName": "Attribute",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/ms.json b/web/l10n/ms.json
index a1c90970..6a9f3c4a 100644
--- a/web/l10n/ms.json
+++ b/web/l10n/ms.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Ralat",
"errorUnknown": "Ralat tidak diketahui",
"errorConnection": "Ralat penyambungan",
@@ -58,6 +59,7 @@
"loginFailed": "Kesalahan emel atau katalaluan",
"loginCreated": "Pengguna baru telah didaftarkan",
"loginLogout": "Keluar",
+ "loginLogo": "Logo",
"devicesAndState": "Peranti dan State",
"deviceTitle": "Peranti",
"deviceIdentifier": "IMEI/ID",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Negeri",
"stateName": "Atribut",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/nb.json b/web/l10n/nb.json
index f4afa0e7..fee18de2 100644
--- a/web/l10n/nb.json
+++ b/web/l10n/nb.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Feil",
"errorUnknown": "Ukjent feil",
"errorConnection": "Forbindelse feilet",
@@ -58,6 +59,7 @@
"loginFailed": "Feil e-post eller passord",
"loginCreated": "Ny bruker har blitt registrert",
"loginLogout": "Logg ut",
+ "loginLogo": "Logo",
"devicesAndState": "Enheter og status",
"deviceTitle": "Enheter",
"deviceIdentifier": "Identifikator",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps-flyfoto",
"mapShapePolygon": "Mangekant",
"mapShapeCircle": "Sirkel",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Status",
"stateName": "Egenskap",
@@ -146,6 +149,7 @@
"commandMessage": "Melding",
"eventAll": "Alle hendelser",
"eventDeviceOnline": "Enhet er tilkoblet",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Enhet er frakoblet",
"eventDeviceMoving": "Enheten beveger seg",
"eventDeviceStopped": "Enheten har stoppet",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmer",
"eventIgnitionOn": "Tenning er PÅ",
"eventIgnitionOff": "Tenning er AV",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS-alarm",
"alarmVibration": "Vibrasjonsalarm",
diff --git a/web/l10n/ne.json b/web/l10n/ne.json
index 1ccbcbec..744153b3 100644
--- a/web/l10n/ne.json
+++ b/web/l10n/ne.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "त्रुटी",
"errorUnknown": "अज्ञात त्रुटी ",
"errorConnection": "जडान मा त्रुटी भयो ",
@@ -58,6 +59,7 @@
"loginFailed": "इ मेल वा गोप्य शब्द गलत भयो ",
"loginCreated": "नया प्रयोगकर्ता दर्ता भयो ",
"loginLogout": "बाहिरिने ",
+ "loginLogo": "Logo",
"devicesAndState": "यन्त्रहरू तथा अवस्था ",
"deviceTitle": "यन्त्रहरू ",
"deviceIdentifier": "परिचायक ",
@@ -111,6 +113,7 @@
"mapBingAerial": "बिंग नक्शा (एरियल)",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "अवस्था ",
"stateName": "गुण ",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/nl.json b/web/l10n/nl.json
index d8d40381..8e2d3b5f 100644
--- a/web/l10n/nl.json
+++ b/web/l10n/nl.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Afstand apparaat",
"sharedDevice": "Apparaat",
+ "sharedTestMail": "Verstuur test-e-mail",
"errorTitle": "Fout",
"errorUnknown": "Onbekende fout",
"errorConnection": "Verbindingsfout",
@@ -58,6 +59,7 @@
"loginFailed": "Onjuist e-mailadres of wachtwoord",
"loginCreated": "De nieuwe gebruiker is geregistreerd",
"loginLogout": "Afmelden",
+ "loginLogo": "Logo",
"devicesAndState": "Apparaten en status",
"deviceTitle": "Apparaten",
"deviceIdentifier": "Identifier",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Luchtfoto",
"mapShapePolygon": "Polygoon",
"mapShapeCircle": "Cirkel",
+ "mapShapePolyline": "Polylijn",
"mapLiveRoutes": "Live routes",
"stateTitle": "Status",
"stateName": "Parameter",
@@ -146,6 +149,7 @@
"commandMessage": "Bericht",
"eventAll": "Alle gebeurtenissen",
"eventDeviceOnline": "Apparaat is online",
+ "eventDeviceUnknown": "Apparaatstatus is onbekend",
"eventDeviceOffline": "Apparaat is offline",
"eventDeviceMoving": "Apparaat beweegt",
"eventDeviceStopped": "Apparaat is gestopt",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmen",
"eventIgnitionOn": "Contact aan",
"eventIgnitionOff": "Contact uit",
+ "eventMaintenance": "Onderhoud vereist",
"alarm": "Alarm",
"alarmSos": "SOS alarm",
"alarmVibration": "Vibratiealarm",
diff --git a/web/l10n/nn.json b/web/l10n/nn.json
index 82e59dc5..40e037f9 100644
--- a/web/l10n/nn.json
+++ b/web/l10n/nn.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Feil",
"errorUnknown": "Ukjent feil",
"errorConnection": "Forbindelse feila",
@@ -58,6 +59,7 @@
"loginFailed": "Feil e-post eller passord",
"loginCreated": "Ny brukar har blitt registrert",
"loginLogout": "Logg ut",
+ "loginLogo": "Logo",
"devicesAndState": "Einingar og status",
"deviceTitle": "Einingar",
"deviceIdentifier": "Identifikator",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps-flyfoto",
"mapShapePolygon": "Mangekant",
"mapShapeCircle": "Sirkel",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Status",
"stateName": "Eigenskap",
@@ -146,6 +149,7 @@
"commandMessage": "Melding",
"eventAll": "Alle hendingar",
"eventDeviceOnline": "Eining er tilkopla",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Eininga er fråkopla",
"eventDeviceMoving": "Eininga rører seg",
"eventDeviceStopped": "Eininga har stoppa",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmar",
"eventIgnitionOn": "Tenninga er PÅ",
"eventIgnitionOff": "Tenninga er AV",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS-alarm",
"alarmVibration": "Vibrasjonsalarm",
diff --git a/web/l10n/pl.json b/web/l10n/pl.json
index 28262aeb..b857a72e 100644
--- a/web/l10n/pl.json
+++ b/web/l10n/pl.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Dystans urządzenia",
"sharedDevice": "Urządzenie",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Bląd",
"errorUnknown": "Nieznany błąd",
"errorConnection": "Błąd przy połączeniu",
@@ -58,6 +59,7 @@
"loginFailed": "Nieprawidłowy adres e-mail lub hasło",
"loginCreated": "Nowy użytkownik został zarejestrowany",
"loginLogout": "Wyloguj",
+ "loginLogo": "Logo",
"devicesAndState": "Urządzenia i stan",
"deviceTitle": "Urządzenia",
"deviceIdentifier": "Identyfikator",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Wielokąt",
"mapShapeCircle": "Okrąg",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Ścieżki na żywo",
"stateTitle": "Stan i lokalizacja",
"stateName": "Właściwość",
@@ -146,6 +149,7 @@
"commandMessage": "Wiadomość",
"eventAll": "Wszystkie zdarzenia",
"eventDeviceOnline": "Urządzenie jest online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Urządzenie jest offline",
"eventDeviceMoving": "Urządzenie przemieszcza się",
"eventDeviceStopped": "Urządzenie się zatrzymało",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmy",
"eventIgnitionOn": "Zapłon włączony",
"eventIgnitionOff": "Zapłon wyłączony",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "Alarm SOS",
"alarmVibration": "Alarm wibracyjny",
diff --git a/web/l10n/pt.json b/web/l10n/pt.json
index 4a63cc55..c516cce4 100644
--- a/web/l10n/pt.json
+++ b/web/l10n/pt.json
@@ -1,8 +1,8 @@
{
"sharedLoading": "Carregando...",
- "sharedHide": "Hide",
+ "sharedHide": "Ocultar",
"sharedSave": "Salvar",
- "sharedSet": "Set",
+ "sharedSet": "Conjunto",
"sharedCancel": "Cancelar",
"sharedAdd": "Adicionar",
"sharedEdit": "Editar",
@@ -17,72 +17,74 @@
"sharedHour": "Hora",
"sharedMinute": "Minuto",
"sharedSecond": "Segundo",
- "sharedDecimalDegrees": "Decimal Degrees",
- "sharedDegreesDecimalMinutes": "Degrees Decimal Minutes",
- "sharedDegreesMinutesSeconds": "Degrees Minutes Seconds",
- "sharedName": "Name",
- "sharedDescription": "Description",
- "sharedSearch": "Search",
- "sharedGeofence": "Geofence",
- "sharedGeofences": "Geofences",
- "sharedNotifications": "Notifications",
- "sharedAttributes": "Attributes",
- "sharedAttribute": "Attribute",
- "sharedArea": "Area",
- "sharedMute": "Mute",
- "sharedType": "Type",
- "sharedDistance": "Distance",
- "sharedHourAbbreviation": "h",
- "sharedMinuteAbbreviation": "m",
- "sharedGetMapState": "Get Map State",
- "sharedAttributeAlias": "Attribute Alias",
- "sharedAttributeAliases": "Attribute Aliases",
+ "sharedDecimalDegrees": "Graus Decimais",
+ "sharedDegreesDecimalMinutes": "Graus Decimais Minutos",
+ "sharedDegreesMinutesSeconds": "Graus Decimais Segundos",
+ "sharedName": "Nome",
+ "sharedDescription": "Descrição",
+ "sharedSearch": "Pesquisar",
+ "sharedGeofence": "Cerca Geográfica",
+ "sharedGeofences": "Cercas Geográficas",
+ "sharedNotifications": "Notificações",
+ "sharedAttributes": "Atributos",
+ "sharedAttribute": "Atributo",
+ "sharedArea": "Área",
+ "sharedMute": "Mudo",
+ "sharedType": "Tipo",
+ "sharedDistance": "Distância",
+ "sharedHourAbbreviation": "H",
+ "sharedMinuteAbbreviation": "M",
+ "sharedGetMapState": "Obter Estado do Mapa",
+ "sharedAttributeAlias": "Alias de Atributo",
+ "sharedAttributeAliases": "Alias de Atributos",
"sharedAlias": "Alias",
- "sharedDeviceDistance": "Device Distance",
- "sharedDevice": "Device",
+ "sharedDeviceDistance": "Distancia do Dispositivo",
+ "sharedDevice": "Dispositivo",
+ "sharedTestMail": "Enviar Email de Teste",
"errorTitle": "Erro",
"errorUnknown": "Erro desconhecido",
"errorConnection": "Erro de conexão",
- "userEmail": "E-mail",
+ "userEmail": "Email",
"userPassword": "Senha",
- "userAdmin": "Admin",
- "userRemember": "Remember",
- "userDisabled": "Disabled",
- "userExpirationTime": "Expiration",
- "userDeviceLimit": "Device Limit",
- "userToken": "Token",
+ "userAdmin": "Administrador",
+ "userRemember": "Relembrar",
+ "userDisabled": "Desactivado",
+ "userExpirationTime": "Expiração",
+ "userDeviceLimit": "Limite do Dipositivo",
+ "userToken": "Símbolo",
"loginTitle": "Entrar",
"loginLanguage": "Idioma",
- "loginRegister": "Registrar",
+ "loginRegister": "Registar",
"loginLogin": "Entrar",
- "loginFailed": "Endereço de e-mail ou senha incorreta",
- "loginCreated": "Novo usuário foi registrado",
+ "loginFailed": "Endereço de e-mail ou senha incorrectos",
+ "loginCreated": "Novo utilizador foi registado",
"loginLogout": "Sair",
- "devicesAndState": "Devices and State",
- "deviceTitle": "Devices",
+ "loginLogo": "Logótipo",
+ "devicesAndState": "Dispositivos e Estados",
+ "deviceTitle": "Dispositivos",
"deviceIdentifier": "Identificador",
- "devicePhone": "Phone",
- "deviceModel": "Model",
- "deviceContact": "Contact",
- "deviceCategory": "Category",
- "deviceLastUpdate": "Last Update",
+ "devicePhone": "Telefone",
+ "deviceModel": "Modelo",
+ "deviceContact": "Contacto",
+ "deviceCategory": "Categoria",
+ "deviceLastUpdate": "Ultima Actualização",
"deviceCommand": "Comando",
- "deviceFollow": "Follow",
- "deviceTotalDistance": "Total Distance",
- "groupDialog": "Group",
- "groupParent": "Group",
- "groupNoGroup": "No Group",
+ "deviceFollow": "Seguir",
+ "deviceTotalDistance": "Distancia Total",
+ "groupDialog": "Grupo",
+ "groupParent": "Grupo",
+ "groupNoGroup": "Sem Grupo",
"settingsTitle": "Configurações",
"settingsUser": "Conta",
- "settingsGroups": "Groups",
+ "settingsGroups": "Grupos",
"settingsServer": "Servidor",
- "settingsUsers": "Usuário",
+ "settingsUsers": "Utilizadores",
"settingsSpeedUnit": "Velocidade",
- "settingsTwelveHourFormat": "12-hour Format",
- "settingsCoordinateFormat": "Coordinates Format",
+ "settingsTwelveHourFormat": "Formato 12 Horas",
+ "settingsCoordinateFormat": "Formato das Coordenadas",
"reportTitle": "Relatórios",
"reportDevice": "Dispositivo",
- "reportGroup": "Group",
+ "reportGroup": "Grupo",
"reportFrom": "De",
"reportTo": "Para",
"reportShow": "Mostrar",
@@ -95,110 +97,113 @@
"positionSpeed": "Velocidade",
"positionCourse": "Curso",
"positionAddress": "Endereço",
- "positionProtocol": "protocolo",
+ "positionProtocol": "Protocolo",
"serverTitle": "Configurações do Servidor",
"serverZoom": "Zoom",
- "serverRegistration": "Registro",
- "serverReadonly": "Readonly",
- "serverForceSettings": "Force Settings",
+ "serverRegistration": "Registo",
+ "serverReadonly": "Apenas Leitura",
+ "serverForceSettings": "Forçar Configurações",
"mapTitle": "Mapa",
"mapLayer": "Camada Mapa",
"mapCustom": "Mapa personalizado",
- "mapCarto": "Carto Basemaps",
- "mapOsm": "Open Street Mapa",
- "mapBingKey": "Bing Maps Key",
- "mapBingRoad": "Bing Mapas Estrada",
- "mapBingAerial": "Bing Mapas Aérea",
- "mapShapePolygon": "Polygon",
- "mapShapeCircle": "Circle",
- "mapLiveRoutes": "Live Routes",
+ "mapCarto": "Mapa Carto",
+ "mapOsm": "Mapa Open Street",
+ "mapBingKey": "Mapa Bing Key",
+ "mapBingRoad": "Mapa Bing Road",
+ "mapBingAerial": "Mapa Bing Aéreo",
+ "mapShapePolygon": "Polígono",
+ "mapShapeCircle": "Circulo",
+ "mapShapePolyline": "Linha Poligono",
+ "mapLiveRoutes": "Rotas ao Vivo",
"stateTitle": "Estado",
"stateName": "Parâmetro",
"stateValue": "Valor",
"commandTitle": "Comando",
"commandSend": "Enviar",
"commandSent": "Comando foi enviado",
- "commandPositionPeriodic": "Posição Tempo",
+ "commandPositionPeriodic": "Relatório Periódico",
"commandPositionStop": "Parar Posição",
- "commandEngineStop": "Bloqueio Veículo",
- "commandEngineResume": "Desbloqueio Veículo",
+ "commandEngineStop": "Parar Motor",
+ "commandEngineResume": "Desbloqueio do Motor",
"commandFrequency": "Frequência",
"commandUnit": "Unidade",
- "commandCustom": "Custom command",
- "commandPositionSingle": "Single Reporting",
- "commandAlarmArm": "Arm Alarm",
- "commandAlarmDisarm": "Disarm Alarm",
- "commandSetTimezone": "Set Timezone",
- "commandRequestPhoto": "Request Photo",
- "commandRebootDevice": "Reboot Device",
- "commandSendSms": "Send SMS",
- "commandSendUssd": "Send USSD",
- "commandSosNumber": "Set SOS Number",
- "commandSilenceTime": "Set Silence Time",
- "commandSetPhonebook": "Set Phonebook",
- "commandVoiceMessage": "Voice Message",
- "commandOutputControl": "Output Control",
- "commandAlarmSpeed": "Overspeed Alarm",
- "commandDeviceIdentification": "Device Identification",
- "commandIndex": "Index",
- "commandData": "Data",
- "commandPhone": "Phone Number",
- "commandMessage": "Message",
- "eventAll": "All Events",
- "eventDeviceOnline": "Device is online",
- "eventDeviceOffline": "Device is offline",
- "eventDeviceMoving": "Device is moving",
- "eventDeviceStopped": "Device has stopped",
- "eventDeviceOverspeed": "Device exceeds the speed",
- "eventCommandResult": "Command result",
- "eventGeofenceEnter": "Device has entered geofence",
- "eventGeofenceExit": "Device has exited geofence",
- "eventAlarm": "Alarms",
- "eventIgnitionOn": "Ignition is ON",
- "eventIgnitionOff": "Ignition is OFF",
- "alarm": "Alarm",
- "alarmSos": "SOS Alarm",
- "alarmVibration": "Vibration Alarm",
- "alarmMovement": "Movement Alarm",
- "alarmOverspeed": "Overspeed Alarm",
- "alarmFallDown": "FallDown Alarm",
- "alarmLowBattery": "LowBattery Alarm",
- "alarmFault": "Fault Alarm",
- "notificationType": "Type of Notification",
- "notificationWeb": "Send via Web",
- "notificationMail": "Send via Mail",
- "reportRoute": "Route",
- "reportEvents": "Events",
- "reportTrips": "Trips",
- "reportSummary": "Summary",
- "reportConfigure": "Configure",
- "reportEventTypes": "Event Types",
- "reportExport": "Export",
- "reportDeviceName": "Device Name",
- "reportAverageSpeed": "Average Speed",
- "reportMaximumSpeed": "Maximum Speed",
- "reportEngineHours": "Engine Hours",
- "reportDuration": "Duration",
- "reportStartTime": "Start Time",
- "reportStartAddress": "Start Address",
- "reportEndTime": "End Time",
- "reportEndAddress": "End Address",
- "reportSpentFuel": "Spent Fuel",
- "statisticsTitle": "Statistics",
- "statisticsCaptureTime": "Capture Time",
- "statisticsActiveUsers": "Active Users",
- "statisticsActiveDevices": "Active Devices",
- "statisticsRequests": "Requests",
- "statisticsMessagesReceived": "Messages Received",
- "statisticsMessagesStored": "Messages Stored",
- "categoryArrow": "Arrow",
- "categoryDefault": "Default",
- "categoryCar": "Car",
- "categoryBus": "Bus",
- "categoryTruck": "Truck",
- "categoryShip": "Ship",
- "categoryPlane": "Plane",
- "categoryMotorcycle": "Motorcycle",
- "categoryBicycle": "Bicycle",
- "categoryPerson": "Person"
+ "commandCustom": "Comando Personalizado",
+ "commandPositionSingle": "Relatórios Únicos",
+ "commandAlarmArm": "Armar Alarme",
+ "commandAlarmDisarm": "Desarmar Alarme",
+ "commandSetTimezone": "Definir Fuso Horário",
+ "commandRequestPhoto": "Solicitar Foto",
+ "commandRebootDevice": "Reiniciar Dispositivo",
+ "commandSendSms": "Enviar SMS",
+ "commandSendUssd": "Enviar USSD",
+ "commandSosNumber": "Definir Numero SOS",
+ "commandSilenceTime": "Definir Tempo de Silencio",
+ "commandSetPhonebook": "Definir Agenda",
+ "commandVoiceMessage": "Mensagem de Voz",
+ "commandOutputControl": "Controlo de Saída ",
+ "commandAlarmSpeed": "Alarme de Excesso de Velocidade",
+ "commandDeviceIdentification": "Identificação do Dispositivo",
+ "commandIndex": "Inicio",
+ "commandData": "Dados",
+ "commandPhone": "Número de Telefone",
+ "commandMessage": "Mensagem",
+ "eventAll": "Todos os Eventos",
+ "eventDeviceOnline": "Dispositivo Conectado",
+ "eventDeviceUnknown": "Estado do dispositivo desconhecido",
+ "eventDeviceOffline": "Dispositivo Desconectado",
+ "eventDeviceMoving": "Dispositivo em Movimento",
+ "eventDeviceStopped": "Dispositivo Parado",
+ "eventDeviceOverspeed": "Dispositivo em Excesso de Velocidade",
+ "eventCommandResult": "Resultado do Comando",
+ "eventGeofenceEnter": "Dispositivo Entrou na Cerca Geográfica",
+ "eventGeofenceExit": "Dispositivo Saiu da Cerca Geográfica",
+ "eventAlarm": "Alarmes",
+ "eventIgnitionOn": "Ignição Ligada",
+ "eventIgnitionOff": "Ignição Desligada",
+ "eventMaintenance": "Necessária manutenção",
+ "alarm": "Alarme",
+ "alarmSos": "Alarme SOS",
+ "alarmVibration": "Alarme de Vibração",
+ "alarmMovement": "Alarme de Movimento",
+ "alarmOverspeed": "Alarme de Excesso de Velocidade",
+ "alarmFallDown": "Alarme de Queda",
+ "alarmLowBattery": "Alarme de Bateria Baixa",
+ "alarmFault": "Alarme de Falha",
+ "notificationType": "Tipo de Notificação",
+ "notificationWeb": "Enviar por Web",
+ "notificationMail": "Enviar por Email",
+ "reportRoute": "Rota",
+ "reportEvents": "Eventos",
+ "reportTrips": "Viagens",
+ "reportSummary": "Resumo",
+ "reportConfigure": "Configurar",
+ "reportEventTypes": "Tipos de Eventos",
+ "reportExport": "Exportar",
+ "reportDeviceName": "Nome do Dispositivo",
+ "reportAverageSpeed": "Velocidade Média",
+ "reportMaximumSpeed": "Velocidade Máxima",
+ "reportEngineHours": "Horas do Motor",
+ "reportDuration": "Duração",
+ "reportStartTime": "Iniciar Hora",
+ "reportStartAddress": "Iniciar Morada",
+ "reportEndTime": "Terminar Hora",
+ "reportEndAddress": "Terminar Morada",
+ "reportSpentFuel": "Combustível Gasto",
+ "statisticsTitle": "Estatísticas",
+ "statisticsCaptureTime": "Hora da Captura",
+ "statisticsActiveUsers": "Activar Utilizadores",
+ "statisticsActiveDevices": "Activar Dispositivos",
+ "statisticsRequests": "Pedidos",
+ "statisticsMessagesReceived": "Mensagens Recebidas",
+ "statisticsMessagesStored": "Mensagens Armazenadas",
+ "categoryArrow": "Seta",
+ "categoryDefault": "Padrão",
+ "categoryCar": "Carro",
+ "categoryBus": "Autocarro",
+ "categoryTruck": "Camião",
+ "categoryShip": "Barco",
+ "categoryPlane": "Avião",
+ "categoryMotorcycle": "Mota",
+ "categoryBicycle": "Bicicleta",
+ "categoryPerson": "Pessoa"
} \ No newline at end of file
diff --git a/web/l10n/pt_BR.json b/web/l10n/pt_BR.json
index c29b3548..3baeda89 100644
--- a/web/l10n/pt_BR.json
+++ b/web/l10n/pt_BR.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Distância do dispositivo",
"sharedDevice": "Dispositivo",
+ "sharedTestMail": "Enviar e-mail de teste",
"errorTitle": "Erro",
"errorUnknown": "Erro desconhecido",
"errorConnection": "Erro de conexão",
@@ -58,6 +59,7 @@
"loginFailed": "Endereço de email ou senha incorretos",
"loginCreated": "O novo usuário foi registrado",
"loginLogout": "Sair",
+ "loginLogo": "Logo",
"devicesAndState": "Dispositivo e Estado",
"deviceTitle": "Dispositivos",
"deviceIdentifier": "Identificador",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aéreo",
"mapShapePolygon": "Polígono",
"mapShapeCircle": "Círculo",
+ "mapShapePolyline": "Polilinha",
"mapLiveRoutes": "Rotas ao Vivo",
"stateTitle": "Estado",
"stateName": "Atributo",
@@ -146,6 +149,7 @@
"commandMessage": "Mensagem",
"eventAll": "Todos Eventos",
"eventDeviceOnline": "Dispositivo está on-line",
+ "eventDeviceUnknown": "Estado do dispositivo desconhecido",
"eventDeviceOffline": "Dispositivo está offline",
"eventDeviceMoving": "Dispositivo está se movendo",
"eventDeviceStopped": "Dispositivo parou",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmes",
"eventIgnitionOn": "Ignição está ON",
"eventIgnitionOff": "Ignição está OFF",
+ "eventMaintenance": "Manutenção necessária",
"alarm": "Alarme",
"alarmSos": "Alarme SOS",
"alarmVibration": "Alarme de Vibração",
diff --git a/web/l10n/ro.json b/web/l10n/ro.json
index ed066efd..191b76e9 100644
--- a/web/l10n/ro.json
+++ b/web/l10n/ro.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Eroare",
"errorUnknown": "Eroare necunoscută",
"errorConnection": "Eroare de conexiune",
@@ -58,6 +59,7 @@
"loginFailed": "E-mail sau parolă incorectă",
"loginCreated": "Un utilizator nou a fost înregistrat",
"loginLogout": "Deconectare",
+ "loginLogo": "Logo",
"devicesAndState": "Stare dispozitive",
"deviceTitle": "Dispozitive",
"deviceIdentifier": "Identificator",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Hartă Aeriană",
"mapShapePolygon": "Poligon",
"mapShapeCircle": "Cerc",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Stare",
"stateName": "Atribut",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Dispozitivul este pornit",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Dispozitivul este oprit",
"eventDeviceMoving": "Dispozitivul este în mişcare",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarme",
"eventIgnitionOn": "Contact pornit",
"eventIgnitionOff": "Contact oprit",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarmă",
"alarmSos": "Alarmă SOS",
"alarmVibration": "Alarmă vibraţii",
diff --git a/web/l10n/ru.json b/web/l10n/ru.json
index 371a6382..bd871cd0 100644
--- a/web/l10n/ru.json
+++ b/web/l10n/ru.json
@@ -40,6 +40,7 @@
"sharedAlias": "Псевдоним",
"sharedDeviceDistance": "Пробег Устройства",
"sharedDevice": "Устройство",
+ "sharedTestMail": "Отправить Тестовое Сообщение",
"errorTitle": "Ошибка",
"errorUnknown": "Неизвестная ошибка",
"errorConnection": "Ошибка соединения",
@@ -47,10 +48,10 @@
"userPassword": "Пароль",
"userAdmin": "Администратор",
"userRemember": "Запомнить",
- "userDisabled": "Disabled",
- "userExpirationTime": "Expiration",
- "userDeviceLimit": "Device Limit",
- "userToken": "Token",
+ "userDisabled": "Оключен",
+ "userExpirationTime": "Срок Действия",
+ "userDeviceLimit": "Ограничение Устройств",
+ "userToken": "Ключ",
"loginTitle": "Вход",
"loginLanguage": "Язык",
"loginRegister": "Регистрация",
@@ -58,6 +59,7 @@
"loginFailed": "Неправильный email адрес или пароль",
"loginCreated": "Новый пользователь зарегистрирован",
"loginLogout": "Выход",
+ "loginLogo": "Логотип",
"devicesAndState": "Устройства и Состояния",
"deviceTitle": "Устройства",
"deviceIdentifier": "Идентификатор",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Спутник",
"mapShapePolygon": "Многоугольник",
"mapShapeCircle": "Круг",
+ "mapShapePolyline": "Линия",
"mapLiveRoutes": " Живые Маршруты",
"stateTitle": "Состояние",
"stateName": "Параметр",
@@ -146,6 +149,7 @@
"commandMessage": "Сообщение",
"eventAll": "Все События",
"eventDeviceOnline": "Устройство в сети",
+ "eventDeviceUnknown": "Статус устройства неизвестен",
"eventDeviceOffline": "Устройство не в сети",
"eventDeviceMoving": "Устройство движется",
"eventDeviceStopped": "Устройство остановилось",
@@ -156,6 +160,7 @@
"eventAlarm": "Тревоги",
"eventIgnitionOn": "Зажигание ВКЛ",
"eventIgnitionOff": "Зажигание ВЫКЛ",
+ "eventMaintenance": "Требуется обслуживание",
"alarm": "Тревога",
"alarmSos": "Тревога SOS",
"alarmVibration": "Тревога Вибрации",
diff --git a/web/l10n/si.json b/web/l10n/si.json
index 7758637e..73d10cf0 100644
--- a/web/l10n/si.json
+++ b/web/l10n/si.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "දෝෂයක් ",
"errorUnknown": "නොදන්නා දෝෂයක් !",
"errorConnection": "සම්බන්ධතා දෝෂයක් !",
@@ -58,6 +59,7 @@
"loginFailed": "ඊ-මේල් ලිපිනය හෝ මුරපදය වැරදිය !",
"loginCreated": "නව පරිශීලක ලියාපදිංචි කරන ලදි !",
"loginLogout": "ඉවත්වන්න",
+ "loginLogo": "Logo",
"devicesAndState": "උපාංග සහ ස්වභාවය",
"deviceTitle": "උපාංග",
"deviceIdentifier": "හඳුනාගැනීමේ කේතය",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "බහුඅශ්‍රය",
"mapShapeCircle": "වෘත්තය",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "තත්වය",
"stateName": "පරාමිතිය",
@@ -146,6 +149,7 @@
"commandMessage": "පණිවිඩය",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "නිවේදන",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "අනතුරු ඇඟවීම්",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/sk.json b/web/l10n/sk.json
index e0caa5c7..36025bda 100644
--- a/web/l10n/sk.json
+++ b/web/l10n/sk.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Chyba",
"errorUnknown": "Neznáma chyba",
"errorConnection": "Chyba pripojenia",
@@ -58,6 +59,7 @@
"loginFailed": "Nesprávna e-mailová adresa alebo heslo",
"loginCreated": "Nový užívateľ sa zaregistroval",
"loginLogout": "Odhlásiť",
+ "loginLogo": "Logo",
"devicesAndState": "Zariadenia a Status",
"deviceTitle": "Zariadena",
"deviceIdentifier": "Identifikátor",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Arial",
"mapShapePolygon": "Polygón",
"mapShapeCircle": "Kruh",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Štát",
"stateName": "Parameter",
@@ -146,6 +149,7 @@
"commandMessage": "Správa",
"eventAll": "Všetky akcie",
"eventDeviceOnline": "Zariadenie je online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Zariadenie je offline",
"eventDeviceMoving": "Zariadenie je v pohybe",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Upozornenia",
"eventIgnitionOn": "Zapaľovanie je ZAPNUTÉ",
"eventIgnitionOff": "Zapaľovanie je VYPNUTÉ",
+ "eventMaintenance": "Maintenance required",
"alarm": "Upozornenie",
"alarmSos": "SOS upozornenie",
"alarmVibration": "Vibračné upozornenie",
diff --git a/web/l10n/sl.json b/web/l10n/sl.json
index 2140046f..dd3ee53e 100644
--- a/web/l10n/sl.json
+++ b/web/l10n/sl.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Razdalja naprave",
"sharedDevice": "Naprava",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Napaka",
"errorUnknown": "Neznana napaka",
"errorConnection": "Napaka v povezavi",
@@ -58,6 +59,7 @@
"loginFailed": "Nepravilna e-pošta ali geslo",
"loginCreated": "Nov uporabnik je registriran",
"loginLogout": "Odjava",
+ "loginLogo": "Logo",
"devicesAndState": "Naprava in stanje",
"deviceTitle": "Naprave",
"deviceIdentifier": "Identifikacija",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Satelit",
"mapShapePolygon": "Poligon",
"mapShapeCircle": "Krog",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Stanje",
"stateName": "Parameter",
@@ -146,6 +149,7 @@
"commandMessage": "Sporočilo",
"eventAll": "Vsi dogodki",
"eventDeviceOnline": "Naprava je povezana",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Naprava ni povezana",
"eventDeviceMoving": "Naprava se premika",
"eventDeviceStopped": "Naprava se je ustavila",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alaram",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/sq.json b/web/l10n/sq.json
index 80f86aa9..822a0b38 100644
--- a/web/l10n/sq.json
+++ b/web/l10n/sq.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Gabim",
"errorUnknown": "Gabim i panjohur",
"errorConnection": "Gabim lidhjeje",
@@ -58,6 +59,7 @@
"loginFailed": "Adresë Email-i ose fjalëkalim i gabuar",
"loginCreated": "Përdoruesi i ri u regjistrua",
"loginLogout": "Shkëputu",
+ "loginLogo": "Logo",
"devicesAndState": "Gjendja e pajisjeve",
"deviceTitle": "Pajisjet",
"deviceIdentifier": "Identifikues",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Gjëndja",
"stateName": "Atribut",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/sr.json b/web/l10n/sr.json
index e003473c..3cce2f6b 100644
--- a/web/l10n/sr.json
+++ b/web/l10n/sr.json
@@ -40,6 +40,7 @@
"sharedAlias": "Pseudonim",
"sharedDeviceDistance": "Odstojanje uređaja",
"sharedDevice": "Uređaj",
+ "sharedTestMail": "Pošalji test email",
"errorTitle": "Greška",
"errorUnknown": "Nepoznata greška",
"errorConnection": "Greška u konekciji",
@@ -50,7 +51,7 @@
"userDisabled": "Onemogućen",
"userExpirationTime": "Ističe",
"userDeviceLimit": "Limit uređaja",
- "userToken": "Token",
+ "userToken": "Znak",
"loginTitle": "Prijava",
"loginLanguage": "Jezik",
"loginRegister": "Registruj se",
@@ -58,6 +59,7 @@
"loginFailed": "Neispravna email adresa ili lozinka",
"loginCreated": "Novi korisnik je registrovan",
"loginLogout": "Odjava",
+ "loginLogo": "Logo",
"devicesAndState": "Uređaji i Stanje ",
"deviceTitle": "Uređaji",
"deviceIdentifier": "Identifikator",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Višeugao",
"mapShapeCircle": "Krug",
+ "mapShapePolyline": "Višelinijski",
"mapLiveRoutes": "Validne rute",
"stateTitle": "Stanje",
"stateName": "Parametar",
@@ -146,6 +149,7 @@
"commandMessage": "Poruka",
"eventAll": "Svi događaji",
"eventDeviceOnline": "Uređaj je na mreži",
+ "eventDeviceUnknown": "Status uređaja je nepoznat",
"eventDeviceOffline": "Uređaj je van mreže",
"eventDeviceMoving": "Uređaj se kreće",
"eventDeviceStopped": "Uređaj se zaustavio",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmi",
"eventIgnitionOn": "Kontakt uklj.",
"eventIgnitionOff": "Kontakt isklj.",
+ "eventMaintenance": "Potrebno održavanje",
"alarm": "Alarm",
"alarmSos": "SOS alarm",
"alarmVibration": "Alarm vibracija",
diff --git a/web/l10n/ta.json b/web/l10n/ta.json
index 51db30d6..cd67a359 100644
--- a/web/l10n/ta.json
+++ b/web/l10n/ta.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "பிழை",
"errorUnknown": "அறியப்படாத பிழை",
"errorConnection": "இணைப்புப் பிழை",
@@ -58,6 +59,7 @@
"loginFailed": "தவறான மின்னஞ்சல் முகவரி அல்லது கடவுச்சொல்",
"loginCreated": "புதிய பயனர் பதிவு செய்யப்பட்டுள்ளது",
"loginLogout": "வெளியேறு",
+ "loginLogo": "Logo",
"devicesAndState": "கருவிகள் மற்றும் அதன் நிலை",
"deviceTitle": "சாதனம்",
"deviceIdentifier": "அடையாளங்காட்டி",
@@ -111,6 +113,7 @@
"mapBingAerial": "பிங் வான்வழி வரைபடம்",
"mapShapePolygon": "பலகோணம்",
"mapShapeCircle": "வட்டம்",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "நிலை",
"stateName": "சாட்டு",
@@ -146,6 +149,7 @@
"commandMessage": "குறுஞ்செய்தி",
"eventAll": "All Events",
"eventDeviceOnline": "சாதனம் இணைப்பில் உள்ளது",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "சாதன இணைப்பு துண்டிக்கபட்டது",
"eventDeviceMoving": "சாதனம் நகருகிறது",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/th.json b/web/l10n/th.json
index 20d7826e..a3c1e4d5 100644
--- a/web/l10n/th.json
+++ b/web/l10n/th.json
@@ -40,6 +40,7 @@
"sharedAlias": "นามแฝง",
"sharedDeviceDistance": "ระยะทาง อุปกรณ์",
"sharedDevice": "อุปกรณ์",
+ "sharedTestMail": "ทดสอบ ส่งอีเมล",
"errorTitle": "ผิดพลาด",
"errorUnknown": "ข้อผิดพลาดที่ไม่รู้จัก",
"errorConnection": "การเชื่อมต่อผิดพลาด",
@@ -58,6 +59,7 @@
"loginFailed": "ที่อยู่อีเมลหรือรหัสผ่านไม่ถูกต้อง",
"loginCreated": "ผู้ใช้ใหม่ ได้รับการลงทะเบียน",
"loginLogout": "ออกจากระบบ",
+ "loginLogo": "Logo",
"devicesAndState": "อุปกรณ์และสถานะ",
"deviceTitle": "เครื่อง/อุปกรณ์",
"deviceIdentifier": "ระบุเลขอุปกรณ์",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps ทางอากาศ",
"mapShapePolygon": "โพลิกอน",
"mapShapeCircle": "วงกลม",
+ "mapShapePolyline": "โพลีไลน์",
"mapLiveRoutes": "เส้นทาง Live",
"stateTitle": "สถานะ",
"stateName": "พารามิเตอร์",
@@ -146,6 +149,7 @@
"commandMessage": "ข้อความ",
"eventAll": "เหตุการณ์ทั้งหมด",
"eventDeviceOnline": "อุปกรณ์เชื่อมต่อแล้ว",
+ "eventDeviceUnknown": "สถานะของอุปกรณ์ไม่เป็นที่รู้จัก",
"eventDeviceOffline": "อุปกรณ์ไม่ได้เชื่อมต่อ",
"eventDeviceMoving": "อุปกรณ์กำลังเคลื่อนที่",
"eventDeviceStopped": "อุปกรณ์กำลังหยุด",
@@ -156,6 +160,7 @@
"eventAlarm": "แจ้งเตือน",
"eventIgnitionOn": "สวิทย์กุญแจ เปิด",
"eventIgnitionOff": "สวิทย์กุญแจ ปิด",
+ "eventMaintenance": "จำเป็นต้อง บำรุงรักษา",
"alarm": "แจ้งเตือน",
"alarmSos": "แจ้งเตือนฉุกเฉิน SOS",
"alarmVibration": "แจ้งเตือนการสั่นสะเทือน",
diff --git a/web/l10n/tr.json b/web/l10n/tr.json
index d3aab3a6..6b57cc62 100644
--- a/web/l10n/tr.json
+++ b/web/l10n/tr.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Hata",
"errorUnknown": "Bilinmeyen hata ",
"errorConnection": "Bağlantı Hatası",
@@ -58,6 +59,7 @@
"loginFailed": "Geçersiz eposta veya şifre",
"loginCreated": "Yeni kullanıcı kaydedildi",
"loginLogout": "Oturumu sonlandır",
+ "loginLogo": "Logo",
"devicesAndState": "Cihazlar ve Bölge",
"deviceTitle": "Cihazlar",
"deviceIdentifier": "Kimlik",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Çokgen",
"mapShapeCircle": "Çember",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Bölge",
"stateName": "Özellik",
@@ -146,6 +149,7 @@
"commandMessage": "Mesaj",
"eventAll": "Tüm Olaylar",
"eventDeviceOnline": "Cihaz çevrimiçi",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Cihaz çevrimdışı",
"eventDeviceMoving": "Cihaz hareket halinde",
"eventDeviceStopped": "Cihaz çalışmıyor",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarmlar",
"eventIgnitionOn": "Kontak Açık",
"eventIgnitionOff": "Kontak Kapalı",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "İmdat Alarmı",
"alarmVibration": "Darbe Alarmı",
diff --git a/web/l10n/uk.json b/web/l10n/uk.json
index e3add330..c6da05d3 100644
--- a/web/l10n/uk.json
+++ b/web/l10n/uk.json
@@ -40,6 +40,7 @@
"sharedAlias": "Алиас",
"sharedDeviceDistance": "Відстань пристроїв",
"sharedDevice": "Пристрій",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Помилка",
"errorUnknown": "Невiдома помилка",
"errorConnection": "Помилка з'єднання",
@@ -58,6 +59,7 @@
"loginFailed": "Неправильне адреса електронної пошти або пароль",
"loginCreated": "Новий користувач був зареєстрований",
"loginLogout": "Вийти",
+ "loginLogo": "Logo",
"devicesAndState": "Пристрої та стан",
"deviceTitle": " Прилади",
"deviceIdentifier": "Iдентифікатор",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Супутник",
"mapShapePolygon": "Багатокутник",
"mapShapeCircle": "Коло",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Поточні маршрути",
"stateTitle": "Стан",
"stateName": "Атрибут",
@@ -146,6 +149,7 @@
"commandMessage": "Повідомлення",
"eventAll": "Всі події",
"eventDeviceOnline": "Пристрій з'єднався",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Пристрій від'єднався",
"eventDeviceMoving": "Пристрій в русі",
"eventDeviceStopped": "Пристрій зупинився",
@@ -156,6 +160,7 @@
"eventAlarm": "Тревоги",
"eventIgnitionOn": "Запалення УВІМК",
"eventIgnitionOff": "Запалення ВИМК",
+ "eventMaintenance": "Maintenance required",
"alarm": "Тревога",
"alarmSos": "Тривога SOS",
"alarmVibration": "Тривога вібрації",
diff --git a/web/l10n/vi.json b/web/l10n/vi.json
index 57791944..c831f691 100644
--- a/web/l10n/vi.json
+++ b/web/l10n/vi.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "Lỗi",
"errorUnknown": "Lỗi không xác định",
"errorConnection": "Lỗi kết nối",
@@ -58,6 +59,7 @@
"loginFailed": "Sai mật khẩu hoặc địa chỉ email",
"loginCreated": "Người dùng mới đã được đăng ký",
"loginLogout": "Đăng xuất",
+ "loginLogo": "Logo",
"devicesAndState": "Các thiết bị và trạng thái",
"deviceTitle": "Các thiết bị",
"deviceIdentifier": "Định danh",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing Maps Aerial",
"mapShapePolygon": "Đa giác",
"mapShapeCircle": "Vòng tròn",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "Trạng thái",
"stateName": "Thuộc tính",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Thiết bị trực tuyến",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Thiết bị ngoại tuyến",
"eventDeviceMoving": "Thiết bị đang di chuyển",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/l10n/zh.json b/web/l10n/zh.json
index 053da280..dd058384 100644
--- a/web/l10n/zh.json
+++ b/web/l10n/zh.json
@@ -40,6 +40,7 @@
"sharedAlias": "Alias",
"sharedDeviceDistance": "Device Distance",
"sharedDevice": "Device",
+ "sharedTestMail": "Send Test Email",
"errorTitle": "错误",
"errorUnknown": "未知错误",
"errorConnection": "连接错误",
@@ -58,6 +59,7 @@
"loginFailed": "邮箱地址或密码不对",
"loginCreated": "新用户已经被注册了",
"loginLogout": "登出",
+ "loginLogo": "Logo",
"devicesAndState": "设备和状态",
"deviceTitle": "设备",
"deviceIdentifier": "标识符",
@@ -111,6 +113,7 @@
"mapBingAerial": "Bing 航测地图",
"mapShapePolygon": "Polygon",
"mapShapeCircle": "Circle",
+ "mapShapePolyline": "Polyline",
"mapLiveRoutes": "Live Routes",
"stateTitle": "状态",
"stateName": "参数",
@@ -146,6 +149,7 @@
"commandMessage": "Message",
"eventAll": "All Events",
"eventDeviceOnline": "Device is online",
+ "eventDeviceUnknown": "Device status is unknown",
"eventDeviceOffline": "Device is offline",
"eventDeviceMoving": "Device is moving",
"eventDeviceStopped": "Device has stopped",
@@ -156,6 +160,7 @@
"eventAlarm": "Alarms",
"eventIgnitionOn": "Ignition is ON",
"eventIgnitionOff": "Ignition is OFF",
+ "eventMaintenance": "Maintenance required",
"alarm": "Alarm",
"alarmSos": "SOS Alarm",
"alarmVibration": "Vibration Alarm",
diff --git a/web/load.js b/web/load.js
index fe5c2805..0fe7ce54 100644
--- a/web/load.js
+++ b/web/load.js
@@ -109,7 +109,7 @@
});
- extjsVersion = '6.0.1';
+ extjsVersion = '6.2.0';
fontAwesomeVersion = '4.7.0';
olVersion = '3.19.1';
@@ -128,8 +128,6 @@
addStyleFile('//cdnjs.cloudflare.com/ajax/libs/ol3/' + olVersion + '/ol.css');
addScriptFile('//cdnjs.cloudflare.com/ajax/libs/ol3/' + olVersion + '/ol-debug.js');
- addStyleFile('app.css');
-
addSvgFile('images/default.svg', 'defaultSvg');
addSvgFile('images/arrow.svg', 'arrowSvg');
addSvgFile('images/car.svg', 'carSvg');
diff --git a/web/logo.svg b/web/logo.svg
new file mode 100644
index 00000000..55da0dcd
--- /dev/null
+++ b/web/logo.svg
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="240"
+ height="64"
+ id="svg2985"
+ version="1.1"
+ inkscape:version="0.91+devel+osxmenu r12922"
+ sodipodi:docname="logo.svg"
+ inkscape:export-filename="/home/user/Documents/website/logo2x.png"
+ inkscape:export-xdpi="123.75"
+ inkscape:export-ydpi="123.75"
+ viewBox="0 0 240 64">
+ <defs
+ id="defs2987" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.49"
+ inkscape:cx="19.718102"
+ inkscape:cy="19.948184"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:object-paths="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:window-width="1633"
+ inkscape:window-height="798"
+ inkscape:window-x="108"
+ inkscape:window-y="80"
+ inkscape:window-maximized="0"
+ inkscape:snap-global="true" />
+ <metadata
+ id="metadata2990">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <rect
+ style="fill:none;stroke:none"
+ id="rect3778"
+ width="236.09605"
+ height="64"
+ x="0"
+ y="0"
+ inkscape:export-filename="/home/user/Documents/website/logo2x.png"
+ inkscape:export-xdpi="154.6875"
+ inkscape:export-ydpi="154.6875" />
+ <g
+ id="g2995"
+ inkscape:export-filename="/home/user/Documents/website/logo2x.png"
+ inkscape:export-xdpi="154.6875"
+ inkscape:export-ydpi="154.6875"
+ transform="matrix(1.0095018,0,0,1.0095018,-0.30405898,-0.30405887)">
+ <ellipse
+ transform="matrix(11.849785,-6.8414759,4.1048857,7.1098702,-141.6761,-453.06363)"
+ id="path3038"
+ style="fill:#ffffff"
+ cx="-6.7327504"
+ cy="61.745384"
+ rx="2.0991254"
+ ry="3.4985423" />
+ <ellipse
+ transform="matrix(0.98000485,-0.56580602,0.76260819,1.3208761,-13.500496,-10.292296)"
+ id="path2993"
+ style="fill:#000000"
+ cx="14.142136"
+ cy="38.929852"
+ rx="1.9927555"
+ ry="1.478496" />
+ <path
+ id="path3004"
+ d="m 36.965211,24.251054 -2.816072,3.57877 c 0.657208,0.517134 1.313001,1.146671 1.756681,1.915146 0.443679,0.768474 0.660975,1.651177 0.780224,2.478901 l 4.507342,-0.649405 C 41.001257,30.166972 40.565802,28.79619 39.81164,27.489944 39.057477,26.183697 38.088074,25.121191 36.965211,24.251054 Z"
+ style="fill:#000000"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path3014"
+ d="m 42.404828,17.041928 -2.816072,3.578769 c 1.591875,1.223919 3.062315,2.767181 4.128704,4.614221 1.066388,1.847038 1.667671,3.892108 1.931679,5.882671 l 4.507341,-0.649405 c -0.336471,-2.571017 -1.155959,-5.102841 -2.5332,-7.488294 -1.377241,-2.385452 -3.160122,-4.36106 -5.218452,-5.937962 z"
+ style="fill:#000000"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:end="4.712389"
+ sodipodi:start="1.5707963"
+ transform="matrix(3.9507144,-2.2809459,1.4097023,2.4416757,-59.699972,-127.24372)"
+ d="m -2.0227272,68.375862 a 1.9772727,3.1992946 0 0 1 -1.7123685,-1.599648 1.9772727,3.1992946 0 0 1 0,-3.199294 1.9772727,3.1992946 0 0 1 1.7123685,-1.599647 l -1e-7,3.199294 z"
+ sodipodi:ry="3.1992946"
+ sodipodi:rx="1.9772727"
+ sodipodi:cy="65.176567"
+ sodipodi:cx="-2.0227273"
+ id="path3036"
+ style="fill:#000000"
+ sodipodi:type="arc" />
+ <path
+ id="path3038-8"
+ d="M 17.638883,7.1258129 C 3.9012503,15.057239 -0.80560983,32.62348 7.1258152,46.361111 15.057241,60.098742 32.623482,64.805603 46.361115,56.874177 60.098748,48.942752 64.805608,31.37651 56.874183,17.63888 48.942758,3.9012493 31.376516,-0.80561226 17.638883,7.1258129 Z m 1.689543,2.9263741 C 31.449867,3.0538711 46.949491,7.2069826 53.947808,19.328422 60.946126,31.449863 56.793012,46.949488 44.671573,53.947803 32.550132,60.94612 17.050507,56.793009 10.05219,44.671568 3.0538724,32.550127 7.2069849,17.050503 19.328426,10.052187 Z"
+ style="fill:#000000"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="font-style:normal;font-weight:normal;font-size:47.16480255px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
+ aria-label="Traccar"
+ id="text3003">
+ <path
+ d="m 89.719355,48.670609 -3.915047,0 0,-30.191922 -10.662746,0 0,-3.477483 25.240538,0 0,3.477483 -10.662745,0 0,30.191922 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4172" />
+ <path
+ d="m 116.3647,22.969476 q 1.68117,0 3.01689,0.276356 l -0.52968,3.546572 q -1.56602,-0.345445 -2.76356,-0.345445 -3.06295,0 -5.25077,2.487206 -2.16479,2.487207 -2.16479,6.194987 l 0,13.541457 -3.82293,0 0,-25.240539 3.15507,0 0.43756,4.675026 0.18424,0 q 1.40481,-2.464176 3.38536,-3.799898 1.98056,-1.335722 4.35261,-1.335722 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4174" />
+ <path
+ d="m 139.62469,48.670609 -0.75998,-3.592632 -0.18424,0 q -1.88843,2.372058 -3.77687,3.224157 -1.8654,0.829068 -4.67502,0.829068 -3.75384,0 -5.8956,-1.934494 -2.11874,-1.934493 -2.11874,-5.504095 0,-7.645857 12.22877,-8.014332 l 4.28352,-0.138178 0,-1.566019 q 0,-2.97083 -1.28966,-4.375641 -1.26663,-1.42784 -4.07626,-1.42784 -3.15506,0 -7.1392,1.934493 l -1.17451,-2.92477 q 1.8654,-1.013306 4.07625,-1.589049 2.23388,-0.575742 4.46776,-0.575742 4.51382,0 6.67861,2.003583 2.18782,2.003583 2.18782,6.425283 l 0,17.226208 -2.83265,0 z m -8.63613,-2.694474 q 3.5696,0 5.59621,-1.957524 2.04964,-1.957523 2.04964,-5.481066 l 0,-2.279939 -3.82293,0.161208 q -4.55987,0.161208 -6.58649,1.427841 -2.00358,1.243603 -2.00358,3.892017 0,2.072672 1.2436,3.155068 1.26664,1.082395 3.52355,1.082395 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4176" />
+ <path
+ d="m 160.44353,49.131202 q -5.48107,0 -8.49796,-3.362334 -2.99386,-3.385365 -2.99386,-9.557321 0,-6.333164 3.03992,-9.787618 3.06295,-3.454453 8.70522,-3.454453 1.81935,0 3.6387,0.391505 1.81934,0.391504 2.85568,0.921187 l -1.17452,3.247186 q -1.26663,-0.506653 -2.76356,-0.829069 -1.49693,-0.345445 -2.64841,-0.345445 -7.69192,0 -7.69192,9.810648 0,4.651997 1.8654,7.139203 1.88844,2.487206 5.57319,2.487206 3.15507,0 6.47134,-1.358751 l 0,3.385364 q -2.53326,1.312692 -6.37922,1.312692 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4178" />
+ <path
+ d="m 182.9205,49.131202 q -5.48106,0 -8.49795,-3.362334 -2.99386,-3.385365 -2.99386,-9.557321 0,-6.333164 3.03992,-9.787618 3.06295,-3.454453 8.70522,-3.454453 1.81934,0 3.63869,0.391505 1.81935,0.391504 2.85568,0.921187 l -1.17451,3.247186 q -1.26664,-0.506653 -2.76357,-0.829069 -1.49693,-0.345445 -2.64841,-0.345445 -7.69192,0 -7.69192,9.810648 0,4.651997 1.86541,7.139203 1.88843,2.487206 5.57318,2.487206 3.15507,0 6.47135,-1.358751 l 0,3.385364 q -2.53327,1.312692 -6.37923,1.312692 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4180" />
+ <path
+ d="m 210.83249,48.670609 -0.75998,-3.592632 -0.18424,0 q -1.88843,2.372058 -3.77687,3.224157 -1.8654,0.829068 -4.67502,0.829068 -3.75384,0 -5.8956,-1.934494 -2.11873,-1.934493 -2.11873,-5.504095 0,-7.645857 12.22876,-8.014332 l 4.28352,-0.138178 0,-1.566019 q 0,-2.97083 -1.28966,-4.375641 -1.26663,-1.42784 -4.07625,-1.42784 -3.15507,0 -7.13921,1.934493 l -1.17451,-2.92477 q 1.8654,-1.013306 4.07625,-1.589049 2.23388,-0.575742 4.46776,-0.575742 4.51382,0 6.67861,2.003583 2.18782,2.003583 2.18782,6.425283 l 0,17.226208 -2.83265,0 z m -8.63613,-2.694474 q 3.5696,0 5.59621,-1.957524 2.04964,-1.957523 2.04964,-5.481066 l 0,-2.279939 -3.82292,0.161208 q -4.55988,0.161208 -6.58649,1.427841 -2.00359,1.243603 -2.00359,3.892017 0,2.072672 1.24361,3.155068 1.26663,1.082395 3.52354,1.082395 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4182" />
+ <path
+ d="m 233.07917,22.969476 q 1.68117,0 3.01689,0.276356 l -0.52968,3.546572 q -1.56602,-0.345445 -2.76357,-0.345445 -3.06294,0 -5.25076,2.487206 -2.1648,2.487207 -2.1648,6.194987 l 0,13.541457 -3.82292,0 0,-25.240539 3.15506,0 0.43757,4.675026 0.18423,0 q 1.40482,-2.464176 3.38537,-3.799898 1.98055,-1.335722 4.35261,-1.335722 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans'"
+ id="path4184" />
+ </g>
+ </g>
+</svg>
diff --git a/web/release.html b/web/release.html
index 3113f36c..cd02272b 100644
--- a/web/release.html
+++ b/web/release.html
@@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Traccar</title>
+<link rel="stylesheet" href="app.css">
</head>
<body>
<div id="spinner"></div>
diff --git a/web/simple/app.js b/web/simple/app.js
new file mode 100644
index 00000000..5ae8ac2c
--- /dev/null
+++ b/web/simple/app.js
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var url = 'http://localhost:8082';
+var token = 'TOKEN';
+
+var style = new ol.style.Style({
+ image: new ol.style.Circle({
+ fill: new ol.style.Fill({
+ color: 'teal'
+ }),
+ stroke: new ol.style.Stroke({
+ color: 'navy',
+ width: 2
+ }),
+ radius: 7
+ })
+});
+
+var source = new ol.source.Vector();
+
+var markers = {};
+
+var map = new ol.Map({
+ layers: [
+ new ol.layer.Tile({
+ source: new ol.source.OSM()
+ }),
+ new ol.layer.Vector({
+ source: source
+ })
+ ],
+ target: 'map',
+ view: new ol.View({
+ center: [0, 0],
+ zoom: 2
+ })
+});
+
+var ajax = function (method, url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.withCredentials = true;
+ xhr.open(method, url, true);
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState == 4) {
+ callback(JSON.parse(xhr.responseText));
+ }
+ };
+ if (method == 'POST') {
+ xhr.setRequestHeader('Content-type', 'application/json');
+ }
+ xhr.send()
+};
+
+ajax('GET', url + '/api/session?token=' + token, function(user) {
+ ajax('GET', url + '/api/devices', function(devices) {
+
+ var socket = new WebSocket('ws' + url.substring(4) + '/api/socket');
+
+ socket.onclose = function (event) {
+ console.log('socket closed');
+ };
+
+ socket.onmessage = function (event) {
+ var data = JSON.parse(event.data);
+ if (data.positions) {
+ for (i = 0; i < data.positions.length; i++) {
+ var position = data.positions[i];
+ var marker = markers[position.deviceId];
+ var point = new ol.geom.Point(ol.proj.fromLonLat([position.longitude, position.latitude]));
+ if (!marker) {
+ marker = new ol.Feature(point);
+ marker.setStyle(style);
+ markers[position.deviceId] = marker;
+ source.addFeature(marker);
+ } else {
+ marker.setGeometry(point);
+ }
+ }
+ }
+ };
+
+ });
+});
diff --git a/web/simple/index.html b/web/simple/index.html
new file mode 100644
index 00000000..d4bfe504
--- /dev/null
+++ b/web/simple/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+<title>Traccar</title>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.css" type="text/css">
+</head>
+<body style="margin: 0; padding: 0;">
+<div id="map" style="width: 100%; height: 100%; position:fixed;"></div>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.js" type="text/javascript"></script>
+<script id="loadScript" src="app.js"></script>
+</body>
+</html>