diff options
12 files changed, 237 insertions, 72 deletions
diff --git a/src/org/traccar/web/client/Application.java b/src/org/traccar/web/client/Application.java index 9b14d42..22f20d8 100644 --- a/src/org/traccar/web/client/Application.java +++ b/src/org/traccar/web/client/Application.java @@ -1,8 +1,6 @@ package org.traccar.web.client; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.traccar.web.client.controller.ArchiveController; import org.traccar.web.client.controller.DeviceController; @@ -33,7 +31,7 @@ public class Application { public Application() { deviceController = new DeviceController(deviceHandler); mapController = new MapController(); - archiveController = new ArchiveController(archiveHanlder); + archiveController = new ArchiveController(archiveHanlder, deviceController.getDeviceStore()); view = new ApplicationView( deviceController.getView(), mapController.getView(), archiveController.getView()); @@ -47,16 +45,10 @@ public class Application { archiveController.run(); } - private Map<Long, Device> devices = new HashMap<Long, Device>(); - private DeviceController.DeviceHandler deviceHandler = new DeviceController.DeviceHandler() { @Override public void onLoad(List<Device> devices) { - Application.this.devices.clear(); - for (Device device : devices) { - Application.this.devices.put(device.getId(), device); - } } @Override @@ -66,21 +58,15 @@ public class Application { @Override public void onAdd(Device device) { - devices.put(device.getId(), device); - archiveController.updateDevices(devices.values()); mapController.update(); } @Override public void onUpdate(Device device) { - devices.put(device.getId(), device); - archiveController.updateDevices(devices.values()); } @Override public void onRemove(Device device) { - devices.remove(device.getId()); - archiveController.updateDevices(devices.values()); mapController.update(); } diff --git a/src/org/traccar/web/client/controller/ArchiveController.java b/src/org/traccar/web/client/controller/ArchiveController.java index 598a744..9f865b6 100644 --- a/src/org/traccar/web/client/controller/ArchiveController.java +++ b/src/org/traccar/web/client/controller/ArchiveController.java @@ -1,12 +1,19 @@ package org.traccar.web.client.controller; -import java.util.Collection; +import java.util.Date; +import java.util.List; +import org.traccar.web.client.Application; +import org.traccar.web.client.model.BaseAsyncCallback; +import org.traccar.web.client.model.PositionProperties; import org.traccar.web.client.view.ArchiveView; import org.traccar.web.shared.model.Device; import org.traccar.web.shared.model.Position; +import com.google.gwt.core.client.GWT; +import com.sencha.gxt.data.shared.ListStore; import com.sencha.gxt.widget.core.client.ContentPanel; +import com.sencha.gxt.widget.core.client.box.AlertMessageBox; public class ArchiveController implements ContentController, ArchiveView.ArchiveHandler { @@ -16,11 +23,19 @@ public class ArchiveController implements ContentController, ArchiveView.Archive private ArchiveHandler archiveHandler; + private ListStore<Position> positionStore; + private ArchiveView archiveView; - public ArchiveController(ArchiveHandler archiveHandler) { + public ArchiveController(ArchiveHandler archiveHandler, ListStore<Device> deviceStore) { this.archiveHandler = archiveHandler; - archiveView = new ArchiveView(this); + PositionProperties positionProperties = GWT.create(PositionProperties.class); + positionStore = new ListStore<Position>(positionProperties.id()); + archiveView = new ArchiveView(this, positionStore, deviceStore); + } + + public ListStore<Position> getPositionStore() { + return positionStore; } @Override @@ -32,13 +47,29 @@ public class ArchiveController implements ContentController, ArchiveView.Archive public void run() { } - public void updateDevices(Collection<Device> devices) { + @Override + public void onSelected(Position position) { + archiveHandler.onSelected(position); + } + @Override + public void onLoad(Device device, Date from, Date to) { + if (device != null && from != null && to != null) { + Application.getDataService().getPositions(device, from, to, new BaseAsyncCallback<List<Position>>() { + @Override + public void onSuccess(List<Position> result) { + positionStore.clear(); + positionStore.addAll(result); + } + }); + } else { + new AlertMessageBox("Error", "All form fields must be filled first").show(); + } } @Override - public void onSelected(Position position) { - archiveHandler.onSelected(position); + public void onClear() { + positionStore.clear(); } } diff --git a/src/org/traccar/web/client/controller/DeviceController.java b/src/org/traccar/web/client/controller/DeviceController.java index b24c205..865aaea 100644 --- a/src/org/traccar/web/client/controller/DeviceController.java +++ b/src/org/traccar/web/client/controller/DeviceController.java @@ -4,10 +4,13 @@ import java.util.List; import org.traccar.web.client.Application; import org.traccar.web.client.model.BaseAsyncCallback; +import org.traccar.web.client.model.DeviceProperties; import org.traccar.web.client.view.DeviceDialog; import org.traccar.web.client.view.DeviceView; import org.traccar.web.shared.model.Device; +import com.google.gwt.core.client.GWT; +import com.sencha.gxt.data.shared.ListStore; import com.sencha.gxt.widget.core.client.ContentPanel; import com.sencha.gxt.widget.core.client.Dialog.PredefinedButton; import com.sencha.gxt.widget.core.client.box.ConfirmMessageBox; @@ -26,11 +29,19 @@ public class DeviceController implements ContentController, DeviceView.DeviceHan private DeviceHandler deviceHandler; + private ListStore<Device> deviceStore; + private DeviceView deviceView; public DeviceController(DeviceHandler deviceHandler) { this.deviceHandler = deviceHandler; - deviceView = new DeviceView(this); + DeviceProperties deviceProperties = GWT.create(DeviceProperties.class); + deviceStore = new ListStore<Device>(deviceProperties.id()); + deviceView = new DeviceView(this, deviceStore); + } + + public ListStore<Device> getDeviceStore() { + return deviceStore; } @Override @@ -43,7 +54,7 @@ public class DeviceController implements ContentController, DeviceView.DeviceHan Application.getDataService().getDevices(new BaseAsyncCallback<List<Device>>() { @Override public void onSuccess(List<Device> result) { - deviceView.load(result); + deviceStore.addAll(result); deviceHandler.onLoad(result); } }); @@ -62,7 +73,7 @@ public class DeviceController implements ContentController, DeviceView.DeviceHan Application.getDataService().addDevice(device, new BaseAsyncCallback<Device>() { @Override public void onSuccess(Device result) { - deviceView.add(result); + deviceStore.add(result); deviceHandler.onAdd(result); } }); @@ -78,7 +89,7 @@ public class DeviceController implements ContentController, DeviceView.DeviceHan Application.getDataService().updateDevice(device, new BaseAsyncCallback<Device>() { @Override public void onSuccess(Device result) { - deviceView.update(result); + deviceStore.update(result); deviceHandler.onUpdate(result); } }); @@ -96,7 +107,7 @@ public class DeviceController implements ContentController, DeviceView.DeviceHan Application.getDataService().removeDevice(device, new BaseAsyncCallback<Device>() { @Override public void onSuccess(Device result) { - deviceView.remove(device); + deviceStore.remove(device); deviceHandler.onRemove(device); } }); diff --git a/src/org/traccar/web/client/controller/MapController.java b/src/org/traccar/web/client/controller/MapController.java index 5a53cf2..5ab5bbc 100644 --- a/src/org/traccar/web/client/controller/MapController.java +++ b/src/org/traccar/web/client/controller/MapController.java @@ -1,9 +1,14 @@ package org.traccar.web.client.controller; +import java.util.List; + +import org.traccar.web.client.Application; import org.traccar.web.client.view.MapView; import org.traccar.web.shared.model.Device; +import org.traccar.web.shared.model.Position; import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.sencha.gxt.widget.core.client.ContentPanel; public class MapController implements ContentController { @@ -36,7 +41,7 @@ public class MapController implements ContentController { public void update() { updateTimer.cancel(); - /*Application.getDataService().getLatestPositions(new AsyncCallback<List<Position>>() { + Application.getDataService().getLatestPositions(new AsyncCallback<List<Position>>() { @Override public void onSuccess(List<Position> result) { mapView.showPositions(result); @@ -46,7 +51,7 @@ public class MapController implements ContentController { public void onFailure(Throwable caught) { updateTimer.schedule(UPDATE_INTERVAL); } - });*/ + }); } public void select(Device device) { diff --git a/src/org/traccar/web/client/model/BaseStoreHandlers.java b/src/org/traccar/web/client/model/BaseStoreHandlers.java new file mode 100644 index 0000000..ed4e541 --- /dev/null +++ b/src/org/traccar/web/client/model/BaseStoreHandlers.java @@ -0,0 +1,58 @@ +package org.traccar.web.client.model; + +import com.sencha.gxt.data.shared.event.StoreAddEvent; +import com.sencha.gxt.data.shared.event.StoreClearEvent; +import com.sencha.gxt.data.shared.event.StoreDataChangeEvent; +import com.sencha.gxt.data.shared.event.StoreFilterEvent; +import com.sencha.gxt.data.shared.event.StoreHandlers; +import com.sencha.gxt.data.shared.event.StoreRecordChangeEvent; +import com.sencha.gxt.data.shared.event.StoreRemoveEvent; +import com.sencha.gxt.data.shared.event.StoreSortEvent; +import com.sencha.gxt.data.shared.event.StoreUpdateEvent; + +public class BaseStoreHandlers<T> implements StoreHandlers<T> { + + @Override + public void onAdd(StoreAddEvent<T> event) { + onAnything(); + } + + @Override + public void onRemove(StoreRemoveEvent<T> event) { + onAnything(); + } + + @Override + public void onFilter(StoreFilterEvent<T> event) { + onAnything(); + } + + @Override + public void onClear(StoreClearEvent<T> event) { + onAnything(); + } + + @Override + public void onUpdate(StoreUpdateEvent<T> event) { + onAnything(); + } + + @Override + public void onDataChange(StoreDataChangeEvent<T> event) { + onAnything(); + } + + @Override + public void onRecordChange(StoreRecordChangeEvent<T> event) { + onAnything(); + } + + @Override + public void onSort(StoreSortEvent<T> event) { + onAnything(); + } + + public void onAnything() { + } + +} diff --git a/src/org/traccar/web/client/model/DeviceProperties.java b/src/org/traccar/web/client/model/DeviceProperties.java index 2c56ff6..2ba4d47 100644 --- a/src/org/traccar/web/client/model/DeviceProperties.java +++ b/src/org/traccar/web/client/model/DeviceProperties.java @@ -2,7 +2,9 @@ package org.traccar.web.client.model; import org.traccar.web.shared.model.Device; +import com.google.gwt.editor.client.Editor.Path; import com.sencha.gxt.core.client.ValueProvider; +import com.sencha.gxt.data.shared.LabelProvider; import com.sencha.gxt.data.shared.ModelKeyProvider; import com.sencha.gxt.data.shared.PropertyAccess; @@ -14,4 +16,7 @@ public interface DeviceProperties extends PropertyAccess<Device> { ValueProvider<Device, String> name(); + @Path("name") + LabelProvider<Device> label(); + } diff --git a/src/org/traccar/web/client/view/ArchiveView.java b/src/org/traccar/web/client/view/ArchiveView.java index 79621ba..f61ffcc 100644 --- a/src/org/traccar/web/client/view/ArchiveView.java +++ b/src/org/traccar/web/client/view/ArchiveView.java @@ -4,7 +4,10 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; +import org.traccar.web.client.model.BaseStoreHandlers; +import org.traccar.web.client.model.DeviceProperties; import org.traccar.web.client.model.PositionProperties; +import org.traccar.web.shared.model.Device; import org.traccar.web.shared.model.Position; import com.google.gwt.cell.client.DateCell; @@ -12,15 +15,21 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.core.client.Style.SelectionMode; import com.sencha.gxt.data.shared.ListStore; +import com.sencha.gxt.data.shared.event.StoreHandlers; import com.sencha.gxt.widget.core.client.ContentPanel; +import com.sencha.gxt.widget.core.client.event.SelectEvent; +import com.sencha.gxt.widget.core.client.form.ComboBox; +import com.sencha.gxt.widget.core.client.form.DateField; +import com.sencha.gxt.widget.core.client.form.TimeField; import com.sencha.gxt.widget.core.client.grid.ColumnConfig; import com.sencha.gxt.widget.core.client.grid.ColumnModel; import com.sencha.gxt.widget.core.client.grid.Grid; -public class ArchiveView extends Composite { +public class ArchiveView { private static ArchiveViewUiBinder uiBinder = GWT.create(ArchiveViewUiBinder.class); @@ -29,6 +38,8 @@ public class ArchiveView extends Composite { public interface ArchiveHandler { public void onSelected(Position position); + public void onLoad(Device device, Date from, Date to); + public void onClear(); } private ArchiveHandler archiveHandler; @@ -40,17 +51,40 @@ public class ArchiveView extends Composite { return contentPanel; } + ListStore<Device> deviceStore; + + @UiField + DateField fromDate; + + @UiField + TimeField fromTime; + + @UiField + DateField toDate; + + @UiField + TimeField toTime; + + @UiField(provided = true) + ComboBox<Device> deviceCombo; + @UiField(provided = true) ColumnModel<Position> columnModel; @UiField(provided = true) - ListStore<Position> store; + ListStore<Position> positionStore; @UiField Grid<Position> grid; - public ArchiveView(ArchiveHandler archiveHandler) { + public ArchiveView(ArchiveHandler archiveHandler, ListStore<Position> positionStore, ListStore<Device> deviceStore) { this.archiveHandler = archiveHandler; + this.positionStore = positionStore; + deviceStore.addStoreHandlers(deviceStoreHandlers); + this.deviceStore = deviceStore; + + DeviceProperties deviceProperties = GWT.create(DeviceProperties.class); + deviceCombo = new ComboBox<Device>(deviceStore, deviceProperties.label()); PositionProperties positionProperties = GWT.create(PositionProperties.class); @@ -71,9 +105,51 @@ public class ArchiveView extends Composite { columnModel = new ColumnModel<Position>(columnConfigList); - store = new ListStore<Position>(positionProperties.id()); - uiBinder.createAndBindUi(this); + + grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + + // Initialize with current time + Date now = new Date(); + fromDate.setValue(now); + fromTime.setValue(now); + toDate.setValue(now); + toTime.setValue(now); + } + + @SuppressWarnings("deprecation") + private static Date getCombineDate(DateField dateField, TimeField timeField) { + Date result = null; + Date date = dateField.getValue(); + Date time = timeField.getValue(); + if (date != null && time != null) { + result = new Date( + date.getYear(), date.getMonth(), date.getDate(), + time.getHours(), time.getMinutes(), time.getSeconds()); + } + return result; + } + + @UiHandler("loadButton") + public void onLoadClicked(SelectEvent event) { + archiveHandler.onLoad( + deviceCombo.getValue(), + getCombineDate(fromDate, fromTime), + getCombineDate(toDate, toTime)); + } + + @UiHandler("clearButton") + public void onClearClicked(SelectEvent event) { + archiveHandler.onClear(); } + private StoreHandlers<Device> deviceStoreHandlers = new BaseStoreHandlers<Device>() { + + @Override + public void onAnything() { + deviceCombo.setValue(deviceStore.findModel(deviceCombo.getValue())); + } + + }; + } diff --git a/src/org/traccar/web/client/view/ArchiveView.ui.xml b/src/org/traccar/web/client/view/ArchiveView.ui.xml index 370eb02..f27d38f 100644 --- a/src/org/traccar/web/client/view/ArchiveView.ui.xml +++ b/src/org/traccar/web/client/view/ArchiveView.ui.xml @@ -16,7 +16,7 @@ <ui:attributes width="1" height="1" /> </ui:with> - <ui:with type="com.sencha.gxt.data.shared.ListStore" field="store" /> + <ui:with type="com.sencha.gxt.data.shared.ListStore" field="positionStore" /> <ui:with type="com.sencha.gxt.widget.core.client.grid.ColumnModel" field="columnModel" /> <ui:with type="com.sencha.gxt.widget.core.client.grid.GridView" field="view"> @@ -30,28 +30,30 @@ <toolbar:ToolBar> <toolbar:LabelToolItem label="Device:" /> - <form:TimeField /> <!-- put combobox here --> + <form:ComboBox ui:field="deviceCombo" editable="false" triggerAction="ALL" /> <toolbar:SeparatorToolItem /> <toolbar:LabelToolItem label="From:" /> - <form:DateField width="125" /> + <form:DateField width="125" ui:field="fromDate" /> <toolbar:LabelToolItem width="5" /> - <form:TimeField width="75" /> + <form:TimeField width="75" ui:field="fromTime" triggerAction="ALL" /> <toolbar:SeparatorToolItem /> <toolbar:LabelToolItem label="To:" /> - <form:DateField width="125" /> + <form:DateField width="125" ui:field="toDate" /> <toolbar:LabelToolItem width="5" /> - <form:TimeField width="75" /> + <form:TimeField width="75" ui:field="toTime" triggerAction="ALL" /> <toolbar:SeparatorToolItem /> - + <button:TextButton ui:field="loadButton" text="Load" /> - + <toolbar:FillToolItem /> + <button:TextButton ui:field="clearButton" text="Clear" /> + </toolbar:ToolBar> </container:child> <container:child layoutData="{layoutData}"> - <grid:Grid ui:field="grid" store="{store}" cm="{columnModel}" view="{view}" /> + <grid:Grid ui:field="grid" store="{positionStore}" cm="{columnModel}" view="{view}" /> </container:child> </container:VerticalLayoutContainer> diff --git a/src/org/traccar/web/client/view/DeviceView.java b/src/org/traccar/web/client/view/DeviceView.java index 157973e..1213e5f 100644 --- a/src/org/traccar/web/client/view/DeviceView.java +++ b/src/org/traccar/web/client/view/DeviceView.java @@ -1,6 +1,5 @@ package org.traccar.web.client.view; -import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -11,7 +10,6 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.sencha.gxt.core.client.Style.SelectionMode; import com.sencha.gxt.data.shared.ListStore; @@ -23,7 +21,7 @@ import com.sencha.gxt.widget.core.client.grid.ColumnModel; import com.sencha.gxt.widget.core.client.grid.Grid; import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent; -public class DeviceView extends Composite implements SelectionChangedEvent.SelectionChangedHandler<Device> { +public class DeviceView implements SelectionChangedEvent.SelectionChangedHandler<Device> { private static DeviceViewUiBinder uiBinder = GWT.create(DeviceViewUiBinder.class); @@ -59,13 +57,14 @@ public class DeviceView extends Composite implements SelectionChangedEvent.Selec ColumnModel<Device> columnModel; @UiField(provided = true) - ListStore<Device> store; + ListStore<Device> deviceStore; @UiField Grid<Device> grid; - public DeviceView(DeviceHandler deviceHandler) { + public DeviceView(DeviceHandler deviceHandler, ListStore<Device> deviceStore) { this.deviceHandler = deviceHandler; + this.deviceStore = deviceStore; DeviceProperties deviceProperties = GWT.create(DeviceProperties.class); @@ -74,8 +73,6 @@ public class DeviceView extends Composite implements SelectionChangedEvent.Selec columnConfigList.add(new ColumnConfig<Device, String>(deviceProperties.uniqueId(), 0, "Unique Identifier")); columnModel = new ColumnModel<Device>(columnConfigList); - store = new ListStore<Device>(deviceProperties.id()); - uiBinder.createAndBindUi(this); grid.getSelectionModel().addSelectionChangedHandler(this); @@ -94,35 +91,19 @@ public class DeviceView extends Composite implements SelectionChangedEvent.Selec } } - public void load(Collection<Device> devices) { - store.addAll(devices); - } - @UiHandler("addButton") public void onAddClicked(SelectEvent event) { deviceHandler.onAdd(); } - public void add(Device device) { - store.add(store.size(), device); - } - @UiHandler("editButton") public void onEditClicked(SelectEvent event) { deviceHandler.onEdit(grid.getSelectionModel().getSelectedItem()); } - public void update(Device device) { - store.update(device); - } - @UiHandler("removeButton") public void onRemoveClicked(SelectEvent event) { deviceHandler.onRemove(grid.getSelectionModel().getSelectedItem()); } - public void remove(Device device) { - store.remove(device); - } - } diff --git a/src/org/traccar/web/client/view/DeviceView.ui.xml b/src/org/traccar/web/client/view/DeviceView.ui.xml index d9988d5..af1b33c 100644 --- a/src/org/traccar/web/client/view/DeviceView.ui.xml +++ b/src/org/traccar/web/client/view/DeviceView.ui.xml @@ -15,7 +15,7 @@ <ui:attributes width="1" height="1" /> </ui:with> - <ui:with type="com.sencha.gxt.data.shared.ListStore" field="store" /> + <ui:with type="com.sencha.gxt.data.shared.ListStore" field="deviceStore" /> <ui:with type="com.sencha.gxt.widget.core.client.grid.ColumnModel" field="columnModel" /> <ui:with type="com.sencha.gxt.widget.core.client.grid.GridView" field="view"> @@ -37,7 +37,7 @@ </container:child> <container:child layoutData="{layoutData}"> - <grid:Grid ui:field="grid" store="{store}" cm="{columnModel}" view="{view}" /> + <grid:Grid ui:field="grid" store="{deviceStore}" cm="{columnModel}" view="{view}" /> </container:child> </container:VerticalLayoutContainer> diff --git a/src/org/traccar/web/server/model/DataServiceImpl.java b/src/org/traccar/web/server/model/DataServiceImpl.java index cfcc622..f9d0e7e 100644 --- a/src/org/traccar/web/server/model/DataServiceImpl.java +++ b/src/org/traccar/web/server/model/DataServiceImpl.java @@ -90,8 +90,10 @@ public class DataServiceImpl extends RemoteServiceServlet implements DataService entityManager.getTransaction().begin(); try { entityManager.persist(user); - } finally { entityManager.getTransaction().commit(); + } catch (Exception e) { + entityManager.getTransaction().rollback(); + throw e; } setUser(user); return true; @@ -112,8 +114,10 @@ public class DataServiceImpl extends RemoteServiceServlet implements DataService try { entityManager.persist(device); user.getDevices().add(device); - } finally { entityManager.getTransaction().commit(); + } catch (Exception e) { + entityManager.getTransaction().rollback(); + throw e; } return device; } @@ -123,8 +127,10 @@ public class DataServiceImpl extends RemoteServiceServlet implements DataService entityManager.getTransaction().begin(); try { device = entityManager.merge(device); - } finally { entityManager.getTransaction().commit(); + } catch (Exception e) { + entityManager.getTransaction().rollback(); + throw e; } return device; } @@ -137,8 +143,10 @@ public class DataServiceImpl extends RemoteServiceServlet implements DataService device = entityManager.merge(device); user.getDevices().remove(device); entityManager.remove(device); - } finally { entityManager.getTransaction().commit(); + } catch (Exception e) { + entityManager.getTransaction().rollback(); + throw e; } return device; } diff --git a/src/org/traccar/web/shared/model/Position.java b/src/org/traccar/web/shared/model/Position.java index 1382730..2980860 100644 --- a/src/org/traccar/web/shared/model/Position.java +++ b/src/org/traccar/web/shared/model/Position.java @@ -11,6 +11,8 @@ import javax.persistence.Table; import org.hibernate.annotations.Index; +//INSERT INTO positions (device_id, valid, time, latitude, longitude, altitude, speed, course) VALUES (11, 1, NOW(), 60, 30, 0, 0, 0); + @Entity @Table(name = "positions") public class Position implements Serializable, Cloneable { |