From 19a9155d988dcee7698a65a45b0558aa0ff279d4 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Wed, 11 Apr 2018 14:31:42 +0500 Subject: Implement Maintenances --- web/app/Application.js | 8 ++- web/app/AttributeFormatter.js | 25 +++++++++ web/app/controller/Root.js | 6 ++- web/app/model/Event.js | 17 ++++-- web/app/model/Maintenance.js | 41 +++++++++++++++ web/app/store/AllMaintenances.js | 30 +++++++++++ web/app/store/CommonDeviceAttributes.js | 10 ---- web/app/store/CommonUserAttributes.js | 4 ++ web/app/store/MaintenanceTypes.js | 23 +++++++++ web/app/store/Maintenances.js | 30 +++++++++++ web/app/view/CustomNumberField.js | 10 ++-- web/app/view/DeviceMenu.js | 9 +++- web/app/view/DeviceMenuController.js | 20 +++++++- web/app/view/ReportController.js | 4 ++ web/app/view/SettingsMenu.js | 8 ++- web/app/view/SettingsMenuController.js | 14 ++++- web/app/view/dialog/AttributeController.js | 5 +- web/app/view/dialog/BaseEdit.js | 1 + web/app/view/dialog/Maintenance.js | 74 ++++++++++++++++++++++++++ web/app/view/dialog/MaintenanceController.js | 70 +++++++++++++++++++++++++ web/app/view/edit/Attributes.js | 8 +-- web/app/view/edit/Groups.js | 10 +++- web/app/view/edit/GroupsController.js | 18 +++++++ web/app/view/edit/Maintenances.js | 77 ++++++++++++++++++++++++++++ web/app/view/edit/MaintenancesController.js | 31 +++++++++++ web/app/view/edit/Users.js | 12 ++++- web/app/view/edit/UsersController.js | 19 +++++++ web/app/view/permissions/Maintenances.js | 65 +++++++++++++++++++++++ web/l10n/en.json | 9 ++-- 29 files changed, 615 insertions(+), 43 deletions(-) create mode 100644 web/app/model/Maintenance.js create mode 100644 web/app/store/AllMaintenances.js create mode 100644 web/app/store/MaintenanceTypes.js create mode 100644 web/app/store/Maintenances.js create mode 100644 web/app/view/dialog/Maintenance.js create mode 100644 web/app/view/dialog/MaintenanceController.js create mode 100644 web/app/view/edit/Maintenances.js create mode 100644 web/app/view/edit/MaintenancesController.js create mode 100644 web/app/view/permissions/Maintenances.js diff --git a/web/app/Application.js b/web/app/Application.js index 6338506c..b1d638d3 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,10 @@ Ext.define('Traccar.Application', { 'Commands', 'AllCommands', 'DeviceCommands', - 'AllNotificationTypes' + 'AllNotificationTypes', + 'Maintenances', + 'AllMaintenances', + 'MaintenanceTypes' ], controllers: [ diff --git a/web/app/AttributeFormatter.js b/web/app/AttributeFormatter.js index 4de8d9e0..bb992c28 100644 --- a/web/app/AttributeFormatter.js +++ b/web/app/AttributeFormatter.js @@ -123,6 +123,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) { @@ -187,6 +200,8 @@ Ext.define('Traccar.AttributeFormatter', { return this.groupIdFormatter; case 'geofenceId': return this.geofenceIdFormatter; + case 'maintenanceId': + return this.maintenanceIdFormatter; case 'calendarId': return this.calendarIdFormatter; case 'lastUpdate': @@ -258,5 +273,15 @@ Ext.define('Traccar.AttributeFormatter', { 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 { + return value; + } } }); diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js index 75c4531c..312fc157 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(); 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 @@ -39,10 +39,13 @@ 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/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 . + */ + +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/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 . + */ + +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/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 @@ -62,6 +62,10 @@ Ext.define('Traccar.store.CommonUserAttributes', { key: 'ui.disableCalendars', name: Strings.attributeUiDisableCalendars, valueType: 'boolean' + }, { + key: 'ui.disableMaintenances', + name: Strings.attributeUiDisableMaintenances, + valueType: 'boolean' }, { key: 'ui.hidePositionAttributes', name: Strings.attributeUiHidePositionAttributes, diff --git a/web/app/store/MaintenanceTypes.js b/web/app/store/MaintenanceTypes.js new file mode 100644 index 00000000..45b89a28 --- /dev/null +++ b/web/app/store/MaintenanceTypes.js @@ -0,0 +1,23 @@ +/* + * 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 . + */ + +Ext.define('Traccar.store.MaintenanceTypes', { + extend: 'Ext.data.Store', + model: 'Traccar.model.KnownAttribute', + proxy: 'memory' +}); 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 . + */ + +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/view/CustomNumberField.js b/web/app/view/CustomNumberField.js index 807bad4d..3226d56f 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 @@ -78,16 +78,16 @@ Ext.define('Traccar.view.CustomNumberField', { config.afterBodyEl = this.unitEl + unitName + ''; 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 @@ -56,6 +56,11 @@ Ext.define('Traccar.view.DeviceMenu', { glyph: 'xf093@FontAwesome', handler: 'onCommandsClick', reference: 'menuCommandsButton' + }, { + text: Strings.sharedMaintenances, + glyph: 'xf0ad@FontAwesome', + handler: 'onMaintenancesClick', + reference: 'menuMaintenancesButton' }, { hidden: true, text: Strings.sharedDeviceDistance, diff --git a/web/app/view/DeviceMenuController.js b/web/app/view/DeviceMenuController.js index 6416314a..e50b0e0c 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' ], @@ -37,6 +38,8 @@ Ext.define('Traccar.view.DeviceMenuController', { 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()); + 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 42e099da..62a8a924 100644 --- a/web/app/view/ReportController.js +++ b/web/app/view/ReportController.js @@ -510,6 +510,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..100c86a4 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 @@ -96,6 +96,12 @@ Ext.define('Traccar.view.SettingsMenu', { glyph: 'xf093@FontAwesome', handler: 'onCommandsClick', reference: 'settingsCommandsButton' + }, { + hidden: true, + text: Strings.sharedMaintenances, + glyph: 'xf0ad@FontAwesome', + handler: 'onMaintenancesClick', + reference: 'settingsMaintenancesButton' }, { text: Strings.loginLogout, glyph: 'xf08b@FontAwesome', diff --git a/web/app/view/SettingsMenuController.js b/web/app/view/SettingsMenuController.js index e8893e3f..56d9cf89 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,6 +33,7 @@ Ext.define('Traccar.view.SettingsMenuController', { 'Traccar.view.dialog.DeviceDistance', 'Traccar.view.edit.Calendars', 'Traccar.view.edit.SavedCommands', + 'Traccar.view.edit.Maintenances', 'Traccar.view.BaseWindow' ], @@ -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/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/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/Maintenance.js b/web/app/view/dialog/Maintenance.js new file mode 100644 index 00000000..e4be7b5b --- /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 . + */ + +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 : 'Can\'t be zero'; + } + }] + }] + } +}); diff --git a/web/app/view/dialog/MaintenanceController.js b/web/app/view/dialog/MaintenanceController.js new file mode 100644 index 00000000..9efcec1f --- /dev/null +++ b/web/app/view/dialog/MaintenanceController.js @@ -0,0 +1,70 @@ +/* + * 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 . + */ + +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); + }, + + onNameChange: function (combobox, newValue) { + var attribute, startField, periodField, 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'); + } + startField = this.lookupReference('startField'); + if (startField.dataType !== config.dataType) { + this.getView().down('fieldset').insert(this.getView().down('fieldset').items.indexOf(startField), + Ext.merge({}, this.startConfig, config)); + this.getView().down('fieldset').remove(startField); + this.lookupReference('startField').validate(); + } else { + startField.setConfig(config); + startField.validate(); + } + + periodField = this.lookupReference('periodField'); + if (periodField.dataType !== config.dataType) { + this.getView().down('fieldset').insert(this.getView().down('fieldset').items.indexOf(periodField), + Ext.merge({}, this.periodConfig, config)); + this.getView().down('fieldset').remove(periodField); + this.lookupReference('periodField').validate(); + } else { + periodField.setConfig(config); + periodField.validate(); + } + } +}); diff --git a/web/app/view/edit/Attributes.js b/web/app/view/edit/Attributes.js index cb07eda1..cb0503de 100644 --- a/web/app/view/edit/Attributes.js +++ b/web/app/view/edit/Attributes.js @@ -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/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..f7b47620 --- /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 . + */ + +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') ? 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 . + */ + +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/Users.js b/web/app/view/edit/Users.js index b0a67ffd..3629e825 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' }] }, diff --git a/web/app/view/edit/UsersController.js b/web/app/view/edit/UsersController.js index db82b4f4..f3154b1a 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' ], @@ -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 () { @@ -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/permissions/Maintenances.js b/web/app/view/permissions/Maintenances.js new file mode 100644 index 00000000..7b5e3fb7 --- /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 . + */ + +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') ? 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/l10n/en.json b/web/l10n/en.json index 1ebccbd3..9b9a4996 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -75,10 +75,10 @@ "sharedNew": "New…", "sharedShowAddress": "Show Address", "sharedDisabled": "Disabled", + "sharedMaintenance": "Maintenance", + "sharedMaintenances": "Maintenances", "attributeSpeedLimit": "Speed Limit", "attributeReportIgnoreOdometer": "Report: Ignore Odometer", - "attributeMaintenanceStart": "Maintenance: Start", - "attributeMaintenanceInterval": "Maintenance: Interval", "attributeWebReportColor": "Web: Report Color", "attributeDevicePassword": "Device Password", "attributeProcessingCopyAttributes": "Processing: Copy Attributes", @@ -103,6 +103,7 @@ "attributeUiDisableDrivers": "UI: Disable Drivers", "attributeUiDisableComputedAttributes": "UI: Disable Computed Attributes", "attributeUiDisableCalendars": "UI: Disable Calendars", + "attributeUiDisableMaintenances": "UI: Disable Maintenances", "attributeUiHidePositionAttributes": "UI: Hide Position Attributes", "errorTitle": "Error", "errorGeneral": "Invalid parameters or constraints violation", @@ -409,5 +410,7 @@ "categoryShip": "Ship", "categoryTractor": "Tractor", "categoryTruck": "Truck", - "categoryVan": "Van" + "categoryVan": "Van", + "maintenanceStart": "Start", + "maintenancePeriod": "Period" } \ No newline at end of file -- cgit v1.2.3