diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index a9ea28ff507..a8d771d1529 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -95,7 +95,7 @@ parallelexecution=0 p2local=0 if [ $# -eq 0 ]; then - echo "buildAndUpdateProduct [-b -u -g -t -a -r -o -c -p -v -m -n -l -x ] [build|install|all|hot-deploy|remote-deploy|local-deploy|release]" + echo "buildAndUpdateProduct [-b -u -g -t -a -r -o -c -p -v -m -n -l -x -j ] [build|install|all|hot-deploy|remote-deploy|local-deploy|release]" echo "" echo "-g Disable GWT compile, no gwt files will be generated, old ones will be preserved." echo "-b Build GWT permutation only for one browser and English language." @@ -115,6 +115,7 @@ if [ $# -eq 0 ]; then echo "-u Run without confirmation messages. Use with extreme care." echo "-v Build local p2 respository, and use this instead of p2.sapsailing.com" echo "-x use this many worker threads for building GWT permutations (default: 2)." + echo "-j only execute the provided test package during tests" echo "" echo "build: builds the server code using Maven to $PROJECT_HOME (log to $START_DIR/build.log)" echo "" @@ -151,7 +152,7 @@ echo SERVERS_HOME is $SERVERS_HOME echo BRANCH is $active_branch echo VERSION is $VERSION_INFO -options=':bgtocparvm:n:l:s:w:x:u' +options=':bgtocparvm:n:l:s:w:x:j:u' while getopts $options option do case $option in @@ -172,6 +173,7 @@ do u) suppress_confirmation=1;; v) p2local=1;; x) GWT_WORKERS=$OPTARG;; + j) TESTCASE_TO_EXECUTE=$OPTARG;; \?) echo "Invalid option" exit 4;; esac @@ -535,7 +537,7 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then fi cd $PROJECT_HOME/java - if [ $gwtcompile -eq 1 ]; then + if [ $gwtcompile -eq 1 ] && [[ "$clean" == "clean" ]]; then echo "INFO: Compiling GWT (rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*)" rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.* GWT_XML_FILES=`find com.sap.$PROJECT_TYPE.gwt.ui/src/main/resources -name '*.gwt.xml'` @@ -587,6 +589,11 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then else extra="$extra -DskipTests=false" # TODO: Think about http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html + if [[ "$TESTCASE_TO_EXECUTE" != "" ]]; then + # http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html + echo "Running only testcase $TESTCASE_TO_EXECUTE" + extra="$extra -Dtest=$TESTCASE_TO_EXECUTE" + fi fi if [ $android -eq 0 ] && [ $gwtcompile -eq 0 ] && [ $testing -eq 0 ]; then diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/compass.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/compass.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/compass.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/compass.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/dashboardicon.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/dashboardicon.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/dashboardicon.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/dashboardicon.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/hourwatch.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/hourwatch.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/hourwatch.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/hourwatch.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow_disabled.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow_disabled.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow_disabled.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow_disabled.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logo_sap.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logo_sap.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logo_sap.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logo_sap.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logoess.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logoess.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logoess.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logoess.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/nointernet.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/nointernet.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/nointernet.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/nointernet.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow_disabled.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow_disabled.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow_disabled.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow_disabled.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/settings.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/settings.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/settings.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/settings.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/watch.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/watch.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/watch.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/watch.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/windarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/windarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/windarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/windarrow.png diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index 817943466eb..c2d57a54820 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -13,6 +13,7 @@ import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumnListener; @@ -430,6 +431,10 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public void removeListener(RegattaLikeListener listener) { } + + @Override + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + } }; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java new file mode 100755 index 00000000000..98209eaeef1 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java @@ -0,0 +1,5 @@ +package com.sap.sailing.domain.base; + +public interface EventFetcher { + Iterable getAllEvents(); +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index 0667d9ade2a..1635e492ca4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -168,4 +168,12 @@ public interface Regatta extends Named, WithID, IsRegattaLike { * Updates the flag deciding whether to use start time inference. See {@link #useStartTimeInference()}. */ void setUseStartTimeInference(boolean useStartTimeInference); + + /** + * {@link Event} manages an association to its {@link Event#getRegattas() regattas}. When something on the + * regatta changes (in particular, the implicit link to an event through an event's {@link CourseArea} that + * is assigned as this regatta's {@link #setDefaultCourseArea(CourseArea) default course area}), the + * opposite end of the association needs to be maintained on the event's side. + */ + void adjustEventToRegattaAssociation(EventFetcher eventFetcher); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index 8dd579aaac4..2a4244f3444 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -15,6 +15,8 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnInSeries; @@ -551,4 +553,17 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene public void removeListener(RegattaLikeListener listener) { regattaLikeHelper.removeListener(listener); } + + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + CourseArea defaultCourseArea = getDefaultCourseArea(); + for (Event event : eventFetcher.getAllEvents()) { + event.removeRegatta(this); + for (CourseArea courseArea : event.getVenue().getCourseAreas()) { + if (defaultCourseArea != null && courseArea.getId().equals(defaultCourseArea)) { + event.addRegatta(this); + } + } + } + + } } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index bf1191a0747..a8a8aab3666 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumnListener; @@ -517,6 +518,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { // TODO Auto-generated method stub } + + @Override + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + // TODO Auto-generated method stub + + } }; } diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index b0332ffab3a..81118d7d4af 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -69,7 +69,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java index c201c80ce34..e11db038d23 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java @@ -6,6 +6,7 @@ import com.google.gwt.i18n.client.Messages; public interface TextMessages extends Messages { public static final TextMessages INSTANCE = GWT.create(TextMessages.class); + String chartSelectionHint(); String chooseALanguage(); String home(); String events(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties index 6a50d7fa2ce..8ad020fd7fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties @@ -1,3 +1,4 @@ +chartSelectionHint=Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. chooseALanguage=Choose a language events=Events home=Home diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties index 3afbaca10ad..55b7a72c686 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties @@ -1,3 +1,4 @@ +chartSelectionHint=Hinweis: Sie können auch Ergebnisstabelle (im Menü ERGEBNISSE) nutzen, um die im Diagramm angezeigten Teilnehmer auszuwählen. chooseALanguage=Wähle eine Sprache events=Veranstaltungen home=Startseite diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml index 4a134f1f2d9..7e3fb498de0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml @@ -9,7 +9,7 @@
-
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java index 0ff0c7ee412..bb66418a237 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -14,9 +16,11 @@ import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.DetailTypeFormatter; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChart; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChartSettings; +import com.sap.sse.common.Util; public class OldCompetitorCharts extends Composite { private static OldCompetitorChartsUiBinder uiBinder = GWT.create(OldCompetitorChartsUiBinder.class); @@ -26,6 +30,7 @@ public class OldCompetitorCharts extends Composite { @UiField HTMLPanel oldCompetitorChartsPanel; @UiField ListBox chartTypeSelectionListBox; + @UiField DivElement competitorSelectionStateUi; private final List availableDetailsTypes; private MultiCompetitorLeaderboardChart multiCompetitorChart; @@ -79,4 +84,15 @@ public class OldCompetitorCharts extends Composite { } return result; } + + public void updateSelectionState(CompetitorSelectionProvider competitorSelectionProvider) { + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + if(selectedCompetitorsCount > 0) { + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + competitorSelectionStateUi.getStyle().setVisibility(Visibility.VISIBLE); + competitorSelectionStateUi.setInnerText(selectedCompetitorsCount + "/" + competitorsCount + " competitors selected."); + } else { + competitorSelectionStateUi.getStyle().setVisibility(Visibility.HIDDEN); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml index 997e1bc24b5..68d7122a180 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml @@ -7,7 +7,7 @@ -
+

@@ -15,6 +15,11 @@
+
+ +
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml index 8f65326ebe2..56f6dc4dbf8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml @@ -7,7 +7,7 @@ -
+

diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml index 5b78dfeda4e..6bf4b5d7afd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml @@ -7,7 +7,7 @@ -
+

diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java index f80497147bf..169f4dd0a5b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java @@ -181,6 +181,7 @@ public class RegattaAnalytics extends Composite implements LeaderboardUpdateList setActiveTabPanel(competitorChartsTabPanel, competitorChartsAnchor); DetailType selectedChartDetailType = oldCompetitorChartsComposite.getSelectedChartDetailType(); regattaAnalyticsManager.showCompetitorChart(selectedChartDetailType); + oldCompetitorChartsComposite.updateSelectionState(regattaAnalyticsManager.getCompetitorSelectionProvider()); handleClickEvent(event, competitorChartsNavigation); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java index 5e7ec9ea299..9b0590d8434 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java @@ -1,7 +1,13 @@ package com.sap.sailing.gwt.home.client.place.event.regattaanalytics; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.DebugIdHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -12,6 +18,7 @@ import com.sap.sailing.gwt.ui.client.shared.components.Component; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; +import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -32,7 +39,8 @@ public class RegattaAnalyticsDataManager { private final UserAgentDetails userAgent; private final SailingServiceAsync sailingService; private final Timer timer; - + private final int MAX_COMPETITORS_IN_CHART = 30; + public RegattaAnalyticsDataManager(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, Timer timer, ErrorReporter errorReporter, UserAgentDetails userAgent) { this.competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */true); this.sailingService = sailingService; @@ -73,12 +81,32 @@ public class RegattaAnalyticsDataManager { return multiCompetitorChart; } + public CompetitorSelectionModel getCompetitorSelectionProvider() { + return competitorSelectionProvider; + } + public void showCompetitorChart(DetailType chartDetailType) { + // preselect the top N competitors in case there was no selection before and there too many competitors for a chart + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + + if(selectedCompetitorsCount == 0 && competitorsCount > MAX_COMPETITORS_IN_CHART) { + List selectedCompetitors = new ArrayList(); + Iterator allCompetitorsIt = competitorSelectionProvider.getAllCompetitors().iterator(); + int counter = 0; + while(counter < MAX_COMPETITORS_IN_CHART) { + selectedCompetitors.add(allCompetitorsIt.next()); + counter++; + } + competitorSelectionProvider.setSelection(selectedCompetitors, (CompetitorSelectionChangeListener[]) null); + } + MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); MultiCompetitorLeaderboardChartSettings settings = new MultiCompetitorLeaderboardChartSettings(chartDetailType); multiCompetitorChart.updateSettings(settings); multiCompetitorChart.setVisible(true); timer.addTimeListener(multiCompetitorChart); + multiCompetitorChart.clearChart(); multiCompetitorChart.timeChanged(timer.getTime(), null); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css index dec9fb3e38a..427b670805c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css @@ -38,6 +38,8 @@ text-align: center; } .regattaleaderboard { + margin-left: 5rem; + margin-right: 5rem; font-size: 15px; font-size: 1rem; width: 100%; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java index 3d48af5335a..be1c4184f59 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java @@ -212,6 +212,7 @@ public class EventSeriesAnalytics extends Composite implements LeaderboardUpdate setActiveTabPanel(competitorChartsTabPanel, eventSeriesAnalyticsManager.getMultiCompetitorChart(), competitorChartsAnchor); DetailType selectedChartDetailType = oldCompetitorChartsComposite.getSelectedChartDetailType(); eventSeriesAnalyticsManager.showCompetitorChart(selectedChartDetailType); + oldCompetitorChartsComposite.updateSelectionState(eventSeriesAnalyticsManager.getCompetitorSelectionProvider()); handleClickEvent(event, competitorChartsNavigation); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java index 52669221b5b..35f0d588f16 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java @@ -1,7 +1,13 @@ package com.sap.sailing.gwt.home.client.place.event.seriesanalytics; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.DebugIdHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -13,6 +19,7 @@ import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; import com.sap.sailing.gwt.ui.leaderboard.MultiLeaderboardPanel; +import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -36,6 +43,7 @@ public class EventSeriesAnalyticsDataManager { private final UserAgentDetails userAgent; private final SailingServiceAsync sailingService; private final Timer timer; + private final int MAX_COMPETITORS_IN_CHART = 30; public EventSeriesAnalyticsDataManager(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, Timer timer, ErrorReporter errorReporter, UserAgentDetails userAgent) { this.competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */true); @@ -93,14 +101,34 @@ public class EventSeriesAnalyticsDataManager { } public void showCompetitorChart(DetailType chartDetailType) { + // preselect the top N competitors in case there was no selection before and there too many competitors for a chart + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + + if(selectedCompetitorsCount == 0 && competitorsCount > MAX_COMPETITORS_IN_CHART) { + List selectedCompetitors = new ArrayList(); + Iterator allCompetitorsIt = competitorSelectionProvider.getAllCompetitors().iterator(); + int counter = 0; + while(counter < MAX_COMPETITORS_IN_CHART) { + selectedCompetitors.add(allCompetitorsIt.next()); + counter++; + } + competitorSelectionProvider.setSelection(selectedCompetitors, (CompetitorSelectionChangeListener[]) null); + } + MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); MultiCompetitorLeaderboardChartSettings settings = new MultiCompetitorLeaderboardChartSettings(chartDetailType); multiCompetitorChart.updateSettings(settings); multiCompetitorChart.setVisible(true); timer.addTimeListener(multiCompetitorChart); + multiCompetitorChart.clearChart(); multiCompetitorChart.timeChanged(timer.getTime(), null); } + public CompetitorSelectionModel getCompetitorSelectionProvider() { + return competitorSelectionProvider; + } + public void hideCompetitorChart() { MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); multiCompetitorChart.setVisible(false); 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 8d9424d2202..7dc5b7fbbc7 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 @@ -11,9 +11,6 @@ interface AdminConsoleResources extends ClientBundle { @Source("com/sap/sailing/gwt/ui/client/images/settingsActionIcon.png") ImageResource settingsActionIcon(); - @Source("com/sap/sse/gwt/client/images/remove.png") - ImageResource removeIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java index 6f7e9c87be9..97463fc4117 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java @@ -2,13 +2,12 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; -import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class CourseManagementWidgetWaypointsImagesBarCell extends ImagesBarCell { public static final String ACTION_DELETE = "ACTION_DELETE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public CourseManagementWidgetWaypointsImagesBarCell(StringMessages stringMessages) { @@ -19,7 +18,7 @@ public class CourseManagementWidgetWaypointsImagesBarCell extends ImagesBarCell @Override protected Iterable getImageSpecs() { ArrayList result = new ArrayList(); - result.add(new ImageSpec(ACTION_DELETE, stringMessages.remove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_DELETE, stringMessages.remove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); 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/DefaultRegattaCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java index 0c061b9c8eb..0b42afc7fb7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -12,12 +11,11 @@ import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public class DefaultRegattaCreateDialog extends AbstractRegattaWithSeriesAndFleetsDialog { - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); - public DefaultRegattaCreateDialog(List existingEvents, RegattaDTO selectedRegatta, SailingServiceAsync sailingService, ErrorReporter errorReporter, StringMessages stringMessages, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback callback) { @@ -34,7 +32,7 @@ public class DefaultRegattaCreateDialog extends AbstractRegattaWithSeriesAndFlee } protected ListEditorComposite createSeriesEditor(Iterable series) { - return new SeriesWithFleetsDefaultListEditor(series, stringMessages, resources.removeIcon(), /* enableFleetRemoval */ false); + return new SeriesWithFleetsDefaultListEditor(series, stringMessages, IconResources.INSTANCE.removeIcon(), /* enableFleetRemoval */ false); } protected void setupAdditionalWidgetsOnPanel(final VerticalPanel panel) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java index 5614548ea1c..3ba15679621 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java @@ -5,7 +5,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -20,6 +19,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationMatcherDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog { @@ -63,7 +63,6 @@ public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog devicesBoxes; @@ -164,7 +163,7 @@ public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog initialValues = originalConfiguration.allowedCourseAreaNames == null ? Collections . emptyList() : originalConfiguration.allowedCourseAreaNames; - allowedCourseAreasList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseAreas(), resources.removeIcon(), + allowedCourseAreasList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseAreas(), IconResources.INSTANCE.removeIcon(), SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName()); allowedCourseAreasList.setWidth("80%"); allowedCourseAreasList.addValueChangeHandler(dirtyValueMarker); @@ -219,7 +220,7 @@ public class DeviceConfigurationDetailComposite extends Composite { List initialValues = originalConfiguration.byNameDesignerCourseNames == null ? Collections . emptyList() : originalConfiguration.byNameDesignerCourseNames; - courseNamesList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseNames(), resources.removeIcon(), suggestedCourseNames, + courseNamesList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseNames(), IconResources.INSTANCE.removeIcon(), suggestedCourseNames, stringMessages.enterCourseName()); courseNamesList.setWidth("80%"); courseNamesList.addValueChangeHandler(dirtyValueMarker); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java index 3c6325ab3b8..d1dd0711f96 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class EventConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -27,7 +28,7 @@ public class EventConfigImagesBarCell extends ImagesBarCell { protected Iterable getImageSpecs() { return Arrays.asList( new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())) + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon())) ); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index cb573c4c8c6..74d0956b7bc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -8,7 +8,6 @@ import java.util.Date; import java.util.List; import java.util.UUID; -import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; @@ -28,11 +27,11 @@ import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.VenueDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.StringConstantsListEditorComposite; import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite; public abstract class EventDialog extends DataEntryDialogWithBootstrap { - private final AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); protected StringMessages stringMessages; protected TextBox nameEntryField; protected TextArea descriptionEntryField; @@ -131,22 +130,22 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap }; courseAreaNameList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), /* suggestValues */ + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName(), 50)); courseAreaNameList.addValueChangeHandler(valueChangeHandler); final List imageSuggestionURLs = Arrays.asList(new String[] { "http://", "https://", "http://www.", "https://www" }); imageURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ imageSuggestionURLs, stringMessages.enterImageURL(), 80)); imageURLList.addValueChangeHandler(valueChangeHandler); List videoURLSuggestions = new ArrayList<>(imageSuggestionURLs); videoURLSuggestions.add("http://www.youtube.com/watch?v="); videoURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ videoURLSuggestions, stringMessages.enterVideoURL(), 80)); videoURLList.addValueChangeHandler(valueChangeHandler); sponsorImageURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ imageSuggestionURLs, stringMessages.enterSponsorImageURL(), 80)); sponsorImageURLList.addValueChangeHandler(valueChangeHandler); List leaderboardGroupNames = new ArrayList<>(); @@ -154,7 +153,7 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap leaderboardGroupNames.add(leaderboardGroupDTO.getName()); } leaderboardGroupList = new StringConstantsListEditorComposite(Collections. emptyList(), - new StringConstantsListEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringConstantsListEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), leaderboardGroupNames, "Select a leaderboard group...")); leaderboardGroupList.addValueChangeHandler(valueChangeHandler); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java index 375a7612bd4..424e67c7971 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java @@ -35,6 +35,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; @@ -48,7 +49,6 @@ public class IgtimiAccountsPanel extends FlowPanel { public static class AccountImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public AccountImagesBarCell(StringMessages stringMessages) { @@ -64,7 +64,7 @@ public class IgtimiAccountsPanel extends FlowPanel { @Override protected Iterable getImageSpecs() { return Arrays.asList( - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java index f83621faf1a..7778bfe95ff 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardConfigImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -35,7 +36,7 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell { new ImageSpec(ACTION_EDIT_SCORES, stringMessages.actionEditScores(), makeImagePrototype(resources.scoresIcon())), new ImageSpec(ACTION_EDIT_COMPETITORS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon())), new ImageSpec(ACTION_CONFIGURE_URL, stringMessages.actionConfigureUrl(), makeImagePrototype(resources.settingsActionIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon())), new ImageSpec(ACTION_EXPORT_XML, stringMessages.actionExportXML(), makeImagePrototype(resources.exportXMLIcon())), new ImageSpec(ACTION_OPEN_COACH_DASHBOARD, stringMessages.actionOpenDashboard(), makeImagePrototype(resources.openCoachDashboard()))); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java index 8e639715f3b..9f4528eda9a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardGroupConfigImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class LeaderboardGroupConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file 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 3a938222b06..f37d691c789 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 @@ -8,6 +8,7 @@ import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { public final static String ACTION_REMOVE = "ACTION_REMOVE"; @@ -35,7 +36,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { StrippedLeaderboardDTO selectedLeaderboard = selectedLeaderboardProvider.getSelectedLeaderboard(); if (selectedLeaderboard != null && selectedLeaderboard.type != LeaderboardType.RegattaLeaderboard && selectedLeaderboard.type != LeaderboardType.RegattaMetaLeaderboard) { // race columns cannot be removed from a regatta leaderboard; they need to be removed from the regatta instead - result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java index e5542f1aec9..cd2ef26340d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java @@ -2,14 +2,13 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Arrays; -import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class MediaActionBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public MediaActionBarCell(StringMessages stringMessages) { @@ -20,6 +19,6 @@ public class MediaActionBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_REMOVE, - stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java index d31582aa965..2cc7ce92ca8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; +import com.sap.sse.gwt.client.IconResources; public class RaceLogTrackingDeviceMappingsImagesBarCell extends ImagesBarCell { public static final String ACTION_CLOSE = "CLOSE"; @@ -23,7 +24,7 @@ public class RaceLogTrackingDeviceMappingsImagesBarCell extends ImagesBarCell { ArrayList result = new ArrayList(); DeviceMappingDTO mapping = (DeviceMappingDTO) getContext().getKey(); - result.add(new ImageSpec(ACTION_REMOVE, stringMessages.remove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_REMOVE, stringMessages.remove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); if (mapping.from == null || mapping.to == null) { result.add(new ImageSpec(ACTION_CLOSE, stringMessages.closeTimeRange(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java index 5ea041d561e..2c24f547e1a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class RegattaConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class RegattaConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java index 0ff24e805ba..bd855d46bea 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; @@ -12,10 +11,10 @@ import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWithSeriesAndFleetsDialog { - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); protected TextBox nameEntryField; protected TextBox boatClassEntryField; @@ -38,7 +37,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi @Override protected ListEditorComposite createSeriesEditor(Iterable series) { - return new SeriesWithFleetsListEditor(series, stringMessages, resources.removeIcon(), isEnableFleetRemoval()); + return new SeriesWithFleetsListEditor(series, stringMessages, IconResources.INSTANCE.removeIcon(), isEnableFleetRemoval()); } protected abstract boolean isEnableFleetRemoval(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java index 839416b3260..2f1263e5921 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class SeriesConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class SeriesConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java index 68b306e0a3e..37c769e6c8a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java @@ -6,7 +6,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import com.google.gwt.core.shared.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -31,14 +30,12 @@ import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.StringListEditorComposite; import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite; import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class SeriesEditDialog extends DataEntryDialog { - - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); - private TextBox seriesNameTextBox; private CheckBox isMedalCheckbox; private CheckBox startWithZeroScoreCheckbox; @@ -204,7 +201,7 @@ public class SeriesEditDialog extends DataEntryDialog { discardThresholdBoxesWidget.setVisible(useSeriesResultDiscardingThresholdsCheckbox.getValue()); additionalWidgetPanel.add(discardThresholdBoxesWidget); - raceNamesEditor = new StringListInlineEditorComposite(getExistingRacesOfSeries(), new RaceNamesEditorUi(regatta, stringMessages, resources.removeIcon(), seriesName)); + raceNamesEditor = new StringListInlineEditorComposite(getExistingRacesOfSeries(), new RaceNamesEditorUi(regatta, stringMessages, IconResources.INSTANCE.removeIcon(), seriesName)); raceNamesEditor.ensureDebugId("RaceNamesStringListEditorComposite"); raceNamesEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java index dd5031d3b76..7343855a644 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; import com.sap.sse.gwt.client.dialog.DataEntryDialog; @@ -146,7 +147,7 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog { protected void initializeFleetListComposite(StringMessages stringMessages) { fleetListComposite = new FleetListEditorComposite(Arrays.asList(new FleetDTO( - LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, resources.removeIcon()); + LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, IconResources.INSTANCE.removeIcon()); fleetListComposite.ensureDebugId("FleetListEditorComposite"); fleetListComposite.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java index 12c7011cd36..2ba1ac26a8b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; /** * A variant of the dialog used to create a series within a regatta that has fleets. This variant is actually more of a @@ -49,7 +50,7 @@ public class SeriesWithFleetsDefaultCreateDialog extends SeriesWithFleetsCreateD protected void initializeFleetListComposite(StringMessages stringMessages) { fleetListComposite = new FleetListEditableEditorComposite(Arrays.asList(new FleetDTO( - LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, resources.removeIcon()); + LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, IconResources.INSTANCE.removeIcon()); fleetListComposite.ensureDebugId("FleetListEditableEditorComposite"); fleetListComposite.addValueChangeHandler(new ValueChangeHandler>() { @Override 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 cbef88b3ee3..de1844cb017 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 @@ -34,6 +34,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages { String carry(); String competitor(); String competitors(); + String competitorsSelected(int selectedCompetitorsCount, int competitorsCount); String defaultLeaderboard(); String noSuchLeaderboard(); String leaderboardConfiguration(); 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 6a71c26d303..5f519f6e1c8 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 @@ -29,6 +29,7 @@ total=\u03A3 carry=Accumulated competitor=Competitor competitors=Competitors +competitorsSelected={0}/{1} competitors selected. defaultLeaderboard=Default Leaderboard noSuchLeaderboard=No such leaderboard leaderboardConfiguration=Leaderboard Configuration 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 5fc7d30cba1..e2736b04394 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 @@ -29,6 +29,7 @@ total=Gesamt carry=übertr. competitor=Team competitors=Teams +competitorsSelected={0}/{1} Teams ausgewählt. defaultLeaderboard=Alle Ergebnisse noSuchLeaderboard=Rangliste nicht gefunden leaderboardConfiguration=Ranglisten-Konfiguration diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index 67d2e6e8c6d..7bccf80bf6d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -29,6 +29,7 @@ total=\u03A3 carry=Суммарная competitor=Участник competitors=Участники +competitorsSelected={0}/{1} Участники. defaultLeaderboard=Таблица лидеров по умолчанию noSuchLeaderboard=Такая таблица лидеров отсутствует leaderboardConfiguration=Форма таблицы лидеров diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java index feb71eaee46..c6899dd8751 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java @@ -27,6 +27,7 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.Marker; import org.moxieapps.gwt.highcharts.client.plotOptions.Marker.Symbol; import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.Widget; @@ -180,7 +181,7 @@ public abstract class AbstractCompetitorLeaderboardChart extends A })); } - protected void clearChart() { + public void clearChart() { competitorSeries.clear(); chart.removeAllSeries(); } @@ -245,7 +246,9 @@ public abstract class AbstractCompetitorLeaderboardChart extends A break; } - chart.setSizeToMatchContainer(); + // TODO will removing the following line do harm on any usage of this abstract base class? + // chart.setSizeToMatchContainer(); + // it's important here to recall the redraw method, otherwise the bug fix for wrong checkbox // positions (nativeAdjustCheckboxPosition) // in the BaseChart class would not be called @@ -296,8 +299,11 @@ public abstract class AbstractCompetitorLeaderboardChart extends A raceColumnNumber++; } } - chart.getYAxis().setMaxPadding(0.5 / maxCompetitorCount).setMinPadding(0.5 / maxCompetitorCount); - chart.setHeight(maxCompetitorCount * 30 + 100 + "px"); + setHeight(); + } + + private void setHeight() { + chart.setSize(chart.getOffsetWidth(), Window.getClientHeight()); } private void fillTotalPointsSeries( @@ -341,8 +347,7 @@ public abstract class AbstractCompetitorLeaderboardChart extends A raceColumnNumber++; } } - chart.getYAxis().setMaxPadding(0.5/maxCompetitorCount).setMinPadding(0.5/maxCompetitorCount); - chart.setHeight(maxCompetitorCount * 30 + 100 + "px"); + setHeight(); } private boolean hasValidValues(List values) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html index b8fe7d2e47c..fba94343b2e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html @@ -180,7 +180,7 @@
  • China races, such as in Qingdao, may have the map background displayed at slightly wrong locations. This is due to an intentional random transformation that Google applies to GPS locations for China. You can circumvent this issue by switching to satellite view where the map background is displayed - correctly. + correctly.
  • Fixed a bug that in some cases has caused the wind chart, the advantage line, the wind indicator on the map and the leaderboard to use slightly different wind values. The problem was related to different averaging and diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini b/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini index 2958f1e5360..d9123231d8e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini @@ -14,10 +14,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html new file mode 100644 index 00000000000..8cb27f6a6b8 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html @@ -0,0 +1,46 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/competitors/{id}/team

    + +Description: +

    Gets the details of a competitor's team

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:Json
    Mandatory parameters:None
    Optional parameters:None
    Request method:GET
    Example:http://www.sapsailing.com/sailingserver/api/v1/competitors/bba11294-9930-11e0-85be-406186cbf87c/team
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html new file mode 100644 index 00000000000..b94a26965db --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html @@ -0,0 +1,61 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/competitors/{id}/team/image

    + +Description: +

    Sets the team image

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:JSON
    Mandatory headers:Content-Type: (image-png|image-jpg)
     Content-Length
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST (Binary data, not multipart)
    Request example:
    curl -H "Content-Type:image/jpeg" --data-binary @{image-path} \
    +   http://sapsailing.com/sailingserver/api/v1/competitors/{competitor-id}/team/image
    Response example:
    {
    +  "teamImageUri" : "http://training.sapsailing.com/team_images/9871d3a2c554b27151cacf1422eec048.jpeg"
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 766f399ca1a..ec818730916 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -96,6 +96,18 @@ name to make sure you get to the event you're interested in. /api/v1/leaderboards/{name} Gets the details of a leaderboard + + /api/v1/leaderboards/{name}/device_mappings/start + Tracking App Device Checkin on leaderboard + + + /api/v1/leaderboards/{name}/device_mappings/end + Tracking App Device Checkout on leaderboard + + + /api/v1/leaderboards/{name}/competitors/{id} + Gets the details of a competitor in the context of a leaderboard + /api/v1/gps_fixes Adds GPS-fixes that originated from a device with a unique identifier @@ -105,8 +117,12 @@ name to make sure you get to the event you're interested in. Gets the details of a competitor - /api/v1/leaderboards/{name}/competitors/{id} - Gets the details of a competitor in the context of a leaderboard + /api/v1/competitors/{id}/team + Gets the details of a competitor's team + + + /api/v1/competitors/{id}/team/image + Sets the team image diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html new file mode 100644 index 00000000000..f56526a95b3 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html @@ -0,0 +1,56 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/device_mappings/start

    + +Description: +

    Tracking App Device Checkin on leaderboard

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:HTTP 200 (no body)
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST
    Mandatory input:JSON
     
    {
    +    "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
    +    "deviceType" : "ios",
    +    "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
    +    "pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78",
    +    "fromMillis" : 1415624564718
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html new file mode 100644 index 00000000000..8be664a81e1 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html @@ -0,0 +1,54 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/device_mappings/end

    + +Description: +

    Tracking App Device Checkout on leaderboard

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:HTTP 200 (no body)
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST
    Mandatory input:JSON
     
    {
    +    "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
    +    "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
    +    "toMillis" : 1415624564719
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html new file mode 100644 index 00000000000..3dbd8660aa3 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html @@ -0,0 +1,46 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/competitors/{competitorId}

    + +Description: +

    Gets the leaderboard-specific version of a competitor

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:Json
    Mandatory parameters:None
    Optional parameters:None
    Request method:GET
    Example:http://www.sapsailing.com/sailingserver/api/v1/leaderboards/{name}/competitors/{id}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index 10a790daf3c..c911c826dec 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch index 5daca9029a3..4e6b443e28e 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index 47e189fd705..043acbe3b14 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch index 5cdd0a51e6d..bf8e01d7760 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch index c33a2b9512e..0aa36441bde 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch @@ -1,31 +1,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch index b29f8efd126..f3037bf7b65 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch index 7154fe55d29..84bce884b0c 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index 6638ff75415..1aedcf345a0 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch index fe9ffeda563..f6aafcac67e 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch index 187ee5a685a..78880eb9552 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch index 02ecc596ff9..066903924b2 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch index 43cc42e85e6..3e55ae7cf5f 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 20d934eeeea..d31005c3dc2 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 @@ -60,6 +60,7 @@ import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardSearchResult; import com.sap.sailing.domain.base.LeaderboardSearchResultBase; @@ -209,7 +210,7 @@ import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; import com.sap.sse.util.ClearStateTestSupport; public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, - LeaderboardRegistry, Replicator { + LeaderboardRegistry, Replicator, EventFetcher { private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); /** @@ -1789,14 +1790,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes regatta.addSeries(seriesObj); } } - for (Event event : getAllEvents()) { - event.removeRegatta(regatta); - for (CourseArea courseArea : event.getVenue().getCourseAreas()) { - if (newDefaultCourseAreaId != null && courseArea.getId().equals(newDefaultCourseAreaId)) { - event.addRegatta(regatta); - } - } - } + regatta.adjustEventToRegattaAssociation(this); if (regatta.isPersistent()) { mongoObjectFactory.storeRegatta(regatta); } diff --git a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote-aad.target similarity index 100% rename from java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target rename to java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote-aad.target diff --git a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF index d62d8cf0d7b..7fbd22023b4 100644 --- a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF @@ -5,5 +5,6 @@ Bundle-SymbolicName: com.sap.sse.gwt.test Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Require-Bundle: org.junit4;bundle-version="4.8.2" -Fragment-Host: com.sap.sse.gwt;bundle-version="1.0.0.qualifier" +Require-Bundle: com.sap.sse.gwt;bundle-version="1.0.0", + com.sap.sse.common;bundle-version="1.0.0", + org.junit4;bundle-version="4.8.2" diff --git a/java/com.sap.sse.gwt.test/build.properties b/java/com.sap.sse.gwt.test/build.properties index f11210d3f2c..0a97af7a804 100644 --- a/java/com.sap.sse.gwt.test/build.properties +++ b/java/com.sap.sse.gwt.test/build.properties @@ -2,4 +2,5 @@ source.. = src/,\ resources/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + resources/ diff --git a/java/com.sap.sse.gwt.test/pom.xml b/java/com.sap.sse.gwt.test/pom.xml index 2d43815d42e..b22d0bb4c1c 100644 --- a/java/com.sap.sse.gwt.test/pom.xml +++ b/java/com.sap.sse.gwt.test/pom.xml @@ -9,18 +9,26 @@ com.sap.sse.gwt.test eclipse-test-plugin - + + org.apache.maven.plugins + maven-surefire-plugin + + + **/AsyncActionsExecutorTest.java + + + org.codehaus.mojo gwt-maven-plugin - 2.4.0 - - **/AsyncActionsExecutorTest.java - + ${gwt.version} + + **/AsyncActionsExecutorTest.java + test diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java new file mode 100755 index 00000000000..dd1a3dcf9ec --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java @@ -0,0 +1,13 @@ +package com.sap.sse.gwt.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +public interface IconResources extends ClientBundle { + + public static final IconResources INSTANCE = GWT.create(IconResources.class); + + @Source("images/remove.png") + ImageResource removeIcon(); +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.css similarity index 100% rename from java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css rename to java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.css diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java index c30cf12450e..c9c9a767128 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java @@ -175,7 +175,7 @@ public class VerticalTabLayoutPanel extends ResizeComposite implements HasWidget } interface VerticalTabLayoutPanelResources extends ClientBundle { - @Source("com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css") + @Source("VerticalTabLayoutPanel.css") CssResource verticalTabPanelStyles(); } diff --git a/java/com.sap.sse.security.test/META-INF/MANIFEST.MF b/java/com.sap.sse.security.test/META-INF/MANIFEST.MF old mode 100644 new mode 100755 index bfc2d1b32f4..c6c6aa543bc --- a/java/com.sap.sse.security.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.test/META-INF/MANIFEST.MF @@ -11,3 +11,4 @@ Require-Bundle: org.junit4;bundle-version="4.8.2", org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.mongodb, com.sap.sse.mail +Import-Package: org.apache.shiro.session.mgt diff --git a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java old mode 100644 new mode 100755 index 5d4cf1fbee5..9229f35686b --- a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java +++ b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java @@ -39,7 +39,7 @@ public class LoginTest { UsernamePasswordRealm.setTestUserStore(store); Activator.setTestUserStore(store); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // to enable shiro to find classes from com.sap.sse.security - new SecurityServiceImpl(store); + Activator.setSecurityService(new SecurityServiceImpl(store)); } @Test diff --git a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java new file mode 100755 index 00000000000..02cf08f4080 --- /dev/null +++ b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java @@ -0,0 +1,83 @@ +package com.sap.sse.security.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.core.Response; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.security.SecurityService; +import com.sap.sse.security.UsernamePasswordRealm; +import com.sap.sse.security.impl.Activator; +import com.sap.sse.security.impl.SecurityServiceImpl; +import com.sap.sse.security.jaxrs.api.SecurityResource; +import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.userstore.mongodb.PersistenceFactory; +import com.sap.sse.security.userstore.mongodb.UserStoreImpl; + +public class SecurityResourceTest { + private SecurityResource servlet; + private SecurityServiceImpl service; + + @Before + public void setUp() throws UserManagementException, MailException { + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase().dropDatabase(); + final UserStoreImpl store = new UserStoreImpl(); + Activator.setTestUserStore(store); + UsernamePasswordRealm.setTestUserStore(store); + service = new SecurityServiceImpl(/* mailServiceTracker */ null, + store, /* setAsActivatorSecurityService */ true); + SecurityUtils.setSecurityManager(service.getSecurityManager()); + Session session = SecurityUtils.getSubject().getSession(); + assertNotNull(session); + servlet = new SecurityResource() { + @Override + public SecurityService getService() { + return service; + } + }; + store.addPermissionForUser("admin", "can do"); + store.addPermissionForUser("admin", "event:view:*"); + store.addPermissionForUser("admin", "event:edit:123"); + } + + private String createAccessToken() throws ParseException { + String responseJsonString = (String) servlet.accessToken("admin", "admin").getEntity(); + JSONObject responseJson = (JSONObject) new JSONParser().parse(responseJsonString); + assertEquals("admin", responseJson.get("username")); + String accessToken = (String) responseJson.get("access_token"); + assertNotNull(accessToken); + return accessToken; + } + + @Ignore("Ignore on master until we've found out what the problem with unloadable UsernameAndPasswordRealm is") + @Test + public void createAccessTokenAndAuthenticate() throws ParseException { + String accessToken = createAccessToken(); + Response response = servlet.authenticate(accessToken); + JSONObject responseJson = (JSONObject) new JSONParser().parse((String) response.getEntity()); + assertEquals("admin", responseJson.get("username")); + final Subject subject = SecurityUtils.getSubject(); + assertTrue(subject.isAuthenticated()); + assertEquals("admin", subject.getPrincipal()); + assertTrue(subject.isPermitted("can do")); + assertFalse(subject.isPermitted("can't do")); + assertTrue(subject.isPermitted("event:view:999")); + assertTrue(subject.isPermitted("event:edit:123")); + assertFalse(subject.isPermitted("event:edit:234")); + subject.logout(); + assertFalse(subject.isAuthenticated()); + } +} diff --git a/java/com.sap.sse.security.ui/Security UI sdm.launch b/java/com.sap.sse.security.ui/Security UI sdm.launch old mode 100644 new mode 100755 index c74715a12d6..7750b7dbad8 --- a/java/com.sap.sse.security.ui/Security UI sdm.launch +++ b/java/com.sap.sse.security.ui/Security UI sdm.launch @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java index 489510d0ea0..2e82d56e3bd 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java @@ -8,36 +8,33 @@ public interface IconResources extends ClientBundle { public static final IconResources INSTANCE = GWT.create(IconResources.class); - @Source("com/sap/sse/security/ui/images/logo.png") + @Source("images/logo.png") ImageResource sapLogo(); - @Source("com/sap/sse/security/ui/images/user.png") + @Source("images/user.png") ImageResource user(); - @Source("com/sap/sse/security/ui/images/user_small.png") + @Source("images/user_small.png") ImageResource userSmall(); - @Source("com/sap/sse/security/ui/images/user_icon.png") + @Source("images/user_icon.png") ImageResource userIcon(); - @Source("com/sap/sse/security/ui/images/status_red.png") + @Source("images/status_red.png") ImageResource statusRed(); - @Source("com/sap/sse/security/ui/images/status_green.png") + @Source("images/status_green.png") ImageResource statusGreen(); - @Source("com/sap/sse/security/ui/images/status_yellow.png") + @Source("images/status_yellow.png") ImageResource statusYellow(); - @Source("com/sap/sse/security/ui/images/status_blue.png") + @Source("images/status_blue.png") ImageResource statusBlue(); - @Source("com/sap/sse/security/ui/images/status_grey.png") + @Source("images/status_grey.png") ImageResource statusGrey(); - @Source("com/sap/sse/security/ui/images/delete.png") + @Source("images/delete.png") ImageResource delete(); - - @Source("com/sap/sse/gwt/client/images/remove.png") - ImageResource remove(); } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java index 839ca489f9d..6ee94c0fe1e 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java @@ -66,7 +66,7 @@ public class UserDetailsView extends FlowPanel { for (DefaultPermissions defaultPermission : DefaultPermissions.values()) { defaultPermissionNames.add(defaultPermission.getPermissionname()); } - rolesEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getRoles(), stringMessages, IconResources.INSTANCE.remove(), defaultRoleNames, + rolesEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getRoles(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultRoleNames, stringMessages.enterRoleName()); rolesEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override @@ -95,7 +95,7 @@ public class UserDetailsView extends FlowPanel { })); } }); - permissionsEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getPermissions(), stringMessages, IconResources.INSTANCE.remove(), defaultPermissionNames, + permissionsEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getPermissions(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultPermissionNames, stringMessages.enterPermissionName()); permissionsEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/delete.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/delete.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/delete.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/delete.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/logo.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/logo.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/logo.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/logo.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_blue.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_blue.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_blue.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_blue.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_green.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_green.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_green.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_green.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_grey.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_grey.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_grey.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_grey.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_red.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_red.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_red.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_red.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_yellow.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_yellow.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_yellow.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_yellow.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_icon.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_icon.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_icon.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_icon.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_small.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_small.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_small.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_small.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/shiro.ini b/java/com.sap.sse.security.ui/src/main/resources/shiro.ini index 8e7d14f8c4b..06ec02bbf2f 100755 --- a/java/com.sap.sse.security.ui/src/main/resources/shiro.ini +++ b/java/com.sap.sse.security.ui/src/main/resources/shiro.ini @@ -6,10 +6,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java index 59f4cf7a7ed..29ecf730a5d 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java @@ -15,4 +15,5 @@ public interface DomainObjectFactory { User loadUser(String name); Map> loadPreferences(); + } diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java index 46c3a062db5..28deb3c062f 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java @@ -29,13 +29,20 @@ public class UserStoreImpl implements UserStore { private static final Logger logger = Logger.getLogger(UserStoreImpl.class.getName()); + private static final String ACCESS_TOKEN_KEY = "___access_token___"; + private String name = "MongoDB user store"; private final ConcurrentHashMap users; private final ConcurrentHashMap> usersByEmail; + private final ConcurrentHashMap usersByAccessToken; private final ConcurrentHashMap emailForUsername; private final ConcurrentHashMap settings; private final ConcurrentHashMap> settingTypes; + + /** + * Keys are the usernames, values are the key/value pairs representing the user's preferences + */ private final ConcurrentHashMap> preferences; /** @@ -48,7 +55,8 @@ public class UserStoreImpl implements UserStore { usersByEmail = new ConcurrentHashMap<>(); emailForUsername = new ConcurrentHashMap<>(); settings = new ConcurrentHashMap<>(); - settingTypes = new ConcurrentHashMap>(); + settingTypes = new ConcurrentHashMap<>(); + usersByAccessToken = new ConcurrentHashMap<>(); preferences = new ConcurrentHashMap<>(); final DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(); mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); @@ -101,6 +109,29 @@ public class UserStoreImpl implements UserStore { } } + @Override + public boolean setAccessToken(String username, String accessToken) { + final boolean result; + final User user = getUserByName(username); + if (user == null) { + result = false; + } else { + result = true; + usersByAccessToken.put(accessToken, user); + setPreference(username, ACCESS_TOKEN_KEY, accessToken); + } + return result; + } + + @Override + public void removeAccessToken(String username, String accessToken) { + User user = usersByAccessToken.remove(accessToken); + if (user != null) { + // the access token actually existed; now we need to update the preferences + unsetPreference(username, ACCESS_TOKEN_KEY); + } + } + private void addToUsersByEmail(User u) { if (u.getEmail() != null && !u.getEmail().isEmpty()) { Set set = usersByEmail.get(u.getEmail()); @@ -175,10 +206,24 @@ public class UserStoreImpl implements UserStore { @Override public User getUserByName(String name) { + final User result; if (name == null) { - return null; + result = null; + } else { + result = users.get(name); } - return users.get(name); + return result; + } + + @Override + public User getUserByAccessToken(String accessToken) { + final User result; + if (accessToken == null) { + result = null; + } else { + result = usersByAccessToken.get(accessToken); + } + return result; } @Override diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java index 147863f9173..9f6ef354951 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java @@ -33,18 +33,16 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { @Override public Iterable loadAllUsers() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); DBCollection userCollection = db.getCollection(CollectionNames.USERS.name()); - try { for (DBObject o : userCollection.find()) { result.add(loadUser(o)); } } catch (Exception e) { - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load events."); - logger.log(Level.SEVERE, "loadAllEvents", e); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load users."); + logger.log(Level.SEVERE, "loadAllUsers", e); } - return result; } diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java index fe9e9ef3feb..41ebcee5c8f 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java @@ -46,13 +46,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbUser.put(FieldNames.User.PERMISSIONS.name(), user.getPermissions()); usersCollection.update(query, dbUser, /* upsrt */true, /* multi */false, WriteConcern.SAFE); } - + @Override public void deleteUser(User user) { DBCollection usersCollection = db.getCollection(CollectionNames.USERS.name()); DBObject dbUser = new BasicDBObject(); dbUser.put(FieldNames.User.NAME.name(), user.getName()); - usersCollection.remove(dbUser); } diff --git a/java/com.sap.sse.security/resources/shiro.ini b/java/com.sap.sse.security/resources/shiro.ini index d751a822a12..0be28cb3e39 100644 --- a/java/com.sap.sse.security/resources/shiro.ini +++ b/java/com.sap.sse.security/resources/shiro.ini @@ -9,10 +9,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java b/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java new file mode 100755 index 00000000000..bacf4debc85 --- /dev/null +++ b/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java @@ -0,0 +1,35 @@ +package com.sap.sse.security; + +import org.apache.shiro.authc.AuthenticationToken; + +import com.sap.sse.security.impl.Activator; + +/** + * An access token as issued by {@link SecurityService#createAccessToken(String)}. The user name which is returned + * by {@link #getPrincipal()} is obtained by looking up the access token using the {@link SecurityService}. + * + * @author Axel Uhl (D043530) + * + */ +public class AccessToken implements AuthenticationToken { + private static final long serialVersionUID = 8528031991813216585L; + private final String accessToken; + + public AccessToken(String accessToken) { + super(); + this.accessToken = accessToken; + } + + @Override + public Object getPrincipal() { + SecurityService securityService = Activator.getSecurityService(); + User user = securityService.getUserByAccessToken(accessToken); + return user == null ? null : user.getName(); + } + + @Override + public String getCredentials() { + return accessToken; + } + +} diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java b/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java new file mode 100755 index 00000000000..c920f0f7b80 --- /dev/null +++ b/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java @@ -0,0 +1,38 @@ +package com.sap.sse.security; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SaltedAuthenticationInfo; + +/** + * A realm that authenticates users by an access token which has previously been obtained through + * {@link SecurityService#createAccessToken(String)}. + * + * @author Axel Uhl (D043530) + * + */ +public class AccessTokenRealm extends AbstractUserStoreBasedRealm { + + public AccessTokenRealm() { + super(); + } + + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof AccessToken; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + AccessToken accessToken = (AccessToken) token; + final User user = getUserStore().getUserByAccessToken(accessToken.getCredentials()); + if (user == null) { + return null; + } + // return salted credentials + SaltedAuthenticationInfo sai = new SimpleSaltedAuthenticationInfo(user.getName(), accessToken.getCredentials(), /* salt */ null); + return sai; + } + +} diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java index 237dcc46241..c04bab7bfef 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java @@ -139,4 +139,24 @@ public interface SecurityService extends ReplicableWithObjectInputStreamusername can be + * authenticated using the token. Any access token previously created for same user will be invalidated by this + * call. + * + * @return a new access token if username identifies a known user, null otherwise + */ + String createAccessToken(String username); + + /** + * Looks up a user by an access token that was created before using {@link #createAccessToken(String)} for same user name. + * + * @return null in case the access token is unknown or was deleted / invalidated + */ + User getUserByAccessToken(String accessToken); + + void removeAccessToken(String username, String accessToken); + + User loginByAccessToken(String accessToken); + } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java b/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java index a8b8fff5a0f..79b2b428079 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java @@ -9,12 +9,12 @@ import org.apache.shiro.util.SimpleByteSource; public class SimpleSaltedAuthenticationInfo implements SaltedAuthenticationInfo { private static final long serialVersionUID = -8423637970683173260L; private String username; - private String password; + private String saltedPassword; private byte[] salt; - public SimpleSaltedAuthenticationInfo(String username, String password, byte[] salt) { + public SimpleSaltedAuthenticationInfo(String username, String saltedPassword, byte[] salt) { this.username = username; - this.password = password; + this.saltedPassword = saltedPassword; this.salt = salt; } @@ -26,7 +26,7 @@ public class SimpleSaltedAuthenticationInfo implements SaltedAuthenticationInfo @Override public Object getCredentials() { - return password; + return saltedPassword; } @Override diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java b/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java index 4dd17e4947f..f0ad1f20670 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java @@ -13,6 +13,8 @@ public interface UserStore extends Named { User getUserByName(String name); User getUserByEmail(String email); + + User getUserByAccessToken(String accessToken); User createUser(String name, String email, Account... accounts) throws UserManagementException; @@ -87,4 +89,14 @@ public interface UserStore extends Named { */ void replaceContentsFrom(UserStore newUserStore); + /** + * Stores an access token that can be used to authenticate the user identified by username. + * If there is no user by that name, calling this method has no effect and it will return false. + * + * @return whether a user could be identified by username + */ + boolean setAccessToken(String username, String accessToken); + + void removeAccessToken(String username, String accessToken); + } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java old mode 100644 new mode 100755 index 97db2ae01ee..a4e6375a4e3 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java @@ -40,6 +40,10 @@ public class Activator implements BundleActivator { UsernamePasswordRealm.setTestUserStore(theTestUserStore); } + public static void setSecurityService(SecurityService securityService) { + Activator.securityService = securityService; + } + public static BundleContext getContext() { return context; } @@ -55,6 +59,7 @@ public class Activator implements BundleActivator { * registered as an OSGi service. */ public void start(BundleContext bundleContext) throws Exception { + context = bundleContext; if (testUserStore != null) { createAndRegisterSecurityService(bundleContext, testUserStore); } else { @@ -63,7 +68,7 @@ public class Activator implements BundleActivator { } private void createAndRegisterSecurityService(BundleContext bundleContext, UserStore store) { - securityService = new SecurityServiceImpl(ServiceTrackerFactory.createAndOpen(context, MailService.class), store); + securityService = new SecurityServiceImpl(ServiceTrackerFactory.createAndOpen(context, MailService.class), store, /* setAsActivatorSecurityService */ true); registration = context.registerService(SecurityService.class.getName(), securityService, null); final Dictionary replicableServiceProperties = new Hashtable<>(); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java index e248a93c404..b51e3094c1c 100755 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java @@ -19,6 +19,10 @@ public interface ReplicableSecurityService extends SecurityService { Void internalSetPreference(String username, String key, String value); Void internalUnsetPreference(String username, String key); + + Void internalSetAccessToken(String username, String accessToken); + + Void internalRemoveAccessToken(String username, String accessToken); Boolean internalSetSetting(String key, Object setting); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java old mode 100644 new mode 100755 index 9424aed58a4..830403f7b44 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java @@ -70,6 +70,7 @@ import com.sap.sse.replication.OperationExecutionListener; import com.sap.sse.replication.OperationWithResult; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; +import com.sap.sse.security.AccessToken; import com.sap.sse.security.ClientUtils; import com.sap.sse.security.Credential; import com.sap.sse.security.GithubApi; @@ -132,7 +133,23 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica * @param mailProperties must not be null */ public SecurityServiceImpl(ServiceTracker mailServiceTracker, UserStore store) { + this(mailServiceTracker, store, /* setAsActivatorTestSecurityService */ false); + } + + /** + * @param setAsActivatorSecurityService + * when true, the {@link Activator#setSecurityService(com.sap.sse.security.SecurityService)} + * will be called with this new instance as argument so that the cache manager can already be accessed + * when the security manager is created. {@link ReplicatingCacheManager#getCache(String)} fetches the + * activator's security service and passes it to the cache entries created. They need it, in turn, for + * replication. + * + */ + public SecurityServiceImpl(ServiceTracker mailServiceTracker, UserStore store, boolean setAsActivatorSecurityService) { logger.info("Initializing Security Service with user store " + store); + if (setAsActivatorSecurityService) { + Activator.setSecurityService(this); + } operationsSentToMasterForReplication = new HashSet<>(); cacheManager = new ReplicatingCacheManager(); this.operationExecutionListeners = new ConcurrentHashMap<>(); @@ -271,6 +288,22 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica logger.info("Redirecturl: " + redirectUrl); return redirectUrl; } + + @Override + public User loginByAccessToken(String accessToken) { + AccessToken token = new AccessToken(accessToken); + logger.info("Trying to login with access token"); + Subject subject = SecurityUtils.getSubject(); + try { + subject.login(token); + final String username = (String) token.getPrincipal(); + SessionUtils.saveUsername(username); + return store.getUserByName(username); + } catch (AuthenticationException e) { + logger.log(Level.INFO, "Authentication failed with access token "+accessToken); + throw e; + } + } @Override public void logout() { @@ -283,6 +316,11 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica public User getUserByName(String name) { return store.getUserByName(name); } + + @Override + public User getUserByAccessToken(String accessToken) { + return store.getUserByAccessToken(accessToken); + } @Override public User getUserByEmail(String email) { @@ -866,6 +904,18 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica return null; } + @Override + public Void internalSetAccessToken(String username, String accessToken) { + store.setAccessToken(username, accessToken); + return null; + } + + @Override + public Void internalRemoveAccessToken(String username, String accessToken) { + store.removeAccessToken(username, accessToken); + return null; + } + @Override public String getPreference(String username, String key) { Subject subject = SecurityUtils.getSubject(); @@ -876,6 +926,26 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica + " does not have permission to read preferences of user " + username); } } + + @Override + public String createAccessToken(String username) { + User user = getUserByName(username); + final String token; + if (user != null) { + RandomNumberGenerator rng = new SecureRandomNumberGenerator(); + byte[] salt = rng.nextBytes().getBytes(); + token = hashPassword(new String(rng.nextBytes().getBytes()), salt); + apply(s -> s.internalSetAccessToken(user.getName(), token)); + } else { + token = null; + } + return token; + } + + @Override + public void removeAccessToken(String username, String accessToken) { + apply(s -> s.internalRemoveAccessToken(username, accessToken)); + } // ----------------- Replication ------------- @Override diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java index a2199c495bd..3baf3a3c261 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java @@ -11,6 +11,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.json.simple.JSONObject; + +import com.sap.sse.security.User; import com.sap.sse.security.jaxrs.AbstractSecurityResource; import com.sap.sse.security.shared.UserManagementException; @@ -42,6 +45,41 @@ public class SecurityResource extends AbstractSecurityResource { } return Response.ok("Logged in!", MediaType.TEXT_PLAIN).build(); } + + @POST + @Path("/access_token") + @Produces("application/json;charset=UTF-8") + public Response accessToken(@FormParam("username") String username, @FormParam("password") String password) { + try { + getService().login(username, password); + logger.info("Successfully logged in " + username + " with password"); + JSONObject response = new JSONObject(); + response.put("username", username); + response.put("access_token", getService().createAccessToken(username)); + return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON).build(); + } catch (UserManagementException e) { + logger.info("Logging in " + username + " with password failed: "+e.getMessage()); + return getSecurityErrorResponse(e.getMessage()); + } + } + + @POST + @Path("/authenticate") + @Produces("application/json;charset=UTF-8") + public Response authenticate(@FormParam("access_token") String accessToken) { + User user = getService().loginByAccessToken(accessToken); + if (user == null) { + logger.info("Invalid access token " + accessToken); + return Response.status(Status.UNAUTHORIZED).entity("Access token " + accessToken + " not recognized") + .build(); + } else { + logger.info("Authenticated " + user.getName() + " with access token"); + } + JSONObject response = new JSONObject(); + response.put("username", user.getName()); + response.put("email", user.getEmail()); + return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON).build(); + } @GET @Path("/logout") diff --git a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF index b2f04cadba2..b10a81fdeaa 100644 --- a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF +++ b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: TracTrac Client module Bundle-SymbolicName: com.tractrac.clientmodule -Bundle-Version: 3.0.7 +Bundle-Version: 3.0.9 Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., lib/TracAPI.jar diff --git a/java/com.tractrac.clientmodule/README.txt b/java/com.tractrac.clientmodule/README.txt index 31ed42bd96f..08aed822c98 100644 --- a/java/com.tractrac.clientmodule/README.txt +++ b/java/com.tractrac.clientmodule/README.txt @@ -16,6 +16,42 @@ It contains also some files: - test.sh -> script that compiles the code in the src folder, creates the test.jar library and execute the code of the example. - Manifest.txt -> manifest used to create the test.jar file +******************************************** +************* TracAPI 3.0.9 **************** +******************************************** +This is a final version. Only fixes bugs in the implementation + +Release date: 13/02/2015 +Build number: 9904 + + 1) Bugs + + - There is a ConcurrentModificationException in the IConnectionStatusListener subscription, when a thread + is adding subscriptions/unsubscriptions and other thread is sending events through this listener (Reported + by Axel Uhl,07/02/2015) + +******************************************** +************* TracAPI 3.0.8 **************** +******************************************** +This is a final version. It fixes bugs in the implementation and it adds a some features. +These features add methods to the API, but they keep the backward compatibility. +This version provides a new JavaDoc version. + +Release date: 07/02/2015 +Build number: 9826 + + 1) New features + + - Adding the method IEvent.getEventType that returns the type of the event (e.g: Sailing, Orienteering...). + (Requested by Jorge Piera, 01/02/2014) + + 2) Bugs + + - The changes in the static fields of the route (including the metadata) were not propagated through + the subscription library. Following the same approach used for the races, controls and competitors, + a new listener IRoutesListener has been added to manage these changes. (Reported by Axel Uhl, + 06/02/2015) + ******************************************** ************* TracAPI 3.0.7 **************** ******************************************** diff --git a/java/com.tractrac.clientmodule/lib/TracAPI.jar b/java/com.tractrac.clientmodule/lib/TracAPI.jar index 57e8e32f66f..f3d5016f5d8 100644 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI.jar and b/java/com.tractrac.clientmodule/lib/TracAPI.jar differ diff --git a/java/com.tractrac.clientmodule/pom.xml b/java/com.tractrac.clientmodule/pom.xml index 93c4be791b1..a9ac043c7fe 100755 --- a/java/com.tractrac.clientmodule/pom.xml +++ b/java/com.tractrac.clientmodule/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.tractrac.clientmodule - 3.0.7 + 3.0.9 eclipse-plugin diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java index 74201014580..cbffc78b2f6 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java @@ -2198,6 +2198,7 @@ public abstract class BaseChart extends Widget { public T redraw() { if (isRendered()) { nativeRedraw(chart); + nativeAdjustCheckboxPosition(chart); } return returnThis(); } @@ -2903,6 +2904,24 @@ public abstract class BaseChart extends Widget { return seriesList.get(seriesIndex).getPlotOptions().getDataLabels().getFormatter().format(new DataLabelsData(nativeData)); } + /** + * Fixing a bug currently in the base Highcharts implementation regarding the placement of the checkbox in the legend. + * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 25. Invoked + * whenever the chart is rendered.

    + * + * The implementation moves the checkbox between the legend symbol and the legend item, using the space made by setting the symbol + * padding to 25px. + */ + private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject chart) /*-{ + var series = chart.series; + for(var i= 0; i - -ea -Xmx1024m -XX:PermSize=256m -XX:+UseG1GC + -ea -Xmx1024m -XX:+UseG1GC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=localhost - -Dmongo.host=localhost + -Dmongo.host=127.0.0.1 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y @@ -187,7 +187,7 @@ no-debug.without-proxy - ${parameters.common} ${parameters.vm-settings} + ${parameters.common} ${parameters.vm-settings} ${parameters.mongodb} @@ -195,7 +195,7 @@ debug.with-proxy - ${parameters.common} ${parameters.vm-settings} ${parameters.proxy} ${parameters.debug} + ${parameters.common} ${parameters.vm-settings} ${parameters.proxy} ${parameters.debug} ${parameters.mongodb} @@ -203,7 +203,7 @@ debug.without-proxy - ${parameters.common} ${parameters.vm-settings} ${parameters.debug} + ${parameters.common} ${parameters.vm-settings} ${parameters.debug} ${parameters.mongodb} diff --git a/mobile/com.sap.sailing.racecommittee.app/lint.xml b/mobile/com.sap.sailing.racecommittee.app/lint.xml index 12d0844263e..5320a5bc7ac 100644 --- a/mobile/com.sap.sailing.racecommittee.app/lint.xml +++ b/mobile/com.sap.sailing.racecommittee.app/lint.xml @@ -1,4 +1,5 @@ + diff --git a/wiki/tracking-app/api-v1.md b/wiki/tracking-app/api-v1.md index 3e056c0c939..78db7439ae0 100644 --- a/wiki/tracking-app/api-v1.md +++ b/wiki/tracking-app/api-v1.md @@ -7,18 +7,32 @@ We have decided to handle checkins etc. at the level of ``Leaderboard``s instead 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. +For the moment, this document also contains the API for the proposed [Buoy Tender (Tonnenleger) App](#buoy-tender-app), which can be moved to a separate document at some point. + ### URL base ``` http:///sailingserver/api/v1/ ``` All relative URLs given below are relative to this base URL. +## Process + +The endpoints listed below should mostly be called in the order they are listed here. +That is, after + +1. receiving the [Checkin Information](#tracking-checkin-info), the App can +2. then perform the [Check-In](#checkin) for the competitor in question +3. and proceed with sending [GPS Fixes](#fixes). + + ## Push Notifications +_not yet implemented_ + 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 +## Check-In Information +

    ### URL and QRCode @@ -105,6 +119,7 @@ _**Note:** Consider using the leaderboard-dependent verison below - which includ ## Check-In +
    After the user has received the event data with the short URL, the smartphone is mapped to a competitor. @@ -162,6 +177,7 @@ Ends the device to competitor coupling. Does not delete it, but rather marks the ## Send Measurements (to the Fix Store) +
    The main data sent by the app. @@ -251,4 +267,97 @@ $ curl -H "Content-Type:image/jpeg" --data-binary @ \ { "teamImageUri" : "http://training.sapsailing.com/team_images/9871d3a2c554b27151cacf1422eec048.jpeg" } -``` \ No newline at end of file +``` + +# Buoy Tender (Tonnenleger) App +
    + +An app aimed at buoy tenders. In v1, this only allows marks of a race to be _pinged_. The steps for doing so are + +1. provide the information for which leaderboard and race to ping marks +2. get the marks for that race (potentially form the RaceLog, if no TrackedRace is yet present) +3. ping the marks by submitting fixes + +## Check-In Information +
    + +_see [bug 2650](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2650)_ + +In contrast to the _Tracking App_, we won't perform a check-in. However, we can deliver the information on leaderboard and race analogously through a URL (potentially QRCode), which is why this section is also called _Check-In Information_. + +This information is represented in a URL with the following structure: +``` +http:///buoy-tender/checkin + &leaderboard_name= + &race_name= +``` + +_also see [Tracking App Check-In Information](#tracking-checkin-info) for additional notes that might apply_ + +## Get Marks + +_see [bug 2651](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2651)_ + +Do not use the course to get the list of marks to ping. Instead, use the ``RaceLogDefineMarkEvent``s in the RaceLog, or ``TrackedRace#getMarks()``. As the JavaDoc of the latter states, not all marks for a race are necessarily present in the course - e.g. if they are backup buoys to be used in the case of a wind shift. + +**Path:** ``leaderboards/{leaderboard-name}/marks?raceColumn={race-column-name}&fleet={fleet-name}`` + +**Verb:** ``GET`` + +**Response:** +``` +[ + { + "@class": "Mark", + "name": "Start (1)", + "id": "Start (1)", + "type": "BUOY" + }, + { + "@class": "Mark", + "name": "Start (2)", + "id": "Start (2)", + "type": "BUOY" + }, + { + "@class": "Mark", + "name": "Windward", + "id": "22a53380-046e-0132-0da7-60a44ce903c3", + "type": "BUOY" + } +] +``` + +## Ping Marks + +_see [bug 2652](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2652)_ + +Instead of the checkin/checkout process of the tracking app, marks can be pinged using an API that hides the inner workings on the server completely. The server creates a device-mapping in the regatta-log for the exact timepoint of every fix, and adds the fixes to the GPSFixStore. + +The interface (apart from the path) is identical to [Send Measurements](#fixes). Several fixes can be sent at once, but in the interest of pinging a mark, this should usually just be a single fix. + +**Path:** ``leaderboards/{leaderboard-name}/marks/{mark-id}/gps_fixes`` + +**Verb:** ``POST`` + +**Request:** +``` +{ + "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf", + "fixes" : [ + { + "timestamp" : 14144160080000, + "latitude" : 54.325246, + "longitude" : 10.148556, + "speed" : 3.61, + "course" : 258.11, + } + ] +} +``` + +**Additional Notes:** +* the path for this endpoint intentionally has the leaderboard as a parent item + * each mark should have a unique ID (``SharedDomainFactory#getOrCreateMark(String toStringRepresentationOfID, String name)``) + * however, the mark cannot be pinged without the leaderboard as context, however, as the GPSFixStore contains only fixes with a device ID, and the mapping from that device to a mark has to be established through a RegattaLog (or RaceLog), which is attached to a (Flexible|Regatta)Leaderboard + * an alternative endpoint definition might be ``POST marks/{mid}/gps_fixes?leaderboard_name={ln}`` \ No newline at end of file