diff --git a/java/com.sap.sailing.gwt.ui/.classpath b/java/com.sap.sailing.gwt.ui/.classpath index f20594dd0e9..bc837f182f1 100755 --- a/java/com.sap.sailing.gwt.ui/.classpath +++ b/java/com.sap.sailing.gwt.ui/.classpath @@ -1,12 +1,12 @@ + + - - - - - + + + diff --git a/java/com.sap.sailing.gwt.ui/AdminConsole.html b/java/com.sap.sailing.gwt.ui/AdminConsole.html index 7fe957dfabe..ea380dc9ac4 100644 --- a/java/com.sap.sailing.gwt.ui/AdminConsole.html +++ b/java/com.sap.sailing.gwt.ui/AdminConsole.html @@ -20,7 +20,7 @@ SAP Sailing Analytics Administration Console - + diff --git a/java/com.sap.sailing.gwt.ui/AdminConsoleDateTimePicker.css b/java/com.sap.sailing.gwt.ui/AdminConsoleDateTimePicker.css new file mode 100644 index 00000000000..f93eb68fa0b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/AdminConsoleDateTimePicker.css @@ -0,0 +1,88 @@ +/*! + * Extracted from Bootstrap v3.0.2 by @fat and @mdo + * Copyright 2013 Twitter, Inc. + * Licensed under http://www.apache.org/licenses/LICENSE-2.0 + */ + +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #428bca; + outline: 0; +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index 8749a6c5e16..710b6c6c104 100755 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -42,5 +42,6 @@ Web-ContextPath: /gwt Bundle-ClassPath: WEB-INF/classes/, WEB-INF/lib/gwt-servlet.jar, WEB-INF/lib/gwt-maps-api-3.9.0-build-17.jar, - WEB-INF/lib/gwt-ajaxloader.jar + WEB-INF/lib/gwt-ajaxloader.jar, + WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar TrackLifecycle: true diff --git a/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar b/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar new file mode 100644 index 00000000000..ed9cab41ba1 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar differ diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index 88c81e2e761..5896d20ddbe 100755 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -46,5 +46,6 @@ bin.includes = META-INF/,\ PolarSheets.css,\ PolarSheets.html,\ ViewerToolbar.css,\ - CommonGwtControls.css + CommonGwtControls.css,\ + AdminConsoleDateTimePicker.css output.. = WEB-INF/classes/ diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index 95ab316fb71..8ff11185382 100644 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -13,6 +13,15 @@ 2.5.1 + + + sonatype + http://oss.sonatype.org/content/repositories/snapshots + true + false + + + @@ -39,6 +48,12 @@ 1.0.0-SNAPSHOT sources + + com.github.gwtbootstrap + gwt-bootstrap + 2.2.1.0 + provided + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index a7ce6453c06..3720c91365c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -23,6 +23,7 @@ import com.sap.sailing.gwt.ui.client.shared.controls.ScrolledTabLayoutPanel; import com.sap.sailing.gwt.ui.client.shared.panels.SystemInformationPanel; import com.sap.sailing.gwt.ui.client.shared.panels.UserStatusPanel; import com.sap.sailing.gwt.ui.masterdataimport.MasterDataImportPanel; +import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox; import com.sap.sailing.gwt.ui.shared.RegattaDTO; public class AdminConsoleEntryPoint extends AbstractEntryPoint implements RegattaRefresher { @@ -33,6 +34,8 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt @Override protected void doOnModuleLoad() { super.doOnModuleLoad(); + BetterDateTimeBox.initialize(); + RootLayoutPanel rootPanel = RootLayoutPanel.get(); DockLayoutPanel dockPanel = new DockLayoutPanel(Unit.EM); rootPanel.add(dockPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java index 52845d4fd81..7943b3ef518 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java @@ -49,4 +49,7 @@ interface AdminConsoleResources extends ClientBundle { @Source("com/sap/sailing/gwt/ui/client/images/help.png") ImageResource help(); + + @Source("com/sap/sailing/gwt/ui/client/images/clock.png") + ImageResource clock(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index bfc430a8779..e60bc6a6337 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -52,7 +52,6 @@ import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.gwt.ui.adminconsole.DisablableCheckboxCell.IsEnabled; import com.sap.sailing.gwt.ui.adminconsole.RaceColumnInLeaderboardDialog.RaceColumnDescriptor; import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback; -import com.sap.sailing.gwt.ui.client.shared.panels.AbstractFilterablePanel; import com.sap.sailing.gwt.ui.client.ErrorReporter; import com.sap.sailing.gwt.ui.client.MarkedAsyncCallback; import com.sap.sailing.gwt.ui.client.ParallelExecutionCallback; @@ -64,10 +63,12 @@ import com.sap.sailing.gwt.ui.client.RegattaDisplayer; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.URLEncoder; +import com.sap.sailing.gwt.ui.client.shared.panels.AbstractFilterablePanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint; import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; @@ -514,6 +515,8 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb unlinkRaceColumnFromTrackedRace(object.getA().getRaceColumnName(), object.getB()); } else if (LeaderboardRaceConfigImagesBarCell.ACTION_REFRESH_RACELOG.equals(value)) { refreshRaceLog(object.getA(), object.getB(), true); + } else if(LeaderboardRaceConfigImagesBarCell.ACTION_SET_STARTTIME.equals(value)) { + setStartTime(object.getA(), object.getB()); } } }); @@ -705,6 +708,31 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb }); } + private void setStartTime(RaceColumnDTO raceColumnDTO, FleetDTO fleetDTO) { + new SetStartTimeDialog(sailingService, errorReporter, getSelectedLeaderboardName(), raceColumnDTO.getName(), + fleetDTO.getName(), stringMessages, new DialogCallback() { + @Override + public void ok(RaceLogSetStartTimeDTO editedObject) { + sailingService.setStartTime(editedObject, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(caught.getMessage()); + } + + @Override + public void onSuccess(Boolean result) { + if (!result) { + Window.alert("Failed to set new start time."); + } + } + }); + } + + @Override + public void cancel() { } + }).show(); + } + private void refreshRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleet, final boolean showAlerts) { final String selectedLeaderboardName = getSelectedLeaderboardName(); sailingService.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, new AsyncCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index 7b9312983e1..1d8ec4c7488 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -10,10 +10,12 @@ import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { - public static final String ACTION_REMOVE = "ACTION_REMOVE"; - public static final String ACTION_UNLINK = "ACTION_UNLINK"; - public static final String ACTION_EDIT = "ACTION_EDIT"; + public final static String ACTION_REMOVE = "ACTION_REMOVE"; + public final static String ACTION_UNLINK = "ACTION_UNLINK"; + public final static String ACTION_EDIT = "ACTION_EDIT"; public final static String ACTION_REFRESH_RACELOG = "ACTION_REFRESH_RACE_LOG"; + public final static String ACTION_SET_STARTTIME = "ACTION_SET_STARTTIME"; + private final StringMessages stringMessages; private final SelectedLeaderboardProvider selectedLeaderboardProvider; private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); @@ -35,6 +37,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(resources.removeIcon()))); } result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); + result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clock()))); return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SetStartTimeDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SetStartTimeDialog.java new file mode 100644 index 00000000000..63e1bf8d97d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SetStartTimeDialog.java @@ -0,0 +1,153 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.Date; + +import com.github.gwtbootstrap.datetimepicker.client.ui.base.HasViewMode.ViewMode; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.logical.shared.AttachEvent; +import com.google.gwt.event.logical.shared.AttachEvent.Handler; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.CaptionPanel; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.PushButton; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.gwt.ui.client.DataEntryDialog; +import com.sap.sailing.gwt.ui.client.ErrorReporter; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox; +import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeDTO; + +public class SetStartTimeDialog extends DataEntryDialog { + + private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); + + private final SailingServiceAsync service; + private final ErrorReporter errorReporter; + private final String leaderboardName; + private final String raceColumnName; + private final String fleetName; + private final StringMessages stringMessages; + + private Label currentStartTimeLabel; + private Label currentPassIdBox; + private BetterDateTimeBox box; + + public SetStartTimeDialog(SailingServiceAsync service, ErrorReporter errorReporter, String leaderboardName, + String raceColumnName, String fleetName, StringMessages stringMessages, + DataEntryDialog.DialogCallback callback) { + super(stringMessages.setStartTime(), "Select a new start time for the race", stringMessages.setStartTime(), stringMessages.cancel(), null, callback); + this.service = service; + this.errorReporter = errorReporter; + this.stringMessages = stringMessages; + this.leaderboardName = leaderboardName; + this.raceColumnName = raceColumnName; + this.fleetName = fleetName; + } + + @Override + protected Widget getAdditionalWidget() { + VerticalPanel content = new VerticalPanel(); + content.add(createCurrentPanel()); + content.add(createInputPanel()); + refreshCurrentStartTime(); + return content; + } + + private Widget createCurrentPanel() { + CaptionPanel current = new CaptionPanel(stringMessages.liveData()); + HorizontalPanel currentPanel = new HorizontalPanel(); + currentPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); + Grid grid = new Grid(2,2); + currentStartTimeLabel = new Label(""); + grid.setWidget(0, 0, createLabel(stringMessages.startTime())); + grid.setWidget(0, 1, currentStartTimeLabel); + + currentPassIdBox = new Label(""); + grid.setWidget(1, 0, createLabel(stringMessages.currentPass())); + grid.setWidget(1, 1, currentPassIdBox); + currentPanel.add(grid); + + PushButton refreshButton = new PushButton(new Image(resources.reloadIcon())); + refreshButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + refreshCurrentStartTime(); + } + }); + currentPanel.add(refreshButton); + + current.add(currentPanel); + return current; + } + + private Widget createInputPanel() { + SimplePanel content = new SimplePanel(); + box = new BetterDateTimeBox(); + box.addAttachHandler(new Handler() { + @Override + public void onAttachOrDetach(AttachEvent event) { + if (event.isAttached()) { + addAutoHidePartner(box.getPicker()); + } + } + }); + box.setAutoClose(true); + box.setStartView(ViewMode.HOUR); + box.setFormat("dd/mm/yyyy hh:ii"); + content.add(box); + return content; + } + + @Override + protected RaceLogSetStartTimeDTO getResult() { + RaceLogSetStartTimeDTO dto = new RaceLogSetStartTimeDTO(); + dto.leaderboardName = leaderboardName; + dto.raceColumnName = raceColumnName; + dto.fleetName = fleetName; + dto.authorName = "Shore"; + dto.authorPriority = 4; + dto.logicalTimePoint = new Date(); + dto.startTime = box.getValue(); + dto.passId = -1; + return dto; + } + + private void refreshCurrentStartTime() { + service.getStartTime(leaderboardName, raceColumnName, fleetName, new AsyncCallback>() { + + @Override + public void onSuccess(Pair result) { + if (result == null) { + currentStartTimeLabel.setText(stringMessages.notAvailable()); + currentPassIdBox.setText(stringMessages.notAvailable()); + } else { + Date startTime = result.getA(); + if (startTime == null) { + currentStartTimeLabel.setText(stringMessages.unknown()); + } else { + currentStartTimeLabel.setText(DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM).format(startTime)); + } + currentPassIdBox.setText(result.getB().toString()); + } + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(caught.getMessage()); + } + }); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DataEntryDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DataEntryDialog.java index c2e9293fbe4..f006bae68eb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DataEntryDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DataEntryDialog.java @@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.client; import java.util.Date; +import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.dom.client.Style.Unit; @@ -427,4 +428,8 @@ public abstract class DataEntryDialog { public void ensureDebugId(String debugId) { dateEntryDialog.ensureDebugId(debugId); } + + protected void addAutoHidePartner(Element element) { + dateEntryDialog.addAutoHidePartner(element); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 17e9ea74c46..cdcb2265055 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -47,6 +47,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; +import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -351,4 +352,8 @@ public interface SailingService extends RemoteService { DeviceConfigurationMatcherDTO createOrUpdateDeviceConfiguration(DeviceConfigurationMatcherDTO matcherDTO, DeviceConfigurationDTO configurationDTO); boolean removeDeviceConfiguration(DeviceConfigurationMatcherDTO.Type type, List clientIds); + + boolean setStartTime(RaceLogSetStartTimeDTO dto); + + Pair getStartTime(String leaderboardName, String raceColumnName, String fleetName); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index fb1e05fdeac..ac1e05ddc70 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -47,6 +47,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; +import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -471,7 +472,12 @@ public interface SailingServiceAsync { void createOrUpdateDeviceConfiguration(DeviceConfigurationMatcherDTO matcherDTO, DeviceConfigurationDTO configurationDTO, AsyncCallback callback); - void removeDeviceConfiguration(DeviceConfigurationMatcherDTO.Type type, List clientIds, AsyncCallback asyncCallback); + void removeDeviceConfiguration(DeviceConfigurationMatcherDTO.Type type, List clientIds, AsyncCallback asyncCallback); + + void setStartTime(RaceLogSetStartTimeDTO dto, AsyncCallback callback); + + void getStartTime(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback> callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index b80331a56ca..d67065354c5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -870,4 +870,7 @@ public interface StringMessages extends Messages { String configured(); String overwriteRacingProceduresConfiguration(); String overwriteRacingProceduresConfigurationHelpText(); + + String setStartTime(); + String currentPass(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 6d3babdf16f..aa70ba57ad7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -859,4 +859,6 @@ essStart=ESS Start basicStart=Basic Start configured=Configured overwriteRacingProceduresConfiguration=Overwrite racing procedures configuration -overwriteRacingProceduresConfigurationHelpText=Enabling this option will overwrite any racing procedure configuration that might be attached to a Regatta. \ No newline at end of file +overwriteRacingProceduresConfigurationHelpText=Enabling this option will overwrite any racing procedure configuration that might be attached to a Regatta. +setStartTime=Set start time +currentPass=Current pass \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 6c653fde12a..7cdb0d524de 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -855,4 +855,6 @@ essStart=ESS Start basicStart=Basic Start configured=Konfiguriert overwriteRacingProceduresConfiguration=Überschreibe Konfiguration der Rennarten -overwriteRacingProceduresConfigurationHelpText=Wenn aktiviert überschreibt jegliche Konfiguration der Rennarten durch eine Regatta. \ No newline at end of file +overwriteRacingProceduresConfigurationHelpText=Wenn aktiviert überschreibt jegliche Konfiguration der Rennarten durch eine Regatta. +setStartTime=Setze Startzeit +currentPass=Aktueller Pass \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index b3760dd9c89..9a759a27126 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -226,6 +226,7 @@ import com.sap.sailing.gwt.ui.shared.RaceInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceInfoDTO.GateStartInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceInfoDTO.RRS26InfoDTO; import com.sap.sailing.gwt.ui.shared.RaceInfoDTO.RaceInfoExtensionDTO; +import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -3523,4 +3524,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return procedures; } + @Override + public boolean setStartTime(RaceLogSetStartTimeDTO dto) { + TimePoint newStartTime = getService().setStartTime(dto.leaderboardName, dto.raceColumnName, + dto.fleetName, dto.authorName, dto.authorPriority, + dto.passId, new MillisecondsTimePoint(dto.logicalTimePoint), new MillisecondsTimePoint(dto.startTime)); + return new MillisecondsTimePoint(dto.startTime).equals(newStartTime); + } + + @Override + public Pair getStartTime(String leaderboardName, String raceColumnName, String fleetName) { + Pair result = getService().getStartTime(leaderboardName, raceColumnName, fleetName); + if (result == null) { + return null; + } + return new Pair(result.getA().asDate(), result.getB()); + } + } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/BetterDateTimeBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/BetterDateTimeBox.java new file mode 100644 index 00000000000..9098a8e273e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/BetterDateTimeBox.java @@ -0,0 +1,29 @@ +package com.sap.sailing.gwt.ui.shared; + +import com.github.gwtbootstrap.client.ui.resources.ResourceInjector; +import com.github.gwtbootstrap.datetimepicker.client.ui.DateTimeBox; +import com.github.gwtbootstrap.datetimepicker.client.ui.resources.DatetimepickerResourceInjector; +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.dom.client.Element; + +public class BetterDateTimeBox extends DateTimeBox { + + /** + * Initializes all needed JavaScript and CSS. Should be called once per {@link EntryPoint}. + */ + public static void initialize() { + // We don't want the full bootstrap css... + ResourceInjector.injectResourceCssAsFile("font-awesome.min.css"); + ResourceInjector.configure(); + DatetimepickerResourceInjector.configureWithCssFile(); + } + + public Element getPicker() { + return getNativePickerElement(getBox().getElement()); + } + + private native Element getNativePickerElement(Element boxElement) /*-{ + return $wnd.jQuery(boxElement).data('datetimepicker').picker[0]; + }-*/; + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceLogSetStartTimeDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceLogSetStartTimeDTO.java new file mode 100644 index 00000000000..67958f30996 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceLogSetStartTimeDTO.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.ui.shared; + +import java.util.Date; + +import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; + +public class RaceLogSetStartTimeDTO implements IsSerializable { + public String leaderboardName; + public String raceColumnName; + public String fleetName; + public int passId; + public String authorName; + public int authorPriority; + public Date logicalTimePoint; + public Date startTime; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/AdminConsole.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/AdminConsole.gwt.xml index d1004ad8f80..26c525dceb9 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/AdminConsole.gwt.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/AdminConsole.gwt.xml @@ -4,7 +4,7 @@ - + @@ -16,6 +16,7 @@ + @@ -24,7 +25,12 @@ - + + + + + + @@ -40,7 +46,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/clock.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/clock.png new file mode 100644 index 00000000000..e2672c20676 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/clock.png differ diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java index b65e90ca113..60a10780156 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java @@ -35,6 +35,7 @@ import com.sap.sailing.domain.common.RegattaFetcher; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.impl.Util.Pair; @@ -49,6 +50,8 @@ import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.racelog.RaceLogEventAuthor; +import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.RaceListener; import com.sap.sailing.domain.tracking.RaceTracker; @@ -455,7 +458,27 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch * Returns all configurations and their matching objects. * @return the {@link DeviceConfiguration}s. */ - Map getAllDeviceConfigurations(); + Map getAllDeviceConfigurations(); + + /** + * Sets a new start time on the RaceLog identified by the passed parameters. + * @param leaderboardName name of the RaceLog's leaderboard. + * @param raceColumnName name of the RaceLog's column + * @param fleetName name of the RaceLog's fleet + * @param authorName name of the {@link RaceLogEventAuthor} the {@link RaceLogStartTimeEvent} will be created with + * @param authorPriority priority of the author. + * @param passId Pass identifier of the new start time event. + * @param logicalTimePoint logical {@link TimePoint} of the new event. + * @param startTime the new Start-Time + * @return + */ + TimePoint setStartTime(String leaderboardName, String raceColumnName, String fleetName, String authorName, + int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime); + + /** + * Gets the start time and pass identifier for the queried race. + */ + Pair getStartTime(String leaderboardName, String raceColumnName, String fleetName); MongoObjectFactory getMongoObjectFactory(); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 30585a2c40e..5ccbcfba4c1 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -91,6 +91,11 @@ import com.sap.sailing.domain.persistence.media.MediaDB; import com.sap.sailing.domain.persistence.media.MediaDBFactory; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl; +import com.sap.sailing.domain.racelog.state.RaceState; +import com.sap.sailing.domain.racelog.state.ReadonlyRaceState; +import com.sap.sailing.domain.racelog.state.impl.RaceStateImpl; +import com.sap.sailing.domain.racelog.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFix; @@ -2027,5 +2032,39 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen public Map getAllDeviceConfigurations() { return new HashMap(configurationMap); } + + @Override + public TimePoint setStartTime(String leaderboardName, String raceColumnName, String fleetName, String authorName, + int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime) { + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + if (raceLog != null) { + RaceState state = RaceStateImpl.create(raceLog, new RaceLogEventAuthorImpl(authorName, authorPriority)); + state.setStartTime(logicalTimePoint, startTime); + return state.getStartTime(); + } + return null; + } + + private RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + Fleet fleetImpl = raceColumn.getFleetByName(fleetName); + return raceColumn.getRaceLog(fleetImpl); + } + } + return null; + } + + @Override + public Pair getStartTime(String leaderboardName, String raceColumnName, String fleetName) { + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + if (raceLog != null) { + ReadonlyRaceState state = ReadonlyRaceStateImpl.create(raceLog); + return new Pair(state.getStartTime(), raceLog.getCurrentPassId()); + } + return null; + } }