aboutsummaryrefslogtreecommitdiff
path: root/web/app/view
diff options
context:
space:
mode:
Diffstat (limited to 'web/app/view')
-rw-r--r--web/app/view/DevicesController.js7
-rw-r--r--web/app/view/Login.js5
-rw-r--r--web/app/view/LoginController.js12
-rw-r--r--web/app/view/Map.js41
-rw-r--r--web/app/view/MapController.js291
-rw-r--r--web/app/view/Register.js2
-rw-r--r--web/app/view/Report.js4
-rw-r--r--web/app/view/ReportController.js16
-rw-r--r--web/app/view/StateController.js98
-rw-r--r--web/app/view/UserDevicesController.js12
-rw-r--r--web/app/view/UsersController.js2
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();
}