diff --git a/src/main/java/org/traccar/web/client/Application.java b/src/main/java/org/traccar/web/client/Application.java index 64f55b4c..c15ecf52 100644 --- a/src/main/java/org/traccar/web/client/Application.java +++ b/src/main/java/org/traccar/web/client/Application.java @@ -17,8 +17,6 @@ import com.google.gwt.i18n.client.TimeZoneInfo; import com.sencha.gxt.data.shared.ListStore; -import com.sencha.gxt.data.shared.SortDir; -import com.sencha.gxt.data.shared.Store; import com.sencha.gxt.widget.core.client.form.CheckBox; import com.sencha.gxt.widget.core.client.form.ComboBox; import com.sencha.gxt.widget.core.client.form.NumberField; @@ -68,6 +66,8 @@ public Application() { final ListStore deviceStore = new ListStore<>(deviceProperties.id()); deviceStore.clearSortInfo(); final GroupStore groupStore = new GroupStore(); + ReportProperties reportProperties = GWT.create(ReportProperties.class); + final ListStore reportStore = new ListStore<>(reportProperties.id()); settingsController = new SettingsController(userSettingsHandler); visibilityController = new VisibilityController(); @@ -84,9 +84,10 @@ public Application() { geoFenceController.getGeoFenceStore(), geoFenceController.getDeviceGeoFences(), groupStore, + reportStore, this); groupsController = new GroupsController(groupStore, deviceController); - reportsController = new ReportsController(deviceController.getDeviceStore(), geoFenceController.getGeoFenceStore()); + reportsController = new ReportsController(reportStore, deviceController.getDeviceStore(), geoFenceController.getGeoFenceStore()); importController = new ImportController(deviceController.getDeviceStore()); logController = new LogController(); navController = new NavController(settingsController, reportsController, importController, logController, groupsController); @@ -107,6 +108,7 @@ public void run() { commandController.run(); groupsController.run(); visibilityController.run(); + reportsController.run(); setupTimeZone(); } diff --git a/src/main/java/org/traccar/web/client/controller/DeviceController.java b/src/main/java/org/traccar/web/client/controller/DeviceController.java index 85e40a79..93afdcd4 100644 --- a/src/main/java/org/traccar/web/client/controller/DeviceController.java +++ b/src/main/java/org/traccar/web/client/controller/DeviceController.java @@ -73,6 +73,7 @@ public DeviceController(MapController mapController, ListStore geoFenceStore, Map> deviceGeoFences, GroupStore groupStore, + final ListStore reportStore, Application application) { this.application = application; this.mapController = mapController; @@ -83,7 +84,7 @@ public DeviceController(MapController mapController, this.groupStore = groupStore; this.deviceVisibilityHandler = deviceVisibilityHandler; - deviceView = new DeviceView(this, geoFenceHandler, commandHandler, deviceVisibilityHandler, deviceStore, geoFenceStore, groupStore); + deviceView = new DeviceView(this, geoFenceHandler, commandHandler, deviceVisibilityHandler, deviceStore, geoFenceStore, groupStore, reportStore); } public ListStore getDeviceStore() { diff --git a/src/main/java/org/traccar/web/client/controller/ReportsController.java b/src/main/java/org/traccar/web/client/controller/ReportsController.java index 6574e4a0..5208b374 100644 --- a/src/main/java/org/traccar/web/client/controller/ReportsController.java +++ b/src/main/java/org/traccar/web/client/controller/ReportsController.java @@ -23,9 +23,9 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RootPanel; import com.sencha.gxt.data.shared.ListStore; +import com.sencha.gxt.widget.core.client.ContentPanel; import org.traccar.web.client.i18n.Messages; import org.traccar.web.client.model.BaseAsyncCallback; -import org.traccar.web.client.model.ReportProperties; import org.traccar.web.client.model.ReportService; import org.traccar.web.client.model.ReportServiceAsync; import org.traccar.web.client.view.NavView; @@ -36,9 +36,10 @@ import java.util.List; -public class ReportsController implements NavView.ReportsHandler { +public class ReportsController implements NavView.ReportsHandler, ContentController { private final Messages i18n = GWT.create(Messages.class); private final ReportMapper reportMapper = GWT.create(ReportMapper.class); + private final ListStore reportStore; private final ListStore deviceStore; private final ListStore geoFenceStore; @@ -50,58 +51,67 @@ public interface ReportHandler { void reportRemoved(Report report); } - public ReportsController(ListStore deviceStore, ListStore geoFenceStore) { + public ReportsController(ListStore reportStore, ListStore deviceStore, ListStore geoFenceStore) { + this.reportStore = reportStore; this.deviceStore = deviceStore; this.geoFenceStore = geoFenceStore; } @Override - public void onShowReports() { + public ContentPanel getView() { + return null; + } + + @Override + public void run() { final ReportServiceAsync service = GWT.create(ReportService.class); service.getReports(new BaseAsyncCallback>(i18n) { + @Override + public void onSuccess(List result) { + reportStore.addAll(result); + } + }); + } + + @Override + public void onShowReports() { + final ReportServiceAsync service = GWT.create(ReportService.class); + new ReportsDialog(reportStore, deviceStore, geoFenceStore, new ReportsDialog.ReportHandler() { @Override - public void onSuccess(List result) { - ReportProperties reportProperties = GWT.create(ReportProperties.class); - ListStore reportStore = new ListStore<>(reportProperties.id()); - reportStore.addAll(result); - new ReportsDialog(reportStore, deviceStore, geoFenceStore, new ReportsDialog.ReportHandler() { + public void onAdd(Report report, final ReportHandler handler) { + service.addReport(report, new BaseAsyncCallback(i18n) { @Override - public void onAdd(Report report, final ReportHandler handler) { - service.addReport(report, new BaseAsyncCallback(i18n) { - @Override - public void onSuccess(Report result) { - handler.reportAdded(result); - } - }); + public void onSuccess(Report result) { + handler.reportAdded(result); } + }); + } + @Override + public void onUpdate(Report report, final ReportHandler handler) { + service.updateReport(report, new BaseAsyncCallback(i18n) { @Override - public void onUpdate(Report report, final ReportHandler handler) { - service.updateReport(report, new BaseAsyncCallback(i18n) { - @Override - public void onSuccess(Report result) { - handler.reportUpdated(result); - } - }); + public void onSuccess(Report result) { + handler.reportUpdated(result); } + }); + } + @Override + public void onRemove(final Report report, final ReportHandler handler) { + service.removeReport(report, new BaseAsyncCallback(i18n) { @Override - public void onRemove(final Report report, final ReportHandler handler) { - service.removeReport(report, new BaseAsyncCallback(i18n) { - @Override - public void onSuccess(Void result) { - handler.reportRemoved(report); - } - }); + public void onSuccess(Void result) { + handler.reportRemoved(report); } + }); + } - @Override - public void onGenerate(Report report) { - generate(report); - } - }).show(); + @Override + public void onGenerate(Report report) { + generate(report); } - }); + }).show(); } private void generate(Report report) { diff --git a/src/main/java/org/traccar/web/client/view/DeviceView.java b/src/main/java/org/traccar/web/client/view/DeviceView.java index d7ecf8f6..f4cb5f00 100644 --- a/src/main/java/org/traccar/web/client/view/DeviceView.java +++ b/src/main/java/org/traccar/web/client/view/DeviceView.java @@ -55,6 +55,7 @@ import com.sencha.gxt.widget.core.client.event.CellDoubleClickEvent; import com.sencha.gxt.widget.core.client.event.RowMouseDownEvent; import com.sencha.gxt.widget.core.client.event.SelectEvent; +import com.sencha.gxt.widget.core.client.event.ShowEvent; import com.sencha.gxt.widget.core.client.form.CheckBox; import com.sencha.gxt.widget.core.client.form.StoreFilterField; import com.sencha.gxt.widget.core.client.grid.ColumnConfig; @@ -503,7 +504,8 @@ public DeviceView(final DeviceHandler deviceHandler, final DeviceVisibilityHandler deviceVisibilityHandler, final ListStore globalDeviceStore, final ListStore geoFenceStore, - GroupStore groupStore) { + GroupStore groupStore, + final ListStore reportStore) { this.deviceHandler = deviceHandler; this.geoFenceHandler = geoFenceHandler; this.commandHandler = commandHandler; @@ -698,7 +700,7 @@ protected void onRightClick(Event event) { } }; grid.setView(view); - grid.setContextMenu(createDeviceGridContextMenu()); + grid.setContextMenu(createDeviceGridContextMenu(reportStore)); // configure device store filtering deviceFilter = new StoreFilterField() { @@ -913,7 +915,7 @@ interface Resources extends ClientBundle { ImageResource footprints(); } - private Menu createDeviceGridContextMenu() { + private Menu createDeviceGridContextMenu(ListStore reportStore) { Menu menu = new Menu(); MenuItem edit = new MenuItem(i18n.edit()); edit.addSelectionHandler(new SelectionHandler() { @@ -947,6 +949,11 @@ public void onSelection(SelectionEvent event) { } }); menu.add(command); + + MenuItem report = new MenuItem(i18n.report()); + report.setSubMenu(new ReportsMenu(reportStore)); + menu.add(report); + return menu; } } diff --git a/src/main/java/org/traccar/web/client/view/ReportsMenu.java b/src/main/java/org/traccar/web/client/view/ReportsMenu.java new file mode 100644 index 00000000..01508e22 --- /dev/null +++ b/src/main/java/org/traccar/web/client/view/ReportsMenu.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016 Vitaly Litvak (vitavaque@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. + */ +package org.traccar.web.client.view; + +import com.google.gwt.core.client.GWT; +import com.sencha.gxt.data.shared.ListStore; +import com.sencha.gxt.widget.core.client.menu.Menu; +import com.sencha.gxt.widget.core.client.menu.MenuItem; +import com.sencha.gxt.widget.core.client.menu.SeparatorMenuItem; +import org.traccar.web.client.i18n.Messages; +import org.traccar.web.client.model.BaseStoreHandlers; +import org.traccar.web.shared.model.Report; +import org.traccar.web.shared.model.ReportType; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class ReportsMenu extends Menu { + private final Messages i18n = GWT.create(Messages.class); + private final ListStore reports; + private final Map userReports = new HashMap<>(); + + public ReportsMenu(ListStore reports) { + this.reports = reports; + syncReports(); + for (ReportType type : ReportType.values()) { + add(new MenuItem(i18n.reportType(type))); + } + this.reports.addStoreHandlers(new BaseStoreHandlers() { + @Override + public void onAnything() { + syncReports(); + } + }); + } + + private void syncReports() { + // process deleted reports + for (Iterator it = userReports.keySet().iterator(); it.hasNext(); ) { + String key = it.next(); + if (reports.findModelWithKey(key) == null) { + MenuItem menuItem = userReports.get(key); + it.remove(); + remove(menuItem); + } + } + + // process added and updated reports + for (int i = 0; i < reports.size(); i++) { + Report report = reports.get(i); + String key = reports.getKeyProvider().getKey(report); + MenuItem reportItem = userReports.get(key); + + if (reportItem == null) { + reportItem = new MenuItem(report.getName()); + if (userReports.isEmpty()) { + insert(new SeparatorMenuItem(), 0); + } + insert(reportItem, i); + + userReports.put(key, reportItem); + } else { + reportItem.setText(report.getName()); + } + } + } +}