From 526d8634d7288496cdaf700a6b82ab5b3d727cd8 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 9 Nov 2014 01:11:49 +0100 Subject: [PATCH 1/8] moved BuildVersionRetriever from adminconsole bundle to com.sap.sse.gwt to avoid, e.g., Home.gwt.xml having to know about adminconsole --- .../java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java | 2 +- .../src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java | 1 + .../com/sap/sse/gwt/adminconsole/SystemInformationPanel.java | 1 + .../src/com/sap/sse/gwt/client}/BuildVersionRetriever.java | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) rename java/{com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole => com.sap.sse.gwt/src/com/sap/sse/gwt/client}/BuildVersionRetriever.java (77%) 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 b86d078800c..1133e9d1a7a 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 @@ -76,7 +76,7 @@ import com.sap.sailing.gwt.ui.shared.WindDTO; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sse.common.Util; import com.sap.sse.common.search.KeywordQuery; -import com.sap.sse.gwt.adminconsole.BuildVersionRetriever; +import com.sap.sse.gwt.client.BuildVersionRetriever; /** * The async counterpart of {@link SailingService} diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java index 4a3b5635fca..61dfbc612f0 100755 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java @@ -18,6 +18,7 @@ import com.google.gwt.user.client.ui.TabLayoutPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sse.common.Util.Triple; import com.sap.sse.gwt.client.AbstractEntryPoint; +import com.sap.sse.gwt.client.BuildVersionRetriever; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel; import com.sap.sse.security.ui.client.UserService; diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java index 58432468f30..3bf5f9e8635 100644 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java @@ -5,6 +5,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; +import com.sap.sse.gwt.client.BuildVersionRetriever; import com.sap.sse.gwt.client.ErrorReporter; public class SystemInformationPanel extends FlowPanel { diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/BuildVersionRetriever.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/BuildVersionRetriever.java similarity index 77% rename from java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/BuildVersionRetriever.java rename to java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/BuildVersionRetriever.java index a67ef0950bd..1be70fe9512 100755 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/BuildVersionRetriever.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/BuildVersionRetriever.java @@ -1,4 +1,4 @@ -package com.sap.sse.gwt.adminconsole; +package com.sap.sse.gwt.client; import com.google.gwt.user.client.rpc.AsyncCallback; From 762d765790091f0948aaa102e517b31d97440598 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 10 Nov 2014 11:07:34 +0100 Subject: [PATCH 2/8] fixed security properties --- java/target/configuration/security.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/target/configuration/security.properties b/java/target/configuration/security.properties index 8c69b875c76..74186c0e18c 100644 --- a/java/target/configuration/security.properties +++ b/java/target/configuration/security.properties @@ -1,16 +1,16 @@ # mail configuration, e.g., for password recovery mail.enabled = false # For production: -#mail.from = noreply@sapsailing.com +mail.from = noreply@sapsailing.com # For testing: -mail.from = uhl@homemp3.dyndns.org +#mail.from = uhl@homemp3.dyndns.org mail.transport.protocol = smtp # For production: -#mail.smtp.host = 127.0.0.1 +mail.smtp.host = 127.0.0.1 # For testing internally: #mail.smtp.host = mail.sap.corp # For testing externally: -mail.smtp.host = www.axel-uhl.de +#mail.smtp.host = www.axel-uhl.de mail.smtp.port = 25 mail.smtp.auth = true mail.smtp.user = From c321fa18379acd1f3f67816873677dd9c64a5430 Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 10 Nov 2014 13:10:33 +0100 Subject: [PATCH 3/8] removed old TvView entrypoint (replaced by new AutoPlay entrypoint) --- ...WT Remote Profiling (Run-Mode only).launch | 4 +- java/com.sap.sailing.gwt.ui/SailingGWT.launch | 20 +- java/com.sap.sailing.gwt.ui/TvView.html | 33 --- java/com.sap.sailing.gwt.ui/build.properties | 1 - java/com.sap.sailing.gwt.ui/pom.xml | 1 - .../sap/sailing/gwt/ui/tv/TVEntryPoint.java | 105 ------- .../sailing/gwt/ui/tv/TVViewController.java | 276 ------------------ .../com/sap/sailing/gwt/ui/tv/TVViews.java | 5 - .../com/sap/sailing/gwt/ui/TvView.gwt.xml | 50 ---- 9 files changed, 3 insertions(+), 492 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/TvView.html delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVEntryPoint.java delete mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViewController.java delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViews.java delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/TvView.gwt.xml diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch index 0eb43530370..153664ac643 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch @@ -51,9 +51,9 @@ - + - + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index 00c608ff9af..d6bbafea3e2 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -3,24 +3,6 @@ - - - - - - - - - - - - - - - - - - @@ -69,7 +51,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/TvView.html b/java/com.sap.sailing.gwt.ui/TvView.html deleted file mode 100644 index 2a0619c18f9..00000000000 --- a/java/com.sap.sailing.gwt.ui/TvView.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - SAP Sailing Analytics TV View - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index 9a09c11a784..ee88e572d5e 100755 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -41,7 +41,6 @@ bin.includes = META-INF/,\ VideoPopup.css,\ com.sap.sailing.gwt.ui.YoutubePopup/,\ YoutubePopup.html,\ - TvView.html,\ com.sap.sailing.gwt.ui.TvView/,\ BrowserUnsupported.html,\ PolarSheets.css,\ diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index 5485f83e539..f4a1bd2c1a3 100644 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -127,7 +127,6 @@ com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.DataMining - com.sap.sailing.gwt.ui.TvView com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVEntryPoint.java deleted file mode 100644 index bd59f8926cd..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVEntryPoint.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.sap.sailing.gwt.ui.tv; - -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.rpc.ServiceDefTarget; -import com.google.gwt.user.client.ui.DockLayoutPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.RootLayoutPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; -import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel; -import com.sap.sailing.gwt.ui.client.MediaService; -import com.sap.sailing.gwt.ui.client.MediaServiceAsync; -import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; -import com.sap.sailing.gwt.ui.client.SailingService; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; -import com.sap.sse.gwt.client.EntryPointHelper; -import com.sap.sse.gwt.shared.GwtHttpRequestUtils; - -public class TVEntryPoint extends AbstractSailingEntryPoint { - - private static final String PARAM_LEADERBOARD_NAME = "name"; - private static final String PARAM_LEADERBOARD_GROUP_NAME = "leaderboardGroupName"; - private static final String PARAM_EMBEDDED = "embedded"; - private static final String PARAM_SHOW_RACE_DETAILS = "showRaceDetails"; - private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis"; - private String leaderboardName; - private String leaderboardGroupName; - private TVViewController tvViewController; - private RaceBoardViewConfiguration raceboardViewConfig; - - private final SailingServiceAsync sailingService = GWT.create(SailingService.class); - private final MediaServiceAsync mediaService = GWT.create(MediaService.class); - - @Override - public void doOnModuleLoad() { - super.doOnModuleLoad(); - - EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.sailingServiceRemotePath); - EntryPointHelper.registerASyncService((ServiceDefTarget) mediaService, RemoteServiceMappingConstants.mediaServiceRemotePath); - - final boolean showRaceDetails = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_RACE_DETAILS, true); - final boolean embedded = GwtHttpRequestUtils.getBooleanParameter(PARAM_EMBEDDED, false); - final long delayToLiveMillis = Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS) != null ? Long - .valueOf(Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS)) : 5000l; // default 5s - final boolean showLeaderboard = GwtHttpRequestUtils.getBooleanParameter( - RaceBoardViewConfiguration.PARAM_VIEW_SHOW_LEADERBOARD, true /* default */); - final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter( - RaceBoardViewConfiguration.PARAM_VIEW_SHOW_WINDCHART, false /* default */); - final boolean showViewStreamlets = GwtHttpRequestUtils.getBooleanParameter( - RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLETS, false /* default */); - final boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter( - RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, false /* default */); - final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter( - RaceBoardViewConfiguration.PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default */); - String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/); - final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default */); - final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, false); - raceboardViewConfig = new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard, - showWindChart, showCompetitorsChart, showViewStreamlets, showViewSimulation, /* canReplayWhileLiveIsPossible */false, autoSelectMedia, defaultMedia); - - sailingService.getLeaderboardNames(new AsyncCallback>() { - @Override - public void onSuccess(List leaderboardNames) { - leaderboardName = Window.Location.getParameter(PARAM_LEADERBOARD_NAME); - leaderboardGroupName = Window.Location.getParameter(PARAM_LEADERBOARD_GROUP_NAME); - if (leaderboardNames.contains(leaderboardName)) { - createUI(showRaceDetails, embedded, delayToLiveMillis); - } else { - RootPanel.get().add(new Label(getStringMessages().noSuchLeaderboard())); - } - } - - @Override - public void onFailure(Throwable t) { - reportError("Error trying to obtain list of leaderboard names: " + t.getMessage()); - } - }); - } - - private void createUI(boolean showRaceDetails, boolean embedded, long delayToLiveMillis) { - DockLayoutPanel mainPanel = new DockLayoutPanel(Unit.PX); - RootLayoutPanel.get().add(mainPanel); - LogoAndTitlePanel logoAndTitlePanel = null; - if (!embedded) { - String leaderboardDisplayName = Window.Location.getParameter("displayName"); - if(leaderboardDisplayName == null || leaderboardDisplayName.isEmpty()) { - leaderboardDisplayName = leaderboardName; - } - logoAndTitlePanel = new LogoAndTitlePanel(leaderboardGroupName, leaderboardDisplayName, getStringMessages(), this, getUserService()); - logoAndTitlePanel.addStyleName("LogoAndTitlePanel"); - mainPanel.addNorth(logoAndTitlePanel, 68); - } - - tvViewController = new TVViewController(sailingService, mediaService, getUserService(), getStringMessages(), - this, leaderboardGroupName, leaderboardName, userAgent, logoAndTitlePanel, mainPanel, - delayToLiveMillis, showRaceDetails, raceboardViewConfig); - tvViewController.updateTvView(TVViews.Leaderboard); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViewController.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViewController.java deleted file mode 100755 index ae36f35b534..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViewController.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.sap.sailing.gwt.ui.tv; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.ui.DockLayoutPanel; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.ScrollPanel; -import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.LeaderboardDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; -import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel; -import com.sap.sailing.gwt.ui.client.MediaServiceAsync; -import com.sap.sailing.gwt.ui.client.RaceSelectionModel; -import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; -import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; -import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; -import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; -import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel; -import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; -import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; -import com.sap.sse.gwt.client.ErrorReporter; -import com.sap.sse.gwt.client.async.AsyncActionsExecutor; -import com.sap.sse.gwt.client.player.Timer; -import com.sap.sse.gwt.client.player.Timer.PlayModes; -import com.sap.sse.gwt.client.useragent.UserAgentDetails; -import com.sap.sse.security.ui.client.UserService; - -public class TVViewController implements RaceTimesInfoProviderListener { - private static final int REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD = 10000; - private static final long REFRESH_INTERVAL_IN_MILLIS_RACEBOARD = 1000; - private final SailingServiceAsync sailingService; - private final MediaServiceAsync mediaService; - private final StringMessages stringMessages; - private final ErrorReporter errorReporter; - private final UserAgentDetails userAgent; - private final LogoAndTitlePanel logoAndTitlePanel; - private final DockLayoutPanel dockPanel; - private final AsyncActionsExecutor asyncActionsExecutor; - - /** - * We use two timers: one for the leaderboard, one for the race board. This way, we can stop one while the other continues. - * This way, the other component stops its auto-updates. - */ - private final Timer leaderboardTimer; - private final Timer raceboardTimer; - private final RaceTimesInfoProvider raceTimesInfoProvider; - private TVViews activeTvView; - - // leaderboard related attributes - private LeaderboardDTO leaderboard; - private final String leaderboardName; - private final String leaderboardGroupName; - private LeaderboardSettings leaderboardSettings; - - // raceboard related attributes - private RegattaAndRaceIdentifier currentLiveRace; - private boolean showRaceDetails; - private boolean showWindChart; - private final RaceBoardViewConfiguration raceboardViewConfig; - private final UserService userService; - - /** - * @param userService TODO - * @param logoAndTitlePanel - * allowed to be null - * @param showNavigationPanel - * tells whether to show the navigation panel for the race board which allows users to turn on and off - * the various components and lets them configure them; makes sense to use only if intended for "manned" mode. - */ - public TVViewController(SailingServiceAsync sailingService, MediaServiceAsync mediaService, - UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, - String leaderboardGroupName, String leaderboardName, UserAgentDetails userAgent, - LogoAndTitlePanel logoAndTitlePanel, DockLayoutPanel dockPanel, long delayToLiveInMillis, - boolean showRaceDetails, RaceBoardViewConfiguration raceboardViewConfig) { - this.userService = userService; - this.raceboardViewConfig = raceboardViewConfig; - this.sailingService = sailingService; - this.mediaService = mediaService; - this.stringMessages = stringMessages; - this.errorReporter = errorReporter; - this.leaderboardName = leaderboardName; - this.leaderboardGroupName = leaderboardGroupName; - this.userAgent = userAgent; - this.logoAndTitlePanel = logoAndTitlePanel; - this.dockPanel = dockPanel; - this.showRaceDetails = showRaceDetails; - - asyncActionsExecutor = new AsyncActionsExecutor(); - showWindChart = false; - leaderboard = null; - leaderboardSettings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, null, /* autoExpandFirstRace */ false, /* showRegattaRank */ true); - - leaderboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l); - leaderboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis); - leaderboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD); - leaderboardTimer.play(); - raceboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l); - raceboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis); - raceboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_RACEBOARD); - raceboardTimer.play(); - - raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, errorReporter, new ArrayList(), 3000l); - raceTimesInfoProvider.addRaceTimesInfoProviderListener(this); - } - - private LeaderboardPanel createLeaderboardPanel(String leaderboardGroupName, String leaderboardName, boolean showRaceDetails) { - CompetitorSelectionModel selectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true); - LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor, - leaderboardSettings, false, - /* preSelectedRace */null, selectionModel, leaderboardTimer, leaderboardGroupName, leaderboardName, - errorReporter, stringMessages, userAgent, showRaceDetails, /* competitorSearchTextBox */ null, /* showRegattaRank */ - /* showSelectionCheckbox */false, /* raceTimesInfoProvider */null, false, /* autoExpandLastRaceColumn */ - /* adjustTimerDelay */true, /*autoApplyTopNFilter*/ false, false) { - @Override - protected void setLeaderboard(LeaderboardDTO leaderboard) { - super.setLeaderboard(leaderboard); - TVViewController.this.leaderboard = leaderboard; - updateRaceTimesInfoProvider(); - } - }; - leaderboardPanel.getElement().getStyle().setMargin(5, Unit.PX); - return leaderboardPanel; - } - - private void updateRaceTimesInfoProvider() { - boolean addedRaces = false; - for (RaceColumnDTO race : leaderboard.getRaceList()) { - for (FleetDTO fleet : race.getFleets()) { - RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet); - if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) { - raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false); - addedRaces = true; - } - } - } - if (addedRaces) { - raceTimesInfoProvider.forceTimesInfosUpdate(); - } - } - - private RaceBoardPanel createRaceBoardPanel(String leaderboardName, RegattaAndRaceIdentifier raceToShow) { - RaceSelectionModel raceSelectionModel = new RaceSelectionModel(); - List singletonList = Collections.singletonList(raceToShow); - raceSelectionModel.setSelection(singletonList); - RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, userService, - asyncActionsExecutor, raceboardTimer, raceSelectionModel, leaderboardName, null, /* event */null, - raceboardViewConfig, errorReporter, stringMessages, userAgent, raceTimesInfoProvider, /* showMapControls */false); - return raceBoardPanel; - } - - private void clearContentPanels() { - int childWidgetCount = dockPanel.getWidgetCount(); - for(int i = childWidgetCount-1; i >=0; i--) { - Widget widget = dockPanel.getWidget(i); - // don't remove the logoAndTitlePanel if exist - if(logoAndTitlePanel == null || widget != logoAndTitlePanel) { - dockPanel.remove(widget); - } - } - } - - private void showLeaderboard() { - if (activeTvView != TVViews.Leaderboard) { - clearContentPanels(); - LeaderboardPanel leaderboardPanel = createLeaderboardPanel(leaderboardGroupName, leaderboardName, showRaceDetails); - ScrollPanel leaderboardContentPanel = new ScrollPanel(); - leaderboardContentPanel.add(leaderboardPanel); - dockPanel.add(leaderboardContentPanel); - if (logoAndTitlePanel != null) { - logoAndTitlePanel.setSubTitle(leaderboardName); - } - currentLiveRace = null; - activeTvView = TVViews.Leaderboard; - raceboardTimer.pause(); - leaderboardTimer.setPlayMode(PlayModes.Live); - } - } - - private void showRaceBoard() { - if (activeTvView != TVViews.Raceboard) { - clearContentPanels(); - RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace); - raceBoardPanel.setSize("100%", "100%"); - if (showWindChart) { - raceBoardPanel.setWindChartVisible(true); - } - FlowPanel timePanel = createTimePanel(raceBoardPanel); - dockPanel.addSouth(timePanel, 90); - dockPanel.add(raceBoardPanel); - if (logoAndTitlePanel != null) { - logoAndTitlePanel.setSubTitle(currentLiveRace.getRaceName()); - } - activeTvView = TVViews.Raceboard; - leaderboardTimer.pause(); - raceboardTimer.setPlayMode(PlayModes.Live); - } - } - - private FlowPanel createTimePanel(RaceBoardPanel raceBoardPanel) { - FlowPanel timeLineInnerBgPanel = new FlowPanel(); - timeLineInnerBgPanel.addStyleName("timeLineInnerBgPanel"); - timeLineInnerBgPanel.add(raceBoardPanel.getTimePanel()); - - FlowPanel timeLineInnerPanel = new FlowPanel(); - timeLineInnerPanel.add(timeLineInnerBgPanel); - timeLineInnerPanel.addStyleName("timeLineInnerPanel"); - - FlowPanel timelinePanel = new FlowPanel(); - timelinePanel.add(timeLineInnerPanel); - timelinePanel.addStyleName("timeLinePanel"); - - return timelinePanel; - } - - public void updateTvView(TVViews tvView) { - switch (tvView) { - case Leaderboard: - showLeaderboard(); - break; - case Raceboard: - showRaceBoard(); - break; - } - } - - @Override - public void raceTimesInfosReceived(Map raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { - raceboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); - leaderboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); - if (currentLiveRace != null) { - RaceTimesInfoDTO currentRaceTimes = raceTimesInfo.get(currentLiveRace); - - Date endOfRace = currentRaceTimes.endOfRace; - long waitTimeAfterEndOfRace = 60 * 1000; // 1 min - if (endOfRace != null && raceboardTimer.getTime().getTime() > endOfRace.getTime() + waitTimeAfterEndOfRace - && raceboardTimer.getPlayMode() == PlayModes.Live) { - updateTvView(TVViews.Leaderboard); - } - } else { - currentLiveRace = checkForLiveRace(); - if (currentLiveRace != null) { - updateTvView(TVViews.Raceboard); - } else { - updateTvView(TVViews.Leaderboard); - } - } - } - - private RegattaAndRaceIdentifier checkForLiveRace() { - RegattaAndRaceIdentifier result = null; - Map raceTimesInfos = raceTimesInfoProvider.getRaceTimesInfos(); - for (RaceColumnDTO race : leaderboard.getRaceList()) { - for (FleetDTO fleet : race.getFleets()) { - RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet); - if (raceIdentifier != null) { - RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier); - if (raceTimes != null && raceTimes.startOfTracking != null && raceTimes.endOfRace == null) { - return raceIdentifier; - } - } - } - } - return result; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViews.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViews.java deleted file mode 100644 index a01d9a0c00a..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/tv/TVViews.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.sap.sailing.gwt.ui.tv; - -public enum TVViews { - Leaderboard, Raceboard; -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/TvView.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/TvView.gwt.xml deleted file mode 100644 index 91a7eb4d5d0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/TvView.gwt.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From da16c0a2980a970a31675a9d31f8ab38e637715f Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 10 Nov 2014 13:11:40 +0100 Subject: [PATCH 4/8] removed tvview folder from build.properties --- java/com.sap.sailing.gwt.ui/build.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index ee88e572d5e..6c095726f5f 100755 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -41,7 +41,6 @@ bin.includes = META-INF/,\ VideoPopup.css,\ com.sap.sailing.gwt.ui.YoutubePopup/,\ YoutubePopup.html,\ - com.sap.sailing.gwt.ui.TvView/,\ BrowserUnsupported.html,\ PolarSheets.css,\ PolarSheets.html,\ From 5a062a5723b1904ae6a0d88613781197e194467f Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 10 Nov 2014 13:15:19 +0100 Subject: [PATCH 5/8] removed unused search.gwt.xml --- .../com/sap/sailing/gwt/ui/Search.gwt.xml | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Search.gwt.xml diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Search.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Search.gwt.xml deleted file mode 100644 index 274ea79fdc5..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Search.gwt.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 296800fa75fa227baae4880b3659a18b5ce1a441 Mon Sep 17 00:00:00 2001 From: Fredrik Teschke Date: Mon, 10 Nov 2014 13:33:02 +0000 Subject: [PATCH 6/8] Updated tracking app api v1 draft (markdown) --- wiki/tracking-app-api-v1-draft.md | 305 ++++++++++++------------------ 1 file changed, 126 insertions(+), 179 deletions(-) diff --git a/wiki/tracking-app-api-v1-draft.md b/wiki/tracking-app-api-v1-draft.md index 2708bb977f4..8b81a6e99a0 100644 --- a/wiki/tracking-app-api-v1-draft.md +++ b/wiki/tracking-app-api-v1-draft.md @@ -3,186 +3,140 @@ ## General This is a design for the REST API to be used by the iOS and Android tracking apps. +We have decided to handle checkins etc. at the level of ``Leaderboard``s instead of ``Regatta``s. For most cases, such a Leaderboard is based on a Regatta (a ``RegattaLeaderboard`` in our domain model). + +This document supplements the [documentation of the existing REST API](http://www.sapsailing.com/sailingserver/webservices/api/v1/index.html), highlighting those resources necessary for the tracking app, and specifying such resources that are not yet present in the API. + +### URL base +``` +http:///sailingserver/api/v1/ +``` +All relative URLs given below are relative to this base URL. ## Push Notifications Event data can be updated via push notifications. These are limited on iOS to 256 bytes (not characters). For this reason, on receiving a push notification, the app must GET the event data. + ## Checkin Information -### Path +### URL and QRCode - http://kielerwoche2015.sapsailing.com:8888/api/v1/checkin_info.json?leaderboard={unique_leaderboard_name}&competitor_id={competitor_id} +We have the following structure of domain objects (look here for [API documentation](http://www.sapsailing.com/sailingserver/webservices/api/v1/index.html) in addition to the examples): +* Event (e.g. [Kieler Woche 2013](http://www.sapsailing.com/sailingserver/api/v1/events/3e4145a7-5473-4670-83e6-fd5ee364f7eb)) + * LeaderboardGroup (e.g. [Kieler Woche 2013](http://www.sapsailing.com/sailingserver/api/v1/leaderboardgroups/Kieler%20Woche%202013)) + * Leaderboard (e.g. [KW 2013 Olympic (2.4M)](http://www.sapsailing.com/sailingserver/api/v1/leaderboards/KW%202013%20Olympic%20(2.4M%29)) + * Race (caution: this is over-simplified) -### Verb +These resources have separate life cycles, the hierarchical presentation only denotes references between the resources (e.g. an Event references some LeaderboardGroups). - GET +The app has to receive the following information: +* ``event-id`` (for description, start- and end-date) +* ``leaderboard-name`` (so that the user can checkin for the correct leaderboard) +* ``competitor-id`` (so the app can register the device for the correct competitor) -### Response +This information is represented in a URL with the following structure: +``` +http://sapsailing.com/tracking/checkin + ?host= + &event_id= + &leaderboard_name= + &competitor_id= +``` - { - "serverUrl" : "http://kielerwoche2015.sapsailing.com:8888", - "event" : { - "id" : "957fab64e36d240dd07aeed2bd5a84b6", - "title" : "Kieler Woche", - "startDate" : 1414414481000, - "endDate" : 1414609200000 - }, - "regatta": { - "id": "237fab64e36d240dd07aeed2bd5a8426", - "title": "49ers" - }, - "competitor":{ - "id" : "e45fab64e36d240dd07aeed2bd5a8a21", - "name" : "Alster Segel Club", - "registration" : "GER 13" - } - } +**Additional Notes:** +* The URL is **only symbolic**. Requesting it will for now result in a 404. In the future, it might be used to redirect to the .apk, play store or app store in case the app is not installed. +* The structure of the URL was chosen for the following reasons: + * If presented to a user as text, it is immediately obvious that he is dealing with sapsailing.com + * If we want to redirect to a server-version-specific .apk under Android, the sapsailing.com server can still simply redirect to the ``host`` + * The variable-length leaderboard name is problematic when thinking about length restrictions in QRCodes anyway. We will have to think about URL-shortening anyhow, so legible parameter names were chosen instead of short ones (e.g. ``e=`` instead of ``event_id=``) +* The app has to get event and competitor data by performing additional REST API calls +* The returned JSON-document for an event includes the names of the associated LeaderboardGroups. The JSON for the LeaderboardGroup in turn includes the names of the associated leaderboards. This structure of the returned resources does not follow the [REST constraints](http://en.wikipedia.org/wiki/Representational_state_transfer#Uniform_interface) in the sense that it does not use URIs to refer to associated resources. Instead, only the unique identifier is given, and one has to refer to the API documentation to construct the URI through which the related resource can be addressed. + +### Event Information + +see [events/{event_id}](http://www.sapsailing.com/sailingserver/webservices/api/v1/eventGetDoc.html) + +### Competitor Information + +**Path:** ``competitors/{competitor-id}`` + +**Verb:** ``GET`` + +**Response:** +``` +{ + "name": "Heiko KRÖGER", + "displayName": "Heiko KRÖGER", + "id": "af855a56-9726-4a9c-a77e-da955bd289be", + "sailID": "GER 1", + "nationality": "GER", + "countryCode": "DE" +} +``` + +**Additional Notes:** +* The semantics of ``displayName`` are explained in the JavaDoc of ``Leaderboard#getDisplayName()``. +* Competitor profile image left out for now. +* No flag image included. These images are present on the server in the GWT-context only as 16x11 pngs currently. How flags are displayed in the app should probably be independent. I would suggest resolving the appropriate image within the app based on the ``countryCode``. -**serverUrl** This is the endpoint to be used for all following REST requests. ## Check-In After the user has received the event data with the short URL, the smartphone is mapped to a competitor. +Result: fixes transmitted after the time specified in the checkin request are added to such races within the leaderboard that have a start/end time matching the fixes timestamp. + _Question: What should be done if a second device is mapped to competitor?_ +* _Answer:_ For now, according to our internal logic, both devices are actually mapped. If they send fixes for the same timerange, we will see some weird behaviour. -### Path +**Path:** ``/leaderboards/{leaderboard-name}/device_mappings/start`` - {serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/competitor/{competitor_id}/checkin.json +**Verb:** ``POST`` -### Verb +**Request:** +``` +{ + "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg", + "deviceType" : "ios", + "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf", + "pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78", + "fromMillis" : 1415624564718 +} +``` +* **competitorId** ID of the competitor to map the device to. For coming versions, using ``markId`` instead might also be valid to map the device to a mark. +* **deviceType**: Either `android` or `ios`. Needed for selecting correct push notification service. +* **deviceUuid**: **UUID** generated by the app on first run. **Not** an identifier that globally identifies the piece of hardware such UDID under iOS, IMEI, or other. +* **pushDeviceId** On Android the GCM regId, on iOS the APNS push token. This is needed for sending push notifications to the device. +* **fromMillis** Milliseconds timestamp from which to map the device to the competitor. - POST +**Response:** +``HTTP 200``, no response body -### Request - - { - "deviceUdid" : "202cb962ac59075b964b07152d234b70", - "deviceType" : "ios", - "pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78" - } - -**deviceUdid** A UDID generated by device, generated on first run. - -**deviceType** Either `android` or `ios`. Needed for selecting correct push notification service. - -**pushDeviceId** On Android the GCM regId, on iOS the APNS push token. This is needed for sending push notifications to the device. +**Additional Notes:** +For future versions, think about whether this is the right place to transmit the data for push notifications. Rather, this should ideally be done when installing the app (or starting it for the first time). Problem is, we don't know which server it will be used with then. So maybe, instead, whenever the user registers for a leaderboard on a _new_ server, the necessary information for push notifications ins transferrend _once_, instead of every time the user registers for a leaderboard on that server. ## Checkout -Needed to destroy a device coupling with leaderboard & competitor. AKA checkout. +Ends the device to competitor coupling. Does not delete it, but rather marks the end timepoint. Fixes submitted for this device that have a timestamp which lies after the end timepoint specified in the checkout request are not added to races in the leaderboard. -### Path +**Path:** ``/leaderboards/{leaderboard-name}/device_mappings/end`` - {serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/competitor/{competitor_id}/device/{deviceUdid}.json +**Verb:** ``POST`` -### Verb - - DELETE +**Request:** +``` +{ + "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg", + "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf", + "toMillis" : 1415624564719 +} +``` +* **toMillis** Milliseconds timestamp up to which to map the device to the competitor. +**Response:** +``HTTP 200``, no response body -## Regatta Info - -Informations regarding a regatta. We need the list of (scheduled) races to remind the user to start tracking. - -### Path - - {serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/regatta.json - -or - - {serverUrl}/api/v1/event/{event_id}/regatta/{regatta_id}.json - -### Verb - - GET - -### Response - - { - "id": "237fab64e36d240dd07aeed2bd5a8426", - "title": "49ers", - "event_id" : "237fab64e36d240dd07aeed2bd5a8426" - "leaderboard" : "Leaderboard Identifier", - "races":[ - { - "startTime" : 1414414481000, - "status" : "finished", - "fleet" : "Blue" - "phase" : "Qualification" - "name" : "Q1" - }, - { - "startTime" : 1414414481005, - "status" : "running", - "fleet" : "Red" - "phase" : "Qualification" - "name" : "Q1" - }, - { - "startTime" : 1414414481010, - "status" : "scheduled", - "fleet" : "Blue" - "phase" : "Qualification" - "name" : "Q2" - }, - { - "startTime" : "", - "status" : "unscheduled", - "fleet" : "Red" - "phase" : "Qualification" - "name" : "Q2" - } - ] - }, - - -## Competitor Info - -Informations for a competitor can be requested. - -### Path - - {serverUrl}/api/v1/competitor/{competitor_id}.json - -### Verb - - GET - -### Response - - { - "Id" : "250cf8b51c773f3f8dc8b4be867a9a02", - "Name" : "Alster Segel Club", - "ProfileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg" - "Flag": {BASE64STRING or URL}, - "Registration": "GER 14" - } - -## Upload Profile Image - -An image can be uploaded per competitor. - -### Path - - {serverUrl}/api/v1/competitor/{competitor_id}/profile_image.json - -### Verb - - POST - -### Request - -Multipart upload with part `image` containing JPEG image 80%, max dimension 1200px. - -### Response - - { - "profileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg" - } - -**profileImageUrl** URL of uploaded image. ## Send Measurements (to the Fix Store) @@ -192,36 +146,29 @@ Measurements should be sent live during an event. In case of missing network, me GZIP compression is a must. Bulk uploads should be chunked, e.g. per 1,000 locations. -### Path +**Path:** ``gps_fixes`` - {serverUrl}/api/v1/fix_store.json +**Verb:** ``POST`` -### Verb - - POST - -### Request - - { - "measurements" : [ - { - "timestamp" : 14144160080000, - "latitude" : 54.325246, - "longitude" : 10.148556, - "speed" : 3.61, - "course" : 258.11, - }, - { - "timestamp" : 14144168490000, - "latitude" : 55.12456, - "longitude" : 8.03456, - "speed" : 5.1, - "course" : 14.2, - }, - ... - ] - } - -**speed** Speed over ground in meters per second. - -**course** Heading in degrees. +**Request:** +``` +[ + { + "timestamp" : 14144160080000, + "latitude" : 54.325246, + "longitude" : 10.148556, + "speed" : 3.61, + "course" : 258.11, + }, + { + "timestamp" : 14144168490000, + "latitude" : 55.12456, + "longitude" : 8.03456, + "speed" : 5.1, + "course" : 14.2, + } +] +``` +* JSON array may contain one or several fixes +* **speed** Speed over ground in meters per second. +* **course** Heading in degrees. \ No newline at end of file From b8542afdf1da8aeae0b4456e5623472a6760c498 Mon Sep 17 00:00:00 2001 From: Fredrik Teschke Date: Mon, 10 Nov 2014 14:22:43 +0000 Subject: [PATCH 7/8] Updated tracking app api v1 draft (markdown) --- wiki/tracking-app-api-v1-draft.md | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/wiki/tracking-app-api-v1-draft.md b/wiki/tracking-app-api-v1-draft.md index 8b81a6e99a0..a9d49b5e2aa 100644 --- a/wiki/tracking-app-api-v1-draft.md +++ b/wiki/tracking-app-api-v1-draft.md @@ -152,22 +152,25 @@ GZIP compression is a must. Bulk uploads should be chunked, e.g. per 1,000 locat **Request:** ``` -[ - { - "timestamp" : 14144160080000, - "latitude" : 54.325246, - "longitude" : 10.148556, - "speed" : 3.61, - "course" : 258.11, - }, - { - "timestamp" : 14144168490000, - "latitude" : 55.12456, - "longitude" : 8.03456, - "speed" : 5.1, - "course" : 14.2, - } -] +{ + deviceUuid: "af855a56-9726-4a9c-a77e-da955bd289bf", + fixes: [ + { + "timestamp" : 14144160080000, + "latitude" : 54.325246, + "longitude" : 10.148556, + "speed" : 3.61, + "course" : 258.11, + }, + { + "timestamp" : 14144168490000, + "latitude" : 55.12456, + "longitude" : 8.03456, + "speed" : 5.1, + "course" : 14.2, + } + ] +} ``` * JSON array may contain one or several fixes * **speed** Speed over ground in meters per second. From 6876463de6a8b81728768677134ae14759106cc8 Mon Sep 17 00:00:00 2001 From: Fredrik Teschke Date: Mon, 10 Nov 2014 17:12:48 +0000 Subject: [PATCH 8/8] Updated tracking app api v1 draft (markdown) --- wiki/tracking-app-api-v1-draft.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wiki/tracking-app-api-v1-draft.md b/wiki/tracking-app-api-v1-draft.md index a9d49b5e2aa..00170f20daf 100644 --- a/wiki/tracking-app-api-v1-draft.md +++ b/wiki/tracking-app-api-v1-draft.md @@ -57,6 +57,10 @@ http://sapsailing.com/tracking/checkin see [events/{event_id}](http://www.sapsailing.com/sailingserver/webservices/api/v1/eventGetDoc.html) +### Leaderboard Information + +see [leaderboards/{leaderboard_name}](http://www.sapsailing.com/sailingserver/webservices/api/v1/leaderboardGetDoc.html) + ### Competitor Information **Path:** ``competitors/{competitor-id}``