From 35e8f4b4974515733737c5cc1dd439ca47860007 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Wed, 31 May 2017 16:55:00 +0500 Subject: Implement Events panel --- web/app/Application.js | 7 +++ web/app/AttributeFormatter.js | 22 ++++++++ web/app/controller/Root.js | 20 +------- web/app/model/Event.js | 25 ++++++++- web/app/store/Events.js | 3 +- web/app/view/Events.js | 105 ++++++++++++++++++++++++++++++++++++++ web/app/view/EventsController.js | 63 +++++++++++++++++++++++ web/app/view/Main.js | 8 +++ web/app/view/MainMobile.js | 3 ++ web/app/view/edit/Devices.js | 20 +------- web/app/view/map/Map.js | 12 +++-- web/app/view/map/MapController.js | 5 ++ web/l10n/en.json | 2 +- 13 files changed, 250 insertions(+), 45 deletions(-) create mode 100644 web/app/view/Events.js create mode 100644 web/app/view/EventsController.js (limited to 'web') diff --git a/web/app/Application.js b/web/app/Application.js index d73378c..3f09a0a 100644 --- a/web/app/Application.js +++ b/web/app/Application.js @@ -110,6 +110,13 @@ Ext.define('Traccar.Application', { } }, + showEvents: function (show) { + var rootPanel = Ext.getCmp('rootPanel'); + if (rootPanel) { + rootPanel.setActiveItem(show ? 2 : 0); + } + }, + setUser: function (data) { var reader = Ext.create('Ext.data.reader.Json', { model: 'Traccar.model.User' diff --git a/web/app/AttributeFormatter.js b/web/app/AttributeFormatter.js index 83d310c..302a894 100644 --- a/web/app/AttributeFormatter.js +++ b/web/app/AttributeFormatter.js @@ -71,6 +71,26 @@ Ext.define('Traccar.AttributeFormatter', { return Ext.getStore('Devices').getById(value).get('name'); }, + lastUpdateFormatter: function (value) { + var seconds, interval; + + if (value) { + seconds = Math.floor((new Date() - value) / 1000); + if (seconds < 0) { + seconds = 0; + } + interval = Math.floor(seconds / 86400); + if (interval > 1) { + return interval + ' ' + Strings.sharedDays; + } + interval = Math.floor(seconds / 3600); + if (interval > 1) { + return interval + ' ' + Strings.sharedHours; + } + return Math.floor(seconds / 60) + ' ' + Strings.sharedMinutes; + } + }, + defaultFormatter: function (value) { if (typeof value === 'number') { return Number(value.toFixed(Traccar.Style.numberPrecision)); @@ -104,6 +124,8 @@ Ext.define('Traccar.AttributeFormatter', { return this.durationFormatter; } else if (key === 'deviceId') { return this.deviceIdFormatter; + } else if (key === 'lastUpdate') { + return this.lastUpdateFormatter; } else { return this.defaultFormatter; } diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js index b69fb0f..8d604b6 100644 --- a/web/app/controller/Root.js +++ b/web/app/controller/Root.js @@ -215,32 +215,16 @@ Ext.define('Traccar.controller.Root', { }, updateEvents: function (array) { - var i, store, device, alarmKey, text, geofence; + var i, store, device; store = Ext.getStore('Events'); for (i = 0; i < array.length; i++) { store.add(array[i]); - if (array[i].type === 'commandResult') { - text = Strings.eventCommandResult + ': ' + array[i].attributes.result; - } else if (array[i].type === 'alarm') { - alarmKey = 'alarm' + array[i].attributes.alarm.charAt(0).toUpperCase() + array[i].attributes.alarm.slice(1); - text = Strings[alarmKey] || alarmKey; - } else if (array[i].type === 'textMessage') { - text = Strings.eventTextMessage + ': ' + array[i].attributes.message; - } else { - text = Traccar.app.getEventString(array[i].type); - } - if (array[i].geofenceId !== 0) { - geofence = Ext.getStore('Geofences').getById(array[i].geofenceId); - if (geofence) { - text += ' \"' + geofence.get('name') + '"'; - } - } device = Ext.getStore('Devices').getById(array[i].deviceId); if (device) { if (this.soundPressed()) { this.beep(); } - Ext.toast(text, device.get('name'), 'br'); + Ext.toast(array[i].text, device.get('name'), 'br'); } } }, diff --git a/web/app/model/Event.js b/web/app/model/Event.js index 7a43086..d225402 100644 --- a/web/app/model/Event.js +++ b/web/app/model/Event.js @@ -1,5 +1,6 @@ /* - * Copyright 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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 @@ -38,6 +39,28 @@ Ext.define('Traccar.model.Event', { }, { name: 'geofenceId', type: 'int' + }, { + name: 'text', + calculate: function (data) { + var text, alarmKey, geofence; + if (data.type === 'commandResult') { + text = Strings.eventCommandResult + ': ' + data.attributes.result; + } else if (data.type === 'alarm') { + alarmKey = 'alarm' + data.attributes.alarm.charAt(0).toUpperCase() + data.attributes.alarm.slice(1); + text = Strings[alarmKey] || alarmKey; + } else if (data.type === 'textMessage') { + text = Strings.eventTextMessage + ': ' + data.attributes.message; + } else { + text = Traccar.app.getEventString(data.type); + } + if (data.geofenceId !== 0) { + geofence = Ext.getStore('Geofences').getById(data.geofenceId); + if (geofence) { + text += ' \"' + geofence.get('name') + '"'; + } + } + return text; + } }, { name: 'attributes' }] diff --git a/web/app/store/Events.js b/web/app/store/Events.js index a31a41d..71192e2 100644 --- a/web/app/store/Events.js +++ b/web/app/store/Events.js @@ -1,5 +1,6 @@ /* - * Copyright 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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 diff --git a/web/app/view/Events.js b/web/app/view/Events.js new file mode 100644 index 0000000..1965690 --- /dev/null +++ b/web/app/view/Events.js @@ -0,0 +1,105 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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.Events', { + extend: 'Ext.grid.Panel', + xtype: 'eventsView', + + requires: [ + 'Traccar.view.EventsController' + ], + + controller: 'events', + + store: 'Events', + + stateful: true, + stateId: 'events-grid', + + title: Strings.reportEvents, + + sortableColumns: false, + + header: false, + + tbar: { + componentCls: 'toolbar-header-style', + defaults: { + xtype: 'button', + tooltipType: 'title', + stateEvents: ['toggle'], + enableToggle: true, + stateful: { + pressed: true + } + }, + items: [{ + xtype: 'tbtext', + html: Strings.reportEvents, + baseCls: 'x-panel-header-title-default' + }, { + xtype: 'tbfill' + }, { + glyph: 'xf063@FontAwesome', + pressed: true, + toggleHandler: 'onScrollToLastClick', + stateId: 'events-scroll-to-last-button', + tooltip: Strings.eventsScrollToLast, + reference: 'scrollToLast' + }, { + id: 'soundButton', + glyph: 'xf0a2@FontAwesome', + tooltip: Strings.sharedSound, + stateId: 'sound-button' + }, { + glyph: 'xf014@FontAwesome', + tooltip: Strings.reportClear, + handler: 'onClearClick', + stateful: false, + enableToggle: false + }, { + glyph: 'xf00d@FontAwesome', + tooltip: Strings.sharedHide, + handler: 'onHideEvents', + reference: 'hideEvents', + hidden: true, + stateful: false, + enableToggle: false + }] + }, + + columns: { + defaults: { + flex: 1, + minWidth: Traccar.Style.columnWidthNormal + }, + items: [{ + text: Strings.reportDeviceName, + dataIndex: 'deviceId', + renderer: Traccar.AttributeFormatter.getFormatter('deviceId') + }, { + flex: 2, + text: Strings.positionEvent, + dataIndex: 'text' + }, { + text: Strings.positionFixTime, + dataIndex: 'serverTime', + renderer: Traccar.AttributeFormatter.getFormatter('lastUpdate') + }] + } +}); diff --git a/web/app/view/EventsController.js b/web/app/view/EventsController.js new file mode 100644 index 0000000..5cd9fb8 --- /dev/null +++ b/web/app/view/EventsController.js @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 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.EventsController', { + extend: 'Ext.app.ViewController', + alias: 'controller.events', + + config: { + listen: { + store: { + '#Events': { + add: 'onAddEvent' + } + } + } + }, + + init: function () { + var self = this; + setInterval(function () { + self.getView().getView().refresh(); + }, Traccar.Style.refreshPeriod); + + if (Traccar.app.isMobile()) { + this.lookupReference('hideEvents').setHidden(false); + } + }, + + onClearClick: function (button) { + Ext.getStore('Events').removeAll(); + }, + + onAddEvent: function (store, data) { + if (this.lookupReference('scrollToLast').pressed) { + this.getView().scrollBy(0, Number.POSITIVE_INFINITY, true); + } + }, + + onScrollToLastClick: function (button, pressed) { + if (pressed) { + this.onAddEvent(); + } + }, + + onHideEvents: function () { + Traccar.app.showEvents(false); + } +}); diff --git a/web/app/view/Main.js b/web/app/view/Main.js index 333928a..3f7cf7c 100644 --- a/web/app/view/Main.js +++ b/web/app/view/Main.js @@ -23,6 +23,7 @@ Ext.define('Traccar.view.Main', { 'Traccar.view.edit.Devices', 'Traccar.view.State', 'Traccar.view.Report', + 'Traccar.view.Events', 'Traccar.view.map.Map' ], @@ -67,5 +68,12 @@ Ext.define('Traccar.view.Main', { region: 'center', xtype: 'mapView', collapsible: false + }, { + region: 'east', + xtype: 'eventsView', + width: Traccar.Style.deviceWidth, + collapsed: true, + titleCollapse: true, + floatable: false }] }); diff --git a/web/app/view/MainMobile.js b/web/app/view/MainMobile.js index 1f262cc..8aab771 100644 --- a/web/app/view/MainMobile.js +++ b/web/app/view/MainMobile.js @@ -25,6 +25,7 @@ Ext.define('Traccar.view.MainMobile', { 'Traccar.view.edit.Devices', 'Traccar.view.State', 'Traccar.view.Report', + 'Traccar.view.Events', 'Traccar.view.map.Map' ], @@ -66,5 +67,7 @@ Ext.define('Traccar.view.MainMobile', { }] }, { xtype: 'reportView' + }, { + xtype: 'eventsView' }] }); diff --git a/web/app/view/edit/Devices.js b/web/app/view/edit/Devices.js index fe3de42..196df73 100644 --- a/web/app/view/edit/Devices.js +++ b/web/app/view/edit/Devices.js @@ -166,25 +166,7 @@ Ext.define('Traccar.view.edit.Devices', { }, { text: Strings.deviceLastUpdate, dataIndex: 'lastUpdate', - renderer: function (value, metaData, record) { - var seconds, interval; - - if (value) { - seconds = Math.floor((new Date() - value) / 1000); - if (seconds < 0) { - seconds = 0; - } - interval = Math.floor(seconds / 86400); - if (interval > 1) { - return interval + ' ' + Strings.sharedDays; - } - interval = Math.floor(seconds / 3600); - if (interval > 1) { - return interval + ' ' + Strings.sharedHours; - } - return Math.floor(seconds / 60) + ' ' + Strings.sharedMinutes; - } - } + renderer: Traccar.AttributeFormatter.getFormatter('lastUpdate') }] } }); diff --git a/web/app/view/map/Map.js b/web/app/view/map/Map.js index d4e654e..82b76ee 100644 --- a/web/app/view/map/Map.js +++ b/web/app/view/map/Map.js @@ -51,6 +51,13 @@ Ext.define('Traccar.view.map.Map', { stateful: false, enableToggle: false, tooltip: Strings.reportTitle + }, { + handler: 'showEvents', + reference: 'showEventsButton', + glyph: 'xf27b@FontAwesome', + stateful: false, + enableToggle: false, + tooltip: Strings.reportEvents }, { handler: 'updateGeofences', reference: 'showGeofencesButton', @@ -70,11 +77,6 @@ Ext.define('Traccar.view.map.Map', { tooltip: Strings.deviceFollow, stateId: 'device-follow-button', toggleHandler: 'onFollowClick' - }, { - id: 'soundButton', - glyph: 'xf0a2@FontAwesome', - tooltip: Strings.sharedSound, - stateId: 'sound-button' }, { xtype: 'settingsMenu', enableToggle: false diff --git a/web/app/view/map/MapController.js b/web/app/view/map/MapController.js index 8a5e81c..02d4e38 100644 --- a/web/app/view/map/MapController.js +++ b/web/app/view/map/MapController.js @@ -45,12 +45,17 @@ Ext.define('Traccar.view.map.MapController', { init: function () { this.callParent(); this.lookupReference('showReportsButton').setVisible(Traccar.app.isMobile()); + this.lookupReference('showEventsButton').setVisible(Traccar.app.isMobile()); }, showReports: function () { Traccar.app.showReports(true); }, + showEvents: function () { + Traccar.app.showEvents(true); + }, + onFollowClick: function (button, pressed) { if (pressed && this.selectedMarker) { this.getView().getMapView().setCenter(this.selectedMarker.getGeometry().getCoordinates()); diff --git a/web/l10n/en.json b/web/l10n/en.json index bb19a1b..6af6e19 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -264,7 +264,7 @@ "eventIgnitionOff": "Ignition is OFF", "eventMaintenance": "Maintenance required", "eventTextMessage": "Text message received", - "alarm": "Alarm", + "eventsScrollToLast": "Scroll To Last", "alarmSos": "SOS Alarm", "alarmVibration": "Vibration Alarm", "alarmMovement": "Movement Alarm", -- cgit v1.2.3