diff options
Diffstat (limited to 'web/app')
59 files changed, 978 insertions, 164 deletions
diff --git a/web/app/Application.js b/web/app/Application.js index 6338506c..d0b6713c 100644 --- a/web/app/Application.js +++ b/web/app/Application.js @@ -42,7 +42,8 @@ Ext.define('Traccar.Application', { 'KnownAttribute', 'Driver', 'KnownCommand', - 'KnownNotification' + 'KnownNotification', + 'Maintenance' ], stores: [ @@ -103,7 +104,12 @@ Ext.define('Traccar.Application', { 'Commands', 'AllCommands', 'DeviceCommands', - 'AllNotificationTypes' + 'AllNotificationTypes', + 'Maintenances', + 'AllMaintenances', + 'MaintenanceTypes', + 'HoursUnits', + 'AllNotificators' ], controllers: [ @@ -123,6 +129,11 @@ Ext.define('Traccar.Application', { return Strings[key] || key; }, + getNotificatorString: function (eventType) { + var key = 'notificator' + 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/AttributeFormatter.js b/web/app/AttributeFormatter.js index 289aff91..c2793827 100644 --- a/web/app/AttributeFormatter.js +++ b/web/app/AttributeFormatter.js @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2018 Anton Tananaev (anton@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 @@ -60,15 +60,29 @@ Ext.define('Traccar.AttributeFormatter', { return Ext.getStore('VolumeUnits').convertValue(value, Traccar.app.getAttributePreference('volumeUnit')); }, + hoursFormatter: function (value) { + return Ext.getStore('HoursUnits').formatValue(value, 'h'); + }, + + hoursConverter: function (value) { + return Ext.getStore('HoursUnits').convertValue(value, 'h'); + }, + durationFormatter: function (value) { - var hours, minutes; - hours = Math.floor(value / 3600000); - minutes = Math.floor(value % 3600000 / 60000); - return hours + ' ' + Strings.sharedHourAbbreviation + ' ' + minutes + ' ' + Strings.sharedMinuteAbbreviation; + return Ext.getStore('HoursUnits').formatValue(value, 'h', true); }, deviceIdFormatter: function (value) { - return Ext.getStore('Devices').getById(value).get('name'); + var device, store; + if (value !== 0) { + store = Ext.getStore('AllDevices'); + if (store.getTotalCount() === 0) { + store = Ext.getStore('Devices'); + } + device = store.getById(value); + return device ? device.get('name') : ''; + } + return null; }, groupIdFormatter: function (value) { @@ -97,6 +111,19 @@ Ext.define('Traccar.AttributeFormatter', { return null; }, + calendarIdFormatter: function (value) { + var calendar, store; + if (value !== 0) { + store = Ext.getStore('AllCalendars'); + if (store.getTotalCount() === 0) { + store = Ext.getStore('Calendars'); + } + calendar = store.getById(value); + return calendar ? calendar.get('name') : ''; + } + return null; + }, + driverUniqueIdFormatter: function (value) { var driver, store; if (value !== 0) { @@ -110,6 +137,19 @@ Ext.define('Traccar.AttributeFormatter', { return null; }, + maintenanceIdFormatter: function (value) { + var maintenance, store; + if (value !== 0) { + store = Ext.getStore('AllMaintenances'); + if (store.getTotalCount() === 0) { + store = Ext.getStore('Maintenances'); + } + maintenance = store.getById(value); + return maintenance ? maintenance.get('name') : ''; + } + return null; + }, + lastUpdateFormatter: function (value) { var seconds, interval; if (value) { @@ -174,6 +214,10 @@ Ext.define('Traccar.AttributeFormatter', { return this.groupIdFormatter; case 'geofenceId': return this.geofenceIdFormatter; + case 'maintenanceId': + return this.maintenanceIdFormatter; + case 'calendarId': + return this.calendarIdFormatter; case 'lastUpdate': return this.lastUpdateFormatter; case 'spentFuel': @@ -221,6 +265,8 @@ Ext.define('Traccar.AttributeFormatter', { return this.numberFormatterFactory(Traccar.Style.numberPrecision, '°C'); case 'volume': return this.volumeFormatter; + case 'hours': + return this.hoursFormatter; case 'consumption': return this.numberFormatterFactory(Traccar.Style.numberPrecision, Strings.sharedLiterPerHourAbbreviation); default: @@ -238,10 +284,24 @@ Ext.define('Traccar.AttributeFormatter', { return this.speedConverter; case 'volume': return this.volumeConverter; + case 'hours': + return this.hoursConverter; default: return function (value) { return value; }; } + }, + + renderAttribute: function (value, attribute) { + if (attribute && attribute.get('dataType') === 'speed') { + return Ext.getStore('SpeedUnits').formatValue(value, Traccar.app.getAttributePreference('speedUnit', 'kn'), true); + } else if (attribute && attribute.get('dataType') === 'distance') { + return Ext.getStore('DistanceUnits').formatValue(value, Traccar.app.getAttributePreference('distanceUnit', 'km'), true); + } else if (attribute && attribute.get('dataType') === 'hours') { + return Ext.getStore('HoursUnits').formatValue(value, 'h', true); + } else { + return value; + } } }); diff --git a/web/app/Style.js b/web/app/Style.js index 27243531..47c49a96 100644 --- a/web/app/Style.js +++ b/web/app/Style.js @@ -20,6 +20,7 @@ Ext.define('Traccar.Style', { refreshPeriod: 60 * 1000, reconnectTimeout: 60 * 1000, + reportTimeout: 120 * 1000, normalPadding: 10, @@ -42,8 +43,8 @@ Ext.define('Traccar.Style', { columnWidthNormal: 100, - mapDefaultLat: 1.283333, - mapDefaultLon: 103.833333, + mapDefaultLat: 48.8567, + mapDefaultLon: 2.3508, mapDefaultZoom: 4, mapRouteColor: [ diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js index 75c4531c..0edc049a 100644 --- a/web/app/controller/Root.js +++ b/web/app/controller/Root.js @@ -27,7 +27,9 @@ Ext.define('Traccar.controller.Root', { ], init: function () { - var i, data, attribute, chartTypesStore = Ext.getStore('ReportChartTypes'); + var i, data, attribute, chartTypesStore, maintenanceTypesStore; + chartTypesStore = Ext.getStore('ReportChartTypes'); + maintenanceTypesStore = Ext.getStore('MaintenanceTypes'); Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); data = Ext.getStore('PositionAttributes').getData().items; for (i = 0; i < data.length; i++) { @@ -43,6 +45,7 @@ Ext.define('Traccar.controller.Root', { key: 'attribute.' + attribute.get('key'), name: attribute.get('name') }); + maintenanceTypesStore.add(attribute); } } }, @@ -110,6 +113,7 @@ Ext.define('Traccar.controller.Root', { Ext.getStore('Drivers').load(); Ext.getStore('Geofences').load(); Ext.getStore('Calendars').load(); + Ext.getStore('Maintenances').load(); Ext.getStore('ComputedAttributes').load(); Ext.getStore('AllCommandTypes').load(); Ext.getStore('Commands').load(); @@ -125,6 +129,7 @@ Ext.define('Traccar.controller.Root', { } } }); + Ext.getStore('AllNotificators').load(); Ext.getStore('Notifications').load(); Ext.getStore('ServerAttributes').loadData(Ext.getStore('CommonDeviceAttributes').getData().items, true); @@ -285,6 +290,8 @@ Ext.define('Traccar.controller.Root', { this.beep(); } Traccar.app.showToast(array[i].text, device.get('name')); + } else { + Traccar.app.showToast(array[i].text); } } }, diff --git a/web/app/model/Event.js b/web/app/model/Event.js index 966cd607..f0c9c3aa 100644 --- a/web/app/model/Event.js +++ b/web/app/model/Event.js @@ -1,6 +1,6 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -40,9 +40,12 @@ Ext.define('Traccar.model.Event', { name: 'geofenceId', type: 'int' }, { + name: 'maintenanceId', + type: 'int' + }, { name: 'text', convert: function (v, rec) { - var text, alarmKey, geofence; + var text, alarmKey, geofence, maintenance; if (rec.get('type') === 'commandResult') { text = Strings.eventCommandResult + ': ' + rec.get('attributes')['result']; } else if (rec.get('type') === 'alarm') { @@ -63,9 +66,15 @@ Ext.define('Traccar.model.Event', { text += ' "' + geofence.get('name') + '"'; } } + if (rec.get('maintenanceId')) { + maintenance = Ext.getStore('Maintenances').getById(rec.get('maintenanceId')); + if (maintenance) { + text += ' "' + maintenance.get('name') + '"'; + } + } return text; }, - depends: ['type', 'attributes', 'geofenceId'] + depends: ['type', 'attributes', 'geofenceId', 'maintenanceId'] }, { name: 'attributes' }] diff --git a/web/app/model/KnownNotificator.js b/web/app/model/KnownNotificator.js new file mode 100644 index 00000000..7855a12b --- /dev/null +++ b/web/app/model/KnownNotificator.js @@ -0,0 +1,32 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.KnownNotificator', { + extend: 'Ext.data.Model', + idProperty: 'type', + + fields: [{ + name: 'type', + type: 'string' + }, { + name: 'name', + convert: function (v, rec) { + return Traccar.app.getNotificatorString(rec.get('type')); + }, + depends: ['type'] + }] +}); diff --git a/web/app/model/Maintenance.js b/web/app/model/Maintenance.js new file mode 100644 index 00000000..a0654275 --- /dev/null +++ b/web/app/model/Maintenance.js @@ -0,0 +1,41 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.Maintenance', { + extend: 'Ext.data.Model', + identifier: 'negative', + + fields: [{ + name: 'id', + type: 'int' + }, { + name: 'name', + type: 'string' + }, { + name: 'type', + type: 'string' + }, { + name: 'start', + type: 'float' + }, { + name: 'period', + type: 'float' + }, { + name: 'attributes' + }] +}); diff --git a/web/app/model/Notification.js b/web/app/model/Notification.js index 6ccaecaf..fc9d84d7 100644 --- a/web/app/model/Notification.js +++ b/web/app/model/Notification.js @@ -31,14 +31,8 @@ Ext.define('Traccar.model.Notification', { }, { name: 'attributes' }, { - name: 'web', - type: 'bool' - }, { - name: 'mail', - type: 'bool' - }, { - name: 'sms', - type: 'bool' + name: 'notificators', + type: 'string' }, { name: 'calendarId', type: 'int' diff --git a/web/app/model/User.js b/web/app/model/User.js index 5232c9f4..76f2a366 100644 --- a/web/app/model/User.js +++ b/web/app/model/User.js @@ -41,7 +41,7 @@ Ext.define('Traccar.model.User', { name: 'readonly', type: 'boolean' }, { - name: 'admin', + name: 'administrator', type: 'boolean' }, { name: 'map', diff --git a/web/app/store/AllCommandTypes.js b/web/app/store/AllCommandTypes.js index c86d0714..c35f50d9 100644 --- a/web/app/store/AllCommandTypes.js +++ b/web/app/store/AllCommandTypes.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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,7 +24,7 @@ Ext.define('Traccar.store.AllCommandTypes', { type: 'rest', url: 'api/commands/types', listeners: { - 'exception': function (proxy, response) { + exception: function (proxy, response) { Traccar.app.showError(response); } } diff --git a/web/app/store/AllMaintenances.js b/web/app/store/AllMaintenances.js new file mode 100644 index 00000000..745b5d64 --- /dev/null +++ b/web/app/store/AllMaintenances.js @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.AllMaintenances', { + extend: 'Ext.data.Store', + model: 'Traccar.model.Maintenance', + + proxy: { + type: 'rest', + url: 'api/maintenances', + extraParams: { + all: true + } + } +}); diff --git a/web/app/store/AllNotificationTypes.js b/web/app/store/AllNotificationTypes.js index ded5ef98..63fec1bc 100644 --- a/web/app/store/AllNotificationTypes.js +++ b/web/app/store/AllNotificationTypes.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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,7 +24,7 @@ Ext.define('Traccar.store.AllNotificationTypes', { type: 'rest', url: 'api/notifications/types', listeners: { - 'exception': function (proxy, response) { + exception: function (proxy, response) { Traccar.app.showError(response); } } diff --git a/web/app/store/AllNotificators.js b/web/app/store/AllNotificators.js new file mode 100644 index 00000000..d81b02fd --- /dev/null +++ b/web/app/store/AllNotificators.js @@ -0,0 +1,32 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.AllNotificators', { + extend: 'Ext.data.Store', + model: 'Traccar.model.KnownNotificator', + + proxy: { + type: 'rest', + url: 'api/notifications/notificators', + listeners: { + exception: function (proxy, response) { + Traccar.app.showError(response); + } + } + } +}); diff --git a/web/app/store/CommonDeviceAttributes.js b/web/app/store/CommonDeviceAttributes.js index 83dd4114..e63daa6b 100644 --- a/web/app/store/CommonDeviceAttributes.js +++ b/web/app/store/CommonDeviceAttributes.js @@ -28,15 +28,5 @@ Ext.define('Traccar.store.CommonDeviceAttributes', { key: 'report.ignoreOdometer', name: Strings.attributeReportIgnoreOdometer, valueType: 'boolean' - }, { - key: 'maintenance.start', - name: Strings.attributeMaintenanceStart, - valueType: 'number', - dataType: 'distance' - }, { - key: 'maintenance.interval', - name: Strings.attributeMaintenanceInterval, - valueType: 'number', - dataType: 'distance' }] }); diff --git a/web/app/store/CommonUserAttributes.js b/web/app/store/CommonUserAttributes.js index c2c29429..0ee9e163 100644 --- a/web/app/store/CommonUserAttributes.js +++ b/web/app/store/CommonUserAttributes.js @@ -63,6 +63,10 @@ Ext.define('Traccar.store.CommonUserAttributes', { name: Strings.attributeUiDisableCalendars, valueType: 'boolean' }, { + key: 'ui.disableMaintenances', + name: Strings.attributeUiDisableMaintenances, + valueType: 'boolean' + }, { key: 'ui.hidePositionAttributes', name: Strings.attributeUiHidePositionAttributes, valueType: 'string' diff --git a/web/app/store/GeofenceAttributes.js b/web/app/store/GeofenceAttributes.js index 2b8d2d89..b1d48c19 100644 --- a/web/app/store/GeofenceAttributes.js +++ b/web/app/store/GeofenceAttributes.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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,5 +24,15 @@ Ext.define('Traccar.store.GeofenceAttributes', { key: 'color', name: Strings.attributeColor, valueType: 'color' + }, { + key: 'speedLimit', + name: Strings.attributeSpeedLimit, + valueType: 'number', + dataType: 'speed' + }, { + key: 'polylineDistance', + name: Strings.attributePolylineDistance, + valueType: 'number', + dataType: 'distance' }] }); diff --git a/web/app/store/HoursUnits.js b/web/app/store/HoursUnits.js new file mode 100644 index 00000000..02f62c65 --- /dev/null +++ b/web/app/store/HoursUnits.js @@ -0,0 +1,43 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.HoursUnits', { + extend: 'Ext.data.Store', + fields: ['key', 'name', 'fullName'], + + data: [{ + key: 'h', + name: Strings.sharedHourAbbreviation, + fullName: Strings.sharedHour + }], + + convertValue: function (value, unit, back) { + return back ? value * 3600000 : value / 3600000; + }, + + formatValue: function (value, unit, convert) { + var hours, minutes; + if (convert) { + hours = Math.floor(value / 3600000); + minutes = Math.floor(value % 3600000 / 60000); + } else { + hours = Math.floor(value); + minutes = Math.floor(value % 1 * 60); + } + return hours + ' ' + Strings.sharedHourAbbreviation + ' ' + minutes + ' ' + Strings.sharedMinuteAbbreviation; + } +}); diff --git a/web/app/store/MaintenanceTypes.js b/web/app/store/MaintenanceTypes.js new file mode 100644 index 00000000..468b67ea --- /dev/null +++ b/web/app/store/MaintenanceTypes.js @@ -0,0 +1,22 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.MaintenanceTypes', { + extend: 'Ext.data.Store', + model: 'Traccar.model.KnownAttribute' +}); diff --git a/web/app/store/Maintenances.js b/web/app/store/Maintenances.js new file mode 100644 index 00000000..43d6ba5b --- /dev/null +++ b/web/app/store/Maintenances.js @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.Maintenances', { + extend: 'Ext.data.Store', + model: 'Traccar.model.Maintenance', + + proxy: { + type: 'rest', + url: 'api/maintenances', + writer: { + writeAllFields: true + } + } +}); diff --git a/web/app/store/MapTypes.js b/web/app/store/MapTypes.js index 77c10ebd..3d322438 100644 --- a/web/app/store/MapTypes.js +++ b/web/app/store/MapTypes.js @@ -44,6 +44,9 @@ Ext.define('Traccar.store.MapTypes', { key: 'yandexSat', name: Strings.mapYandexSat }, { + key: 'wikimedia', + name: Strings.mapWikimedia + }, { key: 'custom', name: Strings.mapCustom }] diff --git a/web/app/store/PositionAttributes.js b/web/app/store/PositionAttributes.js index c8feb0a5..5b1206b7 100644 --- a/web/app/store/PositionAttributes.js +++ b/web/app/store/PositionAttributes.js @@ -90,7 +90,8 @@ Ext.define('Traccar.store.PositionAttributes', { }, { key: 'hours', name: Strings.positionHours, - valueType: 'string' + valueType: 'number', + dataType: 'hours' }, { key: 'steps', name: Strings.positionSteps, diff --git a/web/app/store/ReportEvents.js b/web/app/store/ReportEvents.js index ca90693d..061aaa42 100644 --- a/web/app/store/ReportEvents.js +++ b/web/app/store/ReportEvents.js @@ -22,6 +22,7 @@ Ext.define('Traccar.store.ReportEvents', { proxy: { type: 'rest', url: 'api/reports/events', + timeout: Traccar.Style.reportTimeout, headers: { 'Accept': 'application/json' }, diff --git a/web/app/store/ReportRoute.js b/web/app/store/ReportRoute.js index 6ee4bbcd..7babe163 100644 --- a/web/app/store/ReportRoute.js +++ b/web/app/store/ReportRoute.js @@ -22,6 +22,7 @@ Ext.define('Traccar.store.ReportRoute', { proxy: { type: 'rest', url: 'api/reports/route', + timeout: Traccar.Style.reportTimeout, headers: { 'Accept': 'application/json' }, diff --git a/web/app/store/ReportStops.js b/web/app/store/ReportStops.js index 9e9ba13e..75c9fc18 100644 --- a/web/app/store/ReportStops.js +++ b/web/app/store/ReportStops.js @@ -23,6 +23,7 @@ Ext.define('Traccar.store.ReportStops', { proxy: { type: 'rest', url: 'api/reports/stops', + timeout: Traccar.Style.reportTimeout, headers: { 'Accept': 'application/json' }, diff --git a/web/app/store/ReportSummary.js b/web/app/store/ReportSummary.js index 4e53d948..f328da2d 100644 --- a/web/app/store/ReportSummary.js +++ b/web/app/store/ReportSummary.js @@ -23,6 +23,7 @@ Ext.define('Traccar.store.ReportSummary', { proxy: { type: 'rest', url: 'api/reports/summary', + timeout: Traccar.Style.reportTimeout, headers: { 'Accept': 'application/json' }, diff --git a/web/app/store/ReportTrips.js b/web/app/store/ReportTrips.js index d8aa9226..057cc7c0 100644 --- a/web/app/store/ReportTrips.js +++ b/web/app/store/ReportTrips.js @@ -23,6 +23,7 @@ Ext.define('Traccar.store.ReportTrips', { proxy: { type: 'rest', url: 'api/reports/trips', + timeout: Traccar.Style.reportTimeout, headers: { 'Accept': 'application/json' }, diff --git a/web/app/view/ArrayListFilter.js b/web/app/view/ArrayListFilter.js index b6c1512f..519096eb 100644 --- a/web/app/view/ArrayListFilter.js +++ b/web/app/view/ArrayListFilter.js @@ -25,7 +25,7 @@ Ext.define('Traccar.view.ArrayListFilter', { constructor: function (config) { this.callParent([config]); this.filter.setFilterFn(function (item) { - var i, property, value; + var i, property, value, splits; property = item.get(this.getProperty()); value = this.getValue(); if (Ext.isArray(property)) { @@ -34,6 +34,13 @@ Ext.define('Traccar.view.ArrayListFilter', { return true; } } + } else if (property.match(/[ ,]+/)) { + splits = property.split(/[ ,]+/).filter(Boolean); + for (i = 0; i < splits.length; i++) { + if (value.indexOf(splits[i]) !== -1) { + return true; + } + } } else if (value.indexOf(property) !== -1) { return true; } diff --git a/web/app/view/CustomNumberField.js b/web/app/view/CustomNumberField.js index 807bad4d..8cfac1ee 100644 --- a/web/app/view/CustomNumberField.js +++ b/web/app/view/CustomNumberField.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -72,22 +72,32 @@ Ext.define('Traccar.view.CustomNumberField', { } }; break; + case 'hours': + config.units = {}; + config.units.getStore = function () { + return Ext.getStore('HoursUnits'); + }; + config.units.getValue = function () { + return 'h'; + }; + unitName = Strings.sharedHourAbbreviation; + break; default: break; } config.afterBodyEl = this.unitEl + unitName + '</div></div>'; config.rawToValue = function (rawValue) { if (this.units) { - return this.units.getStore().convertValue(rawValue, this.units.getValue(), true); + return this.units.getStore().convertValue(this.parseValue(rawValue), this.units.getValue(), true); } else { return this.parseValue(rawValue); } }; config.valueToRaw = function (value) { if (this.units) { - return this.units.getStore().convertValue(value, this.units.getValue(), false); + return String(this.units.getStore().convertValue(value, this.units.getValue(), false)); } else { - return this.parseValue(value); + return String(value); } }; if (config.units) { diff --git a/web/app/view/DeviceMenu.js b/web/app/view/DeviceMenu.js index ed4068f1..a3381cc4 100644 --- a/web/app/view/DeviceMenu.js +++ b/web/app/view/DeviceMenu.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -57,6 +57,11 @@ Ext.define('Traccar.view.DeviceMenu', { handler: 'onCommandsClick', reference: 'menuCommandsButton' }, { + text: Strings.sharedMaintenances, + glyph: 'xf0ad@FontAwesome', + handler: 'onMaintenancesClick', + reference: 'menuMaintenancesButton' + }, { hidden: true, text: Strings.sharedDeviceDistance, glyph: 'xf0e4@FontAwesome', diff --git a/web/app/view/DeviceMenuController.js b/web/app/view/DeviceMenuController.js index 6416314a..f191756c 100644 --- a/web/app/view/DeviceMenuController.js +++ b/web/app/view/DeviceMenuController.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -26,6 +26,7 @@ Ext.define('Traccar.view.DeviceMenuController', { 'Traccar.view.permissions.Notifications', 'Traccar.view.edit.ComputedAttributes', 'Traccar.view.permissions.SavedCommands', + 'Traccar.view.permissions.Maintenances', 'Traccar.view.BaseWindow' ], @@ -36,7 +37,9 @@ Ext.define('Traccar.view.DeviceMenuController', { Traccar.app.getBooleanAttributePreference('ui.disableComputedAttributes')); this.lookupReference('menuCommandsButton').setHidden(Traccar.app.getPreference('limitCommands', false)); this.lookupReference('menuDeviceDistanceButton').setHidden( - !Traccar.app.getUser().get('admin') && Traccar.app.getUser().get('userLimit') === 0 || Traccar.app.getVehicleFeaturesDisabled()); + !Traccar.app.getUser().get('administrator') && Traccar.app.getUser().get('userLimit') === 0 || Traccar.app.getVehicleFeaturesDisabled()); + this.lookupReference('menuMaintenancesButton').setHidden( + Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableMaintenances')); }, onGeofencesClick: function () { @@ -104,6 +107,19 @@ Ext.define('Traccar.view.DeviceMenuController', { }).show(); }, + onMaintenancesClick: function () { + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedMaintenances, + items: { + xtype: 'linkMaintenancesView', + baseObjectName: 'deviceId', + linkObjectName: 'maintenanceId', + storeName: 'Maintenances', + baseObject: this.getView().up('deviceMenu').device.getId() + } + }).show(); + }, + onDeviceDistanceClick: function () { var position, dialog = Ext.create('Traccar.view.dialog.DeviceDistance'); dialog.deviceId = this.getView().up('deviceMenu').device.getId(); diff --git a/web/app/view/ReportController.js b/web/app/view/ReportController.js index 9ec75ce2..6079da77 100644 --- a/web/app/view/ReportController.js +++ b/web/app/view/ReportController.js @@ -142,7 +142,7 @@ Ext.define('Traccar.view.ReportController', { reportType = this.lookupReference('reportTypeField').getValue(); devices = this.deviceId && this.deviceId.length !== 0 || this.groupId && this.groupId.length !== 0; time = this.fromDate && this.fromTime && this.toDate && this.toTime; - disabled = !reportType || !devices || !time; + disabled = !reportType || !devices || !time || this.reportProgress; this.lookupReference('showButton').setDisabled(disabled); this.lookupReference('exportButton').setDisabled(reportType === 'chart' || disabled); }, @@ -162,6 +162,9 @@ Ext.define('Traccar.view.ReportController', { this.toDate.getFullYear(), this.toDate.getMonth(), this.toDate.getDate(), this.toTime.getHours(), this.toTime.getMinutes(), this.toTime.getSeconds(), this.toTime.getMilliseconds()); + this.reportProgress = true; + this.updateButtons(); + if (button.reference === 'showButton') { if (reportType === 'chart') { store = this.getChart().getStore(); @@ -171,6 +174,11 @@ Ext.define('Traccar.view.ReportController', { } store.showMarkers = this.showMarkers; store.load({ + scope: this, + callback: function () { + this.reportProgress = false; + this.updateButtons(); + }, params: { deviceId: this.deviceId, groupId: this.groupId, @@ -367,34 +375,40 @@ Ext.define('Traccar.view.ReportController', { Ext.Ajax.request({ url: requestUrl, method: 'GET', + timeout: Traccar.Style.reportTimeout, params: requestParams, headers: { Accept: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, binary: true, - success: function (response) { + scope: this, + callback: function (options, success, response) { var disposition, filename, type, blob, url, downloadUrl; - disposition = response.getResponseHeader('Content-Disposition'); - filename = disposition.slice(disposition.indexOf('=') + 1, disposition.length); - type = response.getResponseHeader('Content-Type'); - blob = new Blob([response.responseBytes], {type: type}); - if (typeof window.navigator.msSaveBlob !== 'undefined') { - // IE workaround - window.navigator.msSaveBlob(blob, filename); - } else { - url = window.URL || window.webkitURL; - downloadUrl = url.createObjectURL(blob); - if (filename) { - Ext.dom.Helper.append(Ext.getBody(), { - tag: 'a', - href: downloadUrl, - download: filename - }).click(); + if (success) { + disposition = response.getResponseHeader('Content-Disposition'); + filename = disposition.slice(disposition.indexOf('=') + 1, disposition.length); + type = response.getResponseHeader('Content-Type'); + blob = new Blob([response.responseBytes], {type: type}); + if (typeof window.navigator.msSaveBlob !== 'undefined') { + // IE workaround + window.navigator.msSaveBlob(blob, filename); + } else { + url = window.URL || window.webkitURL; + downloadUrl = url.createObjectURL(blob); + if (filename) { + Ext.dom.Helper.append(Ext.getBody(), { + tag: 'a', + href: downloadUrl, + download: filename + }).click(); + } + setTimeout(function () { + url.revokeObjectURL(downloadUrl); + }, 100); } - setTimeout(function () { - url.revokeObjectURL(downloadUrl); - }, 100); } + this.reportProgress = false; + this.updateButtons(); } }); }, @@ -510,6 +524,10 @@ Ext.define('Traccar.view.ReportController', { text: Strings.sharedGeofence, dataIndex: 'geofenceId', renderer: Traccar.AttributeFormatter.getFormatter('geofenceId') + }, { + text: Strings.sharedMaintenance, + dataIndex: 'maintenanceId', + renderer: Traccar.AttributeFormatter.getFormatter('maintenanceId') }], summaryColumns: [{ diff --git a/web/app/view/SettingsMenu.js b/web/app/view/SettingsMenu.js index 13d5e398..01a06aa6 100644 --- a/web/app/view/SettingsMenu.js +++ b/web/app/view/SettingsMenu.js @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2018 Anton Tananaev (anton@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 @@ -57,7 +57,7 @@ Ext.define('Traccar.view.SettingsMenu', { }, { hidden: true, text: Strings.settingsServer, - glyph: 'xf0ad@FontAwesome', + glyph: 'xf233@FontAwesome', handler: 'onServerClick', reference: 'settingsServerButton' }, { @@ -97,6 +97,12 @@ Ext.define('Traccar.view.SettingsMenu', { handler: 'onCommandsClick', reference: 'settingsCommandsButton' }, { + hidden: true, + text: Strings.sharedMaintenances, + glyph: 'xf0ad@FontAwesome', + handler: 'onMaintenancesClick', + reference: 'settingsMaintenancesButton' + }, { text: Strings.loginLogout, glyph: 'xf08b@FontAwesome', handler: 'onLogoutClick' diff --git a/web/app/view/SettingsMenuController.js b/web/app/view/SettingsMenuController.js index e8893e3f..59f62c2e 100644 --- a/web/app/view/SettingsMenuController.js +++ b/web/app/view/SettingsMenuController.js @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2018 Anton Tananaev (anton@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 @@ -33,12 +33,13 @@ Ext.define('Traccar.view.SettingsMenuController', { 'Traccar.view.dialog.DeviceDistance', 'Traccar.view.edit.Calendars', 'Traccar.view.edit.SavedCommands', + 'Traccar.view.edit.Maintenances', 'Traccar.view.BaseWindow' ], init: function () { var admin, manager, readonly, deviceReadonly; - admin = Traccar.app.getUser().get('admin'); + admin = Traccar.app.getUser().get('administrator'); manager = Traccar.app.getUser().get('userLimit') !== 0; readonly = Traccar.app.getPreference('readonly', false); deviceReadonly = Traccar.app.getUser().get('deviceReadonly'); @@ -59,6 +60,8 @@ Ext.define('Traccar.view.SettingsMenuController', { this.lookupReference('settingsDriversButton').setHidden( Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableDrivers')); this.lookupReference('settingsCommandsButton').setHidden(Traccar.app.getPreference('limitCommands', false)); + this.lookupReference('settingsMaintenancesButton').setHidden( + Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableMaintenances')); } if (admin || !deviceReadonly && !readonly) { this.lookupReference('settingsComputedAttributesButton').setHidden( @@ -162,6 +165,15 @@ Ext.define('Traccar.view.SettingsMenuController', { }).show(); }, + onMaintenancesClick: function () { + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedMaintenances, + items: { + xtype: 'maintenancesView' + } + }).show(); + }, + onLogoutClick: function () { Ext.create('Traccar.view.dialog.LoginController').logout(); } diff --git a/web/app/view/StateController.js b/web/app/view/StateController.js index 44b01382..6363fc9c 100644 --- a/web/app/view/StateController.js +++ b/web/app/view/StateController.js @@ -53,7 +53,7 @@ Ext.define('Traccar.view.StateController', { init: function () { var i, hideAttributesPreference, attributesList; - if (Traccar.app.getUser().get('admin') || + if (Traccar.app.getUser().get('administrator') || !Traccar.app.getUser().get('deviceReadonly') && !Traccar.app.getPreference('readonly', false)) { this.lookupReference('computedAttributesButton').setDisabled( Traccar.app.getBooleanAttributePreference('ui.disableComputedAttributes')); diff --git a/web/app/view/dialog/AttributeController.js b/web/app/view/dialog/AttributeController.js index e85125d0..9fd452a4 100644 --- a/web/app/view/dialog/AttributeController.js +++ b/web/app/view/dialog/AttributeController.js @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 Anton Tananaev (anton@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 @@ -110,7 +110,8 @@ Ext.define('Traccar.view.dialog.AttributeController', { } break; } - if (valueField.getXType() !== config.xtype) { + if (valueField.getXType() !== config.xtype || + config.xtype === 'customNumberField' && valueField.dataType !== config.dataType) { this.getView().down('form').insert(this.getView().down('form').items.indexOf(valueField), config); this.getView().down('form').remove(valueField); } else if (config.xtype === 'customNumberField') { diff --git a/web/app/view/dialog/Base.js b/web/app/view/dialog/Base.js index 20945c0a..6affb370 100644 --- a/web/app/view/dialog/Base.js +++ b/web/app/view/dialog/Base.js @@ -20,7 +20,7 @@ Ext.define('Traccar.view.dialog.Base', { bodyPadding: Traccar.Style.normalPadding, resizable: false, - autoScroll: true, + scrollable: true, constrain: true, initComponent: function () { diff --git a/web/app/view/dialog/BaseEdit.js b/web/app/view/dialog/BaseEdit.js index 362823e3..286afba5 100644 --- a/web/app/view/dialog/BaseEdit.js +++ b/web/app/view/dialog/BaseEdit.js @@ -31,6 +31,7 @@ Ext.define('Traccar.view.dialog.BaseEdit', { xtype: 'tbfill' }, { glyph: 'xf00c@FontAwesome', + reference: 'saveButton', tooltip: Strings.sharedSave, tooltipType: 'title', minWidth: 0, diff --git a/web/app/view/dialog/DeviceController.js b/web/app/view/dialog/DeviceController.js index d6ddc58b..d7a4493b 100644 --- a/web/app/view/dialog/DeviceController.js +++ b/web/app/view/dialog/DeviceController.js @@ -21,7 +21,7 @@ Ext.define('Traccar.view.dialog.DeviceController', { alias: 'controller.device', init: function () { - if (Traccar.app.getUser().get('admin')) { + if (Traccar.app.getUser().get('administrator')) { this.lookupReference('disabledField').setHidden(false); } } diff --git a/web/app/view/dialog/Login.js b/web/app/view/dialog/Login.js index c46d52d6..3a2c247a 100644 --- a/web/app/view/dialog/Login.js +++ b/web/app/view/dialog/Login.js @@ -43,8 +43,8 @@ Ext.define('Traccar.view.dialog.Login', { xtype: 'image', src: 'logo.svg', alt: Strings.loginLogo, - width: 180, - height: 48, + width: 240, + height: 64, style: { display: 'block', margin: '10px auto 25px' diff --git a/web/app/view/dialog/Maintenance.js b/web/app/view/dialog/Maintenance.js new file mode 100644 index 00000000..5705278f --- /dev/null +++ b/web/app/view/dialog/Maintenance.js @@ -0,0 +1,74 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.dialog.Maintenance', { + extend: 'Traccar.view.dialog.BaseEdit', + + requires: [ + 'Traccar.view.dialog.MaintenanceController', + 'Traccar.view.CustomNumberField' + ], + + controller: 'maintenance', + + title: Strings.sharedMaintenance, + + items: { + xtype: 'form', + listeners: { + validitychange: 'onValidityChange' + }, + items: [{ + xtype: 'fieldset', + title: Strings.sharedRequired, + items: [{ + xtype: 'textfield', + name: 'name', + fieldLabel: Strings.sharedName, + allowBlank: false + }, { + xtype: 'combobox', + name: 'type', + reference: 'typeComboField', + fieldLabel: Strings.sharedType, + displayField: 'name', + valueField: 'key', + allowBlank: false, + queryMode: 'local', + store: 'MaintenanceTypes', + listeners: { + change: 'onNameChange' + } + }, { + xtype: 'customNumberField', + name: 'start', + reference: 'startField', + fieldLabel: Strings.maintenanceStart + }, { + xtype: 'customNumberField', + name: 'period', + reference: 'periodField', + allowBlank: false, + fieldLabel: Strings.maintenancePeriod, + validator: function (value) { + return this.parseValue(value) !== 0 ? true : Strings.errorZero; + } + }] + }] + } +}); diff --git a/web/app/view/dialog/MaintenanceController.js b/web/app/view/dialog/MaintenanceController.js new file mode 100644 index 00000000..d5a27b54 --- /dev/null +++ b/web/app/view/dialog/MaintenanceController.js @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.dialog.MaintenanceController', { + extend: 'Traccar.view.dialog.BaseEditController', + alias: 'controller.maintenance', + + init: function () { + this.startConfig = Ext.clone(this.lookupReference('startField').initialConfig); + this.startConfig.value = 0; + this.periodConfig = Ext.clone(this.lookupReference('periodField').initialConfig); + this.periodConfig.value = 0; + this.lookupReference('saveButton').setDisabled(true); + }, + + onValidityChange: function (form, valid) { + this.lookupReference('saveButton').setDisabled(!valid); + }, + + updateFieldConfig: function (fieldReference, initialConfig, newConfig) { + var field = this.lookupReference(fieldReference); + if (field.dataType !== newConfig.dataType) { + this.getView().down('fieldset').insert(this.getView().down('fieldset').items.indexOf(field), + Ext.merge({}, initialConfig, newConfig)); + this.getView().down('fieldset').remove(field); + this.lookupReference(fieldReference).validate(); + } else { + field.setConfig(newConfig); + field.validate(); + } + }, + + onNameChange: function (combobox, newValue) { + var attribute, config = {}; + attribute = combobox.getStore().getById(newValue); + if (attribute) { + if (attribute.get('allowDecimals') !== undefined) { + config.allowDecimals = attribute.get('allowDecimals'); + } else { + config.allowDecimals = true; + } + config.dataType = attribute.get('dataType'); + config.maxValue = attribute.get('maxValue'); + config.minValue = attribute.get('minValue'); + } + + this.updateFieldConfig('startField', this.startConfig, config); + this.updateFieldConfig('periodField', this.periodConfig, config); + } +}); diff --git a/web/app/view/dialog/Notification.js b/web/app/view/dialog/Notification.js index f4204cb9..dc4362d9 100644 --- a/web/app/view/dialog/Notification.js +++ b/web/app/view/dialog/Notification.js @@ -49,24 +49,21 @@ Ext.define('Traccar.view.dialog.Notification', { name: 'always', fieldLabel: Strings.notificationAlways }, { - xtype: 'checkboxfield', - inputValue: true, - uncheckedValue: false, - name: 'web', - fieldLabel: Strings.notificationWeb - }, { - xtype: 'checkboxfield', - inputValue: true, - uncheckedValue: false, - name: 'mail', - fieldLabel: Strings.notificationMail - }, { - xtype: 'checkboxfield', - inputValue: true, - uncheckedValue: false, - name: 'sms', - fieldLabel: Strings.notificationSms - }, { + fieldLabel: Strings.notificationNotificators, + xtype: 'tagfield', + name: 'notificators', + maxWidth: Traccar.Style.formFieldWidth, + store: 'AllNotificators', + valueField: 'type', + displayField: 'name', + queryMode: 'local' + }] + }, { + xtype: 'fieldset', + title: Strings.sharedExtra, + collapsible: true, + collapsed: true, + items: [{ xtype: 'clearableComboBox', reference: 'calendarCombo', name: 'calendarId', diff --git a/web/app/view/dialog/User.js b/web/app/view/dialog/User.js index 69bbd705..86f91672 100644 --- a/web/app/view/dialog/User.js +++ b/web/app/view/dialog/User.js @@ -115,7 +115,7 @@ Ext.define('Traccar.view.dialog.User', { xtype: 'checkboxfield', inputValue: true, uncheckedValue: false, - name: 'admin', + name: 'administrator', fieldLabel: Strings.userAdmin, disabled: true, reference: 'adminField' diff --git a/web/app/view/dialog/UserController.js b/web/app/view/dialog/UserController.js index 953093ea..7383f9ee 100644 --- a/web/app/view/dialog/UserController.js +++ b/web/app/view/dialog/UserController.js @@ -20,12 +20,12 @@ Ext.define('Traccar.view.dialog.UserController', { alias: 'controller.user', init: function () { - if (Traccar.app.getUser().get('admin')) { + if (Traccar.app.getUser().get('administrator')) { this.lookupReference('adminField').setDisabled(false); this.lookupReference('deviceLimitField').setDisabled(false); this.lookupReference('userLimitField').setDisabled(false); } - if (Traccar.app.getUser().get('admin') || !this.getView().selfEdit) { + if (Traccar.app.getUser().get('administrator') || !this.getView().selfEdit) { this.lookupReference('readonlyField').setDisabled(false); this.lookupReference('disabledField').setDisabled(false); this.lookupReference('expirationTimeField').setDisabled(false); diff --git a/web/app/view/edit/Attributes.js b/web/app/view/edit/Attributes.js index cb07eda1..af4f5a90 100644 --- a/web/app/view/edit/Attributes.js +++ b/web/app/view/edit/Attributes.js @@ -48,7 +48,7 @@ Ext.define('Traccar.view.edit.Attributes', { if (this.attributesStore) { attribute = Ext.getStore(this.attributesStore).getById(value); } - return attribute && attribute.get('name') ? attribute.get('name') : value; + return attribute && attribute.get('name') || value; } }, { text: Strings.stateValue, @@ -58,13 +58,7 @@ Ext.define('Traccar.view.edit.Attributes', { if (this.attributesStore) { attribute = Ext.getStore(this.attributesStore).getById(record.get('name')); } - if (attribute && attribute.get('dataType') === 'speed') { - return Ext.getStore('SpeedUnits').formatValue(value, Traccar.app.getAttributePreference('speedUnit', 'kn'), true); - } else if (attribute && attribute.get('dataType') === 'distance') { - return Ext.getStore('DistanceUnits').formatValue(value, Traccar.app.getAttributePreference('distanceUnit', 'km'), true); - } else { - return value; - } + return Traccar.AttributeFormatter.renderAttribute(value, attribute); } }] } diff --git a/web/app/view/edit/Devices.js b/web/app/view/edit/Devices.js index 2f7f80ee..21fdb32a 100644 --- a/web/app/view/edit/Devices.js +++ b/web/app/view/edit/Devices.js @@ -104,7 +104,8 @@ Ext.define('Traccar.view.edit.Devices', { }, { text: Strings.deviceIdentifier, dataIndex: 'uniqueId', - hidden: true + hidden: true, + filter: 'string' }, { text: Strings.sharedPhone, dataIndex: 'phone', diff --git a/web/app/view/edit/DevicesController.js b/web/app/view/edit/DevicesController.js index a0bf9dc4..2b4ff14f 100644 --- a/web/app/view/edit/DevicesController.js +++ b/web/app/view/edit/DevicesController.js @@ -59,8 +59,8 @@ Ext.define('Traccar.view.edit.DevicesController', { init: function () { var self = this, readonly, deviceReadonly; - deviceReadonly = Traccar.app.getPreference('deviceReadonly', false) && !Traccar.app.getUser().get('admin'); - readonly = Traccar.app.getPreference('readonly', false) && !Traccar.app.getUser().get('admin'); + deviceReadonly = Traccar.app.getPreference('deviceReadonly', false) && !Traccar.app.getUser().get('administrator'); + readonly = Traccar.app.getPreference('readonly', false) && !Traccar.app.getUser().get('administrator'); this.lookupReference('toolbarAddButton').setDisabled(readonly || deviceReadonly); this.lookupReference('toolbarDeviceMenu').setHidden(readonly || deviceReadonly); @@ -98,8 +98,8 @@ Ext.define('Traccar.view.edit.DevicesController', { updateButtons: function (selected) { var readonly, deviceReadonly, empty, deviceMenu; - deviceReadonly = Traccar.app.getPreference('deviceReadonly', false) && !Traccar.app.getUser().get('admin'); - readonly = Traccar.app.getPreference('readonly', false) && !Traccar.app.getUser().get('admin'); + deviceReadonly = Traccar.app.getPreference('deviceReadonly', false) && !Traccar.app.getUser().get('administrator'); + readonly = Traccar.app.getPreference('readonly', false) && !Traccar.app.getUser().get('administrator'); empty = selected.length === 0; this.lookupReference('toolbarEditButton').setDisabled(empty || readonly || deviceReadonly); this.lookupReference('toolbarRemoveButton').setDisabled(empty || readonly || deviceReadonly); diff --git a/web/app/view/edit/Geofences.js b/web/app/view/edit/Geofences.js index 9c564bc3..0e1e6773 100644 --- a/web/app/view/edit/Geofences.js +++ b/web/app/view/edit/Geofences.js @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 Anton Tananaev (anton@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 @@ -48,6 +48,16 @@ Ext.define('Traccar.view.edit.Geofences', { text: Strings.sharedDescription, dataIndex: 'description', filter: 'string' + }, { + text: Strings.sharedCalendar, + dataIndex: 'calendarId', + hidden: true, + filter: { + type: 'list', + labelField: 'name', + store: 'AllCalendars' + }, + renderer: Traccar.AttributeFormatter.getFormatter('calendarId') }] } }); diff --git a/web/app/view/edit/Groups.js b/web/app/view/edit/Groups.js index 0808201d..1ff4de80 100644 --- a/web/app/view/edit/Groups.js +++ b/web/app/view/edit/Groups.js @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 Anton Tananaev (anton@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 @@ -70,6 +70,14 @@ Ext.define('Traccar.view.edit.Groups', { glyph: 'xf003@FontAwesome', tooltip: Strings.sharedNotifications, tooltipType: 'title' + }, { + xtype: 'button', + disabled: true, + handler: 'onMaintenancesClick', + reference: 'toolbarMaintenancesButton', + glyph: 'xf0ad@FontAwesome', + tooltip: Strings.sharedMaintenances, + tooltipType: 'title' }] }, diff --git a/web/app/view/edit/GroupsController.js b/web/app/view/edit/GroupsController.js index 04c9692f..2e62a283 100644 --- a/web/app/view/edit/GroupsController.js +++ b/web/app/view/edit/GroupsController.js @@ -25,6 +25,7 @@ Ext.define('Traccar.view.edit.GroupsController', { 'Traccar.view.permissions.ComputedAttributes', 'Traccar.view.permissions.Drivers', 'Traccar.view.permissions.SavedCommands', + 'Traccar.view.permissions.Maintenances', 'Traccar.view.BaseWindow', 'Traccar.model.Group' ], @@ -39,6 +40,8 @@ Ext.define('Traccar.view.edit.GroupsController', { this.lookupReference('toolbarAttributesButton').setHidden( Traccar.app.getBooleanAttributePreference('ui.disableComputedAttributes')); this.lookupReference('toolbarCommandsButton').setHidden(Traccar.app.getPreference('limitCommands', false)); + this.lookupReference('toolbarMaintenancesButton').setHidden( + Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableMaintenances')); }, onGeofencesClick: function () { @@ -111,6 +114,20 @@ Ext.define('Traccar.view.edit.GroupsController', { }).show(); }, + onMaintenancesClick: function () { + var group = this.getView().getSelectionModel().getSelection()[0]; + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedMaintenances, + items: { + xtype: 'linkMaintenancesView', + baseObjectName: 'groupId', + linkObjectName: 'maintenanceId', + storeName: 'Maintenances', + baseObject: group.getId() + } + }).show(); + }, + onSelectionChange: function (selection, selected) { var disabled = selected.length === 0; this.lookupReference('toolbarGeofencesButton').setDisabled(disabled); @@ -118,6 +135,7 @@ Ext.define('Traccar.view.edit.GroupsController', { this.lookupReference('toolbarDriversButton').setDisabled(disabled); this.lookupReference('toolbarCommandsButton').setDisabled(disabled); this.lookupReference('toolbarNotificationsButton').setDisabled(disabled); + this.lookupReference('toolbarMaintenancesButton').setDisabled(disabled); this.callParent(arguments); } }); diff --git a/web/app/view/edit/Maintenances.js b/web/app/view/edit/Maintenances.js new file mode 100644 index 00000000..da129154 --- /dev/null +++ b/web/app/view/edit/Maintenances.js @@ -0,0 +1,77 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.edit.Maintenances', { + extend: 'Traccar.view.GridPanel', + xtype: 'maintenancesView', + + requires: [ + 'Traccar.view.edit.MaintenancesController', + 'Traccar.view.edit.Toolbar' + ], + + controller: 'maintenances', + store: 'Maintenances', + + tbar: { + xtype: 'editToolbar' + }, + + listeners: { + selectionchange: 'onSelectionChange' + }, + + columns: { + defaults: { + flex: 1, + minWidth: Traccar.Style.columnWidthNormal + }, + items: [{ + text: Strings.sharedName, + dataIndex: 'name', + filter: 'string' + }, { + text: Strings.sharedType, + dataIndex: 'type', + filter: { + type: 'list', + idField: 'key', + labelField: 'name', + store: 'MaintenanceTypes' + }, + renderer: function (value) { + var attribute = Ext.getStore('MaintenanceTypes').getById(value); + return attribute && attribute.get('name') || value; + } + }, { + text: Strings.maintenanceStart, + dataIndex: 'start', + renderer: function (value, metaData, record) { + return Traccar.AttributeFormatter.renderAttribute( + value, Ext.getStore('MaintenanceTypes').getById(record.get('type'))); + } + }, { + text: Strings.maintenancePeriod, + dataIndex: 'period', + renderer: function (value, metaData, record) { + return Traccar.AttributeFormatter.renderAttribute( + value, Ext.getStore('MaintenanceTypes').getById(record.get('type'))); + } + }] + } +}); diff --git a/web/app/view/edit/MaintenancesController.js b/web/app/view/edit/MaintenancesController.js new file mode 100644 index 00000000..19762e61 --- /dev/null +++ b/web/app/view/edit/MaintenancesController.js @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.edit.MaintenancesController', { + extend: 'Traccar.view.edit.ToolbarController', + alias: 'controller.maintenances', + + requires: [ + 'Traccar.view.dialog.Maintenance', + 'Traccar.model.Maintenance' + ], + + objectModel: 'Traccar.model.Maintenance', + objectDialog: 'Traccar.view.dialog.Maintenance', + removeTitle: Strings.sharedMaintenance +}); diff --git a/web/app/view/edit/Notifications.js b/web/app/view/edit/Notifications.js index e17100a4..9e24d3d0 100644 --- a/web/app/view/edit/Notifications.js +++ b/web/app/view/edit/Notifications.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -60,20 +60,35 @@ Ext.define('Traccar.view.edit.Notifications', { renderer: Traccar.AttributeFormatter.getFormatter('always'), filter: 'boolean' }, { - text: Strings.notificationWeb, - dataIndex: 'web', - renderer: Traccar.AttributeFormatter.getFormatter('web'), - filter: 'boolean' - }, { - text: Strings.notificationMail, - dataIndex: 'mail', - renderer: Traccar.AttributeFormatter.getFormatter('mail'), - filter: 'boolean' + text: Strings.notificationNotificators, + dataIndex: 'notificators', + flex: 2, + filter: { + type: 'arraylist', + idField: 'type', + labelField: 'name', + store: 'AllNotificators' + }, + renderer: function (value) { + var result = '', i, notificators; + if (value) { + notificators = value.split(/[ ,]+/).filter(Boolean); + for (i = 0; i < notificators.length; i++) { + result += Traccar.app.getNotificatorString(notificators[i]) + (i < notificators.length - 1 ? ', ' : ''); + } + } + return result; + } }, { - text: Strings.notificationSms, - dataIndex: 'sms', - renderer: Traccar.AttributeFormatter.getFormatter('sms'), - filter: 'boolean' + text: Strings.sharedCalendar, + dataIndex: 'calendarId', + hidden: true, + filter: { + type: 'list', + labelField: 'name', + store: 'AllCalendars' + }, + renderer: Traccar.AttributeFormatter.getFormatter('calendarId') }] } }); diff --git a/web/app/view/edit/Users.js b/web/app/view/edit/Users.js index b0a67ffd..e2dd9aa6 100644 --- a/web/app/view/edit/Users.js +++ b/web/app/view/edit/Users.js @@ -1,6 +1,6 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 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 @@ -95,6 +95,14 @@ Ext.define('Traccar.view.edit.Users', { glyph: 'xf093@FontAwesome', tooltip: Strings.sharedSavedCommands, tooltipType: 'title' + }, { + xtype: 'button', + disabled: true, + handler: 'onMaintenancesClick', + reference: 'userMaintenancesButton', + glyph: 'xf0ad@FontAwesome', + tooltip: Strings.sharedMaintenances, + tooltipType: 'title' }] }, @@ -117,8 +125,8 @@ Ext.define('Traccar.view.edit.Users', { filter: 'string' }, { text: Strings.userAdmin, - dataIndex: 'admin', - renderer: Traccar.AttributeFormatter.getFormatter('admin'), + dataIndex: 'administrator', + renderer: Traccar.AttributeFormatter.getFormatter('administrator'), filter: 'boolean' }, { text: Strings.serverReadonly, diff --git a/web/app/view/edit/UsersController.js b/web/app/view/edit/UsersController.js index db82b4f4..9d998162 100644 --- a/web/app/view/edit/UsersController.js +++ b/web/app/view/edit/UsersController.js @@ -31,6 +31,7 @@ Ext.define('Traccar.view.edit.UsersController', { 'Traccar.view.permissions.Drivers', 'Traccar.view.permissions.SavedCommands', 'Traccar.view.permissions.Notifications', + 'Traccar.view.permissions.Maintenances', 'Traccar.view.BaseWindow', 'Traccar.model.User' ], @@ -41,7 +42,7 @@ Ext.define('Traccar.view.edit.UsersController', { init: function () { Ext.getStore('Users').load(); - this.lookupReference('userUsersButton').setHidden(!Traccar.app.getUser().get('admin')); + this.lookupReference('userUsersButton').setHidden(!Traccar.app.getUser().get('administrator')); this.lookupReference('userDriversButton').setHidden( Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableDrivers')); this.lookupReference('userAttributesButton').setHidden( @@ -49,6 +50,8 @@ Ext.define('Traccar.view.edit.UsersController', { this.lookupReference('userCalendarsButton').setHidden( Traccar.app.getBooleanAttributePreference('ui.disableCalendars')); this.lookupReference('userCommandsButton').setHidden(Traccar.app.getPreference('limitCommands', false)); + this.lookupReference('userMaintenancesButton').setHidden( + Traccar.app.getVehicleFeaturesDisabled() || Traccar.app.getBooleanAttributePreference('ui.disableMaintenances')); }, onEditClick: function () { @@ -63,7 +66,7 @@ Ext.define('Traccar.view.edit.UsersController', { onAddClick: function () { var user, dialog; user = Ext.create('Traccar.model.User'); - if (Traccar.app.getUser().get('admin')) { + if (Traccar.app.getUser().get('administrator')) { user.set('deviceLimit', -1); } if (Traccar.app.getUser().get('expirationTime')) { @@ -209,6 +212,21 @@ Ext.define('Traccar.view.edit.UsersController', { }).show(); }, + onMaintenancesClick: function () { + var user = this.getView().getSelectionModel().getSelection()[0]; + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedMaintenances, + items: { + xtype: 'linkMaintenancesView', + baseObjectName: 'userId', + linkObjectName: 'maintenanceId', + storeName: 'AllMaintenances', + linkStoreName: 'Maintenances', + baseObject: user.getId() + } + }).show(); + }, + onSelectionChange: function (selection, selected) { var disabled = selected.length === 0; this.lookupReference('userDevicesButton').setDisabled(disabled); @@ -219,6 +237,7 @@ Ext.define('Traccar.view.edit.UsersController', { this.lookupReference('userAttributesButton').setDisabled(disabled); this.lookupReference('userDriversButton').setDisabled(disabled); this.lookupReference('userCommandsButton').setDisabled(disabled); + this.lookupReference('userMaintenancesButton').setDisabled(disabled); this.lookupReference('userUsersButton').setDisabled(disabled || selected[0].get('userLimit') === 0); this.callParent(arguments); } diff --git a/web/app/view/map/BaseMap.js b/web/app/view/map/BaseMap.js index 68173a99..07e391ff 100644 --- a/web/app/view/map/BaseMap.js +++ b/web/app/view/map/BaseMap.js @@ -130,10 +130,18 @@ Ext.define('Traccar.view.map.BaseMap', { }) }); break; - default: + case 'osm': layer = new ol.layer.Tile({ source: new ol.source.OSM({}) }); + break; + default: + layer = new ol.layer.Tile({ + source: new ol.source.OSM({ + url: 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png' + }) + }); + break; } lat = Traccar.app.getPreference('latitude', Traccar.Style.mapDefaultLat); diff --git a/web/app/view/permissions/Geofences.js b/web/app/view/permissions/Geofences.js index efdf18da..e2e85a36 100644 --- a/web/app/view/permissions/Geofences.js +++ b/web/app/view/permissions/Geofences.js @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 Anton Tananaev (anton@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 @@ -26,6 +26,18 @@ Ext.define('Traccar.view.permissions.Geofences', { flex: 1, minWidth: Traccar.Style.columnWidthNormal, filter: 'string' + }, { + text: Strings.sharedCalendar, + dataIndex: 'calendarId', + flex: 1, + minWidth: Traccar.Style.columnWidthNormal, + hidden: true, + filter: { + type: 'list', + labelField: 'name', + store: 'AllCalendars' + }, + renderer: Traccar.AttributeFormatter.getFormatter('calendarId') }] } }); diff --git a/web/app/view/permissions/Maintenances.js b/web/app/view/permissions/Maintenances.js new file mode 100644 index 00000000..c5255769 --- /dev/null +++ b/web/app/view/permissions/Maintenances.js @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 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.permissions.Maintenances', { + extend: 'Traccar.view.permissions.Base', + xtype: 'linkMaintenancesView', + + columns: { + items: [{ + text: Strings.sharedName, + dataIndex: 'name', + flex: 1, + minWidth: Traccar.Style.columnWidthNormal, + filter: 'string' + }, { + text: Strings.sharedType, + dataIndex: 'type', + flex: 1, + minWidth: Traccar.Style.columnWidthNormal, + filter: { + type: 'list', + idField: 'key', + labelField: 'name', + store: 'MaintenanceTypes' + }, + renderer: function (value) { + var attribute = Ext.getStore('MaintenanceTypes').getById(value); + return attribute && attribute.get('name') || value; + } + }, { + text: Strings.maintenanceStart, + dataIndex: 'start', + flex: 1, + minWidth: Traccar.Style.columnWidthNormal, + renderer: function (value, metaData, record) { + return Traccar.AttributeFormatter.renderAttribute( + value, Ext.getStore('MaintenanceTypes').getById(record.get('type'))); + } + }, { + text: Strings.maintenancePeriod, + dataIndex: 'period', + flex: 1, + minWidth: Traccar.Style.columnWidthNormal, + renderer: function (value, metaData, record) { + return Traccar.AttributeFormatter.renderAttribute( + value, Ext.getStore('MaintenanceTypes').getById(record.get('type'))); + } + }] + } +}); diff --git a/web/app/view/permissions/Notifications.js b/web/app/view/permissions/Notifications.js index 9386d6d6..a8570fea 100644 --- a/web/app/view/permissions/Notifications.js +++ b/web/app/view/permissions/Notifications.js @@ -1,6 +1,6 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2018 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 @@ -42,26 +42,37 @@ Ext.define('Traccar.view.permissions.Notifications', { renderer: Traccar.AttributeFormatter.getFormatter('always'), filter: 'boolean' }, { - text: Strings.notificationWeb, - dataIndex: 'web', - flex: 1, - minWidth: Traccar.Style.columnWidthNormal, - renderer: Traccar.AttributeFormatter.getFormatter('web'), - filter: 'boolean' - }, { - text: Strings.notificationMail, - dataIndex: 'mail', - flex: 1, - minWidth: Traccar.Style.columnWidthNormal, - renderer: Traccar.AttributeFormatter.getFormatter('mail'), - filter: 'boolean' + text: Strings.notificationNotificators, + dataIndex: 'notificators', + flex: 2, + filter: { + type: 'arraylist', + idField: 'type', + labelField: 'name', + store: 'AllNotificators' + }, + renderer: function (value) { + var result = '', i, notificators; + if (value) { + notificators = value.split(/[ ,]+/).filter(Boolean); + for (i = 0; i < notificators.length; i++) { + result += Traccar.app.getNotificatorString(notificators[i]) + (i < notificators.length - 1 ? ', ' : ''); + } + } + return result; + } }, { - text: Strings.notificationSms, - dataIndex: 'sms', + text: Strings.sharedCalendar, + dataIndex: 'calendarId', flex: 1, minWidth: Traccar.Style.columnWidthNormal, - renderer: Traccar.AttributeFormatter.getFormatter('sms'), - filter: 'boolean' + hidden: true, + filter: { + type: 'list', + labelField: 'name', + store: 'AllCalendars' + }, + renderer: Traccar.AttributeFormatter.getFormatter('calendarId') }] } }); |