From 001424d7ada69390fd7ebea8e585fb0408e147ac Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 3 Oct 2015 13:39:53 +1300 Subject: More clean up for web interface --- web/app/Application.js | 124 +++++++++--------- web/app/controller/Root.js | 2 +- web/app/view/BaseDialogController.js | 23 ---- web/app/view/BaseEditDialog.js | 2 +- web/app/view/BaseEditDialogController.js | 2 +- web/app/view/CommandDialog.js | 2 +- web/app/view/CommandDialogController.js | 2 +- web/app/view/DeviceController.js | 4 +- web/app/view/Login.js | 91 +++++++++++++ web/app/view/LoginController.js | 104 +++++++++++++++ web/app/view/Main.js | 4 +- web/app/view/MainMobile.js | 2 +- web/app/view/Map.js | 87 +++++++++++++ web/app/view/MapController.js | 214 +++++++++++++++++++++++++++++++ web/app/view/Register.js | 58 +++++++++ web/app/view/RegisterController.js | 40 ++++++ web/app/view/Report.js | 118 +++++++++++++++++ web/app/view/ReportController.js | 80 ++++++++++++ web/app/view/State.js | 39 ++++++ web/app/view/StateController.js | 137 ++++++++++++++++++++ web/app/view/login/Login.js | 95 -------------- web/app/view/login/LoginController.js | 105 --------------- web/app/view/login/Register.js | 64 --------- web/app/view/login/RegisterController.js | 40 ------ web/app/view/map/Map.js | 87 ------------- web/app/view/map/MapController.js | 214 ------------------------------- web/app/view/report/Report.js | 118 ----------------- web/app/view/report/ReportController.js | 79 ------------ 28 files changed, 1042 insertions(+), 895 deletions(-) delete mode 100644 web/app/view/BaseDialogController.js create mode 100644 web/app/view/Login.js create mode 100644 web/app/view/LoginController.js create mode 100644 web/app/view/Map.js create mode 100644 web/app/view/MapController.js create mode 100644 web/app/view/Register.js create mode 100644 web/app/view/RegisterController.js create mode 100644 web/app/view/Report.js create mode 100644 web/app/view/ReportController.js create mode 100644 web/app/view/State.js create mode 100644 web/app/view/StateController.js delete mode 100644 web/app/view/login/Login.js delete mode 100644 web/app/view/login/LoginController.js delete mode 100644 web/app/view/login/Register.js delete mode 100644 web/app/view/login/RegisterController.js delete mode 100644 web/app/view/map/Map.js delete mode 100644 web/app/view/map/MapController.js delete mode 100644 web/app/view/report/Report.js delete mode 100644 web/app/view/report/ReportController.js (limited to 'web') diff --git a/web/app/Application.js b/web/app/Application.js index 67dc96536..def000f04 100644 --- a/web/app/Application.js +++ b/web/app/Application.js @@ -13,67 +13,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +(function() { + "use strict"; -Ext.define('Traccar.Application', { - extend: 'Ext.app.Application', - name: 'Traccar', + Ext.define('Traccar.Application', { + extend: 'Ext.app.Application', + name: 'Traccar', - requires: [ - 'Traccar.Resources', - 'Traccar.ErrorManager', - 'Traccar.AttributeFormatter' - ], - - models: [ - 'Server', - 'User', - 'Device', - 'Position', - 'Attribute', - 'Command' - ], - - stores: [ - 'Devices', - 'Positions', - 'LatestPositions', - 'Users', - 'Attributes', - 'MapTypes', - 'DistanceUnits', - 'SpeedUnits', - 'CommandTypes', - 'TimeUnits', - 'Languages' - ], + requires: [ + 'Traccar.Resources', + 'Traccar.ErrorManager', + 'Traccar.AttributeFormatter' + ], - controllers: [ - 'Root' - ], - - setUser: function(data) { - var reader = Ext.create('Ext.data.reader.Json', { - model: 'Traccar.model.User' - }); - this.user = reader.readRecords(data).getRecords()[0]; - }, - - getUser: function() { - return this.user; - }, - - setServer: function(data) { - var reader = Ext.create('Ext.data.reader.Json', { - model: 'Traccar.model.Server' - }); - this.server = reader.readRecords(data).getRecords()[0]; - }, - - getServer: function() { - return this.server; - }, + models: [ + 'Server', + 'User', + 'Device', + 'Position', + 'Attribute', + 'Command' + ], - getPreference: function(key, defaultValue) { - return this.getUser().get(key) || this.getServer().get(key) || defaultValue; - } -}); + stores: [ + 'Devices', + 'Positions', + 'LatestPositions', + 'Users', + 'Attributes', + 'MapTypes', + 'DistanceUnits', + 'SpeedUnits', + 'CommandTypes', + 'TimeUnits', + 'Languages' + ], + + controllers: [ + 'Root' + ], + + setUser: function(data) { + var reader = Ext.create('Ext.data.reader.Json', { + model: 'Traccar.model.User' + }); + this.user = reader.readRecords(data).getRecords()[0]; + }, + + getUser: function() { + return this.user; + }, + + setServer: function(data) { + var reader = Ext.create('Ext.data.reader.Json', { + model: 'Traccar.model.Server' + }); + this.server = reader.readRecords(data).getRecords()[0]; + }, + + getServer: function() { + return this.server; + }, + + getPreference: function(key, defaultValue) { + return this.getUser().get(key) || this.getServer().get(key) || defaultValue; + } + }); + +})(); diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js index d4b3e794d..490019b1a 100644 --- a/web/app/controller/Root.js +++ b/web/app/controller/Root.js @@ -19,7 +19,7 @@ Ext.define('Traccar.controller.Root', { requires: [ 'Traccar.LoginManager', - 'Traccar.view.login.Login', + 'Traccar.view.Login', 'Traccar.view.Main', 'Traccar.view.MainMobile' ], diff --git a/web/app/view/BaseDialogController.js b/web/app/view/BaseDialogController.js deleted file mode 100644 index 4bf23d94e..000000000 --- a/web/app/view/BaseDialogController.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.BaseDialogController', { - extend: 'Ext.app.ViewController', - - onCancelClick: function(button) { - button.up('window').close(); - } -}); diff --git a/web/app/view/BaseEditDialog.js b/web/app/view/BaseEditDialog.js index df8bfda93..0788c30d2 100644 --- a/web/app/view/BaseEditDialog.js +++ b/web/app/view/BaseEditDialog.js @@ -22,6 +22,6 @@ Ext.define('Traccar.view.BaseEditDialog', { handler: 'onSaveClick' }, { text: strings.sharedCancel, - handler: 'onCancelClick' + handler: 'closeView' }] }); diff --git a/web/app/view/BaseEditDialogController.js b/web/app/view/BaseEditDialogController.js index 863a75dcb..0c45b3097 100644 --- a/web/app/view/BaseEditDialogController.js +++ b/web/app/view/BaseEditDialogController.js @@ -15,7 +15,7 @@ */ Ext.define('Traccar.view.BaseEditDialogController', { - extend: 'Traccar.view.BaseDialogController', + extend: 'Ext.app.ViewController', alias: 'controller.baseEditDialog', onSaveClick: function(button) { diff --git a/web/app/view/CommandDialog.js b/web/app/view/CommandDialog.js index 1cc96b195..5d37f3173 100644 --- a/web/app/view/CommandDialog.js +++ b/web/app/view/CommandDialog.js @@ -62,6 +62,6 @@ Ext.define('Traccar.view.CommandDialog', { handler: 'onSendClick' }, { text: strings.sharedCancel, - handler: 'onCancelClick' + handler: 'closeView' }] }); diff --git a/web/app/view/CommandDialogController.js b/web/app/view/CommandDialogController.js index 66a10bbb6..6aba4a6f1 100644 --- a/web/app/view/CommandDialogController.js +++ b/web/app/view/CommandDialogController.js @@ -15,7 +15,7 @@ */ Ext.define('Traccar.view.CommandDialogController', { - extend: 'Traccar.view.BaseDialogController', + extend: 'Ext.app.ViewController', alias: 'controller.commandDialog', onSelect: function(selected) { diff --git a/web/app/view/DeviceController.js b/web/app/view/DeviceController.js index e315d6f8d..d714d89d4 100644 --- a/web/app/view/DeviceController.js +++ b/web/app/view/DeviceController.js @@ -23,7 +23,7 @@ Ext.define('Traccar.view.DeviceController', { 'Traccar.view.DeviceDialog', 'Traccar.view.user.UserDialog', 'Traccar.view.user.User', - 'Traccar.view.login.LoginController' + 'Traccar.view.LoginController' ], config: { @@ -44,7 +44,7 @@ Ext.define('Traccar.view.DeviceController', { }, onLogoutClick: function() { - Ext.create('Traccar.view.login.LoginController').logout(); + Ext.create('Traccar.view.LoginController').logout(); }, onAddClick: function() { diff --git a/web/app/view/Login.js b/web/app/view/Login.js new file mode 100644 index 000000000..23f813c66 --- /dev/null +++ b/web/app/view/Login.js @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.Login', { + extend: 'Traccar.view.BaseDialog', + alias: 'widget.login', + + requires: [ + 'Traccar.view.LoginController' + ], + + controller: 'login', + + closable: false, + + items: { + xtype: 'form', + reference: 'form', + + autoEl: { + tag: 'form', + method: 'POST', + action: 'blank', + target: 'submitTarget' + }, + + items: [{ + xtype: 'combobox', + name: 'language', + fieldLabel: strings.loginLanguage, + store: 'Languages', + displayField: 'name', + valueField: 'code', + submitValue: false, + listeners: { + select: 'onSelectLanguage' + }, + reference: 'languageField' + }, { + xtype: 'textfield', + name: 'email', + fieldLabel: strings.userEmail, + allowBlank: false, + enableKeyEvents: true, + listeners: { + specialKey: 'onSpecialKey', + afterrender: 'onAfterRender' + }, + inputAttrTpl: ['autocomplete="on"'] + }, { + xtype: 'textfield', + name: 'password', + fieldLabel: strings.userPassword, + inputType: 'password', + allowBlank: false, + enableKeyEvents: true, + listeners: { + specialKey: 'onSpecialKey' + }, + inputAttrTpl: ['autocomplete="on"'] + }, { + xtype: 'component', + html: '' + }, { + xtype: 'component', + html: '' + }] + }, + + buttons: [{ + text: strings.loginRegister, + handler: 'onRegisterClick', + reference: 'registerButton' + }, { + text: strings.loginLogin, + handler: 'onLoginClick' + }] +}); diff --git a/web/app/view/LoginController.js b/web/app/view/LoginController.js new file mode 100644 index 000000000..f6b2fe228 --- /dev/null +++ b/web/app/view/LoginController.js @@ -0,0 +1,104 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.LoginController', { + extend: 'Ext.app.ViewController', + alias: 'controller.login', + + requires: [ + 'Traccar.view.Register' + ], + + init: function() { + this.lookupReference('registerButton').setDisabled( + !Traccar.app.getServer().get('registration')); + this.lookupReference('languageField').setValue(language); + }, + + login: function() { + var form = this.lookupReference('form'); + if (form.isValid()) { + Ext.getBody().mask(strings.sharedLoading); + Ext.Ajax.request({ + scope: this, + url: '/api/login', + params: form.getValues(), + callback: function(options, success, response) { + Ext.getBody().unmask(); + if (Traccar.ErrorManager.check(success, response)) { + var result = Ext.decode(response.responseText); + if (result.success) { + Traccar.app.setUser(result.data); + this.fireViewEvent('login'); + } else { + Traccar.ErrorManager.error(strings.loginFailed); + } + } + + } + }); + } + }, + + logout: function() { + Ext.Ajax.request({ + scope: this, + url: '/api/logout', + callback: function() { + window.location.reload(); + } + }); + }, + + onSelectLanguage: function(selected) { + var paramName = 'locale'; + var paramValue = selected.getValue(); + var url = window.location.href; + if (url.indexOf(paramName + '=') >= 0) { + var prefix = url.substring(0, url.indexOf(paramName)); + var suffix = url.substring(url.indexOf(paramName)); + suffix = suffix.substring(suffix.indexOf("=") + 1); + suffix = (suffix.indexOf('&') >= 0) ? suffix.substring(suffix.indexOf('&')) : ''; + url = prefix + paramName + "=" + paramValue + suffix; + } else { + if (url.indexOf('?') < 0) { + url += '?' + paramName + '=' + paramValue; + } else { + url += '&' + paramName + '=' + paramValue; + } + } + window.location.href = url; + }, + + onAfterRender: function(field) { + field.focus(); + }, + + onSpecialKey: function(field, e) { + if (e.getKey() === e.ENTER) { + this.login(); + } + }, + + onLoginClick: function() { + Ext.getElementById('submitButton').click(); + this.login(); + }, + + onRegisterClick: function() { + Ext.create('Traccar.view.login.Register').show(); + } +}); diff --git a/web/app/view/Main.js b/web/app/view/Main.js index 781cfad6b..ee1073e92 100644 --- a/web/app/view/Main.js +++ b/web/app/view/Main.js @@ -21,8 +21,8 @@ Ext.define('Traccar.view.Main', { requires: [ 'Traccar.view.Device', 'Traccar.view.State', - 'Traccar.view.report.Report', - 'Traccar.view.map.Map' + 'Traccar.view.Report', + 'Traccar.view.Map' ], layout: 'border', diff --git a/web/app/view/MainMobile.js b/web/app/view/MainMobile.js index 0562edb70..e42fc7f7f 100644 --- a/web/app/view/MainMobile.js +++ b/web/app/view/MainMobile.js @@ -21,7 +21,7 @@ Ext.define('Traccar.view.MainMobile', { requires: [ 'Traccar.view.Device', 'Traccar.view.State', - 'Traccar.view.map.Map' + 'Traccar.view.Map' ], layout: 'border', diff --git a/web/app/view/Map.js b/web/app/view/Map.js new file mode 100644 index 000000000..5d2fd579c --- /dev/null +++ b/web/app/view/Map.js @@ -0,0 +1,87 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.Map', { + extend: 'Ext.form.Panel', + xtype: 'mapView', + + requires: [ + 'Traccar.view.MapController' + ], + + controller: 'map', + + title: strings.mapTitle, + layout: 'fit', + + listeners: { + afterrender: function() { + + var user = Traccar.app.getUser(); + var server = Traccar.app.getServer(); + + var layer; + var mapLayer = user.get('map') || server.get('map'); + + var bingKey = server.get('bingKey'); + + if (mapLayer === 'custom') { + layer = new ol.layer.Tile({ source: new ol.source.XYZ({ + url: server.get('mapUrl') + })}); + } else if (mapLayer === 'bingRoad') { + layer = new ol.layer.Tile({ source: new ol.source.BingMaps({ + key: bingKey, + imagerySet: 'Road' + })}); + } else if (mapLayer === 'bingAerial') { + layer = new ol.layer.Tile({ source: new ol.source.BingMaps({ + key: bingKey, + imagerySet: 'Aerial' + })}); + } else { + layer = new ol.layer.Tile({ source: new ol.source.OSM({ + })}); + } + + this.vectorSource = new ol.source.Vector({}); + var vectorLayer = new ol.layer.Vector({ + source: this.vectorSource + }); + + var lat = user.get('latitude') || server.get('latitude') || styles.mapDefaultLat; + var lon = user.get('longitude') || server.get('longitude') || styles.mapDefaultLon; + var zoom = user.get('zoom') || server.get('zoom') || styles.mapDefaultZoom; + + this.mapView = new ol.View({ + center: ol.proj.fromLonLat([ lon, lat ]), + zoom: zoom, + maxZoom: styles.mapMaxZoom + }); + + this.map = new ol.Map({ + target: this.body.dom.id, + layers: [ layer, vectorLayer ], + view: this.mapView + }); + }, + + resize: function() { + this.map.updateSize(); + } + } + +}); diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js new file mode 100644 index 000000000..4979cd920 --- /dev/null +++ b/web/app/view/MapController.js @@ -0,0 +1,214 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.MapController', { + extend: 'Ext.app.ViewController', + alias: 'controller.map', + + config: { + listen: { + controller: { + '*': { + reportShow: 'reportShow', + reportClear: 'reportClear', + selectDevice: 'selectDevice', + selectReport: 'selectReport' + } + } + } + }, + + init: function() { + this.liveData = {}; + this.update(true); + }, + + update: function(first) { + Ext.Ajax.request({ + scope: this, + url: '/api/async', + params: { + first: first + }, + success: function(response) { + var data = Ext.decode(response.responseText).data; + + var i; + for (i = 0; i < data.length; i++) { + + var store = Ext.getStore('LatestPositions'); + + var found = store.query('deviceId', data[i].deviceId); + if (found.getCount() > 0) { + found.first().set(data[i]); + } else { + store.add(Ext.create('Traccar.model.Position', data[i])); + } + + var geometry = new ol.geom.Point(ol.proj.fromLonLat([ + data[i].longitude, + data[i].latitude + ])); + + if (data[i].deviceId in this.liveData) { + this.liveData[data[i].deviceId].setGeometry(geometry); + } else { + var style = this.getMarkerStyle(styles.mapLiveRadius, styles.mapLiveColor); + var marker = new ol.Feature({ + geometry: geometry, + originalStyle: style + }); + marker.setStyle(style); + this.getView().vectorSource.addFeature(marker); + this.liveData[data[i].deviceId] = marker; + } + } + + this.update(false); + }, + failure: function() { + // TODO: error + } + }); + }, + + getLineStyle: function() { + return new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: styles.mapStrokeColor, + width: styles.mapRouteWidth + }) + }); + }, + + getMarkerStyle: function(radius, color) { + /*return new ol.style.Style({ + text: new ol.style.Text({ + text: '\uf041', + font: 'normal 32px FontAwesome', + textBaseline: 'Bottom', + fill: new ol.style.Fill({ + color: color + }), + stroke: new ol.style.Stroke({ + color: 'black', + width: 2 + }) + }) + });*/ + return new ol.style.Style({ + image: new ol.style.Circle({ + radius: radius, + fill: new ol.style.Fill({ + color: color + }), + stroke: new ol.style.Stroke({ + color: styles.mapStrokeColor, + width: styles.mapMarkerStroke + }) + }) + }); + }, + + reportShow: function() { + this.reportClear(); + + var vectorSource = this.getView().vectorSource; + + var data = Ext.getStore('Positions').getData(); + + var index; + var positions = []; + this.reportRoutePoints = {}; + + for (index = 0; index < data.getCount(); index++) { + var point = ol.proj.fromLonLat([ + data.getAt(index).data.longitude, + data.getAt(index).data.latitude + ]); + positions.push(point); + + var style = this.getMarkerStyle(styles.mapReportRadius, styles.mapReportColor); + var feature = new ol.Feature({ + geometry: new ol.geom.Point(positions[index]), + originalStyle: style + }); + feature.setStyle(style); + this.reportRoutePoints[data.getAt(index).get('id')] = feature; + } + + this.reportRoute = new ol.Feature({ + geometry: new ol.geom.LineString(positions) + }); + this.reportRoute.setStyle(this.getLineStyle()); + vectorSource.addFeature(this.reportRoute); + + for (var key in this.reportRoutePoints) { + if (this.reportRoutePoints.hasOwnProperty(key)) { + vectorSource.addFeature(this.reportRoutePoints[key]); + } + } + }, + + reportClear: function() { + var index; + var vectorSource = this.getView().vectorSource; + + if (this.reportRoute !== undefined) { + vectorSource.removeFeature(this.reportRoute); + this.reportRoute = undefined; + } + + if (this.reportRoutePoints !== undefined) { + for (var key in this.reportRoutePoints) { + if (this.reportRoutePoints.hasOwnProperty(key)) { + vectorSource.removeFeature(this.reportRoutePoints[key]); + } + } + this.reportRoutePoints = {}; + } + }, + + selectPosition: function(feature) { + if (this.currentFeature !== undefined) { + this.currentFeature.setStyle(this.currentFeature.get('originalStyle')); + } + + if (feature !== undefined) { + feature.setStyle(this.getMarkerStyle(styles.mapSelectRadius, styles.mapSelectColor)); + + var pan = ol.animation.pan({ + duration: styles.mapDelay, + source: this.getView().mapView.getCenter() + }); + this.getView().map.beforeRender(pan); + this.getView().mapView.setCenter(feature.getGeometry().getCoordinates()); + } + + this.currentFeature = feature; + }, + + selectDevice: function(device) { + this.selectPosition(this.liveData[device.get('id')]); + }, + + selectReport: function(position) { + if (this.reportRoutePoints[position.get('id')] !== undefined) { + this.selectPosition(this.reportRoutePoints[position.get('id')]); + } + } + +}); diff --git a/web/app/view/Register.js b/web/app/view/Register.js new file mode 100644 index 000000000..464b7bb1f --- /dev/null +++ b/web/app/view/Register.js @@ -0,0 +1,58 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.Register', { + extend: 'Traccar.view.BaseDialog', + + requires: [ + 'Traccar.view.RegisterController' + ], + + controller: 'register', + + items: { + xtype: 'form', + reference: 'form', + jsonSubmit: true, + + items: [{ + xtype: 'textfield', + name: 'name', + fieldLabel: strings.userName, + allowBlank: false + }, { + xtype: 'textfield', + name: 'email', + fieldLabel: strings.userEmail, + vtype: 'email', + allowBlank: false + }, { + xtype: 'textfield', + name: 'password', + fieldLabel: strings.userPassword, + inputType: 'password', + allowBlank: false + }] + }, + + buttons: [{ + text: strings.sharedSave, + handler: 'onCreateClick' + }, { + text: strings.sharedCancel, + handler: 'closeView' + }] +}); diff --git a/web/app/view/RegisterController.js b/web/app/view/RegisterController.js new file mode 100644 index 000000000..b470aa343 --- /dev/null +++ b/web/app/view/RegisterController.js @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.RegisterController', { + extend: 'Ext.app.ViewController', + alias: 'controller.register', + + onCreateClick: function() { + var form = this.lookupReference('form'); + if (form.isValid()) { + Ext.Ajax.request({ + scope: this, + url: '/api/register', + jsonData: form.getValues(), + callback: this.onCreateReturn + }); + } + }, + + onCreateReturn: function(options, success, response) { + if (Traccar.ErrorManager.check(success, response)) { + this.closeView(); + Ext.toast(strings.loginCreated); + } + } + +}); diff --git a/web/app/view/Report.js b/web/app/view/Report.js new file mode 100644 index 000000000..060c9c46a --- /dev/null +++ b/web/app/view/Report.js @@ -0,0 +1,118 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.Report', { + extend: 'Ext.grid.Panel', + xtype: 'reportView', + + requires: [ + 'Traccar.view.ReportController' + ], + + controller: 'report', + store: 'Positions', + + title: strings.reportTitle, + + tbar: [{ + xtype: 'tbtext', + html: strings.reportDevice + }, { + xtype: 'combobox', + reference: 'deviceField', + store: 'Devices', + valueField: 'id', + displayField: 'name', + typeAhead: true, + queryMode: 'local' + }, '-', { + xtype: 'tbtext', + html: strings.reportFrom + }, { + xtype: 'datefield', + reference: 'fromDateField', + startDay: styles.weekStartDay, + value: new Date(new Date().getTime() - 30 * 60 * 1000) + }, { + xtype: 'timefield', + reference: 'fromTimeField', + maxWidth: styles.reportTime, + format: styles.timeFormat, + value: new Date(new Date().getTime() - 30 * 60 * 1000) + }, '-', { + xtype: 'tbtext', + html: strings.reportTo + }, { + xtype: 'datefield', + reference: 'toDateField', + startDay: styles.weekStartDay, + value: new Date() + }, { + xtype: 'timefield', + reference: 'toTimeField', + maxWidth: styles.reportTime, + format: styles.timeFormat, + value: new Date() + }, '-', { + text: strings.reportShow, + handler: 'onShowClick' + }, { + text: strings.reportClear, + handler: 'onClearClick' + }], + + listeners: { + selectionchange: 'onSelectionChange' + }, + + columns: [{ + text: strings.positionValid, + dataIndex: 'valid', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('valid') + }, { + text: strings.positionTime, + dataIndex: 'fixTime', + flex: 1, + xtype: 'datecolumn', + renderer: Traccar.AttributeFormatter.getFormatter('fixTime') + }, { + text: strings.positionLatitude, + dataIndex: 'latitude', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('latitude') + }, { + text: strings.positionLongitude, + dataIndex: 'longitude', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('latitude') + }, { + text: strings.positionAltitude, + dataIndex: 'altitude', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('altitude') + }, { + text: strings.positionSpeed, + dataIndex: 'speed', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('speed') + }, { + text: strings.positionAddress, + dataIndex: 'address', + flex: 1, + renderer: Traccar.AttributeFormatter.getFormatter('address') + }] +}); diff --git a/web/app/view/ReportController.js b/web/app/view/ReportController.js new file mode 100644 index 000000000..0b3e30f17 --- /dev/null +++ b/web/app/view/ReportController.js @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.ReportController', { + extend: 'Ext.app.ViewController', + alias: 'controller.report', + + config: { + listen: { + controller: { + '*': { + selectDevice: 'selectDevice' + } + } + } + }, + + onShowClick: function() { + var deviceId, fromDate, fromTime, from, toDate, toTime, to, store; + + deviceId = this.lookupReference('deviceField').getValue(); + + fromDate = this.lookupReference('fromDateField').getValue(); + fromTime = this.lookupReference('fromTimeField').getValue(); + + from = new Date( + fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate(), + fromTime.getHours(), fromTime.getMinutes(), fromTime.getSeconds(), fromTime.getMilliseconds()); + + toDate = this.lookupReference('toDateField').getValue(); + toTime = this.lookupReference('toTimeField').getValue(); + + to = new Date( + toDate.getFullYear(), toDate.getMonth(), toDate.getDate(), + toTime.getHours(), toTime.getMinutes(), toTime.getSeconds(), toTime.getMilliseconds()); + + store = Ext.getStore('Positions'); + store.load({ + params:{ + deviceId: deviceId, + from: from.toISOString(), + to: to.toISOString() + }, + scope: this, + callback: function() { + this.fireEvent("reportShow"); + } + }); + }, + + onClearClick: function() { + Ext.getStore('Positions').removeAll(); + this.fireEvent("reportClear"); + }, + + onSelectionChange: function(selected) { + if (selected.getCount() > 0) { + this.fireEvent("selectReport", selected.getLastSelected()); + } + }, + + selectDevice: function(device) { + if (device !== undefined) { + this.getView().getSelectionModel().deselectAll(); + } + } +}); diff --git a/web/app/view/State.js b/web/app/view/State.js new file mode 100644 index 000000000..0804234f9 --- /dev/null +++ b/web/app/view/State.js @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.State', { + extend: 'Ext.grid.Panel', + xtype: 'stateView', + + requires: [ + 'Traccar.view.StateController' + ], + + controller: 'state', + store: 'Attributes', + + title: strings.stateTitle, + + columns: [{ + text: strings.stateName, + dataIndex: 'name', + flex: 1 + }, { + text: strings.stateValue, + dataIndex: 'value', + flex: 1 + }] +}); diff --git a/web/app/view/StateController.js b/web/app/view/StateController.js new file mode 100644 index 000000000..dc2ddfb2b --- /dev/null +++ b/web/app/view/StateController.js @@ -0,0 +1,137 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.define('Traccar.view.StateController', { + extend: 'Ext.app.ViewController', + alias: 'controller.state', + + config: { + listen: { + controller: { + '*': { + selectDevice: 'selectDevice' + } + } + } + }, + + init: function() { + var store = Ext.getStore('LatestPositions'); + store.on('add', this.add, this); + store.on('update', this.update, this); + }, + + keys: { + fixTime: { + priority: 1, + name: strings.positionTime + }, + latitude: { + priority: 2, + name: strings.positionLatitude + }, + longitude: { + priority: 3, + name: strings.positionLongitude + }, + valid: { + priority: 4, + name: strings.positionValid + }, + altitude: { + priority: 5, + name: strings.positionAltitude + }, + speed: { + priority: 6, + name: strings.positionSpeed + }, + course: { + priority: 7, + name: strings.positionCourse + }, + address: { + priority: 8, + name: strings.positionAddress + }, + protocol: { + priority: 9, + name: strings.positionProtocol + } + }, + + formatValue: function(value) { + if (typeof(id) === 'number') { + return value.toFixed(2); + } else { + return value; + } + }, + + updatePosition: function(position) { + var attributes, value, unit, store, key; + store = Ext.getStore('Attributes'); + store.removeAll(); + + for (key in position.data) { + if (position.data.hasOwnProperty(key) && this.keys[key] !== undefined) { + store.add(Ext.create('Traccar.model.Attribute', { + priority: this.keys[key].priority, + name: this.keys[key].name, + value: Traccar.AttributeFormatter.getFormatter(key)(position.get(key)) + })); + } + } + + attributes = position.get('attributes'); + if (attributes instanceof Object) { + for (key in attributes) { + if (attributes.hasOwnProperty(key)) { + store.add(Ext.create('Traccar.model.Attribute', { + priority: 1024, + name: key.replace(/^./, function (match) { + return match.toUpperCase(); + }), + value: Traccar.AttributeFormatter.getFormatter(key)(attributes[key]) + })); + } + } + } + }, + + selectDevice: function(device) { + var found; + this.deviceId = device.get('id'); + found = Ext.getStore('LatestPositions').query('deviceId', this.deviceId); + if (found.getCount() > 0) { + this.updatePosition(found.first()); + } else { + Ext.getStore('Attributes').removeAll(); + } + }, + + add: function(store, data) { + if (this.deviceId === data[0].get('deviceId')) { + this.updatePosition(data[0]); + } + }, + + update: function(store, data) { + if (this.deviceId === data.get('deviceId')) { + this.updatePosition(data); + } + } +}); diff --git a/web/app/view/login/Login.js b/web/app/view/login/Login.js deleted file mode 100644 index a2d53fdf1..000000000 --- a/web/app/view/login/Login.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.login.Login', { - extend: 'Ext.window.Window', - alias: 'widget.login', - - requires: [ - 'Traccar.view.login.LoginController' - ], - - controller: 'login', - - bodyPadding: styles.panelPadding, - title: strings.loginTitle, - closable: false, - resizable: false, - - items: { - xtype: 'form', - reference: 'form', - - autoEl: { - tag: 'form', - method: 'POST', - action: 'blank', - target: 'submitTarget' - }, - - items: [{ - xtype: 'combobox', - name: 'language', - fieldLabel: strings.loginLanguage, - store: 'Languages', - displayField: 'name', - valueField: 'code', - submitValue: false, - listeners: { - select: 'onSelectLanguage' - }, - reference: 'languageField' - }, { - xtype: 'textfield', - name: 'email', - fieldLabel: strings.userEmail, - allowBlank: false, - enableKeyEvents: true, - listeners: { - specialKey: 'onSpecialKey', - afterrender: 'onAfterRender' - }, - inputAttrTpl: ['autocomplete="on"'] - }, { - xtype: 'textfield', - name: 'password', - fieldLabel: strings.userPassword, - inputType: 'password', - allowBlank: false, - enableKeyEvents: true, - listeners: { - specialKey: 'onSpecialKey' - }, - inputAttrTpl: ['autocomplete="on"'] - }, { - xtype: 'component', - html: '' - }, { - xtype: 'component', - html: '' - }] - }, - - buttons: [{ - text: strings.loginRegister, - handler: 'onRegisterClick', - reference: 'registerButton' - }, { - text: strings.loginLogin, - handler: 'onLoginClick' - }] - -}); diff --git a/web/app/view/login/LoginController.js b/web/app/view/login/LoginController.js deleted file mode 100644 index 0344f5542..000000000 --- a/web/app/view/login/LoginController.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.login.LoginController', { - extend: 'Ext.app.ViewController', - alias: 'controller.login', - - requires: [ - 'Traccar.view.login.Register' - ], - - init: function() { - this.lookupReference('registerButton').setDisabled( - !Traccar.app.getServer().get('registration')); - this.lookupReference('languageField').setValue(language); - }, - - login: function() { - var form = this.lookupReference('form'); - if (form.isValid()) { - Ext.getBody().mask(strings.sharedLoading); - Ext.Ajax.request({ - scope: this, - url: '/api/login', - params: form.getValues(), - callback: function(options, success, response) { - Ext.getBody().unmask(); - if (Traccar.ErrorManager.check(success, response)) { - var result = Ext.decode(response.responseText); - if (result.success) { - Traccar.app.setUser(result.data); - this.fireViewEvent('login'); - } else { - Traccar.ErrorManager.error(strings.loginFailed); - } - } - - } - }); - } - }, - - logout: function() { - Ext.Ajax.request({ - scope: this, - url: '/api/logout', - callback: function() { - window.location.reload(); - } - }); - }, - - onSelectLanguage: function(selected) { - var paramName = 'locale'; - var paramValue = selected.getValue(); - var url = window.location.href; - if (url.indexOf(paramName + '=') >= 0) { - var prefix = url.substring(0, url.indexOf(paramName)); - var suffix = url.substring(url.indexOf(paramName)); - suffix = suffix.substring(suffix.indexOf("=") + 1); - suffix = (suffix.indexOf('&') >= 0) ? suffix.substring(suffix.indexOf('&')) : ''; - url = prefix + paramName + "=" + paramValue + suffix; - } else { - if (url.indexOf('?') < 0) { - url += '?' + paramName + '=' + paramValue; - } else { - url += '&' + paramName + '=' + paramValue; - } - } - window.location.href = url; - }, - - onAfterRender: function(field) { - field.focus(); - }, - - onSpecialKey: function(field, e) { - if (e.getKey() === e.ENTER) { - this.login(); - } - }, - - onLoginClick: function() { - Ext.getElementById('submitButton').click(); - this.login(); - }, - - onRegisterClick: function() { - Ext.create('Traccar.view.login.Register').show(); - } - -}); diff --git a/web/app/view/login/Register.js b/web/app/view/login/Register.js deleted file mode 100644 index 91a5775a1..000000000 --- a/web/app/view/login/Register.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.login.Register', { - extend: 'Ext.window.Window', - - requires: [ - 'Traccar.view.login.RegisterController' - ], - - controller: 'register', - - bodyPadding: styles.panelPadding, - title: strings.loginRegister, - resizable: false, - modal: true, - - items: { - xtype: 'form', - reference: 'form', - jsonSubmit: true, - - items: [{ - xtype: 'textfield', - name: 'name', - fieldLabel: strings.userName, - allowBlank: false - }, { - xtype: 'textfield', - name: 'email', - fieldLabel: strings.userEmail, - vtype: 'email', - allowBlank: false - }, { - xtype: 'textfield', - name: 'password', - fieldLabel: strings.userPassword, - inputType: 'password', - allowBlank: false - }] - }, - - buttons: [{ - text: strings.sharedSave, - handler: 'onCreateClick' - }, { - text: strings.sharedCancel, - handler: 'closeView' - }] - -}); diff --git a/web/app/view/login/RegisterController.js b/web/app/view/login/RegisterController.js deleted file mode 100644 index b1957ba8f..000000000 --- a/web/app/view/login/RegisterController.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.login.RegisterController', { - extend: 'Ext.app.ViewController', - alias: 'controller.register', - - onCreateClick: function() { - var form = this.lookupReference('form'); - if (form.isValid()) { - Ext.Ajax.request({ - scope: this, - url: '/api/register', - jsonData: form.getValues(), - callback: this.onCreateReturn - }); - } - }, - - onCreateReturn: function(options, success, response) { - if (Traccar.ErrorManager.check(success, response)) { - this.closeView(); - Ext.toast(strings.loginCreated); - } - } - -}); diff --git a/web/app/view/map/Map.js b/web/app/view/map/Map.js deleted file mode 100644 index 6e8ab6fad..000000000 --- a/web/app/view/map/Map.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.map.Map', { - extend: 'Ext.form.Panel', - xtype: 'mapView', - - requires: [ - 'Traccar.view.map.MapController' - ], - - controller: 'map', - - title: strings.mapTitle, - layout: 'fit', - - listeners: { - afterrender: function() { - - var user = Traccar.app.getUser(); - var server = Traccar.app.getServer(); - - var layer; - var mapLayer = user.get('map') || server.get('map'); - - var bingKey = server.get('bingKey') || 'AseEs0DLJhLlTNoxbNXu7DGsnnH4UoWuGue7-irwKkE3fffaClwc9q_Mr6AyHY8F'; - - if (mapLayer === 'custom') { - layer = new ol.layer.Tile({ source: new ol.source.XYZ({ - url: server.get('mapUrl') - })}); - } else if (mapLayer === 'bingRoad') { - layer = new ol.layer.Tile({ source: new ol.source.BingMaps({ - key: bingKey, - imagerySet: 'Road' - })}); - } else if (mapLayer === 'bingAerial') { - layer = new ol.layer.Tile({ source: new ol.source.BingMaps({ - key: bingKey, - imagerySet: 'Aerial' - })}); - } else { - layer = new ol.layer.Tile({ source: new ol.source.OSM({ - })}); - } - - this.vectorSource = new ol.source.Vector({}); - var vectorLayer = new ol.layer.Vector({ - source: this.vectorSource - }); - - var lat = user.get('latitude') || server.get('latitude') || styles.mapDefaultLat; - var lon = user.get('longitude') || server.get('longitude') || styles.mapDefaultLon; - var zoom = user.get('zoom') || server.get('zoom') || styles.mapDefaultZoom; - - this.mapView = new ol.View({ - center: ol.proj.fromLonLat([ lon, lat ]), - zoom: zoom, - maxZoom: styles.mapMaxZoom - }); - - this.map = new ol.Map({ - target: this.body.dom.id, - layers: [ layer, vectorLayer ], - view: this.mapView - }); - }, - - resize: function() { - this.map.updateSize(); - } - } - -}); diff --git a/web/app/view/map/MapController.js b/web/app/view/map/MapController.js deleted file mode 100644 index b0d8b8f39..000000000 --- a/web/app/view/map/MapController.js +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.map.MapController', { - extend: 'Ext.app.ViewController', - alias: 'controller.map', - - config: { - listen: { - controller: { - '*': { - reportShow: 'reportShow', - reportClear: 'reportClear', - selectDevice: 'selectDevice', - selectReport: 'selectReport' - } - } - } - }, - - init: function() { - this.liveData = {}; - this.update(true); - }, - - update: function(first) { - Ext.Ajax.request({ - scope: this, - url: '/api/async', - params: { - first: first - }, - success: function(response) { - var data = Ext.decode(response.responseText).data; - - var i; - for (i = 0; i < data.length; i++) { - - var store = Ext.getStore('LatestPositions'); - - var found = store.query('deviceId', data[i].deviceId); - if (found.getCount() > 0) { - found.first().set(data[i]); - } else { - store.add(Ext.create('Traccar.model.Position', data[i])); - } - - var geometry = new ol.geom.Point(ol.proj.fromLonLat([ - data[i].longitude, - data[i].latitude - ])); - - if (data[i].deviceId in this.liveData) { - this.liveData[data[i].deviceId].setGeometry(geometry); - } else { - var style = this.getMarkerStyle(styles.mapLiveRadius, styles.mapLiveColor); - var marker = new ol.Feature({ - geometry: geometry, - originalStyle: style - }); - marker.setStyle(style); - this.getView().vectorSource.addFeature(marker); - this.liveData[data[i].deviceId] = marker; - } - } - - this.update(false); - }, - failure: function() { - // TODO: error - } - }); - }, - - getLineStyle: function() { - return new ol.style.Style({ - stroke: new ol.style.Stroke({ - color: styles.mapStrokeColor, - width: styles.mapRouteWidth - }) - }); - }, - - getMarkerStyle: function(radius, color) { - /*return new ol.style.Style({ - text: new ol.style.Text({ - text: '\uf041', - font: 'normal 32px FontAwesome', - textBaseline: 'Bottom', - fill: new ol.style.Fill({ - color: color - }), - stroke: new ol.style.Stroke({ - color: 'black', - width: 2 - }) - }) - });*/ - return new ol.style.Style({ - image: new ol.style.Circle({ - radius: radius, - fill: new ol.style.Fill({ - color: color - }), - stroke: new ol.style.Stroke({ - color: styles.mapStrokeColor, - width: styles.mapMarkerStroke - }) - }) - }); - }, - - reportShow: function() { - this.reportClear(); - - var vectorSource = this.getView().vectorSource; - - var data = Ext.getStore('Positions').getData(); - - var index; - var positions = []; - this.reportRoutePoints = {}; - - for (index = 0; index < data.getCount(); index++) { - var point = ol.proj.fromLonLat([ - data.getAt(index).data.longitude, - data.getAt(index).data.latitude - ]); - positions.push(point); - - var style = this.getMarkerStyle(styles.mapReportRadius, styles.mapReportColor); - var feature = new ol.Feature({ - geometry: new ol.geom.Point(positions[index]), - originalStyle: style - }); - feature.setStyle(style); - this.reportRoutePoints[data.getAt(index).get('id')] = feature; - } - - this.reportRoute = new ol.Feature({ - geometry: new ol.geom.LineString(positions) - }); - this.reportRoute.setStyle(this.getLineStyle()); - vectorSource.addFeature(this.reportRoute); - - for (var key in this.reportRoutePoints) { - if (this.reportRoutePoints.hasOwnProperty(key)) { - vectorSource.addFeature(this.reportRoutePoints[key]); - } - } - }, - - reportClear: function() { - var index; - var vectorSource = this.getView().vectorSource; - - if (this.reportRoute !== undefined) { - vectorSource.removeFeature(this.reportRoute); - this.reportRoute = undefined; - } - - if (this.reportRoutePoints !== undefined) { - for (var key in this.reportRoutePoints) { - if (this.reportRoutePoints.hasOwnProperty(key)) { - vectorSource.removeFeature(this.reportRoutePoints[key]); - } - } - this.reportRoutePoints = {}; - } - }, - - selectPosition: function(feature) { - if (this.currentFeature !== undefined) { - this.currentFeature.setStyle(this.currentFeature.get('originalStyle')); - } - - if (feature !== undefined) { - feature.setStyle(this.getMarkerStyle(styles.mapSelectRadius, styles.mapSelectColor)); - - var pan = ol.animation.pan({ - duration: styles.mapDelay, - source: this.getView().mapView.getCenter() - }); - this.getView().map.beforeRender(pan); - this.getView().mapView.setCenter(feature.getGeometry().getCoordinates()); - } - - this.currentFeature = feature; - }, - - selectDevice: function(device) { - this.selectPosition(this.liveData[device.get('id')]); - }, - - selectReport: function(position) { - if (this.reportRoutePoints[position.get('id')] !== undefined) { - this.selectPosition(this.reportRoutePoints[position.get('id')]); - } - } - -}); diff --git a/web/app/view/report/Report.js b/web/app/view/report/Report.js deleted file mode 100644 index 720de698f..000000000 --- a/web/app/view/report/Report.js +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.report.Report', { - extend: 'Ext.grid.Panel', - xtype: 'reportView', - - requires: [ - 'Traccar.view.report.ReportController' - ], - - controller: 'report', - store: 'Positions', - - title: strings.reportTitle, - - tbar: [{ - xtype: 'tbtext', - html: strings.reportDevice - }, { - xtype: 'combobox', - reference: 'deviceField', - store: 'Devices', - valueField: 'id', - displayField: 'name', - typeAhead: true, - queryMode: 'local' - }, '-', { - xtype: 'tbtext', - html: strings.reportFrom - }, { - xtype: 'datefield', - reference: 'fromDateField', - startDay: styles.weekStartDay, - value: new Date(new Date().getTime() - 30 * 60 * 1000) - }, { - xtype: 'timefield', - reference: 'fromTimeField', - maxWidth: styles.reportTime, - format: styles.timeFormat, - value: new Date(new Date().getTime() - 30 * 60 * 1000) - }, '-', { - xtype: 'tbtext', - html: strings.reportTo - }, { - xtype: 'datefield', - reference: 'toDateField', - startDay: styles.weekStartDay, - value: new Date() - }, { - xtype: 'timefield', - reference: 'toTimeField', - maxWidth: styles.reportTime, - format: styles.timeFormat, - value: new Date() - }, '-', { - text: strings.reportShow, - handler: 'onShowClick' - }, { - text: strings.reportClear, - handler: 'onClearClick' - }], - - listeners: { - selectionchange: 'onSelectionChange' - }, - - columns: [{ - text: strings.positionValid, - dataIndex: 'valid', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('valid') - }, { - text: strings.positionTime, - dataIndex: 'fixTime', - flex: 1, - xtype: 'datecolumn', - renderer: Traccar.AttributeFormatter.getFormatter('fixTime') - }, { - text: strings.positionLatitude, - dataIndex: 'latitude', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('latitude') - }, { - text: strings.positionLongitude, - dataIndex: 'longitude', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('latitude') - }, { - text: strings.positionAltitude, - dataIndex: 'altitude', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('altitude') - }, { - text: strings.positionSpeed, - dataIndex: 'speed', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('speed') - }, { - text: strings.positionAddress, - dataIndex: 'address', - flex: 1, - renderer: Traccar.AttributeFormatter.getFormatter('address') - }] -}); diff --git a/web/app/view/report/ReportController.js b/web/app/view/report/ReportController.js deleted file mode 100644 index 64c89867d..000000000 --- a/web/app/view/report/ReportController.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ext.define('Traccar.view.report.ReportController', { - extend: 'Ext.app.ViewController', - alias: 'controller.report', - - config: { - listen: { - controller: { - '*': { - selectDevice: 'selectDevice' - } - } - } - }, - - onShowClick: function() { - var deviceId = this.lookupReference('deviceField').getValue(); - - var fromDate = this.lookupReference('fromDateField').getValue(); - var fromTime = this.lookupReference('fromTimeField').getValue(); - - var from = new Date( - fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate(), - fromTime.getHours(), fromTime.getMinutes(), fromTime.getSeconds(), fromTime.getMilliseconds()); - - var toDate = this.lookupReference('toDateField').getValue(); - var toTime = this.lookupReference('toTimeField').getValue(); - - var to = new Date( - toDate.getFullYear(), toDate.getMonth(), toDate.getDate(), - toTime.getHours(), toTime.getMinutes(), toTime.getSeconds(), toTime.getMilliseconds()); - - var store = Ext.getStore('Positions'); - store.load({ - params:{ - deviceId: deviceId, - from: from.toISOString(), - to: to.toISOString() - }, - scope: this, - callback: function() { - this.fireEvent("reportShow"); - } - }); - }, - - onClearClick: function() { - Ext.getStore('Positions').removeAll(); - this.fireEvent("reportClear"); - }, - - onSelectionChange: function(selected) { - if (selected.getCount() > 0) { - this.fireEvent("selectReport", selected.getLastSelected()); - } - }, - - selectDevice: function(device) { - if (device !== undefined) { - this.getView().getSelectionModel().deselectAll(); - } - } - -}); -- cgit v1.2.3