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;
+ }
}