diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2016-06-20 22:56:18 +1200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-20 22:56:18 +1200 |
commit | 63aa4472c7d851a0b414dd3c295ccce2bc8c827f (patch) | |
tree | fca526a145f48ba07128649dd77348dbab257721 | |
parent | cc26f01471506935d6f438a102fbf9478dcebb1b (diff) | |
parent | f82970ac21ec2f050a09493fa7bc46c7178b57c3 (diff) | |
download | traccar-server-63aa4472c7d851a0b414dd3c295ccce2bc8c827f.tar.gz traccar-server-63aa4472c7d851a0b414dd3c295ccce2bc8c827f.tar.bz2 traccar-server-63aa4472c7d851a0b414dd3c295ccce2bc8c827f.zip |
Merge pull request #2030 from Abyss777/master
Link and unlink geofences in web client
23 files changed, 401 insertions, 118 deletions
diff --git a/src/org/traccar/api/resource/GeofenceResource.java b/src/org/traccar/api/resource/GeofenceResource.java index 9c80e61a1..44f6fc2f5 100644 --- a/src/org/traccar/api/resource/GeofenceResource.java +++ b/src/org/traccar/api/resource/GeofenceResource.java @@ -17,6 +17,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; +import org.traccar.database.GeofenceManager; import org.traccar.model.Geofence; import javax.ws.rs.Consumes; @@ -33,6 +34,8 @@ import javax.ws.rs.core.Response; import java.sql.SQLException; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; @Path("geofences") @Produces(MediaType.APPLICATION_JSON) @@ -41,17 +44,33 @@ public class GeofenceResource extends BaseResource { @GET public Collection<Geofence> get( - @QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException { + @QueryParam("all") boolean all, @QueryParam("userId") long userId, @QueryParam("groupId") long groupId, + @QueryParam("deviceId") long deviceId) throws SQLException { + + GeofenceManager geofenceManager = Context.getGeofenceManager(); + Set<Long> result; if (all) { Context.getPermissionsManager().checkAdmin(getUserId()); - return Context.getGeofenceManager().getAllGeofences(); + result = new HashSet<>(geofenceManager.getAllGeofencesIds()); } else { if (userId == 0) { userId = getUserId(); } Context.getPermissionsManager().checkUser(getUserId(), userId); - return Context.getGeofenceManager().getUserGeofences(userId); + result = new HashSet<Long>(geofenceManager.getUserGeofencesIds(userId)); + } + + if (groupId != 0) { + Context.getPermissionsManager().checkGroup(getUserId(), groupId); + result.retainAll(geofenceManager.getGroupGeofencesIds(groupId)); } + + if (deviceId != 0) { + Context.getPermissionsManager().checkDevice(getUserId(), deviceId); + result.retainAll(geofenceManager.getDeviceGeofencesIds(deviceId)); + } + return geofenceManager.getGeofences(result); + } @POST diff --git a/src/org/traccar/database/GeofenceManager.java b/src/org/traccar/database/GeofenceManager.java index 0a07e2cf3..3f4d4c5ce 100644 --- a/src/org/traccar/database/GeofenceManager.java +++ b/src/org/traccar/database/GeofenceManager.java @@ -70,6 +70,15 @@ public class GeofenceManager { return groupGeofences.get(groupId); } + public Set<Long> getGroupGeofencesIds(long groupId) { + groupGeofencesLock.readLock().lock(); + try { + return getGroupGeofences(groupId); + } finally { + groupGeofencesLock.readLock().unlock(); + } + } + public Set<Long> getAllDeviceGeofences(long deviceId) { deviceGeofencesLock.readLock().lock(); try { @@ -77,10 +86,9 @@ public class GeofenceManager { } finally { deviceGeofencesLock.readLock().unlock(); } - } - public Set<Long> getDeviceGeofences(long deviceId) { + public Set<Long> getDeviceGeofencesIds(long deviceId) { deviceGeofencesLock.readLock().lock(); try { return getDeviceGeofences(deviceGeofences, deviceId); @@ -174,11 +182,20 @@ public class GeofenceManager { } } - public final Collection<Geofence> getUserGeofences(long userId) { + public final Set<Long> getAllGeofencesIds() { + geofencesLock.readLock().lock(); + try { + return geofences.keySet(); + } finally { + geofencesLock.readLock().unlock(); + } + } + + public final Collection<Geofence> getGeofences(Set<Long> geofencesIds) { geofencesLock.readLock().lock(); try { Collection<Geofence> result = new LinkedList<>(); - for (Long geofenceId : getUserGeofencesIds(userId)) { + for (Long geofenceId : geofencesIds) { result.add(getGeofence(geofenceId)); } return result; diff --git a/web/app/Application.js b/web/app/Application.js index e798a73e2..dbbc7a594 100644 --- a/web/app/Application.js +++ b/web/app/Application.js @@ -31,7 +31,8 @@ Ext.define('Traccar.Application', { 'Position', 'Attribute', 'Command', - 'Event' + 'Event', + 'Geofence' ], stores: [ @@ -49,7 +50,9 @@ Ext.define('Traccar.Application', { 'CommandTypes', 'TimeUnits', 'Languages', - 'Events' + 'Events', + 'Geofences', + 'AllGeofences' ], controllers: [ diff --git a/web/app/controller/Root.js b/web/app/controller/Root.js index 991a2572c..56a076edd 100644 --- a/web/app/controller/Root.js +++ b/web/app/controller/Root.js @@ -75,6 +75,7 @@ Ext.define('Traccar.controller.Root', { loadApp: function () { Ext.getStore('Groups').load(); Ext.getStore('Devices').load(); + Ext.getStore('Geofences').load(); Ext.get('attribution').remove(); if (this.isPhone) { Ext.create('widget.mainMobile'); @@ -94,7 +95,7 @@ Ext.define('Traccar.controller.Root', { }; socket.onmessage = function (event) { - var i, j, store, data, array, entity, device, typeKey, text; + var i, j, store, data, array, entity, device, typeKey, text, geofence; data = Ext.decode(event.data); @@ -147,6 +148,12 @@ Ext.define('Traccar.controller.Root', { text = typeKey; } } + if (array[i].geofenceId !== 0) { + geofence = Ext.getStore('Geofences').getById(array[i].geofenceId); + if (typeof geofence != "undefined") { + text += ' \"' + geofence.getData().name + '"'; + } + } device = Ext.getStore('Devices').getById(array[i].deviceId); if (typeof device != "undefined") { Ext.toast(text, device.getData().name); diff --git a/web/app/model/Device.js b/web/app/model/Device.js index 588d53c1f..247f72ba9 100644 --- a/web/app/model/Device.js +++ b/web/app/model/Device.js @@ -37,5 +37,7 @@ Ext.define('Traccar.model.Device', { }, { name: 'groupId', type: 'int' + }, { + name: 'geofenceIds' }] }); diff --git a/web/app/model/Event.js b/web/app/model/Event.js index 4dd3ea7ff..698ebb535 100644 --- a/web/app/model/Event.js +++ b/web/app/model/Event.js @@ -35,6 +35,9 @@ Ext.define('Traccar.model.Event', { name: 'positionId', type: 'int' }, { + name: 'geofenceId', + type: 'int' + }, { name: 'attributes' }] }); diff --git a/web/app/model/Geofence.js b/web/app/model/Geofence.js new file mode 100644 index 000000000..a832455ac --- /dev/null +++ b/web/app/model/Geofence.js @@ -0,0 +1,36 @@ +/* + * Copyright 2016 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.model.Geofence', { + extend: 'Ext.data.Model', + identifier: 'negative', + + fields: [{ + name: 'id', + type: 'int' + }, { + name: 'name', + type: 'string' + }, { + name: 'description', + type: 'string' + }, { + name: 'area', + type: 'string' + }, { + name: 'attributes' + }] +}); diff --git a/web/app/store/AllGeofences.js b/web/app/store/AllGeofences.js new file mode 100644 index 000000000..aa6f9abfc --- /dev/null +++ b/web/app/store/AllGeofences.js @@ -0,0 +1,28 @@ +/* + * Copyright 2016 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.store.AllGeofences', { + extend: 'Ext.data.Store', + model: 'Traccar.model.Geofence', + + proxy: { + type: 'rest', + url: '/api/geofences', + extraParams: { + all: true + } + } +}); diff --git a/web/app/store/Geofences.js b/web/app/store/Geofences.js new file mode 100644 index 000000000..8c5c0b3cf --- /dev/null +++ b/web/app/store/Geofences.js @@ -0,0 +1,28 @@ +/* + * Copyright 2016 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.store.Geofences', { + extend: 'Ext.data.Store', + model: 'Traccar.model.Geofence', + + proxy: { + type: 'rest', + url: '/api/geofences', + writer: { + writeAllFields: true + } + } +}); diff --git a/web/app/view/UserGroupsController.js b/web/app/view/BasePermissionsController.js index 662508f0a..713d91770 100644 --- a/web/app/view/UserGroupsController.js +++ b/web/app/view/BasePermissionsController.js @@ -14,21 +14,23 @@ * limitations under the License. */ -Ext.define('Traccar.view.UserGroupsController', { +Ext.define('Traccar.view.BasePermissionsController', { extend: 'Ext.app.ViewController', - alias: 'controller.userGroups', + alias: 'controller.basePermissionsController', init: function () { - this.userId = this.getView().user.getData().id; + var params = {}; + params[this.getView().baseObjectName] = this.getView().baseObject; + var linkStoreName = this.getView().linkStoreName; + var storeName = this.getView().storeName; + linkStoreName = (typeof linkStoreName === 'undefined') ? storeName : linkStoreName; + this.getView().setStore(Ext.getStore(storeName)); this.getView().getStore().load({ scope: this, callback: function (records, operation, success) { - var userStore = Ext.create('Traccar.store.Groups'); - - userStore.load({ - params: { - userId: this.userId - }, + var linkStore = Ext.create('Traccar.store.' + linkStoreName); + linkStore.load({ + params: params, scope: this, callback: function (records, operation, success) { var i, index; @@ -45,13 +47,13 @@ Ext.define('Traccar.view.UserGroupsController', { }, onBeforeSelect: function (object, record, index) { + var data = {}; + data[this.getView().baseObjectName] = this.getView().baseObject; + data[this.getView().linkObjectName] = record.getData().id; Ext.Ajax.request({ scope: this, - url: '/api/permissions/groups', - jsonData: { - userId: this.userId, - groupId: record.getData().id - }, + url: this.getView().urlApi, + jsonData: Ext.util.JSON.encode(data), callback: function (options, success, response) { if (!success) { Traccar.app.showError(response); @@ -61,14 +63,14 @@ Ext.define('Traccar.view.UserGroupsController', { }, onBeforeDeselect: function (object, record, index) { + var data = {}; + data[this.getView().baseObjectName] = this.getView().baseObject; + data[this.getView().linkObjectName] = record.getData().id; Ext.Ajax.request({ scope: this, method: 'DELETE', - url: '/api/permissions/groups', - jsonData: { - userId: this.userId, - groupId: record.getData().id - }, + url: this.getView().urlApi, + jsonData: Ext.util.JSON.encode(data), callback: function (options, success, response) { if (!success) { Traccar.app.showError(response); diff --git a/web/app/view/DeviceGeofences.js b/web/app/view/DeviceGeofences.js new file mode 100644 index 000000000..9e2c12a77 --- /dev/null +++ b/web/app/view/DeviceGeofences.js @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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.DeviceGeofences', { + extend: 'Ext.grid.Panel', + xtype: 'deviceGeofencesView', + + requires: [ + 'Traccar.view.BasePermissionsController' + ], + + controller: 'basePermissionsController', + + selModel: { + selType: 'checkboxmodel', + checkOnly: true, + showHeaderCheckbox: false + }, + + listeners: { + beforedeselect: 'onBeforeDeselect', + beforeselect: 'onBeforeSelect' + }, + + columns: [{ + text: Strings.sharedName, + dataIndex: 'name', + flex: 1 + }] +}); diff --git a/web/app/view/Devices.js b/web/app/view/Devices.js index f06c2658b..1a70dfef8 100644 --- a/web/app/view/Devices.js +++ b/web/app/view/Devices.js @@ -41,6 +41,14 @@ Ext.define('Traccar.view.Devices', { tbar: { xtype: 'editToolbar', items: [{ + xtype: 'button', + disabled: true, + handler: 'onGeofencesClick', + reference: 'toolbarGeofencesButton', + glyph: 'xf21d@FontAwesome', + tooltip: Strings.sharedGeofences, + tooltipType: 'title' + }, { disabled: true, handler: 'onCommandClick', reference: 'deviceCommandButton', diff --git a/web/app/view/DevicesController.js b/web/app/view/DevicesController.js index 6b79a6804..cf31dd7bb 100644 --- a/web/app/view/DevicesController.js +++ b/web/app/view/DevicesController.js @@ -20,7 +20,8 @@ Ext.define('Traccar.view.DevicesController', { requires: [ 'Traccar.view.CommandDialog', - 'Traccar.view.DeviceDialog' + 'Traccar.view.DeviceDialog', + 'Traccar.view.DeviceGeofences' ], config: { @@ -84,6 +85,22 @@ Ext.define('Traccar.view.DevicesController', { }); }, + onGeofencesClick: function () { + var admin = Traccar.app.getUser().get('admin'); + var device = this.getView().getSelectionModel().getSelection()[0]; + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedGeofences, + items: { + xtype: 'deviceGeofencesView', + baseObjectName: 'deviceId', + linkObjectName: 'geofenceId', + storeName: (admin) ? 'AllGeofences' : 'Geofences', + urlApi: '/api/devices/geofences', + baseObject: device.getData().id + } + }).show(); + }, + onCommandClick: function () { var device, deviceId, command, dialog, comboStore; device = this.getView().getSelectionModel().getSelection()[0]; @@ -108,6 +125,7 @@ Ext.define('Traccar.view.DevicesController', { var empty = selected.getCount() === 0; this.lookupReference('toolbarEditButton').setDisabled(empty); this.lookupReference('toolbarRemoveButton').setDisabled(empty); + this.lookupReference('toolbarGeofencesButton').setDisabled(empty); this.lookupReference('deviceCommandButton').setDisabled(empty || (selected.getLastSelected().get('status') !== 'online')); if (!empty) { this.fireEvent('selectDevice', selected.getLastSelected(), true); diff --git a/web/app/view/GroupGeofences.js b/web/app/view/GroupGeofences.js new file mode 100644 index 000000000..8ef2984ea --- /dev/null +++ b/web/app/view/GroupGeofences.js @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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.GroupGeofences', { + extend: 'Ext.grid.Panel', + xtype: 'groupGeofencesView', + + requires: [ + 'Traccar.view.BasePermissionsController' + ], + + controller: 'basePermissionsController', + + selModel: { + selType: 'checkboxmodel', + checkOnly: true, + showHeaderCheckbox: false + }, + + listeners: { + beforedeselect: 'onBeforeDeselect', + beforeselect: 'onBeforeSelect' + }, + + columns: [{ + text: Strings.sharedName, + dataIndex: 'name', + flex: 1 + }] +}); diff --git a/web/app/view/Groups.js b/web/app/view/Groups.js index 8404c59a9..59d20df31 100644 --- a/web/app/view/Groups.js +++ b/web/app/view/Groups.js @@ -29,7 +29,16 @@ Ext.define('Traccar.view.Groups', { selType: 'rowmodel', tbar: { - xtype: 'editToolbar' + xtype: 'editToolbar', + items: [{ + xtype: 'button', + disabled: true, + handler: 'onGeofencesClick', + reference: 'toolbarGeofencesButton', + glyph: 'xf21d@FontAwesome', + tooltip: Strings.sharedGeofences, + tooltipType: 'title' + }] }, listeners: { diff --git a/web/app/view/GroupsController.js b/web/app/view/GroupsController.js index 6cc568ea2..bc713bb6d 100644 --- a/web/app/view/GroupsController.js +++ b/web/app/view/GroupsController.js @@ -18,6 +18,10 @@ Ext.define('Traccar.view.GroupsController', { extend: 'Ext.app.ViewController', alias: 'controller.groups', + requires: [ + 'Traccar.view.GroupGeofences' + ], + onAddClick: function () { var group, dialog; group = Ext.create('Traccar.model.Group'); @@ -55,9 +59,26 @@ Ext.define('Traccar.view.GroupsController', { }); }, + onGeofencesClick: function () { + var admin = Traccar.app.getUser().get('admin'); + var group = this.getView().getSelectionModel().getSelection()[0]; + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedGeofences, + items: { + xtype: 'groupGeofencesView', + baseObjectName: 'groupId', + linkObjectName: 'geofenceId', + storeName: (admin) ? 'AllGeofences' : 'Geofences', + urlApi: '/api/groups/geofences', + baseObject: group.getData().id + } + }).show(); + }, + onSelectionChange: function (selected) { var disabled = selected.length > 0; this.lookupReference('toolbarEditButton').setDisabled(disabled); this.lookupReference('toolbarRemoveButton').setDisabled(disabled); + this.lookupReference('toolbarGeofencesButton').setDisabled(disabled); } }); diff --git a/web/app/view/UserDevices.js b/web/app/view/UserDevices.js index fe16dd93a..6a1a718aa 100644 --- a/web/app/view/UserDevices.js +++ b/web/app/view/UserDevices.js @@ -19,11 +19,10 @@ Ext.define('Traccar.view.UserDevices', { xtype: 'userDevicesView', requires: [ - 'Traccar.view.UserDevicesController' + 'Traccar.view.BasePermissionsController' ], - controller: 'userDevices', - store: 'AllDevices', + controller: 'basePermissionsController', selModel: { selType: 'checkboxmodel', diff --git a/web/app/view/UserDevicesController.js b/web/app/view/UserDevicesController.js deleted file mode 100644 index e5dbbdbb8..000000000 --- a/web/app/view/UserDevicesController.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.UserDevicesController', { - extend: 'Ext.app.ViewController', - alias: 'controller.userDevices', - - init: function () { - this.userId = this.getView().user.getData().id; - this.getView().getStore().load({ - scope: this, - callback: function (records, operation, success) { - var userStore = Ext.create('Traccar.store.Devices'); - - userStore.load({ - params: { - userId: this.userId - }, - scope: this, - callback: function (records, operation, success) { - var i, index; - if (success) { - for (i = 0; i < records.length; i++) { - index = this.getView().getStore().find('id', records[i].getData().id); - this.getView().getSelectionModel().select(index, true, true); - } - } - } - }); - } - }); - }, - - onBeforeSelect: function (object, record, index) { - Ext.Ajax.request({ - scope: this, - url: '/api/permissions/devices', - jsonData: { - userId: this.userId, - deviceId: record.getData().id - }, - callback: function (options, success, response) { - if (!success) { - Traccar.app.showError(response); - } - } - }); - }, - - onBeforeDeselect: function (object, record, index) { - Ext.Ajax.request({ - scope: this, - method: 'DELETE', - url: '/api/permissions/devices', - jsonData: { - userId: this.userId, - deviceId: record.getData().id - }, - callback: function (options, success, response) { - if (!success) { - Traccar.app.showError(response); - } - } - }); - } -}); diff --git a/web/app/view/UserGeofences.js b/web/app/view/UserGeofences.js new file mode 100644 index 000000000..03a02ff3b --- /dev/null +++ b/web/app/view/UserGeofences.js @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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.UserGeofences', { + extend: 'Ext.grid.Panel', + xtype: 'userGeofencesView', + + requires: [ + 'Traccar.view.BasePermissionsController' + ], + + controller: 'basePermissionsController', + + selModel: { + selType: 'checkboxmodel', + checkOnly: true, + showHeaderCheckbox: false + }, + + listeners: { + beforedeselect: 'onBeforeDeselect', + beforeselect: 'onBeforeSelect' + }, + + columns: [{ + text: Strings.sharedName, + dataIndex: 'name', + flex: 1 + }] +}); diff --git a/web/app/view/UserGroups.js b/web/app/view/UserGroups.js index cb0f0bd5d..84032f021 100644 --- a/web/app/view/UserGroups.js +++ b/web/app/view/UserGroups.js @@ -19,11 +19,10 @@ Ext.define('Traccar.view.UserGroups', { xtype: 'userGroupsView', requires: [ - 'Traccar.view.UserGroupsController' + 'Traccar.view.BasePermissionsController' ], - controller: 'userGroups', - store: 'AllGroups', + controller: 'basePermissionsController', selModel: { selType: 'checkboxmodel', diff --git a/web/app/view/Users.js b/web/app/view/Users.js index 408a70885..b6301b38b 100644 --- a/web/app/view/Users.js +++ b/web/app/view/Users.js @@ -40,6 +40,11 @@ Ext.define('Traccar.view.Users', { disabled: true, handler: 'onGroupsClick', reference: 'userGroupsButton' + }, { + text: Strings.sharedGeofences, + disabled: true, + handler: 'onGeofencesClick', + reference: 'userGeofencesButton' }] }, diff --git a/web/app/view/UsersController.js b/web/app/view/UsersController.js index c48f57cf4..acba66b4d 100644 --- a/web/app/view/UsersController.js +++ b/web/app/view/UsersController.js @@ -22,6 +22,7 @@ Ext.define('Traccar.view.UsersController', { 'Traccar.view.UserDialog', 'Traccar.view.UserDevices', 'Traccar.view.UserGroups', + 'Traccar.view.UserGeofences', 'Traccar.view.BaseWindow' ], @@ -71,7 +72,12 @@ Ext.define('Traccar.view.UsersController', { title: Strings.deviceTitle, items: { xtype: 'userDevicesView', - user: user + baseObjectName: 'userId', + linkObjectName: 'deviceId', + storeName: 'AllDevices', + linkStoreName: 'Devices', + urlApi: '/api/permissions/devices', + baseObject: user.getData().id } }).show(); }, @@ -82,7 +88,28 @@ Ext.define('Traccar.view.UsersController', { title: Strings.settingsGroups, items: { xtype: 'userGroupsView', - user: user + baseObjectName: 'userId', + linkObjectName: 'groupId', + storeName: 'AllGroups', + linkStoreName: 'Groups', + urlApi: '/api/permissions/groups', + baseObject: user.getData().id + } + }).show(); + }, + + onGeofencesClick: function () { + var user = this.getView().getSelectionModel().getSelection()[0]; + Ext.create('Traccar.view.BaseWindow', { + title: Strings.sharedGeofences, + items: { + xtype: 'userGeofencesView', + baseObjectName: 'userId', + linkObjectName: 'geofenceId', + storeName: 'AllGeofences', + linkStoreName: 'Geofences', + urlApi: '/api/permissions/geofences', + baseObject: user.getData().id } }).show(); }, @@ -93,5 +120,6 @@ Ext.define('Traccar.view.UsersController', { this.lookupReference('toolbarRemoveButton').setDisabled(disabled); this.lookupReference('userDevicesButton').setDisabled(disabled); this.lookupReference('userGroupsButton').setDisabled(disabled); + this.lookupReference('userGeofencesButton').setDisabled(disabled); } }); diff --git a/web/l10n/en.json b/web/l10n/en.json index 48dc6533c..2809ea66a 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -16,6 +16,7 @@ "sharedSecond": "Second", "sharedName": "Name", "sharedSearch": "Search", + "sharedGeofences": "Geofences", "errorTitle": "Error", "errorUnknown": "Unknown error", "errorConnection": "Connection error", |