diff options
Diffstat (limited to 'web/app/view')
-rw-r--r-- | web/app/view/DevicesController.js | 7 | ||||
-rw-r--r-- | web/app/view/Login.js | 5 | ||||
-rw-r--r-- | web/app/view/LoginController.js | 12 | ||||
-rw-r--r-- | web/app/view/Map.js | 41 | ||||
-rw-r--r-- | web/app/view/MapController.js | 291 | ||||
-rw-r--r-- | web/app/view/Register.js | 2 | ||||
-rw-r--r-- | web/app/view/Report.js | 4 | ||||
-rw-r--r-- | web/app/view/ReportController.js | 16 | ||||
-rw-r--r-- | web/app/view/StateController.js | 98 | ||||
-rw-r--r-- | web/app/view/UserDevicesController.js | 12 | ||||
-rw-r--r-- | web/app/view/UsersController.js | 2 |
11 files changed, 265 insertions, 225 deletions
diff --git a/web/app/view/DevicesController.js b/web/app/view/DevicesController.js index dd3ca5a05..c29854d12 100644 --- a/web/app/view/DevicesController.js +++ b/web/app/view/DevicesController.js @@ -27,6 +27,7 @@ Ext.define('Traccar.view.DevicesController', { listen: { controller: { '*': { + selectDevice: 'selectDevice', selectReport: 'selectReport' } } @@ -87,10 +88,14 @@ Ext.define('Traccar.view.DevicesController', { this.lookupReference('toolbarRemoveButton').setDisabled(empty); this.lookupReference('deviceCommandButton').setDisabled(empty); if (!empty) { - this.fireEvent('selectDevice', selected.getLastSelected()); + this.fireEvent('selectDevice', selected.getLastSelected(), true); } }, + selectDevice: function (device, center) { + this.getView().getSelectionModel().select([device], false, true); + }, + selectReport: function (position) { if (position !== undefined) { this.getView().getSelectionModel().deselectAll(); diff --git a/web/app/view/Login.js b/web/app/view/Login.js index a4a68843d..14a3fa41f 100644 --- a/web/app/view/Login.js +++ b/web/app/view/Login.js @@ -24,6 +24,7 @@ Ext.define('Traccar.view.Login', { controller: 'login', + title: Strings.loginTitle, closable: false, modal: false, @@ -33,8 +34,8 @@ Ext.define('Traccar.view.Login', { autoEl: { tag: 'form', - method: 'POST', - action: 'blank', + method: 'GET', + action: 'favicon.ico', target: 'submitTarget' }, diff --git a/web/app/view/LoginController.js b/web/app/view/LoginController.js index e0dbcce88..0b2090ffb 100644 --- a/web/app/view/LoginController.js +++ b/web/app/view/LoginController.js @@ -48,7 +48,6 @@ Ext.define('Traccar.view.LoginController', { Traccar.ErrorManager.error(Strings.loginFailed); } } - } }); } @@ -65,12 +64,13 @@ Ext.define('Traccar.view.LoginController', { }, onSelectLanguage: function (selected) { - var paramName = 'locale'; - var paramValue = selected.getValue(); - var url = window.location.href; + var paramName, paramValue, url, prefix, suffix; + paramName = 'locale'; + paramValue = selected.getValue(); + url = window.location.href; if (url.indexOf(paramName + '=') >= 0) { - var prefix = url.substring(0, url.indexOf(paramName)); - var suffix = url.substring(url.indexOf(paramName)); + prefix = url.substring(0, url.indexOf(paramName)); + 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; diff --git a/web/app/view/Map.js b/web/app/view/Map.js index 9a032e79f..7d81699a3 100644 --- a/web/app/view/Map.js +++ b/web/app/view/Map.js @@ -27,9 +27,21 @@ Ext.define('Traccar.view.Map', { title: Strings.mapTitle, layout: 'fit', + getMap: function () { + return this.map; + }, + + getMapView: function () { + return this.mapView; + }, + + getVectorSource: function () { + return this.vectorSource; + }, + listeners: { afterrender: function () { - var user, server, layer, type, bingKey, vectorLayer, lat, lon, zoom; + var user, server, layer, type, bingKey, vectorLayer, lat, lon, zoom, target; user = Traccar.app.getUser(); server = Traccar.app.getServer(); @@ -40,7 +52,10 @@ Ext.define('Traccar.view.Map', { if (type === 'custom') { layer = new ol.layer.Tile({ source: new ol.source.XYZ({ - url: server.get('mapUrl') + url: server.get('mapUrl'), + attributions: [new ol.Attribution({ + html: '' + })] }) }); } else if (type === 'bingRoad') { @@ -83,6 +98,28 @@ Ext.define('Traccar.view.Map', { layers: [layer, vectorLayer], view: this.mapView }); + + target = this.map.getTarget(); + if (typeof target === 'string') { + target = Ext.get(target).dom; + } + + this.map.on('pointermove', function (e) { + var hit = this.forEachFeatureAtPixel(e.pixel, function (feature, layer) { + return true; + }); + if (hit) { + target.style.cursor = 'pointer'; + } else { + target.style.cursor = ''; + } + }); + + this.map.on('click', function (e) { + this.map.forEachFeatureAtPixel(e.pixel, function (feature, layer) { + this.fireEvent('selectFeature', feature); + }, this); + }, this); }, resize: function () { diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js index b53e46671..c153ebd45 100644 --- a/web/app/view/MapController.js +++ b/web/app/view/MapController.js @@ -22,197 +22,214 @@ Ext.define('Traccar.view.MapController', { listen: { controller: { '*': { - reportShow: 'reportShow', - reportClear: 'reportClear', selectDevice: 'selectDevice', selectReport: 'selectReport' } + }, + store: { + '#LatestPositions': { + add: 'updateLatest', + update: 'updateLatest' + }, + '#Positions': { + load: 'loadReport', + clear: 'clearReport' + } + }, + component: { + '#': { + selectFeature: 'selectFeature' + } } } }, init: function () { - this.liveData = {}; - this.update(true); + this.latestMarkers = {}; + this.reportMarkers = {}; }, - 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 deviceStore = Ext.getStore('Devices'); - - 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 name = deviceStore.query('id', data[i].deviceId).first().get('name'); - - var style = this.getMarkerStyle(Traccar.Style.mapLiveRadius, Traccar.Style.mapLiveColor, data[i].course, name); - var marker = new ol.Feature({ - geometry: geometry, - originalStyle: style - }); - marker.setStyle(style); - this.getView().vectorSource.addFeature(marker); - this.liveData[data[i].deviceId] = marker; - } - } + updateLatest: function (store, data) { + var i, position, geometry, device, deviceId, marker, style; - this.update(false); - }, - failure: function () { - // TODO: error + if (!Ext.isArray(data)) { + data = [data]; + } + + for (i = 0; i < data.length; i++) { + position = data[i]; + deviceId = position.get('deviceId'); + device = Ext.getStore('Devices').findRecord('id', deviceId, 0, false, false, true); + + geometry = new ol.geom.Point(ol.proj.fromLonLat([ + position.get('longitude'), + position.get('latitude') + ])); + + if (deviceId in this.latestMarkers) { + marker = this.latestMarkers[deviceId]; + marker.setGeometry(geometry); + } else { + marker = new ol.Feature(geometry); + marker.set('record', device); + this.latestMarkers[deviceId] = marker; + this.getView().getVectorSource().addFeature(marker); + + style = this.getLatestMarker(); + style.getText().setText(device.get('name')); + marker.setStyle(style); } + + marker.getStyle().getImage().setRotation(position.get('course') * Math.PI / 180); + } + }, + + loadReport: function (store, data) { + var i, position, point, geometry, marker, style; + + this.clearReport(store); + + this.reportRoute = new ol.Feature({ + geometry: new ol.geom.LineString([]) }); + this.reportRoute.setStyle(this.getRouteStyle()); + this.getView().getVectorSource().addFeature(this.reportRoute); + + for (i = 0; i < data.length; i++) { + position = data[i]; + + point = ol.proj.fromLonLat([ + position.get('longitude'), + position.get('latitude') + ]); + geometry = new ol.geom.Point(point); + + marker = new ol.Feature(geometry); + marker.set('record', position); + this.reportMarkers[position.get('id')] = marker; + this.getView().getVectorSource().addFeature(marker); + + style = this.getReportMarker(); + style.getImage().setRotation(position.get('course') * Math.PI / 180); + style.getText().setText( + Ext.Date.format(position.get('fixTime'), Traccar.Style.dateTimeFormat)); + + marker.setStyle(style); + + this.reportRoute.getGeometry().appendCoordinate(point); + } }, - getLineStyle: function () { + clearReport: function (store) { + var vectorSource, key; + vectorSource = this.getView().getVectorSource(); + + if (this.reportRoute) { + vectorSource.removeFeature(this.reportRoute); + this.reportRoute = null; + } + + if (this.reportMarkers) { + for (key in this.reportMarkers) { + if (this.reportMarkers.hasOwnProperty(key)) { + vectorSource.removeFeature(this.reportMarkers[key]); + } + } + this.reportMarkers = {}; + } + }, + + getRouteStyle: function () { return new ol.style.Style({ stroke: new ol.style.Stroke({ - color: Traccar.Style.mapStrokeColor, + color: Traccar.Style.mapRouteColor, width: Traccar.Style.mapRouteWidth }) }); }, - getMarkerStyle: function (radius, color, rotation, text) { + getMarkerStyle: function (radius, color) { return new ol.style.Style({ - image: new ol.style.RegularShape({ - points: 3, + image: new ol.style.Arrow({ radius: radius, fill: new ol.style.Fill({ color: color }), stroke: new ol.style.Stroke({ - color: Traccar.Style.mapStrokeColor, - width: Traccar.Style.mapMarkerStroke - }), - rotation: rotation * Math.PI / 180 + color: Traccar.Style.mapArrowStrokeColor, + width: Traccar.Style.mapArrowStrokeWidth + }) }), text: new ol.style.Text({ textBaseline: 'bottom', - text: text, fill: new ol.style.Fill({ - color: '#000' + color: Traccar.Style.mapTextColor }), stroke: new ol.style.Stroke({ - color: '#FFF', - width: 2 + color: Traccar.Style.mapTextStrokeColor, + width: Traccar.Style.mapTextStrokeWidth }), - offsetY: -12, - font : 'bold 12px sans-serif' + offsetY: -radius / 2 - Traccar.Style.mapTextOffset, + font : Traccar.Style.mapTextFont }) }); }, - reportShow: function () { - this.reportClear(); - - var vectorSource = this.getView().vectorSource; - - var data = Ext.getStore('Positions').getData(); - - var index; - var positions = []; - this.reportRoutePoints = {}; + getLatestMarker: function () { + return this.getMarkerStyle( + Traccar.Style.mapRadiusNormal, Traccar.Style.mapColorUnknown); + }, - 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(Traccar.Style.mapReportRadius, Traccar.Style.mapReportColor, data.getAt(index).data.course); - 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; - } + getReportMarker: function () { + return this.getMarkerStyle( + Traccar.Style.mapRadiusNormal, Traccar.Style.mapColorReport); + }, - this.reportRoute = new ol.Feature({ - geometry: new ol.geom.LineString(positions) + resizeMarker: function (style, radius) { + return new ol.style.Style({ + image: new ol.style.Arrow({ + radius: radius, + fill: style.getImage().getFill(), + stroke: style.getImage().getStroke(), + rotation: style.getImage().getRotation() + }), + text: style.getText() }); - 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 vectorSource = this.getView().vectorSource; - - if (this.reportRoute !== undefined) { - vectorSource.removeFeature(this.reportRoute); - this.reportRoute = undefined; + selectMarker: function (marker, center) { + if (this.selectedMarker) { + this.selectedMarker.setStyle( + this.resizeMarker(this.selectedMarker.getStyle(), Traccar.Style.mapRadiusNormal)); } - if (this.reportRoutePoints !== undefined) { - for (var key in this.reportRoutePoints) { - if (this.reportRoutePoints.hasOwnProperty(key)) { - vectorSource.removeFeature(this.reportRoutePoints[key]); - } + if (marker) { + marker.setStyle( + this.resizeMarker(marker.getStyle(), Traccar.Style.mapRadiusSelected)); + if (center) { + this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); } - this.reportRoutePoints = {}; - } - }, - - selectPosition: function (feature) { - if (this.currentFeature !== undefined) { - this.currentFeature.setStyle(this.currentFeature.get('originalStyle')); } - if (feature !== undefined) { - var name = feature.getStyle().getText().getText(); - feature.setStyle(this.getMarkerStyle(Traccar.Style.mapSelectRadius, Traccar.Style.mapSelectColor, 0, name)); - - var pan = ol.animation.pan({ - duration: Traccar.Style.mapDelay, - source: this.getView().mapView.getCenter() - }); - this.getView().map.beforeRender(pan); - this.getView().mapView.setCenter(feature.getGeometry().getCoordinates()); - } + this.selectedMarker = marker; + }, - this.currentFeature = feature; + selectDevice: function (device, center) { + this.selectMarker(this.latestMarkers[device.get('id')], center); }, - selectDevice: function (device) { - this.selectPosition(this.liveData[device.get('id')]); + selectReport: function (position, center) { + this.selectMarker(this.reportMarkers[position.get('id')], center); }, - selectReport: function (position) { - if (this.reportRoutePoints[position.get('id')] !== undefined) { - this.selectPosition(this.reportRoutePoints[position.get('id')]); + selectFeature: function (feature) { + var record = feature.get('record'); + if (record) { + if (record instanceof Traccar.model.Device) { + this.fireEvent('selectDevice', record, false); + } else { + this.fireEvent('selectReport', record, false); + } } } - }); diff --git a/web/app/view/Register.js b/web/app/view/Register.js index 445f335f9..7c2881d62 100644 --- a/web/app/view/Register.js +++ b/web/app/view/Register.js @@ -23,6 +23,8 @@ Ext.define('Traccar.view.Register', { controller: 'register', + title: Strings.loginRegister, + items: { xtype: 'form', reference: 'form', diff --git a/web/app/view/Report.js b/web/app/view/Report.js index 6f2359253..91ccba917 100644 --- a/web/app/view/Report.js +++ b/web/app/view/Report.js @@ -45,6 +45,7 @@ Ext.define('Traccar.view.Report', { xtype: 'datefield', reference: 'fromDateField', startDay: Traccar.Style.weekStartDay, + format: Traccar.Style.dateFormat, value: new Date(new Date().getTime() - 30 * 60 * 1000) }, { xtype: 'timefield', @@ -59,6 +60,7 @@ Ext.define('Traccar.view.Report', { xtype: 'datefield', reference: 'toDateField', startDay: Traccar.Style.weekStartDay, + format: Traccar.Style.dateFormat, value: new Date() }, { xtype: 'timefield', @@ -84,7 +86,7 @@ Ext.define('Traccar.view.Report', { flex: 1, renderer: Traccar.AttributeFormatter.getFormatter('valid') }, { - text: Strings.positionTime, + text: Strings.positionFixTime, dataIndex: 'fixTime', flex: 1, xtype: 'datecolumn', diff --git a/web/app/view/ReportController.js b/web/app/view/ReportController.js index 2badfea63..9c2abcc71 100644 --- a/web/app/view/ReportController.js +++ b/web/app/view/ReportController.js @@ -22,7 +22,8 @@ Ext.define('Traccar.view.ReportController', { listen: { controller: { '*': { - selectDevice: 'selectDevice' + selectDevice: 'selectDevice', + selectReport: 'selectReport' } } } @@ -53,28 +54,27 @@ Ext.define('Traccar.view.ReportController', { 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()); + this.fireEvent('selectReport', selected.getLastSelected(), true); } }, selectDevice: function (device) { - if (device !== undefined) { + if (device) { this.getView().getSelectionModel().deselectAll(); } + }, + + selectReport: function (position, center) { + this.getView().getSelectionModel().select([position], false, true); } }); diff --git a/web/app/view/StateController.js b/web/app/view/StateController.js index 29f6a7c6d..01df6645d 100644 --- a/web/app/view/StateController.js +++ b/web/app/view/StateController.js @@ -25,58 +25,49 @@ Ext.define('Traccar.view.StateController', { selectDevice: 'selectDevice', selectReport: 'selectReport' } + }, + store: { + '#LatestPositions': { + add: 'updateLatest', + update: 'updateLatest' + }, + '#Positions': { + clear: 'clearReport' + } } } }, - init: function () { - var store = Ext.getStore('LatestPositions'); - store.on('add', this.add, this); - store.on('update', this.update, this); - }, + keys: (function () { + var i, list, result; + result = {}; + list = ['fixTime', 'latitude', 'longitude', 'valid', 'altitude', 'speed', 'course', 'address', 'protocol']; + for (i = 0; i < list.length; i++) { + result[list[i]] = { + priority: i, + name: Strings['position' + list[i].replace(/^\w/g, function (s) { + return s.toUpperCase(); + })] + }; + } + return result; + }()), - 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 + updateLatest: function (store, data) { + var i; + if (!Ext.isArray(data)) { + data = [data]; + } + for (i = 0; i < data.length; i++) { + if (this.deviceId === data[i].get('deviceId')) { + this.updatePosition(data[i]); + } } }, formatValue: function (value) { if (typeof (id) === 'number') { - return value.toFixed(2); + return Number(value.toFixed(2)); } else { return value; } @@ -114,29 +105,22 @@ Ext.define('Traccar.view.StateController', { }, selectDevice: function (device) { - var found; + var position; this.deviceId = device.get('id'); - found = Ext.getStore('LatestPositions').query('deviceId', this.deviceId); - if (found.getCount() > 0) { - this.updatePosition(found.first()); + position = Ext.getStore('LatestPositions').findRecord('deviceId', this.deviceId, 0, false, false, true); + if (position) { + this.updatePosition(position); } else { Ext.getStore('Attributes').removeAll(); } }, selectReport: function (position) { - console.log(position); + this.deviceId = null; + this.updatePosition(position); }, - 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); - } + clearReport: function (store) { + Ext.getStore('Attributes').removeAll(); } }); diff --git a/web/app/view/UserDevicesController.js b/web/app/view/UserDevicesController.js index a50ab8c80..aeb99c21c 100644 --- a/web/app/view/UserDevicesController.js +++ b/web/app/view/UserDevicesController.js @@ -52,11 +52,7 @@ Ext.define('Traccar.view.UserDevicesController', { userId: this.userId, deviceId: record.getData().id }, - callback: Traccar.app.getErrorHandler(this, function (options, success, response) { - if (!success) { - // TODO deselect again - } - }) + callback: Traccar.app.getErrorHandler() }); }, @@ -68,11 +64,7 @@ Ext.define('Traccar.view.UserDevicesController', { userId: this.userId, deviceId: record.getData().id }, - callback: Traccar.app.getErrorHandler(this, function (options, success, response) { - if (!success) { - // TODO select again - } - }) + callback: Traccar.app.getErrorHandler() }); } }); diff --git a/web/app/view/UsersController.js b/web/app/view/UsersController.js index 30eb8b1a5..3d0e813e8 100644 --- a/web/app/view/UsersController.js +++ b/web/app/view/UsersController.js @@ -55,8 +55,8 @@ Ext.define('Traccar.view.UsersController', { no: Strings.sharedCancel }, fn: function (btn) { + var store = Ext.getStore('Users'); if (btn === 'yes') { - var store = Ext.getStore('Users'); store.remove(user); store.sync(); } |