Merge branch 'tw2015-stage' into tw2015

Conflicts:
	java/com.sap.sailing.gwt.ui/SailingGWT.launch
This commit is contained in:
Axel Uhl committed 2015-07-17 00:39:59 +02:00
commit afac875f85
181 files changed
+6279 -1772

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# groups Apache / httpd log entries into "${referrer}.ips" files, where ${referrer} is the
# referrer URL identifying the "event"; the lines written to the .ips files hold the IP
# address of the requestor, the date (not the time) and the user agent string.
# Sorting for unique entries should give a count similar to what goaccess is using to
# determine "unique visitors."
# A sample line:
# 505Worlds2012.sapsailing.com 66.249.73.53 - - [12/Jan/2014:03:33:11 +0000] "GET /robots.txt HTTP/1.1" 404 238 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
#cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]\" \"\([\"]*\)\"\(.*\)$/\1 \2 \5 \7/'
cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]*\" \"\([^\"]*\)\"/\1 \2 \5 \7/' | while read referrer hit; do
echo "$hit" >>${referrer}.ips
done
for i in *.ips; do
echo -n "$i "
cat $i | sort -u | wc | awk '{ print $1; }'
done | tee unique-ips-days-useragents-per-event
echo "Done. Wrote results to `pwd`/unique-ips-days-useragents-per-event
Binary file not shown.
@@ -29,6 +29,7 @@ public class RibDashboardEntryPoint extends AbstractEntryPoint<StringMessages> {
@Override
public void doOnModuleLoad() {
SailingServiceAsync sailingService = GWT.create(SailingService.class);
EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.WEB_CONTEXT_PATH, RemoteServiceMappingConstants.sailingServiceRemotePath);
@@ -148,7 +148,7 @@ public class StartlineAnalysisCard extends Composite implements HasWidgets, Star
asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */);
raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel,
StringMessages.INSTANCE, false, false, false, startAnalysisDTO.regattaAndRaceIdentifier,
resources.combinedWindPanelStyle());
resources.combinedWindPanelStyle(), /* showHeaderPanel */ true);
raceMap.onRaceSelectionChange(Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier));
raceMap.getSettings().setZoomSettings(new RaceMapZoomSettings(zoomTypes, false));
raceMap.getSettings().setHelpLinesSettings(getHelpLineSettings());
@@ -27,9 +27,10 @@ public enum WindSourceType {
TRACK_BASED_ESTIMATION(false, 0.5, /* useSpeed */ false),
/**
* Inferred from the race course layout if the course is known to have its first leg be an upwind leg
* Inferred from the race course layout if the course is known to have its first leg be an upwind leg. This
* source has very low confidence and must be superseded by any other wind source.
*/
COURSE_BASED(false, 0.3, /* useSpeed */ false),
COURSE_BASED(false, 0.01, /* useSpeed */ false),
/**
* Wind estimation combined from all other wind sources, using <code>TrackedRace.getWind(...)</code>, based on
@@ -1,7 +1,10 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
@@ -13,6 +16,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
private static final long serialVersionUID = -1900955198751393727L;
private final Course course;
private final LinkedHashMap<Serializable, Competitor> competitorsById;
private final Set<Competitor> competitors;
private final BoatClass boatClass;
private final Serializable id;
@@ -23,11 +27,12 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable<? extends Competitor> competitors, Serializable id) {
super(name);
assert name != null;
this.course = course;
this.competitors = new HashSet<>();
this.competitorsById = new LinkedHashMap<>();
for (Competitor competitor : competitors) {
Competitor competitorWithEqualID = competitorsById.put(competitor.getId(), competitor);
this.competitors.add(competitor);
if (competitorWithEqualID != null && competitorWithEqualID != competitor) {
throw new IllegalArgumentException("Two distinct competitors with equal ID "+competitor.getId()+" are not allowed within the single race "+name);
}
@@ -48,7 +53,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
@Override
public Iterable<Competitor> getCompetitors() {
return competitorsById.values();
return Collections.unmodifiableSet(competitors);
}
@Override
@@ -99,6 +99,14 @@ public interface ScoreCorrection extends Serializable {
*/
boolean hasCorrectionFor(RaceColumn raceInLeaderboard);
/**
* Similar to {@link #hasCorrectionFor(RaceColumn)}, but returns <code>true</code> only if score corrections are found
* for any competitor who in <code>raceInLeaderboard</code> is not in a tracked race and hence the fleet assignment
* cannot be determined. This is helpful, e.g., for progress detection. If score corrections are present for such
* untracked competitors then all untracked fleets need to be assumed as finished.
*/
boolean hasCorrectionForNonTrackedFleet(RaceColumn raceInLeaderboard);
/**
* @return all race columns for which this score corrections object has at least one correction; note that this
* object may hold corrections also for competitors that are not currently returned by
@@ -472,19 +472,30 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override
public boolean hasCorrectionFor(RaceColumn raceInLeaderboard) {
return internalHasScoreCorrectionFor(raceInLeaderboard, /* considerOnlyUntrackedRaces */ false);
}
private boolean internalHasScoreCorrectionFor(RaceColumn raceInLeaderboard, boolean considerOnlyUntrackedRaces) {
for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> correctedScoresKey : correctedScores.keySet()) {
if (correctedScoresKey.getB() == raceInLeaderboard) {
if (correctedScoresKey.getB() == raceInLeaderboard &&
(!considerOnlyUntrackedRaces || raceInLeaderboard.getTrackedRace(correctedScoresKey.getA()) == null)) {
return true;
}
}
for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> maxPointsReasonsKey : maxPointsReasons.keySet()) {
if (maxPointsReasonsKey.getB() == raceInLeaderboard) {
if (maxPointsReasonsKey.getB() == raceInLeaderboard &&
(!considerOnlyUntrackedRaces || raceInLeaderboard.getTrackedRace(maxPointsReasonsKey.getA()) == null)) {
return true;
}
}
return false;
}
@Override
public boolean hasCorrectionForNonTrackedFleet(RaceColumn raceInLeaderboard) {
return internalHasScoreCorrectionFor(raceInLeaderboard, /* considerOnlyUntrackedRaces */ true);
}
@Override
public TimePoint getTimePointOfLastCorrectionsValidity() {
return timePointOfLastCorrectionsValidity;
@@ -139,7 +139,6 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
@@ -3669,7 +3668,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
if (polarDataService == null) {
throw new NotEnoughDataHasBeenAddedException("Target time estimation failed. No polar service available.");
}
Duration durationOfAllLegs = new MillisecondsDurationImpl(0);
Duration durationOfAllLegs = Duration.NULL;
for (TrackedLeg leg : trackedLegs.values()) {
Duration durationOfLeg = leg.getEstimatedTimeToComplete(polarDataService, timepoint);
durationOfAllLegs = durationOfAllLegs.plus(durationOfLeg);
@@ -0,0 +1 @@
com.*
@@ -0,0 +1,695 @@
/** Add css rules here for your application. */
/*
body #calendar:after
content: " ";
display: block;
height: 0;
clear: both;
visibility: hidden;
*/
* {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
}
iframe {
display: block;
width: 100%;
height: 100%;
border: none;
overflow-y: auto;
overflow-x: hidden;
}
.clear {
clear: both;
font-size: 1px;
height: 0px;
line-height: 0px;
margin: -1px 0 0;
width: 100%;
}
.cover {
left: -1000px;
overflow: hidden;
position: absolute;
top: -1000px;
}
body {
background: white;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
line-height: 1;
font-size: 14px;
font-weight: 400;
margin: 0;
}
table td, select, button {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
line-height: 1;
font-size: 14px;
}
.contentOuterPanel {
background: #dddcdc;
margin: 0 12px 0 12px;
padding: 12px;
}
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 700;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
table {
border-collapse: separate;
}
.CombinedWindPanelParentDiv {
padding-top: 34px;
padding-left: 10px;
}
.TrueNorthIndicatorPanelParentDiv {
padding-top: 10px;
padding-left: 10px;
}
.MapSimulationLegendParentDiv {
padding-bottom: 10px;
padding-right: 10px;
pointer-events: none;
}
.MapSimulationLegend {
pointer-events: all;
}
.RaceMap-HeaderPanel {
height: 60px;
width: 100%;
background-color: #333;
opacity: .5;
}
.leaderboardLabel {
border-bottom: 2px solid #007dc0;
padding: 0 0 6px 0;
font-weight: 700;
}
.refreshAndSettings {
background: #f2f2f2;
border-bottom: 2px solid #fff;
border-top: 2px solid #fff;
height: 30px;
}
.refreshAndSettings table td {
padding: 0 10px 0 0;
}
.refreshAndSettings table table td {
padding: 0 0 0 0;
}
.race-name {
line-height: 1.0;
}
.openColumn {
position: relative;
vertical-align: middle;
}
img.openColumn {
display: block;
margin: 3px auto 3px auto !important;
}
.breadcrumbPanel {
height: 30px;
margin: 0 12px 13px 12px;
}
.mainPanel {
width: 100%;
}
.raceBoardNavigation {
float: left;
margin: 9px 0 0 12px;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 300;
}
.raceBoardControls {
float: right;
margin: 9px 0 0 12px;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 300;
}
.raceBoardNavigation-navigationitem {
color: #dddcdc;
text-transform: uppercase;
font-weight: 500;
margin: 0 12px 0 0;
padding: 0 0 5px 0;
}
.raceBoardNavigation-navigationitem:hover {
border-bottom: 4px solid #f0ab00;
color: #dddcdc;
text-decoration: none;
}
.raceBoardNavigation-navigationitem:active {
border-bottom: 4px solid #f0ab00;
color: #dddcdc;
text-decoration: none;
}
.competitorInfo-Canvas {
pointer-events: none;
}
.gwt-DialogBox {
z-index: 20;
}
.abstractChartPanel-importantMessageOfChart {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 600;
font-size: 20px;
height: 70px;
margin: 0 auto;
padding: 49px 0 0 80px;
width: 300px;
color: #7c7c7c;
background: url(images/important-message.png) left center no-repeat;
}
.breadcrumbPanel-NextArrow {
display: none;
}
.errorLabel {
color: #FF0000;
}
.raceBoardNavigation-settingsButtonPanel {
float: right;
margin: 9px 12px 0 0;
}
.raceBoardNavigation-settingsButton {
background: url(images/settings_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center 0;
background-repeat: no-repeat, repeat-x;
width: 27px;
height: 23px;
margin: 0 12px 0 1px;
-webkit-border-radius: 0px 3px 3px 0px;
-moz-border-radius: 0px 3px 3px 0px;
-o-border-radius: 0px 3px 3px 0px;
-ms-border-radius: 0px 3px 3px 0px;
border-radius: 0px 3px 3px 0px;
}
.raceBoardNavigation-settingsButton:hover {
background-image: url(images/settings_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center -30px;
background-repeat: no-repeat, repeat-x;
cursor: pointer;
}
.raceBoardNavigation-filterButton:hover {
background-image: url(images/filter_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center -30px;
background-repeat: no-repeat, repeat-x;
cursor: pointer;
}
.raceBoardNavigation-innerElement {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
0 transparent;
color: #FFFFFF;
cursor: pointer;
font-family: 'Open Sans', Verdana, Arial, sans-serif;
font-weight: 600;
font-size: 14px;
margin: 0 0 0 0;
padding: 2px 7px 2px 3px;
height: 18px;
display: inline-block;
text-decoration: none;
border-radius: 5px 0 0 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
}
.raceBoardNavigation-innerElement:active {
top: 1px;
position: relative;
}
.raceBoardNavigation-innerElement:hover {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
-30px transparent;
cursor: pointer;
}
.raceBoardNavigation-innerElement label {
cursor: pointer;
}
.raceBoardNavigation-standaloneElement {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
0 transparent;
color: #FFFFFF;
cursor: pointer;
font-family: 'Open Sans', Verdana, Arial, sans-serif;
font-weight: 600;
font-size: 14px;
margin: 0 0 0 0;
padding: 2px 7px 2px 3px;
height: 23px;
display: inline-block;
text-decoration: none;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 5px 5px 5px 5px;
}
.raceBoardNavigation-standaloneElement:active {
top: 1px;
position: relative;
}
.raceBoardNavigation-standaloneElement:hover {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
-30px transparent;
cursor: pointer;
}
.raceBoardNavigation-standaloneElement label {
cursor: pointer;
}
.timePanelButton {
float: left;
margin: 0 0 0 5px;
}
.timePanelButton-SlowDown {
background-color: red !important;
}
.timePanelButton-SpeedUp {
background-color: green !important;
}
.playPauseButton {
padding: 0;
float: left;
width: 32px;
height: 28px;
background: url(images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png)
center no-repeat;
cursor: pointer;
border: 1px solid #cecece;
border-radius: 4px;
outline: 0;
}
.playPauseButton:hover {
cursor: pointer;
background-color: #cecece;
}
.playPauseButtonPause {
background: url(images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png) 2px
0 no-repeat;
outline: 0;
background-size: contain;
}
.playPauseButtonPause:hover {
cursor: pointer;
}
.backToLivePlayButton {
width: 42px;
height: 38px;
font-size: 8px;
white-space: normal;
border-radius: 4px;
border: none;
margin-right: 23px;
margin-top: 5px;
margin-bottom: 5px;
z-index: 1;
}
.backToLivePlayButton-Inactive {
color: #6dc021;
background-color: white;
font-weight: bold;
}
.backToLivePlayButton-Active {
background-color: #6dc021;
color: white;
font-weight: normal;
}
.backToLivePlayButton:hover {
border: 2px solid gray;
}
.backToLivePlayButton:focus {
outline: 0 !important;
}
.dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"]
{
z-index: 10;
}
.browserOptimizedMessage {
padding: 15px 0px;
}
.trackingQuality-circle {
width: 8px;
height: 8px;
border-radius: 50%;
float: left;
}
.circleYellow {
background: #fbba00;
}
.circleGreen {
background: #8ab54e;
}
.circleRed {
background: #f01010;
}
.busyIndicator-Simple {
position: absolute;
top: 0.7em;
right: 7.4em;
}
.busyIndicator-Circle {
}
.raceBoard-TitlePanel {
position: relative;
top: 10px;
z-index: 10;
color: #fff;
margin-left: auto;
margin-right: auto;
}
.raceBoard-TitlePanel-RaceNameLabel {
font-size: 32px;
font-weight: bold;
padding: 7px;
}
.raceBoard-Logo {
position: absolute;
top: 6px;
left: 10px;
z-index: 10;
cursor: pointer;
}
.SideBySideComponentViewer-MainPanel {
top: 12px;
}
.TimePanel-ShowExtended-Button {
width: 29px;
height: 28px;
float: left;
cursor: pointer;
border-radius: 4px;
border: 1px solid #ececec;
}
.TimePanel-ShowExtended-Button-Open {
background: white url(images/arrows_bottom_black.png) center no-repeat;
}
.TimePanel-ShowExtended-Button-Closed {
background: white url(images/arrows_top_black.png) center no-repeat;
}
.TimePanel-ShowExtended-Button:hover {
background-color: #cecece;
}
.TimePanel-ShowExtended-Button:focus {
outline: 0 !important;
}
.RaceBoard-globalNavigation-Link {
display: inline;
margin-right: 3px;
}
.RaceBoard-globalNavigation-Link a {
color: #fff;
cursor: pointer;
}
.RaceBoard-globalNavigation-Link+.RaceBoard-globalNavigation-Link:before
{
content: ' \00bb\00a0';
}
.TimePanel-settingsButtonStyle {
position: absolute;
right: 0px;
z-index: 1;
border: none;
}
.TimePanel-settingsButtonStyle:focus {
outline: 0 !important;
}
.TimePanel-settingsButtonStyle:hover {
border: 1px solid gray;
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-multiCompetitorRaceChart
{
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-multiCompetitorRaceChart
{
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-windChart {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-windChart {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 4% 50%, 96% 50%
}
.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 4% 50%, 96% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-media,
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-media {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png);
background-repeat: no-repeat, no-repeat;
background-position: 10% 50%, 90% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-mediaplaying {
background-image:
url(images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png);
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Small-media {
background-position: 5% 50%, 100% 50% !important;
margin-left: 0px !important;
padding: 2px 35px !important;
}
@external gwt-ToggleButton-up, gwt-ToggleButton-down, gwt-ToggleButton-up-hovering, gwt-ToggleButton-down-hovering;
.gwt-ToggleButton-up, .gwt-ToggleButton-up-hovering {
background: url(images/unlock.png) center no-repeat;
margin-left: 5px;
}
.gwt-ToggleButton-down, .gwt-ToggleButton-down-hovering {
background: url(images/lock.png) center no-repeat;
margin-left: 5px;
}
.RegattaRaceInformation-Header {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
position: relative;
left: 140px;
top: 11px;
}
.RegattaRaceInformation-Header .RaceName-Label {
display: inline;
color: white;
margin-right: 10px;
font-size: 36px;
}
.RegattaRaceInformation-Header .RaceSeriesAndFleet-Label {
display: inline;
color: white;
font-size: 15px;
}
.RegattaAndRaceTime-Header {
position: absolute;
right: 10px;
top: 13px;
text-align: right;
color: white;
}
.RegattaAndRaceTime-Header .RegattaName-Anchor {
font-size: 15px;
color: white;
text-decoration: none;
padding-left: 25px;
background-image: url(images/home.png);
background-repeat: no-repeat;
background-size: 17px;
background-position: 4px 1px;
}
.RegattaAndRaceTime-Header .RegattaName-Anchor:hover {
text-decoration: underline;
}
.RegattaAndRaceTime-Header .RaceTime-Label {
font-size: 15px;
margin-top: 5px;
}
.VideoPopup-Close-Button {
border: none;
}
.Media-Select-Button {
font-size: 15px;
font-size: 1rem;
display: inline-block;
font-weight: 400;
color: #111;
border: none;
padding: 0.5em 0.3em 0.5em 0.8em;
background-color: #fff;
-webkit-transition: background-color 0.2s;
-moz-transition: background-color 0.2s;
-o-transition: background-color 0.2s;
-ms-transition: background-color 0.2s;
transition: background-color 0.2s;
width: 100%;
max-width: 25em;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.Media-Select-Button:hover, .Media-Select-Button:focus {
background-color: #f0ab00;
}
.Media-Select-Button-playing {
color: #999;
}
.Media-Select-Button-playing:hover, .Media-Select-Button-playing:focus {
color: #fff;
background-color: #ccc;
}
.Media-Select-Popup .dialogMiddleCenterInner {
padding: 0;
}
.Media-Select-Popup .Caption {
padding: 4px 10px;
}
@@ -0,0 +1,41 @@
<!doctype html>
<html>
<head>
<!--[if lt IE 9]>
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
<![endif]-->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>SAP Sailing Analytics Race Board</title>
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
<link rel="stylesheet" type="text/css" href="EmbeddedMapAndWindChart.css">
<script type="text/javascript" src="js/jquery-1.5.2.min.js"></script>
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
@@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
<title>SAP Sailing - Homepage</title>
</head>
<body>
<script>
<!--
window.location = "Home.html"+window.location.search+window.location.hash;
//->
</script>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
@@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
<title>SAP Sailing - Homepage</title>
</head>
<body>
<script>
<!--
window.location = "Home.html"+window.location.search+window.location.hash;
//->
</script>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
@@ -54,7 +54,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart.html com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
</launchConfiguration>
@@ -4,6 +4,7 @@
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
@@ -70,7 +71,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Desktop com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Desktop com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xms1024m -Xmx3072m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration>
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
@@ -16,7 +17,7 @@
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
<listEntry value="com.sap.sailing.gwt.AutoPlay"/>
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
<listEntry value="com.sap.sailing.gwt.Home"/>
<listEntry value="com.sap.sailing.gwt.home.Home"/>
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
</listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
@@ -70,7 +71,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
</launchConfiguration>
+6 -1
View File
@@ -48,5 +48,10 @@ bin.includes = META-INF/,\
AutoPlay.html,\
Home.css,\
Home.html,\
SettingsDialog.css
HomeDesktop.html,\
HomeMobile.html,\
SettingsDialog.css,\
EmbeddedMapAndWindChart.css,\
EmbeddedMapAndWindChart.html,\
com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/
output.. = WEB-INF/classes/
Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17.6 17.6"><circle fill="#8AB54E" cx="8.8" cy="8.8" r="8.8"/><path fill="#FFF" d="M12.9 6.1c-.4-.4-1-.4-1.4 0L7.9 9.6 6.5 8.2c-.4-.4-1-.4-1.4 0-.4.4-.4 1 0 1.4l2.1 2.1c.4.4 1 .4 1.4 0l4.2-4.2c.5-.4.5-1 .1-1.4z"/></svg>

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

+1
View File
@@ -130,6 +130,7 @@
<module>com.sap.sailing.gwt.ui.Leaderboard</module>
<module>com.sap.sailing.gwt.ui.LeaderboardEditing</module>
<module>com.sap.sailing.gwt.ui.RaceBoard</module>
<module>com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart</module>
<module>com.sap.sailing.gwt.ui.Spectator</module>
<module>com.sap.sailing.gwt.ui.DataMining</module>
<module>com.sap.sailing.gwt.ui.VideoPopup</module>
@@ -1,10 +1,12 @@
package com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -18,12 +20,22 @@ import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregatt
import com.sap.sailing.gwt.home.client.place.event.multiregatta.MultiregattaTabView;
import com.sap.sailing.gwt.home.client.place.event.overview.EventOverviewStage;
import com.sap.sailing.gwt.home.client.place.event.partials.eventregatta.EventRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter.DropdownFilterList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListStepsLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLive;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshManager;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
import com.sap.sse.common.Util.Triple;
/**
@@ -31,10 +43,21 @@ import com.sap.sse.common.Util.Triple;
*/
public class MultiregattaOverviewTabView extends Composite implements MultiregattaTabView<MultiregattaOverviewPlace> {
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaOverviewTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField SimplePanel content;
@UiField(provided = true) EventOverviewStage stage;
@UiField(provided = true) RacesListLive racesListLive;
@UiField DivElement newContentContainerUi;
@UiField(provided = true) DropdownFilter<String> boatCategoryFilterUi;
@UiField MultiRegattaListStepsLegend regattaProgressLegendUi;
@UiField(provided = true) MultiRegattaList regattaListUi;
private Presenter currentPresenter;
public MultiregattaOverviewTabView() {
}
@Override
@@ -54,78 +77,93 @@ public class MultiregattaOverviewTabView extends Composite implements Multiregat
@Override
public void start(MultiregattaOverviewPlace myPlace, AcceptsOneWidget contentArea) {
racesListLive = new RacesListLive(currentPresenter, true);
stage = new EventOverviewStage(currentPresenter);
racesListLive = new RacesListLive(currentPresenter, true);
MultiregattaOverviewRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaOverviewRegattasTabViewRegattaFilterList();
boatCategoryFilterUi = new DropdownFilter<String>(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList);
regattaListUi = new MultiRegattaList(currentPresenter);
initWidget(ourUiBinder.createAndBindUi(this));
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
stage.setupRefresh(refreshManager);
refreshManager.add(racesListLive, new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
refreshManager.add(racesListLive.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
if (ExperimentalFeatures.SHOW_NEW_REGATTA_LIST) {
refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId()));
content.removeFromParent();
} else {
boatCategoryFilterUi.removeFromParent();
regattaProgressLegendUi.removeFromParent();
regattaListUi.removeFromParent();
newContentContainerUi.removeFromParent();
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
contentArea.setWidget(this);
}
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
protected void initView() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> regattaStructure = getRegattaStructure();
EventRegattaList eventRegattaList = new EventRegattaList(regattaStructure, currentPresenter);
content.setWidget(eventRegattaList);
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
protected void initView() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> regattaStructure = getRegattaStructure();
EventRegattaList eventRegattaList = new EventRegattaList(regattaStructure, currentPresenter);
content.setWidget(eventRegattaList);
}
private Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> getRegattaStructure() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> result = new HashMap<>();
Map<String, RaceGroupDTO> raceGroupsMap = new HashMap<>();
for (RaceGroupDTO raceGroup: currentPresenter.getCtx().getRaceGroups()) {
raceGroupsMap.put(raceGroup.getName(), raceGroup);
}
for (LeaderboardGroupDTO leaderboardGroup : currentPresenter.getCtx().getLeaderboardGroups()) {
for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) {
String leaderboardName = leaderboard.name;
result.put(leaderboardName, new Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>(raceGroupsMap.get(leaderboardName),
leaderboard, leaderboardGroup));
}
}
return result;
}
private Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> getRegattaStructure() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> result = new HashMap<>();
Map<String, RaceGroupDTO> raceGroupsMap = new HashMap<>();
for (RaceGroupDTO raceGroup : currentPresenter.getCtx().getRaceGroups()) {
raceGroupsMap.put(raceGroup.getName(), raceGroup);
}
for (LeaderboardGroupDTO leaderboardGroup : currentPresenter.getCtx().getLeaderboardGroups()) {
for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.getLeaderboards()) {
String leaderboardName = leaderboard.name;
result.put(leaderboardName, new Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>(
raceGroupsMap.get(leaderboardName), leaderboard, leaderboardGroup));
}
}
return result;
}
@Override
public void stop() {
}
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaOverviewTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField SimplePanel content;
@UiField(provided = true) RacesListLive racesListLive;
@UiField(provided = true) EventOverviewStage stage;
@Override
public MultiregattaOverviewPlace placeToFire() {
return new MultiregattaOverviewPlace(currentPresenter.getCtx());
}
private class MultiregattaOverviewRegattasTabViewRegattaFilterList implements
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
@Override
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
regattaListUi.setData(data, nextUpdate, updateNo);
boatCategoryFilterUi.updateFilterValues();
}
@Override
public Collection<String> getSelectableValues() {
return regattaListUi.getSelectableBoatCategories();
}
@Override
public void onSelectFilter(String value) {
regattaListUi.setVisibleBoatCategory(value);
}
}
}
@@ -1,13 +1,27 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:r="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.raceListLive"
xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials"
xmlns:o="urn:import:com.sap.sailing.gwt.home.client.place.event.overview">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
.legend_and_filter {
text-align: right;
}
.legend_and_filter > div {
display: inline-block;
vertical-align: middle;
}
</ui:style>
<g:HTMLPanel>
<o:EventOverviewStage ui:field="stage" />
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<r:RacesListLive ui:field="racesListLive" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmediumbig}" />
<div class="{res.mediaCss.grid}" ui:field="newContentContainerUi">
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}">
<p:raceListLive.RacesListLive ui:field="racesListLive" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
<div class="{res.mainCss.spacermargintopmedium} {style.legend_and_filter}">
<p:multiRegattaList.MultiRegattaListStepsLegend ui:field="regattaProgressLegendUi" />
<p:listNavigation.DropdownFilter ui:field="boatCategoryFilterUi" />
</div>
<p:multiRegattaList.MultiRegattaList ui:field="regattaListUi" />
</div>
</div>
<g:SimplePanel ui:field="content" />
@@ -1,10 +1,12 @@
package com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -17,12 +19,22 @@ import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregatt
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.MultiregattaTabView;
import com.sap.sailing.gwt.home.client.place.event.partials.eventregatta.EventRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter.DropdownFilterList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListStepsLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLive;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshManager;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
import com.sap.sse.common.Util.Triple;
/**
@@ -30,12 +42,20 @@ import com.sap.sse.common.Util.Triple;
*/
public class MultiregattaRegattasTabView extends Composite implements MultiregattaTabView<MultiregattaRegattasPlace> {
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaRegattasTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField SimplePanel content;
@UiField(provided = true) RacesListLive racesListLive;
@UiField DivElement newContentContainerUi;
@UiField(provided = true) RacesListLive racesListLiveUi;
@UiField(provided = true) DropdownFilter<String> boatCategoryFilterUi;
@UiField MultiRegattaListStepsLegend regattaProgressLegendUi;
@UiField(provided = true) MultiRegattaList regattaListUi;
private Presenter currentPresenter;
public MultiregattaRegattasTabView() {
}
@Override
@@ -55,30 +75,43 @@ public class MultiregattaRegattasTabView extends Composite implements Multiregat
@Override
public void start(final MultiregattaRegattasPlace myPlace, final AcceptsOneWidget contentArea) {
racesListLive = new RacesListLive(currentPresenter, true);
racesListLiveUi = new RacesListLive(currentPresenter, true);
MultiregattaRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaRegattasTabViewRegattaFilterList();
boatCategoryFilterUi = new DropdownFilter<String>(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList);
regattaListUi = new MultiRegattaList(currentPresenter);
initWidget(ourUiBinder.createAndBindUi(this));
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
refreshManager.add(racesListLive, new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
refreshManager.add(racesListLiveUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
if (ExperimentalFeatures.SHOW_NEW_REGATTA_LIST) {
refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId()));
content.removeFromParent();
} else {
boatCategoryFilterUi.removeFromParent();
regattaProgressLegendUi.removeFromParent();
regattaListUi.removeFromParent();
newContentContainerUi.removeFromParent();
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
contentArea.setWidget(this);
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
protected void initView() {
@@ -106,17 +139,32 @@ public class MultiregattaRegattasTabView extends Composite implements Multiregat
@Override
public void stop() {
}
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaRegattasTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@Override
public MultiregattaRegattasPlace placeToFire() {
return new MultiregattaRegattasPlace(currentPresenter.getCtx());
}
private class MultiregattaRegattasTabViewRegattaFilterList implements
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
@Override
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
regattaListUi.setData(data, nextUpdate, updateNo);
boatCategoryFilterUi.updateFilterValues();
}
@Override
public Collection<String> getSelectableValues() {
return regattaListUi.getSelectableBoatCategories();
}
@Override
public void onSelectFilter(String value) {
regattaListUi.setVisibleBoatCategory(value);
}
}
}
@@ -1,19 +1,27 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:r="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.raceListLive">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
.space-top {
margin-top: 2em;
margin-bottom: 2em;
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="res"
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
.legend_and_filter {
text-align: right;
}
</ui:style>
<g:HTMLPanel>
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<r:RacesListLive ui:field="racesListLive" addStyleNames="{style.space-top}" />
</div>
</div>
<g:SimplePanel ui:field="content" addStyleNames="{style.space-top}" />
</g:HTMLPanel>
.legend_and_filter > div {
display: inline-block;
vertical-align: middle;
}
</ui:style>
<g:HTMLPanel>
<div class="{res.mediaCss.grid}" ui:field="newContentContainerUi">
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}">
<p:raceListLive.RacesListLive ui:field="racesListLiveUi" addStyleNames="{res.mainCss.spacermargintopmedium}" />
<div class="{res.mainCss.spacermargintopmedium} {style.legend_and_filter}">
<p:multiRegattaList.MultiRegattaListStepsLegend ui:field="regattaProgressLegendUi" />
<p:listNavigation.DropdownFilter ui:field="boatCategoryFilterUi" />
</div>
<p:multiRegattaList.MultiRegattaList ui:field="regattaListUi" />
</div>
</div>
<g:SimplePanel ui:field="content" />
</g:HTMLPanel>
</ui:UiBinder>
@@ -41,6 +41,8 @@ public class EventHeader extends Composite {
@UiField StringMessages i18n;
@UiField DivElement eventLogo;
@UiField
AnchorElement eventLogoAnchorUi;
@UiField HeadingElement staticTitle;
@UiField SpanElement eventName;
@UiField DivElement eventState;
@@ -56,6 +58,7 @@ public class EventHeader extends Composite {
@UiField DivElement races;
@UiField DivElement trackedRaces;
@UiField DivElement eventCategory;
@UiField DivElement courseAreaUi;
@UiField FlowPanel dropdownContent;
@@ -96,7 +99,9 @@ public class EventHeader extends Composite {
private void initFields() {
LogoUtil.setEventLogo(eventLogo, event);
if (presenter.showRegattaMetadata()) {
presenter.getCurrentEventNavigation().configureAnchorElement(eventLogoAnchorUi);
}
String eventDisplayName = event.getDisplayName();
String nameToShow;
if(presenter.showRegattaMetadata()) {
@@ -123,6 +128,11 @@ public class EventHeader extends Composite {
} else {
hide(trackedRaces);
}
if(regattaMetadata.getDefaultCourseAreaName() != null) {
courseAreaUi.setInnerText(i18n.courseAreaName(regattaMetadata.getDefaultCourseAreaName()));
} else {
hide(courseAreaUi);
}
if(regattaMetadata.getBoatCategory() != null) {
eventCategory.setInnerText(regattaMetadata.getBoatCategory());
} else {
@@ -149,7 +159,7 @@ public class EventHeader extends Composite {
hide(eventLink);
}
hide(competitors, races, trackedRaces);
hide(competitors, races, trackedRaces, courseAreaUi, eventCategory);
}
initTitleAndSelection(nameToShow);
@@ -10,7 +10,7 @@
<div class="{res.mediaCss.small12} {res.mediaCss.large9} {res.mediaCss.columns}">
<div class="{local_res.css.eventheader_intro}">
<div class="{local_res.css.eventheader_intro_logo}">
<div ui:field="eventLogo" class="{local_res.css.eventheader_intro_logo_image}" />
<a ui:field="eventLogoAnchorUi"><div ui:field="eventLogo" class="{local_res.css.eventheader_intro_logo_image}" /></a>
</div>
<!-- IF header.dropdown === 'regattas' -->
<div ui:field="dropdownTitle" class="{local_res.css.dropdown} {local_res.css.dropdownregattas} {local_res.css.jsdropdown}">
@@ -53,9 +53,8 @@
<div ui:field="competitors" class="{local_res.css.eventheader_intro_details_item}" />
<div ui:field="races" class="{local_res.css.eventheader_intro_details_item}" />
<div ui:field="trackedRaces" class="{local_res.css.eventheader_intro_details_item}" />
<div ui:field="eventCategory" class="{local_res.css.eventheader_intro_details_item}">
<!-- event.category -->
</div>
<div ui:field="courseAreaUi" class="{local_res.css.eventheader_intro_details_item}" />
<div ui:field="eventCategory" class="{local_res.css.eventheader_intro_details_item}" />
<!-- IFEND event.eventType === 'multi-regatta-event' -->
</div>
</div>
@@ -0,0 +1,112 @@
package com.sap.sailing.gwt.home.client.place.event.partials.listNavigation;
import java.util.Collection;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RegattaNavigationResources.LocalCss;
import com.sap.sailing.gwt.home.client.shared.DropdownHandler;
public class DropdownFilter<T> extends Composite {
private static final LocalCss CSS = RegattaNavigationResources.INSTANCE.css();
private static ListDropdownFilterUiBinder uiBinder = GWT.create(ListDropdownFilterUiBinder.class);
interface ListDropdownFilterUiBinder extends UiBinder<Widget, DropdownFilter<?>> {
}
@UiField DivElement dropdownContainerUi;
@UiField DivElement currentValueUi;
@UiField FlowPanel filterItemContainerUi;
private final DropdownFilterList<T> filterList;
private final DropdownHandler dropdownHandler;
private final String nullValueLabel;
private T selectedFilterValue = null;
public DropdownFilter(String nullValueLabel, DropdownFilterList<T> filterList) {
this.nullValueLabel = nullValueLabel;
this.filterList = filterList;
CSS.ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
this.dropdownHandler = new ListFilterDropdownHandler();
}
public void updateFilterValues() {
filterItemContainerUi.clear();
DropdownFilterItem filterItemToSelect = addFilterValue(null, nullValueLabel);
for (T value : filterList.getSelectableValues()) {
DropdownFilterItem newFilterItem = addFilterValue(value, String.valueOf(value));
filterItemToSelect = value.equals(selectedFilterValue) ? newFilterItem : filterItemToSelect;
}
filterItemToSelect.select();
setVisible(filterList.getSelectableValues().size() > 1);
}
private DropdownFilterItem addFilterValue(T value, String label) {
DropdownFilterItem filterItem = new DropdownFilterItem(value, label);
filterItemContainerUi.add(filterItem);
return filterItem;
}
public interface DropdownFilterList<T> {
Collection<T> getSelectableValues();
void onSelectFilter(T value);
}
private class ListFilterDropdownHandler extends DropdownHandler {
private ListFilterDropdownHandler() {
super(dropdownContainerUi, filterItemContainerUi.getElement());
}
@Override
protected void dropdownStateChanged(boolean dropdownShown) {
if (dropdownShown) dropdownContainerUi.addClassName(CSS.jsdropdownactive());
else dropdownContainerUi.removeClassName(CSS.jsdropdownactive());
}
}
private class DropdownFilterItem extends Widget {
private final T value;
private final String label;
private DropdownFilterItem(T value, String label) {
this.value = value;
this.label = label;
this.setElement(DOM.createDiv().<DivElement>cast());
this.getElement().setInnerText(label);
this.addStyleName(CSS.regattanavigation_filter_dropdown_link());
this.initClickHandler();
}
private void initClickHandler() {
this.addDomHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(LinkUtil.handleLinkClick((Event) event.getNativeEvent())) {
event.preventDefault();
DropdownFilterItem.this.select();
DropdownFilter.this.dropdownHandler.setVisible(false);
}
}
}, ClickEvent.getType());
}
private void select() {
DropdownFilter.this.selectedFilterValue = value;
DropdownFilter.this.currentValueUi.setInnerText(label);
for (int i=0; i < filterItemContainerUi.getWidgetCount(); i++) {
filterItemContainerUi.getWidget(i).removeStyleName(CSS.regattanavigation_filter_dropdown_linkactive());
}
this.addStyleName(CSS.regattanavigation_filter_dropdown_linkactive());
DropdownFilter.this.filterList.onSelectFilter(value);
}
}
}
@@ -0,0 +1,18 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_ubi" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RegattaNavigationResources" />
<g:HTMLPanel>
<div class="{local_res.css.regattanavigation_filter} {local_res.css.jsdropdown}" ui:field="dropdownContainerUi">
<div class="{local_res.css.jsdropdown_head}">
<div class="{local_res.css.regattanavigation_filter_text}">
<ui:text from="{i18n.filterBy}" />:
</div>
<div class="{local_res.css.regattanavigation_filter_current}" ui:field="currentValueUi"></div>
</div>
<g:FlowPanel addStyleNames="{local_res.css.regattanavigation_filter_dropdown} {local_res.css.jsdropdown_content}" ui:field="filterItemContainerUi" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,85 @@
package com.sap.sailing.gwt.home.client.place.event.partials.listNavigation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.ListNavigationPanel.ListNavigationAction;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RegattaNavigationResources.LocalCss;
public class ListNavigationPanel<T extends ListNavigationAction> extends Composite {
private static final LocalCss CSS = RegattaNavigationResources.INSTANCE.css();
private static ListNavigationPanelUiBinder uiBinder = GWT.create(ListNavigationPanelUiBinder.class);
interface ListNavigationPanelUiBinder extends UiBinder<Widget, ListNavigationPanel<?>> {
}
@UiField FlowPanel actionContainerUi;
@UiField SimplePanel additionalWidgetContainerUi;
private SelectionCallback<T> selectionCallback;
public ListNavigationPanel(SelectionCallback<T> selectionCallback) {
this.selectionCallback = selectionCallback;
CSS.ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
public void addAction(final T action, boolean select) {
ActionWidget actionWidget = new ActionWidget(action);
actionContainerUi.add(actionWidget);
if (select) {
actionWidget.select();
}
}
public void setAdditionalWidget(Widget additionalWidget) {
this.additionalWidgetContainerUi.setWidget(additionalWidget);
}
public interface SelectionCallback<T> {
void onSelectAction(T action);
}
public interface ListNavigationAction {
String getDisplayName();
boolean isShowAdditionalWidget();
}
private class ActionWidget extends Label {
private final T action;
private final Display displayStyle;
private ActionWidget(T action) {
super(action.getDisplayName());
this.action = action;
this.displayStyle = action.isShowAdditionalWidget() ? Display.BLOCK : Display.NONE;
this.addStyleName(CSS.regattanavigation_button());
this.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
ActionWidget.this.select();
}
});
}
private void select() {
additionalWidgetContainerUi.getElement().getStyle().setDisplay(displayStyle);
for (int i=0; i < actionContainerUi.getWidgetCount(); i++) {
actionContainerUi.getWidget(i).removeStyleName(CSS.regattanavigation_buttonactive());
}
this.addStyleName(CSS.regattanavigation_buttonactive());
selectionCallback.onSelectAction(action);
}
}
}
@@ -0,0 +1,15 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_ubi" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RegattaNavigationResources" />
<g:FlowPanel addStyleNames="{res.mediaCss.grid} {local_res.css.regattanavigation}" >
<g:FlowPanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.large7} {res.mediaCss.columns}" ui:field="actionContainerUi">
<g:Label addStyleNames="{local_res.css.regattanavigation_text}">
<ui:text from='{i18n.display}' />:
</g:Label>
</g:FlowPanel>
<g:SimplePanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.large5} {res.mediaCss.columns}" ui:field="additionalWidgetContainerUi"/>
</g:FlowPanel>
</ui:UiBinder>
@@ -0,0 +1,19 @@
package com.sap.sailing.gwt.home.client.place.event.partials.listNavigation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Widget;
public class RaceStateLegend extends Widget {
private static RaceStateLegendUiBinder uiBinder = GWT.create(RaceStateLegendUiBinder.class);
interface RaceStateLegendUiBinder extends UiBinder<Element, RaceStateLegend> {
}
public RaceStateLegend() {
setElement(uiBinder.createAndBindUi(this));
}
}
@@ -0,0 +1,21 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_ubi" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RegattaNavigationResources" />
<div class="{local_res.css.regattanavigation_legend}">
<div class="{local_res.css.regattanavigation_legend_item} {local_res.css.regattanavigation_legend_itemtracked}">
<ui:text from='{i18n.tracked}' />
</div>
<div class="{local_res.css.regattanavigation_legend_item} {local_res.css.regattanavigation_legend_itemuntracked}">
<ui:text from='{i18n.untracked}' />
</div>
<div class="{local_res.css.regattanavigation_legend_item} {local_res.css.regattanavigation_legend_itemlive}">
<ui:text from='{i18n.playModeLive}' />
</div>
<div class="{local_res.css.regattanavigation_legend_item} {local_res.css.regattanavigation_legend_itemplanned}">
<ui:text from='{i18n.raceIsPlanned}' />
</div>
</div>
</ui:UiBinder>
@@ -0,0 +1,148 @@
/**
* A toggle buttons and legend for regatta races views
*/
.jsdropdown {
position: relative;
}
.jsdropdown_head {
padding-right: 2em;
}
.jsdropdown_head,
.jsdropdown_content {
text-indent: 0;
}
.regattanavigation {
font-size: 1rem;
margin-top: 1em;
margin-bottom: 1em;
}
.regattanavigation_text {
font-size: 0.866666666666667rem;
line-height: 2.307692307692307em;
margin-right: 0.769230769230769em;
display: inline-block;
color: #999;
}
.regattanavigation_button {
display: inline-block;
font-weight: 600;
padding: 0.333333333333333em 0.666666666666667em;
line-height: 1.333333333333333em;
margin-right: 0.666666666666667em;
color: #666;
background-color: #f2f2f2;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
transition: all 0.2s;
cursor: pointer;
}
.regattanavigation_button:hover {
text-decoration: none;
color: #fff;
background-color: #efaa00;
}
.regattanavigation_buttonactive {
color: #fff;
background-color: #efaa00;
}
.regattanavigation_filter {
font-size: 0.866666666666667rem;
text-align: right;
margin-top: 0;
background: transparent url("images/home/arrow-down-filled-black.png") no-repeat;
background-position: 96%;
background-size: 0.923076923076923em 0.538461538461538em;
border: 1px solid transparent;
border-radius: 0.333333333333333em 0.333333333333333em 0 0;
position: relative;
float: right;
cursor: pointer;
padding-left: 0.5em;
}
.regattanavigation_filter:hover,
.regattanavigation_filter.jsdropdownactive {
border-color: #dedede;
background-color: #f2f2f2;
}
.regattanavigation_filter.jsdropdownactive {
background-image: url("images/home/arrow-down-filled-yellow.png");
}
.regattanavigation_filter.jsdropdownactive .regattanavigation_filter_dropdown {
display: block;
}
.regattanavigation_filter_text,
.regattanavigation_filter_current {
display: inline-block;
line-height: 2.307692307692307em;
}
.regattanavigation_filter_text {
color: #999;
}
.regattanavigation_filter_dropdown {
display: none;
position: absolute;
right: -1px;
background: #fff;
border: 1px solid #dedede;
line-height: 2.307692307692307em;
z-index: 10;
width: 110%;
}
.regattanavigation_filter_dropdown_link {
display: block;
color: #999;
text-align: left;
padding: 0 2.307692307692307em 0 0.769230769230769em;
}
.regattanavigation_filter_dropdown_link:hover {
text-decoration: underline;
}
.regattanavigation_filter_dropdown_linkactive {
background: url("images/home/dropdown__check@2x.png") no-repeat;
background-position: 95%;
background-size: 1.2em 0.933333333333333em;
}
.regattanavigation_legend {
font-size: 1rem;
width: 100%;
margin-top: 1.333333333333333em;
}
@media (min-width: 61em) {
.regattanavigation_legend {
text-align: right;
margin-top: 0;
}
.regattanavigation_legend_item {
margin-right: 0;
margin-left: 0.666666666666667em;
}
}
.regattanavigation_legend_item {
display: inline-block;
padding: 0.4em 0.666666666666667em;
margin: 0.333333333333333em 0.666666666666667em 0.333333333333333em 0;
font-size: 0.666em;
font-weight: 700;
line-height: 0.666666666666667em;
border: 1px solid #008fcc;
}
.regattanavigation_legend_itemtracked {
color: #fff;
border-color: #008fcc;
background-color: #008fcc;
}
.regattanavigation_legend_itemuntracked {
color: #fff;
border-color: #ccc;
background-color: #666;
}
.regattanavigation_legend_itemlive {
color: #fff;
border-color: #e94a1b;
background-color: #e94a1b;
}
.regattanavigation_legend_itemplanned {
color: #ccc;
border-color: #ccc;
background-color: #fff;
}
@@ -0,0 +1,35 @@
package com.sap.sailing.gwt.home.client.place.event.partials.listNavigation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
public interface RegattaNavigationResources extends ClientBundle {
public static final RegattaNavigationResources INSTANCE = GWT.create(RegattaNavigationResources.class);
@Source("RegattaNavigation.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String jsdropdown();
String jsdropdown_head();
String jsdropdown_content();
String regattanavigation();
String regattanavigation_text();
String regattanavigation_button();
String regattanavigation_buttonactive();
String regattanavigation_filter();
String jsdropdownactive();
String regattanavigation_filter_dropdown();
String regattanavigation_filter_text();
String regattanavigation_filter_current();
String regattanavigation_filter_dropdown_link();
String regattanavigation_filter_dropdown_linkactive();
String regattanavigation_legend();
String regattanavigation_legend_item();
String regattanavigation_legend_itemtracked();
String regattanavigation_legend_itemuntracked();
String regattanavigation_legend_itemlive();
String regattanavigation_legend_itemplanned();
}
}
@@ -0,0 +1,255 @@
/**
* A list of regattas to an event
*/
.race {
color: #333;
font-size: 1rem;
overflow: hidden;
}
.race:last-of-type .race_item {
border: none;
}
.race_fleetcorner {
width: 1em;
vertical-align: top;
border-bottom: 1px solid #ebebeb;
}
.race_fleetcorner_icon {
width: 1em;
margin-right: -2.333333333333333em;
position: relative;
top: 1px;
left: 1px;
border-style: solid;
border-color: transparent;
border-width: 1em 1em 0 0;
}
.race_item {
text-align: left;
vertical-align: baseline;
border-bottom: 1px solid #ebebeb;
white-space: nowrap;
padding: 1.4em 0.666666666666667em 0.733333333333333em 1.333333333333333em;
}
.race_item .button {
white-space: nowrap;
}
.race_item:first-of-type {
padding-left: 2em;
}
.race_itemrank:after {
content: '.';
}
.race_itemshort {
width: 5em;
}
.race_itemlong {
width: 32.5%;
}
.race_itemwind {
white-space: nowrap;
}
.race_itemwindflag {
padding: 1.066666666666667em 0.666666666666667em 0.4em 1.333333333333333em;
}
img.race_item_windflag {
max-width: 2.4em;
max-height: 2.4em;
vertical-align: middle;
}
.race_itemname {
font-weight: 600;
}
.race_itemwinner {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
min-width: 13.333333333333334em;
max-width: 16.666666666666668em;
}
.race_item_flag {
max-width: 1.6em;
max-height: 1.6em;
vertical-align: middle;
}
.race_item_position {
margin-right: 0.333333333333333em;
}
.race_item_winner {
margin-left: 5px;
vertical-align: middle;
}
.race_itemwinner {
padding: 0.733333333333333em 1.333333333333333em;
}
.race_itemcenter {
text-align: center;
}
.race_itemright {
text-align: right;
vertical-align: middle;
padding-left: 0;
padding-right: 0.666666666666667em;
padding-top: 0.666666666666667em;
}
.race_itemright_button {
padding: 0.666666666666667em;
}
.race_itemstatus {
position: relative;
}
.race_itemstatus:first-letter {
text-transform: capitalize;
}
.race_itemstatus_container {
min-width: 5.333333333333333em;
display: inline-block;
}
.race_itemstatus_container_text {
clip: auto;
}
.race_itemstatus_container_progressbar {
height: 0.2em;
position: relative;
top: 0.2em;
width: 100%;
background-color: #dedede;
}
.race_itemstatus_container_progressbar_progress {
height: 100%;
background-color: #efaa00;
}
.racewinners .race_item {
padding: 1.2em 0.666666666666667em 1.2em 1.333333333333333em;
}
.racewinners .race_item:nth-last-child(1) {
display: none;
}
@media (min-width: 61em) {
.racewinners .race_item:nth-last-child(1) {
display: inline-block;
}
}
.racewinners .race_itemname {
vertical-align: middle;
}
.race_fleetcornerblue:before {
border-top-color: #00f;
}
.race_fleetcornerred:before {
border-top-color: #f00;
}
.race_fleetcornersilver:before {
border-top-color: #c0c0c0;
}
.race_fleetcornergold:before {
border-top-color: #ffd700;
}
.race_fleetcorneryellow:before {
border-top-color: #ff0;
}
.regattalistitem {
font-size: 1rem;
float: left;
width: 100%;
margin-top: 2em;
border: 1px solid #ddd;
border-radius: 0.333333333333333em;
overflow: hidden;
}
.regattalistitem > div:last-child {
border-bottom: none;
}
.regattalistitem_table {
width: 100%;
border-spacing: 0;
border-collapse: separate;
border-bottom: 1px solid #ddd;
}
.regattalistitem_table:last-of-type {
border-bottom: none;
}
.regattalistitem_tableborderTop {
border-top: 1px solid #ebebeb;
}
.regattalistitem_steps {
border-bottom: 1px solid #ddd;
overflow: hidden;
}
.regattalistitem_steps_step {
float: left;
position: relative;
height: 4em;
text-transform: uppercase;
padding: 0 0.666666666666667em;
}
.regattalistitem_steps_stepinactive {
color: #ddd;
}
.regattalistitem_steps_step_infowrapper {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
white-space: nowrap;
}
.regattalistitem_steps_step_name {
font-weight: 600;
display: inline-block;
margin-right: 0.333333333333333em;
font-size: 0;
}
.regattalistitem_steps_step_name::first-letter {
font-size: 0.866666666666667rem;
margin-right: 0.333333333333333rem;
}
@media (min-width: 49.0625em) {
.regattalistitem_steps_step_name::first-letter {
margin-right: 0;
}
}
@media (min-width: 49.0625em) {
.regattalistitem_steps_step_name {
font-size: 0.866666666666667em;
}
}
.regattalistitem_steps_step_check {
display: inline-block;
vertical-align: middle;
width: 1.066666666666667em;
height: 1.066666666666667em;
background-image: url("images/home/icon-green-check.svg");
background-repeat: no-repeat;
background-size: contain;
margin-right: 0.333333333333333em;
}
.regattalistitem_steps_step_progress {
display: inline-block;
font-size: 0.866666666666667em;
text-transform: none;
}
.regattalistitem_steps_step_fleets {
width: 100%;
height: 17px;
outline: 1px solid #dedede;
margin-top: 0.266666666666667em;
padding: 1px;
}
.regattalistitem_steps_step_fleets_fleet {
font-size: inherit;
}
.regattalistitem_steps_step_fleets_fleet_progress {
height: 100%;
}
.regattalistitem_steps_button {
height: 100%;
padding: 0.666666666666667em;
text-align: right;
margin-top: 3px;
}
.regattalistitem_steps_button .button {
margin-left: 0.8em;
}
@@ -0,0 +1,62 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import java.util.Collection;
import java.util.Collections;
import java.util.TreeSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
public class MultiRegattaList extends Composite implements RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
private static MultiRegattaListUiBinder uiBinder = GWT.create(MultiRegattaListUiBinder.class);
interface MultiRegattaListUiBinder extends UiBinder<Widget, MultiRegattaList> {
}
@UiField FlowPanel regattasContainerUi;
private final Presenter currentPresenter;
private final Collection<String> selectableBoatCategories = new TreeSet<>();
public MultiRegattaList(Presenter presenter) {
this.currentPresenter = presenter;
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void setData(SortedSetResult<RegattaWithProgressDTO> data, long nextUpdate, int updateNo) {
this.setListData(data == null ? Collections.<RegattaWithProgressDTO>emptySet() : data.getValues());
}
public void setListData(Collection<RegattaWithProgressDTO> data) {
regattasContainerUi.clear();
selectableBoatCategories.clear();
for (RegattaWithProgressDTO regattaWithProgress : data) {
regattasContainerUi.add(new MultiRegattaListItem(regattaWithProgress, currentPresenter));
String boatCategory = regattaWithProgress.getBoatCategory();
if(boatCategory != null) {
selectableBoatCategories.add(boatCategory);
}
}
}
public Collection<String> getSelectableBoatCategories() {
return selectableBoatCategories;
}
public void setVisibleBoatCategory(String visibleBoatCategory) {
for (int i=0; i < regattasContainerUi.getWidgetCount(); i++) {
MultiRegattaListItem item = (MultiRegattaListItem) regattasContainerUi.getWidget(i);
item.setVisibilityDependingOnBoatCategory(visibleBoatCategory);
}
}
}
@@ -0,0 +1,9 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListResources" />
<g:FlowPanel ui:field="regattasContainerUi">
</g:FlowPanel>
</ui:UiBinder>
@@ -0,0 +1,42 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader.RegattaHeader;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
public class MultiRegattaListItem extends Composite {
private static MultiRegattaListItemUiBinder uiBinder = GWT.create(MultiRegattaListItemUiBinder.class);
interface MultiRegattaListItemUiBinder extends UiBinder<Widget, MultiRegattaListItem> {
}
@UiField(provided = true) RegattaHeader regattaHeaderUi;
@UiField(provided = true) MultiRegattaListSteps regattaStepsUi;
private final RegattaWithProgressDTO regattaWithProgress;
public MultiRegattaListItem(RegattaWithProgressDTO regattaWithProgress) {
this.regattaWithProgress = regattaWithProgress;
regattaHeaderUi = new RegattaHeader(regattaWithProgress);
regattaStepsUi = new MultiRegattaListSteps(regattaWithProgress.getProgress());
initWidget(uiBinder.createAndBindUi(this));
}
public MultiRegattaListItem(RegattaWithProgressDTO regattaWithProgress, Presenter presenter) {
this(regattaWithProgress);
regattaHeaderUi.setRegattaNavigation(presenter.getRegattaNavigation(regattaWithProgress.getId()));
PlaceNavigation<?> leaderboardNavigation = presenter.getRegattaLeaderboardNavigation(regattaWithProgress.getId());
regattaStepsUi.setLeaderboardNavigation(regattaWithProgress.getState(), leaderboardNavigation);
}
void setVisibilityDependingOnBoatCategory(String visibleBoatCategory) {
setVisible(visibleBoatCategory == null || visibleBoatCategory.equals(regattaWithProgress.getBoatCategory()));
}
}
@@ -0,0 +1,18 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListResources" />
<g:HTMLPanel>
<div class="{local_res.css.regattalistitem}">
<p:regattaHeader.RegattaHeader ui:field="regattaHeaderUi" />
<p:multiRegattaList.MultiRegattaListSteps ui:field="regattaStepsUi" />
<!--
<ubi:multiRegattaList.MultiRegattaListRace ui:fields='races'> </ubi>
<ubi:multiRegattaList.MultiRegattaListResult ui:fields='boatclass'> </ubi>
<ubi:multiRegattaList.MultiRegattaListFinalresult ui:fields='boatclass'> </ubi>
-->
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,59 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
public interface MultiRegattaListResources extends ClientBundle {
public static final MultiRegattaListResources INSTANCE = GWT.create(MultiRegattaListResources.class);
@Source("MultiRegattaList.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String race();
String race_item();
String race_fleetcorner();
String race_fleetcorner_icon();
String button();
String race_itemrank();
String race_itemshort();
String race_itemlong();
String race_itemwind();
String race_itemwindflag();
String race_item_windflag();
String race_itemname();
String race_itemwinner();
String race_item_flag();
String race_item_position();
String race_item_winner();
String race_itemcenter();
String race_itemright();
String race_itemright_button();
String race_itemstatus();
String race_itemstatus_container();
String race_itemstatus_container_text();
String race_itemstatus_container_progressbar();
String race_itemstatus_container_progressbar_progress();
String racewinners();
String race_fleetcornerblue();
String race_fleetcornerred();
String race_fleetcornersilver();
String race_fleetcornergold();
String race_fleetcorneryellow();
String regattalistitem();
String regattalistitem_table();
String regattalistitem_tableborderTop();
String regattalistitem_steps();
String regattalistitem_steps_step();
String regattalistitem_steps_stepinactive();
String regattalistitem_steps_step_infowrapper();
String regattalistitem_steps_step_name();
String regattalistitem_steps_step_check();
String regattalistitem_steps_step_progress();
String regattalistitem_steps_step_fleets();
String regattalistitem_steps_step_fleets_fleet();
String regattalistitem_steps_step_fleets_fleet_progress();
String regattalistitem_steps_button();
}
}
@@ -0,0 +1,100 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressSeriesDTO;
import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata.RegattaState;
public class MultiRegattaListSteps extends Composite {
private static MultiRegattaListStepsUiBinder uiBinder = GWT.create(MultiRegattaListStepsUiBinder.class);
interface MultiRegattaListStepsUiBinder extends UiBinder<Widget, MultiRegattaListSteps> {
}
@UiField DivElement progressContainerUi;
@UiField DivElement stepsContainerUi;
@UiField DivElement leaderboardButtonContainerUi;
@UiField AnchorElement leaderboardButtonUi;
private HandlerRegistration windowResizeHandlerRegistration;
private final List<MultiRegattaListStepsBody> allMultiregattaSteps = new ArrayList<MultiRegattaListStepsBody>();
public MultiRegattaListSteps(RegattaProgressDTO regattaProgress) {
MultiRegattaListResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
double sumParts = 0;
for(RegattaProgressSeriesDTO seriesProgress : regattaProgress.getSeries()) {
double parts = Math.pow(seriesProgress.getTotalRaceCount(), 0.4);
sumParts += parts;
}
for(RegattaProgressSeriesDTO seriesProgress : regattaProgress.getSeries()) {
double parts = Math.pow(seriesProgress.getTotalRaceCount(), 0.4);
double percentage = 100.0 * parts / sumParts;
MultiRegattaListStepsBody stepsBody = new MultiRegattaListStepsBody(seriesProgress);
allMultiregattaSteps.add(stepsBody);
stepsBody.getElement().getStyle().setWidth(percentage, Unit.PCT);
stepsContainerUi.appendChild(stepsBody.getElement());
}
}
@Override
protected void onLoad() {
windowResizeHandlerRegistration = Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
for (MultiRegattaListStepsBody widget : allMultiregattaSteps) {
widget.onResize();
}
}
});
}
@Override
protected void onUnload() {
windowResizeHandlerRegistration.removeHandler();
}
void setLeaderboardNavigation(RegattaState regattaState, PlaceNavigation<?> placeNavigation) {
placeNavigation.configureAnchorElement(leaderboardButtonUi);
leaderboardButtonUi.getStyle().clearDisplay();
leaderboardButtonUi.addClassName(getLeaderboardButtonStyle(regattaState));
stepsContainerUi.getStyle().setDisplay(Display.NONE);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
stepsContainerUi.getStyle().clearDisplay();
stepsContainerUi.getStyle().setMarginRight(leaderboardButtonUi.getOffsetWidth() + 20, Unit.PX);
}
});
}
private String getLeaderboardButtonStyle(RegattaState regattaState) {
switch (regattaState) {
case UPCOMING: return SharedResources.INSTANCE.mainCss().buttoninactive();
case RUNNING: return SharedResources.INSTANCE.mainCss().buttonred();
default: return SharedResources.INSTANCE.mainCss().buttonprimary();
}
}
}
@@ -0,0 +1,18 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListResources" />
<g:HTMLPanel>
<div class="{local_res.css.regattalistitem_steps}" ui:field="progressContainerUi">
<div ui:field="stepsContainerUi" />
<div class="{local_res.css.regattalistitem_steps_button}" ui:field="leaderboardButtonContainerUi">
<a class="{res.mainCss.button} {res.mainCss.buttonstrong} {res.mainCss.buttonarrowrightwhite}"
style="display:none;" ui:field="leaderboardButtonUi">
<ui:text from='{i18n.leaderboard}' />
</a>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,89 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import static com.sap.sailing.domain.common.LeaderboardNameConstants.DEFAULT_SERIES_NAME;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.UIObject;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressFleetDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressSeriesDTO;
import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO;
public class MultiRegattaListStepsBody extends UIObject implements RequiresResize {
private static final StringMessages I18N = StringMessages.INSTANCE;
private static MultiRegattaListStepsBodyUiBinder uiBinder = GWT.create(MultiRegattaListStepsBodyUiBinder.class);
interface MultiRegattaListStepsBodyUiBinder extends UiBinder<Element, MultiRegattaListStepsBody> {
}
@UiField DivElement nameUi;
@UiField DivElement checkUi;
@UiField DivElement progressUi;
@UiField DivElement fleetsContainerUi;
private final String seriesName;
public MultiRegattaListStepsBody(RegattaProgressSeriesDTO seriesProgress) {
setElement(uiBinder.createAndBindUi(this));
nameUi.getStyle().setVisibility(Visibility.HIDDEN);
seriesName = DEFAULT_SERIES_NAME.equals(seriesProgress.getName()) ? I18N.races() : seriesProgress.getName();
nameUi.setInnerText(seriesName);
if (seriesProgress.isCompleted()) {
progressUi.setInnerText(String.valueOf(seriesProgress.getTotalRaceCount()));
} else {
checkUi.getStyle().setDisplay(Display.NONE);
progressUi.setInnerText(I18N.currentOfTotal(
seriesProgress.getProgressRaceCount(), seriesProgress.getTotalRaceCount()));
}
addFleetProgresses(seriesProgress.getFleetState(), seriesProgress.getTotalRaceCount());
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
renderNames();
}
});
}
private void addFleetProgresses(Map<FleetMetadataDTO, RegattaProgressFleetDTO> fleetStates, int totalRaceCount) {
double height = fleetStates.isEmpty() ? 100.0 : 100.0 / fleetStates.size();
for (Entry<FleetMetadataDTO, RegattaProgressFleetDTO> fleetState : fleetStates.entrySet()) {
double finishedWidth = (fleetState.getValue().getFinishedRaceCount() * 100.0) / totalRaceCount;
double liveWidth = (fleetState.getValue().getFinishedAndLiveRaceCount() * 100.0) / totalRaceCount;
String fleetColor = fleetState.getKey().getFleetColor();
MultiRegattaListStepsBodyFleet fleet = new MultiRegattaListStepsBodyFleet(finishedWidth, liveWidth, height, fleetColor);
fleetsContainerUi.appendChild(fleet.getElement());
}
}
private void renderNames() {
if (getElement().getOffsetWidth() < nameUi.getOffsetWidth() + checkUi.getOffsetWidth()
+ progressUi.getOffsetWidth()) {
String[] tokens = seriesName.split(" ");
StringBuilder initials = new StringBuilder();
for (int i = 0; i < tokens.length; i++) {
initials.append(tokens[i].charAt(0));
}
nameUi.setInnerText(initials.toString());
}
nameUi.setTitle(seriesName);
nameUi.getStyle().setVisibility(Visibility.VISIBLE);
}
@Override
public void onResize() {
renderNames();
}
}
@@ -0,0 +1,15 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListResources" />
<div class="{local_res.css.regattalistitem_steps_step}">
<div class="{local_res.css.regattalistitem_steps_step_infowrapper}">
<div class="{local_res.css.regattalistitem_steps_step_name}" ui:field="nameUi"></div>
<div class="{local_res.css.regattalistitem_steps_step_check}" ui:field="checkUi"></div>
<div class="{local_res.css.regattalistitem_steps_step_progress}" ui:field="progressUi"></div>
<div class="{local_res.css.regattalistitem_steps_step_fleets}" ui:field="fleetsContainerUi"></div>
</div>
</div>
</ui:UiBinder>
@@ -0,0 +1,30 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.UIObject;
public class MultiRegattaListStepsBodyFleet extends UIObject {
private static MultiRegattaListStepsBodyFleetUiBinder uiBinder = GWT.create(MultiRegattaListStepsBodyFleetUiBinder.class);
interface MultiRegattaListStepsBodyFleetUiBinder extends UiBinder<Element, MultiRegattaListStepsBodyFleet> {
}
@UiField DivElement fleetProgressBarUi;
@UiField DivElement fleetProgressBarLiveUi;
public MultiRegattaListStepsBodyFleet(double finishedWidth, double liveWidth, double height, String color) {
setElement(uiBinder.createAndBindUi(this));
getElement().getStyle().setHeight(height, Unit.PCT);
fleetProgressBarUi.getStyle().setWidth(finishedWidth, Unit.PCT);
fleetProgressBarUi.getStyle().setBackgroundColor(color);
fleetProgressBarLiveUi.getStyle().setWidth(liveWidth, Unit.PCT);
fleetProgressBarLiveUi.getStyle().setBackgroundColor("#ff4040");
}
}
@@ -0,0 +1,11 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListResources" />
<div class="{local_res.css.regattalistitem_steps_step_fleets_fleet}" style="position:relative;">
<div class="{local_res.css.regattalistitem_steps_step_fleets_fleet_progress}" style="position:absolute; top:0;" ui:field="fleetProgressBarLiveUi"></div>
<div class="{local_res.css.regattalistitem_steps_step_fleets_fleet_progress}" style="position:absolute; top:0;" ui:field="fleetProgressBarUi"></div>
</div>
</ui:UiBinder>
@@ -0,0 +1,19 @@
package com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Widget;
public class MultiRegattaListStepsLegend extends Widget {
private static MultiRegattaListStepsLegendUiBinder uiBinder = GWT.create(MultiRegattaListStepsLegendUiBinder.class);
interface MultiRegattaListStepsLegendUiBinder extends UiBinder<Element, MultiRegattaListStepsLegend> {
}
public MultiRegattaListStepsLegend() {
setElement(uiBinder.createAndBindUi(this));
}
}
@@ -0,0 +1,45 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:style>
.multiregatta_steps_legend {
font-size: 1rem;
text-align: right;
}
.multiregatta_steps_legend_item {
display: inline-block;
padding: 0.4em 0.666666666666667em;
margin: 0.333333333333333em 0 0.333333333333333em 0.666666666666667em;
font-size: 0.666em;
font-weight: 700;
line-height: 0.666666666666667em;
border: 1px solid #008fcc;
}
.multiregatta_steps_legend_item_finished {
color: #fff;
border-color: #ccc;
background-color: #f0ab00;
}
.multiregatta_steps_legend_item_live {
color: #fff;
border-color: #e94a1b;
background-color: #e94a1b;
}
.multiregatta_steps_legend_item_planned {
color: #ccc;
border-color: #ccc;
background-color: #fff;
}
</ui:style>
<div class="{style.multiregatta_steps_legend}">
<div class="{style.multiregatta_steps_legend_item} {style.multiregatta_steps_legend_item_finished}">
<ui:text from='{i18n.raceIsFinished}' />
</div>
<div class="{style.multiregatta_steps_legend_item} {style.multiregatta_steps_legend_item_live}">
<ui:text from='{i18n.playModeLive}' />
</div>
<div class="{style.multiregatta_steps_legend_item} {style.multiregatta_steps_legend_item_planned}">
<ui:text from='{i18n.raceIsPlanned}' />
</div>
</div>
</ui:UiBinder>
@@ -0,0 +1,174 @@
/**
* Competitions View Component for regatta races
*/
.phase {
font-size: 1rem;
margin-bottom: 2em;
}
.phase_head {
padding: 1.333333333333333em 1.333333333333333em 2.666666666666667em 2em;
background-color: #f2f2f2;
border: 1px solid #dedede;
border-radius: 0.333333333333333em 0.333333333333333em 0 0;
font-weight: 600;
color: #666;
}
.phase_head_title {
text-transform: uppercase;
float: left;
}
.phase_head_info {
font-size: 0.866666666666667em;
text-align: right;
float: right;
}
.phase_head_info_item {
display: inline-block;
padding-left: 0.769230769230769em;
margin-left: 0.769230769230769em;
border-left: 1px solid #dedede;
}
.phase_head_info_item:first-child {
border: none;
padding-left: 0;
margin-left: 0;
}
.regattalistitem .phase {
margin: 0;
}
.regattalistitem .phase_head {
background-color: transparent;
border: none;
border-radius: 0;
border-bottom: 1px solid #dedede;
}
.fleet {
font-size: 1rem;
border: 1px solid #dedede;
border-top: none;
position: relative;
}
.fleet:last-child {
border-radius: 0 0 0.333333333333333em 0.333333333333333em;
}
.fleet_corner {
position: absolute;
content: '';
display: block;
top: 1px;
left: 1px;
border-style: solid;
border-width: 1em 1em 0 0;
border-color: transparent;
}
.fleet_details {
color: #333;
position: absolute;
top: 1.333333333333333em;
left: 2em;
width: 20%;
}
@media (min-width: 61em) {
.fleet_details {
width: 13%;
}
}
.fleet_details_name {
font-weight: 600;
}
.fleet_details_competitors {
font-size: 0.866666666666667em;
color: #666;
}
.fleet_races {
padding: 0 1.333333333333333em 1% 25%;
}
@media (min-width: 61em) {
.fleet_races {
padding-left: 17%;
}
}
.fleet_races_race {
display: inline-block;
width: 19%;
margin: 1% 0 0 1%;
height: 4em;
line-height: 3.333333333333333em;
background-color: #008fcc;
border-radius: 0.2em;
-webkit-transition: background 0.2s;
-moz-transition: background 0.2s;
transition: background 0.2s;
text-decoration: none;
text-align: center;
color: #fff;
padding: 0.333333333333333em 0.333333333333333em;
}
@media (min-width: 45em) {
.fleet_races_race {
width: 15.66%;
line-height: inherit;
}
}
@media (min-width: 61em) {
.fleet_races_race {
width: 9%;
}
}
.fleet_races_race:hover {
background-color: #0081b8;
text-decoration: none;
}
.fleet_races_race_name,
.fleet_races_race_date {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fleet_races_race_name {
font-size: 1.466666666666667em;
font-weight: 700;
}
.fleet_races_race_name:after {
content: '';
display: inline-block;
width: 0.466666666666667em;
height: 0.466666666666667em;
background: url("../images/home/skip-forward.png") no-repeat center center;
margin: 0 0 0.133333333333333em 0.133333333333333em;
}
.fleet_races_race_date {
width: 100%;
font-size: 0.666666666666667em;
font-weight: 600;
}
.fleet_races_raceuntracked {
background-color: #999;
}
.fleet_races_raceuntracked:hover {
background-color: #8a8a8a;
}
.fleet_races_racelive {
background-color: #e94a1b;
}
.fleet_races_racelive:hover {
background-color: #d54115;
}
.fleet_races_raceplanned {
color: #999;
background-color: #fff;
border: 1px solid #999;
}
.fleet_races_raceplanned:hover {
background-color: #e6e6e6;
}
.fleet_races_raceplanned .fleet_races_race_name:after {
display: none;
}
.regattalistitem .fleet {
border: none;
border-bottom: 1px solid #dedede;
}
.regattalistitem .fleet:last-of-type {
border-radius: 0;
}
@@ -0,0 +1,38 @@
package com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListFleetDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
public class RegattaCompetitionFleet extends Widget {
private static RegattaCompetitionFleetUiBinder uiBinder = GWT.create(RegattaCompetitionFleetUiBinder.class);
interface RegattaCompetitionFleetUiBinder extends UiBinder<Element, RegattaCompetitionFleet> {
}
@UiField DivElement fleetCornerUi;
@UiField DivElement fleetNameUi;
@UiField DivElement competitorCountUi;
@UiField DivElement racesContainerUi;
public RegattaCompetitionFleet(RaceListFleetDTO fleet) {
setElement(uiBinder.createAndBindUi(this));
this.competitorCountUi.setInnerText(fleet.getCompetitorCount() + " Comp. TODO");
if (fleet.getFleet() != null) {
fleetNameUi.setInnerText(fleet.getFleet().getFleetName());
fleetCornerUi.getStyle().setProperty("borderTopColor", fleet.getFleet().getFleetColor());
}
}
public void addRace(RaceListRaceDTO race, String raceViewerURL) {
RegattaCompetitionFleetRace competitionRace = new RegattaCompetitionFleetRace(race, raceViewerURL);
racesContainerUi.appendChild(competitionRace.getElement());
}
}
@@ -0,0 +1,14 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p='urn:import:com.sap.sailing.gwt.home.client.place.event.partials'>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition.RegattaCompetitionResources" />
<div class="{local_res.css.fleet}">
<div class="{local_res.css.fleet_corner}" ui:field="fleetCornerUi"></div>
<div class="{local_res.css.fleet_details}">
<div class="{local_res.css.fleet_details_name}" ui:field="fleetNameUi"></div>
<div class="{local_res.css.fleet_details_competitors}" ui:field="competitorCountUi"></div>
</div>
<div class="{local_res.css.fleet_races}" ui:field="racesContainerUi"></div>
</div>
</ui:UiBinder>
@@ -0,0 +1,48 @@
package com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.UIObject;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceTrackingState;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceViewState;
public class RegattaCompetitionFleetRace extends UIObject {
private static RegattaCompetitionFleetRaceUiBinder uiBinder = GWT.create(RegattaCompetitionFleetRaceUiBinder.class);
interface RegattaCompetitionFleetRaceUiBinder extends UiBinder<AnchorElement, RegattaCompetitionFleetRace> {
}
@UiField RegattaCompetitionResources local_res;
@UiField DivElement raceNameUi;
@UiField DivElement raceDateUi;
private final AnchorElement anchor;
public RegattaCompetitionFleetRace(RaceListRaceDTO race, String raceViewerUrl) {
anchor = uiBinder.createAndBindUi(this);
anchor.setHref(raceViewerUrl);
local_res.css().ensureInjected();
setupRaceState(race.getTrackingState(), race.getViewState());
this.raceNameUi.setInnerText(race.getRaceName());
if (race.getStart() != null) {
this.raceDateUi.setInnerText(DateAndTimeFormatterUtil.defaultDateFormatter.render(race.getStart()));
}
setElement(anchor);
}
private void setupRaceState(RaceTrackingState trackingState, RaceViewState viewState) {
if (viewState == RaceViewState.RUNNING) {
anchor.addClassName(local_res.css().fleet_races_racelive());
} else if (viewState == RaceViewState.PLANNED || viewState == RaceViewState.SCHEDULED) {
anchor.addClassName(local_res.css().fleet_races_raceplanned());
}
if (trackingState != RaceTrackingState.TRACKED_VALID_DATA) {
anchor.addClassName(local_res.css().fleet_races_raceuntracked());
}
}
}
@@ -0,0 +1,10 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p='urn:import:com.sap.sailing.gwt.home.client.place.event.partials'>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition.RegattaCompetitionResources" />
<a class="{local_res.css.fleet_races_race}" target="_blank">
<div class="{local_res.css.fleet_races_race_name}" ui:field="raceNameUi"></div>
<div class="{local_res.css.fleet_races_race_date} {res.mediaCss.hideonsmall}" ui:field="raceDateUi"></div>
</a>
</ui:UiBinder>
@@ -0,0 +1,33 @@
package com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
public interface RegattaCompetitionResources extends ClientBundle {
public static final RegattaCompetitionResources INSTANCE = GWT.create(RegattaCompetitionResources.class);
@Source("RegattaCompetition.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String phase();
String phase_head();
String phase_head_title();
String phase_head_info();
String phase_head_info_item();
String regattalistitem();
String fleet();
String fleet_corner();
String fleet_details();
String fleet_details_name();
String fleet_details_competitors();
String fleet_races();
String fleet_races_race();
String fleet_races_race_name();
String fleet_races_race_date();
String fleet_races_raceuntracked();
String fleet_races_racelive();
String fleet_races_raceplanned();
}
}
@@ -0,0 +1,47 @@
package com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.sap.sailing.gwt.home.client.place.event.regatta.EventRegattaView.Presenter;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListFleetDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListSeriesDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceTrackingState;
public class RegattaCompetitionSeries extends Composite {
private static RegattaCompetitionSeriesUiBinder uiBinder = GWT.create(RegattaCompetitionSeriesUiBinder.class);
interface RegattaCompetitionSeriesUiBinder extends UiBinder<HTMLPanel, RegattaCompetitionSeries> {
}
@UiField DivElement seriesNameUi;
@UiField DivElement competitorCountUi;
@UiField DivElement raceCountUi;
private final HTMLPanel containerUi;
public RegattaCompetitionSeries(Presenter presenter, RaceListSeriesDTO series) {
initWidget(containerUi = uiBinder.createAndBindUi(this));
this.seriesNameUi.setInnerText(series.getSeriesName());
this.competitorCountUi.setInnerText(series.getCompetitorCount() + " Comp. TODO");
this.raceCountUi.setInnerText(series.getRaceCount() + " Races TODO");
for (RaceListFleetDTO fleet : series.getFleets()) {
addFleet(presenter, fleet);
}
}
public void addFleet(Presenter presenter, RaceListFleetDTO fleet) {
RegattaCompetitionFleet competitionFleet = new RegattaCompetitionFleet(fleet);
for (RaceListRaceDTO race : fleet.getRaces()) {
boolean tracked = race.getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA;
String raceViewerUrl = tracked ? presenter.getRaceViewerURL(race.getRegattaName(), race.getTrackedRaceName()) : null;
competitionFleet.addRace(race, raceViewerUrl);
}
containerUi.add(competitionFleet);
}
}
@@ -0,0 +1,15 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p='urn:import:com.sap.sailing.gwt.home.client.place.event.partials'>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.raceCompetition.RegattaCompetitionResources" />
<g:HTMLPanel addStyleNames="{local_res.css.phase}">
<div class="{local_res.css.phase_head}">
<div class="{local_res.css.phase_head_title}" ui:field="seriesNameUi"></div>
<div class="{local_res.css.phase_head_info}">
<div class="{local_res.css.phase_head_info_item}" ui:field="competitorCountUi"></div>
<div class="{local_res.css.phase_head_info_item}" ui:field="raceCountUi"></div>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -66,7 +66,7 @@
}
.race_itemwinner {
overflow: hidden;
white-space: nowrap;
white-space: normal;
text-overflow: ellipsis;
vertical-align: middle;
min-width: 13.333333333333334em;
@@ -1,40 +1,77 @@
package com.sap.sailing.gwt.home.client.place.event.partials.raceListLive;
import com.google.gwt.core.client.GWT;
import java.util.Collection;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceList;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.AbstractRaceList;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListColumnFactory;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListContainer;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListDataUtil;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.SortableRaceListColumn;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRacesDTO;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.dispatch.CollectionResult;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO;
public class RacesListLive extends Composite implements RefreshableWidget<LiveRacesDTO> {
public class RacesListLive extends Composite {
private static RacesListLiveUiBinder uiBinder = GWT.create(RacesListLiveUiBinder.class);
interface RacesListLiveUiBinder extends UiBinder<Widget, RacesListLive> {
}
@UiField(provided = true) RaceList raceList;
private final RaceListLiveRaces raceList;
private final RaceListContainer<LiveRaceDTO> raceListContainer;
public RacesListLive(EventView.Presenter presenter, boolean showRegattaDetails) {
RacesListLiveResources.INSTANCE.css().ensureInjected();
raceList = new RaceList(presenter, showRegattaDetails);
initWidget(uiBinder.createAndBindUi(this));
raceList = new RaceListLiveRaces(presenter, showRegattaDetails);
raceListContainer = new RaceListContainer<LiveRaceDTO>(StringMessages.INSTANCE.liveNow(), raceList);
initWidget(raceListContainer);
getElement().getStyle().setDisplay(Display.NONE);
}
@Override
public void setData(LiveRacesDTO data, long nextUpdate, int updateNo) {
if(data == null || data.getRaces().isEmpty()) {
getElement().getStyle().setDisplay(Display.NONE);
} else {
getElement().getStyle().clearDisplay();
this.raceList.setListData(data);
}
public RefreshableWidget<CollectionResult<LiveRaceDTO>> getRefreshable() {
return raceListContainer;
}
private class RaceListLiveRaces extends AbstractRaceList<LiveRaceDTO> {
private final SortableRaceListColumn<LiveRaceDTO, ?> regattaNameColumn = RaceListColumnFactory.getRegattaNameColumn();
private final SortableRaceListColumn<LiveRaceDTO, ?> flagsColumn = RaceListColumnFactory.getFlagsColumn();
private final SortableRaceListColumn<LiveRaceDTO, ?> windSpeedColumn = RaceListColumnFactory.getWindSpeedColumn();
private final SortableRaceListColumn<LiveRaceDTO, ?> courseAreaColumn = RaceListColumnFactory.getCourseAreaColumn();
private final SortableRaceListColumn<LiveRaceDTO, ?> courseColumn = RaceListColumnFactory.getCourseColumn();
private final SortableRaceListColumn<LiveRaceDTO, ?> raceViewStateColumn = RaceListColumnFactory.getRaceViewStateColumn();
public RaceListLiveRaces(EventView.Presenter presenter, boolean showRegattaDetails) {
super(presenter);
this.regattaNameColumn.setShowDetails(showRegattaDetails);
}
@Override
protected void setTableData(Collection<LiveRaceDTO> data) {
boolean hasFleets = RaceListDataUtil.hasFleets(data);
this.fleetCornerColumn.setShowDetails(hasFleets);
this.fleetNameColumn.setShowDetails(hasFleets);
this.startTimeColumn.setShowTimeOnly(!RaceListDataUtil.hasDifferentStartDates(data));
this.courseAreaColumn.setShowDetails(RaceListDataUtil.hasCourseAreas(data));
this.courseColumn.setShowDetails(RaceListDataUtil.hasCourses(data));
boolean hasWind = RaceListDataUtil.hasWind(data);
this.windSpeedColumn.setShowDetails(hasWind);
this.windDirectionColumn.setShowDetails(hasWind);
super.setTableData(data);
}
@Override
protected void initTableColumns() {
add(fleetCornerColumn);
add(regattaNameColumn);
add(raceNameColumn);
add(fleetNameColumn);
add(startTimeColumn);
add(flagsColumn);
add(windSpeedColumn);
add(windDirectionColumn);
add(courseAreaColumn);
add(courseColumn);
add(raceViewStateColumn);
add(raceViewerButtonColumn);
}
}
}
@@ -1,14 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
xmlns:r="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.racelist">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources" />
<g:HTMLPanel addStyleNames="{local_res.css.raceslistlive}">
<h3>
<ui:text from='{i18n.liveNow}' />
</h3>
<r:RaceList ui:field="raceList"/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,243 +1,64 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import java.util.Collection;
import java.util.Date;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.TextTransform;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesBuilder;
import com.google.gwt.safecss.shared.SafeStylesUtils;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.cellview.client.RowStyles;
import com.google.gwt.user.cellview.client.TextHeader;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.SortingOrder;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.common.client.SharedResources.MediaCss;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources.LocalCss;
import com.sap.sailing.gwt.regattaoverview.client.FlagsMeaningExplanator;
import com.sap.sailing.gwt.regattaoverview.client.SailingFlagsBuilder;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListColumnFactory.SortableRaceListStartTimeColumn;
import com.sap.sailing.gwt.ui.leaderboard.SortedCellTable;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO;
import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO;
import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceTrackingState;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceViewState;
import com.sap.sailing.gwt.ui.shared.race.RaceProgressDTO;
import com.sap.sailing.gwt.ui.shared.race.SimpleWindDTO;
import com.sap.sailing.gwt.ui.shared.util.NullSafeComparableComparator;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sailing.gwt.ui.shared.race.wind.AbstractWindDTO;
import com.sap.sse.gwt.theme.client.component.celltable.CleanCellTableResources;
import com.sap.sse.gwt.theme.client.component.celltable.StyledHeaderOrFooterBuilder;
public abstract class AbstractRaceList<T extends RaceMetadataDTO> extends Composite {
public abstract class AbstractRaceList<T extends RaceMetadataDTO<? extends AbstractWindDTO>> extends Composite {
private static final LocalCss CSS = RacesListLiveResources.INSTANCE.css();
private static final MediaCss MEDIA_CSS = SharedResources.INSTANCE.mediaCss();
private static final StringMessages I18N = StringMessages.INSTANCE;
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
interface CellTemplates extends SafeHtmlTemplates {
@Template("<div style=\"{1}\" class=\"{0}\"></div>")
SafeHtml fleetCorner(String styleNames, SafeStyles color);
@Template("<div>{3}</div><div class=\"{0}\"><div style=\"{2}\" class=\"{1}\"></div></div>")
SafeHtml viewStateRunning(String styleNamesBar, String styleNamesProgress, SafeStyles width, String text);
@Template("<img style=\"{0}\" src=\"images/home/windkompass_nord.svg\"/>")
SafeHtml windDirection(SafeStyles rotation);
@Template("<div style=\"{0}\">{1}</div>")
SafeHtml raceNotTracked(SafeStyles styles, String text);
@Template("<a href=\"{2}\" class=\"{0}\" target=\"_blank\">{1}</a>")
SafeHtml raceViewerLinkButton(String styleNames, String text, String link);
}
private final SimplePanel cellTableContainer = new SimplePanel();
private final EventView.Presenter presenter;
protected final SortableRaceListColumn<?> fleetCornerColumn = new RaceListColumn<FleetMetadataDTO>("",
new FleetCornerCell()) {
@Override
public String getColumnStyle() {
return CSS.race_fleetcorner();
}
@Override
public FleetMetadataDTO getValue(T object) {
return object.getFleet();
}
};
protected final SortableRaceListColumn<?> raceNameColumn = new SortableRaceListColumn<String>(I18N.race(),
new TextCell(), new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getRaceName();
}
}) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemname());
}
@Override
public String getValue(T object) {
return object.getRaceName();
}
};
protected final SortableRaceListColumn<?> fleetNameColumn = new SortableRaceListColumn<String>(I18N.fleet(),
new TextCell(), new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getFleet() != null ? object.getFleet().getFleetName() : null;
}
}) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getFleet() != null ? object.getFleet().getFleetName() : null;
}
};
protected final SortableRaceListColumn<?> startTimeColumn = new SortableRaceListColumn<Date>(I18N.start(),
new DateCell(DateTimeFormat.getFormat(PredefinedFormat.HOUR24_MINUTE)),
new InvertibleComparatorWrapper<T, Date>(new NullSafeComparableComparator<Date>()) {
@Override
protected Date getComparisonValue(T object) {
return object.getStart();
}
}) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
@Override
public Date getValue(T object) {
return object.getStart();
}
};
protected final SortableRaceListColumn<?> courseAreaColumn = new SortableRaceListColumn<String>(I18N.courseArea(),
new TextCell(), new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getCourseArea();
}
}) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getCourseArea();
}
};
protected final SortableRaceListColumn<?> courseColumn = new SortableRaceListColumn<String>(I18N.course(),
new TextCell(), new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getCourse();
}
}) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getCourse();
}
};
protected final SortableRaceListColumn<?> raceViewerButtonColumn = new RaceListColumn<T>("",
new RaceViewerButtonCell()) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), CSS.raceslist_head_itembutton());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemright());
}
@Override
public T getValue(T object) {
return object;
}
};
protected final SortableRaceListColumn<T, ?> fleetCornerColumn = RaceListColumnFactory.getFleetCornerColumn();
protected final SortableRaceListColumn<T, ?> raceNameColumn = RaceListColumnFactory.getRaceNameColumn();
protected final SortableRaceListColumn<T, ?> fleetNameColumn = RaceListColumnFactory.getFleetNameColumn();
protected final SortableRaceListStartTimeColumn<T> startTimeColumn = RaceListColumnFactory.getStartTimeColumn();
protected final SortableRaceListColumn<T, ?> windDirectionColumn = RaceListColumnFactory.getWindDirectionColumn();
protected final SortableRaceListColumn<T, ?> raceViewerButtonColumn;
private SortedCellTable<T> cellTable;
protected AbstractRaceList(EventView.Presenter presenter) {
CSS.ensureInjected();
this.presenter = presenter;
this.raceViewerButtonColumn = RaceListColumnFactory.getRaceViewerButtonColumn(presenter);
this.initWidget(cellTableContainer);
}
@SuppressWarnings("unchecked")
protected void setTableData(Collection<T> data) {
Column<T, ?> sortColumn = (this.cellTable == null ? null : this.cellTable.getCurrentlySortedColumn());
ColumnSortList sortList = this.cellTable == null ? null : this.cellTable.getColumnSortList();
this.cellTable = new SortedCellTable<T>(data.size(), CleanCellTableResources.INSTANCE);
this.cellTableContainer.setWidget(this.cellTable);
this.initTableStyle();
this.initTableColumns();
this.cellTable.setList(data);
if (sortColumn != null && this.cellTable.getColumnIndex(sortColumn) >= 0) {
this.cellTable.sortColumn(sortColumn);
if (sortList != null && sortList.size() > 0) {
for (int i = sortList.size() - 1; i >= 0; i--) {
ColumnSortInfo sortInfo = sortList.get(i);
Column<T, ?> column = (Column<T, ?>) sortInfo.getColumn();
if(this.cellTable.getColumnIndex(column) >= 0) {
this.cellTable.sortColumn(column, sortInfo.isAscending());
}
}
} else {
this.cellTable.sortColumn(startTimeColumn);
}
}
@@ -254,124 +75,22 @@ public abstract class AbstractRaceList<T extends RaceMetadataDTO> extends Compos
protected abstract void initTableColumns();
protected void add(SortableRaceListColumn<?> column) {
if (column.getColumnStyle() != null) {
column.setCellStyleNames(column.getColumnStyle());
}
Header<?> header = column.getHeader();
if (header != null && column.getHeaderStyle() != null) {
header.setHeaderStyleNames(column.getHeaderStyle());
}
boolean ascending = column.getPreferredSortingOrder().isAscending();
this.cellTable.addColumn(column, header, column.getComparator(), ascending);
}
protected abstract class SortableRaceListColumn<C> extends SortableColumn<T, C> {
private final String headerText;
private final InvertibleComparator<T> comparator;
protected SortableRaceListColumn(String headerText, Cell<C> cell, InvertibleComparator<T> comparator) {
super(cell, SortingOrder.ASCENDING);
this.headerText = headerText;
this.comparator = comparator;
}
@Override
public final InvertibleComparator<T> getComparator() {
return comparator;
}
@Override
public final Header<?> getHeader() {
return new TextHeader(headerText);
}
protected final String getStyleNamesString(String... styleNames) {
return Util.join(" ", styleNames);
}
}
protected abstract class RaceListColumn<C> extends SortableRaceListColumn<C> {
protected RaceListColumn(String headerText, Cell<C> cell) {
super(headerText, cell, null);
}
}
private class FleetCornerCell extends AbstractCell<FleetMetadataDTO> {
@Override
public void render(Context context, FleetMetadataDTO value, SafeHtmlBuilder sb) {
if (value != null) {
sb.append(TEMPLATE.fleetCorner(CSS.race_fleetcorner_icon(),
SafeStylesUtils.fromTrustedNameAndValue("border-top-color", value.getFleetColor())));
protected void add(SortableRaceListColumn<T, ?> column) {
if (column.isShowDetails()) {
if (column.getColumnStyle() != null) {
column.setCellStyleNames(column.getColumnStyle());
}
}
}
protected class FlagsCell extends AbstractCell<FlagStateDTO> {
@Override
public void render(Context context, FlagStateDTO value, SafeHtmlBuilder sb) {
if (value != null) {
sb.append(SailingFlagsBuilder.render(value, 0.55, FlagsMeaningExplanator.getFlagsMeaning(I18N,
value.getLastUpperFlag(), value.getLastLowerFlag(), value.isLastFlagsAreDisplayed())));
Header<?> header = column.getHeader();
if (header != null && column.getHeaderStyle() != null) {
header.setHeaderStyleNames(column.getHeaderStyle());
}
}
}
protected class WindDirectionCell extends AbstractCell<SimpleWindDTO> {
@Override
public void render(Context context, SimpleWindDTO value, SafeHtmlBuilder sb) {
if (value != null) {
SafeStylesBuilder safeStyles = new SafeStylesBuilder();
safeStyles.trustedNameAndValue("-webkit-transform", "rotate(" + value.getTrueWindFromDeg() + "deg)");
safeStyles.trustedNameAndValue("transform", "rotate(" + value.getTrueWindFromDeg() + "deg)");
safeStyles.width(2.75, Unit.EM).height(2.75, Unit.EM);
sb.append(TEMPLATE.windDirection(safeStyles.toSafeStyles()));
boolean ascending = column.getPreferredSortingOrder().isAscending();
InvertibleComparator<T> comperator = column.getComparator();
if (comperator != null) {
comperator.setAscending(ascending);
}
this.cellTable.addColumn(column, header, comperator, ascending);
}
}
protected class RaceViewStateCell extends AbstractCell<LiveRaceDTO> {
@Override
public void render(Context context, LiveRaceDTO value, SafeHtmlBuilder sb) {
RaceViewState state = value.getViewState();
RaceProgressDTO progress = value.getProgress();
if (state == RaceViewState.SCHEDULED) {
double min = MillisecondsTimePoint.now().until(new MillisecondsTimePoint(value.getStart())).asMinutes();
sb.appendEscaped(I18N.startingInMinutes((int) min));
} else if (state == RaceViewState.RUNNING && progress != null) {
SafeStyles width = SafeStylesUtils.forWidth(progress.getPercentageProgress(), Unit.PCT);
String text = I18N.currentOfTotalLegs(progress.getCurrentLeg(), progress.getTotalLegs());
sb.append(TEMPLATE.viewStateRunning(CSS.race_itemstatus_progressbar(),
CSS.race_itemstatus_progressbar_progress(), width, text));
} else {
sb.appendEscaped(state.getLabel());
}
}
}
private class RaceViewerButtonCell extends AbstractCell<T> {
private final TextMessages I18N_UBI = TextMessages.INSTANCE;
private final MainCss css = SharedResources.INSTANCE.mainCss();
private final String watchNowStyle = getButtonStyleNames(css.buttonred());
private final String analyseRaceStyle = getButtonStyleNames(css.buttonprimary());
@Override
public void render(Context context, T data, SafeHtmlBuilder sb) {
if (data.getTrackingState() != RaceTrackingState.TRACKED_VALID_DATA) {
SafeStylesBuilder styles = new SafeStylesBuilder().textTransform(TextTransform.UPPERCASE);
styles.trustedColor("#666").trustedNameAndValue("font-size", "0.933333333333333rem").toSafeStyles();
styles.trustedNameAndValue("padding", "0.714285714285714em 1.071428571428571em");
sb.append(TEMPLATE.raceNotTracked(styles.toSafeStyles(), I18N_UBI.eventRegattaRaceNotTracked()));
} else {
String styleNames = data.getViewState() == RaceViewState.FINISHED ? analyseRaceStyle : watchNowStyle;
String text = data.getViewState() == RaceViewState.FINISHED ? I18N.analyseRace() : I18N_UBI.watchNow();
String raceViewerURL = presenter.getRaceViewerURL(data.getRegattaName(), data.getTrackedRaceName());
sb.append(TEMPLATE.raceViewerLinkButton(styleNames, text, raceViewerURL));
}
}
private final String getButtonStyleNames(String buttonColor) {
return Util.join(" ", css.button(), css.buttonstrong(), buttonColor, css.buttonarrowrightwhite());
}
}
}
@@ -1,179 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import com.google.gwt.cell.client.TextCell;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MediaCss;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources.LocalCss;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRacesDTO;
import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceViewState;
import com.sap.sailing.gwt.ui.shared.race.SimpleWindDTO;
import com.sap.sailing.gwt.ui.shared.util.NullSafeComparableComparator;
public class RaceList extends AbstractRaceList<LiveRaceDTO> {
private static final LocalCss CSS = RacesListLiveResources.INSTANCE.css();
private static final MediaCss MEDIA_CSS = SharedResources.INSTANCE.mediaCss();
private static final StringMessages I18N = StringMessages.INSTANCE;
private final boolean showRegattaDetails;
private boolean showFleetDetails;
private boolean showCourseAreaDetails;
private boolean showCourseDetails;
private boolean showWindDetails;
private final SortableRaceListColumn<?> regattaNameColumn = new SortableRaceListColumn<String>(I18N.regatta(),
new TextCell(), new InvertibleComparatorWrapper<LiveRaceDTO, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(LiveRaceDTO object) {
return object.getRegattaDisplayName();
}
}) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemname());
}
@Override
public String getValue(LiveRaceDTO object) {
return object.getRegattaDisplayName();
}
};
private final SortableRaceListColumn<?> flagsColumn = new RaceListColumn<FlagStateDTO>(I18N.flags(),
new FlagsCell()) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.racesListIcon());
}
@Override
public FlagStateDTO getValue(LiveRaceDTO object) {
return object.getFlagState();
}
};
private final SortableRaceListColumn<?> windSpeedColumn = new SortableRaceListColumn<String>(I18N.wind(),
new TextCell(), new InvertibleComparatorWrapper<LiveRaceDTO, Double>(
new NullSafeComparableComparator<Double>()) {
@Override
protected Double getComparisonValue(LiveRaceDTO object) {
return object.getWind() != null ? object.getWind().getTrueWindSpeedInKnots() : null;
}
}) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
@Override
public String getValue(LiveRaceDTO object) {
return object.getWind() != null ? I18N.knotsValue(object.getWind().getTrueWindSpeedInKnots()) : null;
}
};
private final SortableRaceListColumn<?> windDirectionColumn = new SortableRaceListColumn<SimpleWindDTO>(
I18N.from(), new WindDirectionCell(), new InvertibleComparatorWrapper<LiveRaceDTO, Double>(
new NullSafeComparableComparator<Double>()) {
@Override
protected Double getComparisonValue(LiveRaceDTO object) {
return object.getWind() != null ? object.getWind().getTrueWindFromDeg() : null;
}
}) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.hideonsmall());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.racesListIcon(), MEDIA_CSS.hideonsmall());
}
@Override
public SimpleWindDTO getValue(LiveRaceDTO object) {
return object.getWind();
}
};
private final SortableRaceListColumn<?> raceViewStateColumn = new SortableRaceListColumn<LiveRaceDTO>(
I18N.status(), new RaceViewStateCell(), new InvertibleComparatorWrapper<LiveRaceDTO, RaceViewState>(
new NullSafeComparableComparator<RaceViewState>()) {
@Override
protected RaceViewState getComparisonValue(LiveRaceDTO object) {
return object.getViewState();
}
}) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
@Override
public LiveRaceDTO getValue(LiveRaceDTO object) {
return object;
}
};
public RaceList(EventView.Presenter presenter, boolean showRegattaDetails) {
super(presenter);
this.showRegattaDetails = showRegattaDetails;
}
public void setListData(LiveRacesDTO data) {
this.showFleetDetails = data.hasFleets();
this.showCourseAreaDetails = data.hasCourseAreas();
this.showCourseDetails = data.hasCourses();
this.showWindDetails = data.hasWind();
setTableData(data.getRaces());
}
@Override
protected void initTableColumns() {
if (showFleetDetails) {
add(fleetCornerColumn);
}
if (showRegattaDetails) {
add(regattaNameColumn);
}
add(raceNameColumn);
if (showFleetDetails) {
add(fleetNameColumn);
}
add(startTimeColumn);
add(flagsColumn);
if(showWindDetails) {
add(windSpeedColumn);
add(windDirectionColumn);
}
if (showCourseAreaDetails) {
add(courseAreaColumn);
}
if(showCourseDetails) {
add(courseColumn);
}
add(raceViewStateColumn);
add(raceViewerButtonColumn);
}
}
@@ -0,0 +1,625 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import java.util.Date;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.TextTransform;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesBuilder;
import com.google.gwt.safecss.shared.SafeStylesUtils;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.cellview.client.SafeHtmlHeader;
import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.SortingOrder;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.common.client.SharedResources.MediaCss;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources.LocalCss;
import com.sap.sailing.gwt.regattaoverview.client.FlagsMeaningExplanator;
import com.sap.sailing.gwt.regattaoverview.client.SailingFlagsBuilder;
import com.sap.sailing.gwt.ui.client.FlagImageResolver;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.SimpleCompetitorDTO;
import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO;
import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceTrackingState;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO.RaceViewState;
import com.sap.sailing.gwt.ui.shared.race.RaceProgressDTO;
import com.sap.sailing.gwt.ui.shared.race.wind.AbstractWindDTO;
import com.sap.sailing.gwt.ui.shared.race.wind.WindStatisticsDTO;
import com.sap.sailing.gwt.ui.shared.util.NullSafeComparableComparator;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class RaceListColumnFactory {
private static final LocalCss CSS = RacesListLiveResources.INSTANCE.css();
private static final MainCss MAIN_CSS = SharedResources.INSTANCE.mainCss();
private static final MediaCss MEDIA_CSS = SharedResources.INSTANCE.mediaCss();
private static final StringMessages I18N = StringMessages.INSTANCE;
private static final TextMessages I18N_UBI = TextMessages.INSTANCE;
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
interface CellTemplates extends SafeHtmlTemplates {
@Template("<div style=\"{1}\" class=\"{0}\"></div>")
SafeHtml fleetCorner(String styleNames, SafeStyles color);
@Template("<div>{3}</div><div class=\"{0}\"><div style=\"{2}\" class=\"{1}\"></div></div>")
SafeHtml viewStateRunning(String styleNamesBar, String styleNamesProgress, SafeStyles width, String text);
@Template("<img style=\"{0}\" src=\"images/home/windkompass_nord.svg\"/>")
SafeHtml windDirection(SafeStyles rotation);
@Template("<div style=\"{0}\">{1}</div>")
SafeHtml raceNotTracked(SafeStyles styles, String text);
@Template("<a href=\"{2}\" class=\"{0}\" target=\"_blank\">{1}</a>")
SafeHtml raceViewerLinkButton(String styleNames, String text, String link);
@Template("<img src=\"{2}\" class=\"{0}\" /><span class=\"{1}\">{3}</span>")
SafeHtml winner(String styleNamesFlag, String styleNamesText, SafeUri flagImageURL, String name);
@Template("<img src=\"{1}\" class=\"{0}\" />")
SafeHtml imageHeader(String styleNames, SafeUri imageURL);
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, FleetMetadataDTO> getFleetCornerColumn() {
Cell<FleetMetadataDTO> cell = new AbstractCell<FleetMetadataDTO>() {
@Override
public void render(Context context, FleetMetadataDTO value, SafeHtmlBuilder sb) {
if (value != null) {
SafeStyles style = SafeStylesUtils.fromTrustedNameAndValue("border-top-color", value.getFleetColor());
sb.append(TEMPLATE.fleetCorner(CSS.race_fleetcorner_icon(), style));
}
}
};
InvertibleComparator<T> comparator = null;
return new SortableRaceListColumn<T, FleetMetadataDTO>("", cell, comparator) {
@Override
public String getColumnStyle() {
return CSS.race_fleetcorner();
}
@Override
public FleetMetadataDTO getValue(T object) {
return object.getFleet();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, String> getRegattaNameColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getRegattaDisplayName();
}
};
return new SortableRaceListColumn<T, String>(I18N.regatta(), cell, comparator) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemname());
}
@Override
public String getValue(T object) {
return object.getRegattaDisplayName();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, String> getRaceNameColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getRaceName();
}
};
return new SortableRaceListColumn<T, String>(I18N.race(), cell, comparator) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemname());
}
@Override
public String getValue(T object) {
return object.getRaceName();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, String> getFleetNameColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getFleet() != null ? object.getFleet().getFleetName() : null;
}
};
return new SortableRaceListColumn<T, String>(I18N.fleet(), cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getFleet() != null ? object.getFleet().getFleetName() : null;
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListStartTimeColumn<T> getStartTimeColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Date>(new NullSafeComparableComparator<Date>()) {
@Override
protected Date getComparisonValue(T object) {
return object.getStart();
}
};
return new SortableRaceListStartTimeColumn<T>(comparator);
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, String> getDurationColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Duration>(new NullSafeComparableComparator<Duration>(false)) {
@Override
protected Duration getComparisonValue(T object) {
return object.getDuration();
}
};
return new SortableRaceListColumn<T, String>(I18N.durationPlain(), cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getDuration() != null ? DateAndTimeFormatterUtil.formatElapsedTime(object.getDuration().asMillis()) : null;
}
};
}
public static <T extends LiveRaceDTO> SortableRaceListColumn<T, FlagStateDTO> getFlagsColumn() {
Cell<FlagStateDTO> cell = new AbstractCell<FlagStateDTO>() {
@Override
public void render(Context context, FlagStateDTO value, SafeHtmlBuilder sb) {
if (value != null) {
sb.append(SailingFlagsBuilder.render(value, 0.55, FlagsMeaningExplanator.getFlagsMeaning(I18N,
value.getLastUpperFlag(), value.getLastLowerFlag(), value.isLastFlagsAreDisplayed())));
}
}
};
InvertibleComparator<T> comparator = null;
return new SortableRaceListColumn<T, FlagStateDTO>(I18N.flags(), cell, comparator) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.racesListIcon());
}
@Override
public FlagStateDTO getValue(T object) {
return object.getFlagState();
}
};
}
public static <T extends LiveRaceDTO> SortableRaceListColumn<T, String> getWindSpeedColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Double>( new NullSafeComparableComparator<Double>()) {
@Override
protected Double getComparisonValue(T object) {
return object.getWind() != null ? object.getWind().getTrueWindSpeedInKnots() : null;
}
};
return new WindSpeedOrRangeColumn<T>(comparator) {
@Override
public String getValue(T object) {
return object.getWind() != null ? I18N.knotsValue(object.getWind().getTrueWindSpeedInKnots()) : null;
}
};
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, String> getWindRangeColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Double>(new NullSafeComparableComparator<Double>()) {
@Override
protected Double getComparisonValue(T object) {
WindStatisticsDTO wind = object.getWind();
return wind != null ? (wind.getTrueUpperboundWindInKnots() + wind .getTrueLowerboundWindInKnots()) : null;
}
};
return new WindSpeedOrRangeColumn<T>(comparator) {
@Override
public String getValue(T object) {
WindStatisticsDTO wind = object.getWind();
if (wind == null) {
return "";
} else if (wind.getRoundedDifference() <= 0d) {
return I18N.knotsValue(wind.getTrueLowerboundWindInKnots());
}
return I18N.knotsRange(wind.getTrueLowerboundWindInKnots(), wind.getTrueUpperboundWindInKnots());
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, AbstractWindDTO> getWindDirectionColumn() {
Cell<AbstractWindDTO> cell = new AbstractCell<AbstractWindDTO>() {
@Override
public void render(Context context, AbstractWindDTO value, SafeHtmlBuilder sb) {
if (value != null) {
SafeStylesBuilder safeStyles = new SafeStylesBuilder();
safeStyles.trustedNameAndValue("-webkit-transform", "rotate(" + value.getTrueWindFromDeg() + "deg)");
safeStyles.trustedNameAndValue("transform", "rotate(" + value.getTrueWindFromDeg() + "deg)");
safeStyles.width(2.75, Unit.EM).height(2.75, Unit.EM);
sb.append(TEMPLATE.windDirection(safeStyles.toSafeStyles()));
}
}
};
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Double>( new NullSafeComparableComparator<Double>()) {
@Override
protected Double getComparisonValue(T object) {
return object.getWind() != null ? object.getWind().getTrueWindFromDeg() : null;
}
};
return new SortableRaceListColumn<T, AbstractWindDTO>(I18N.from(), cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.hideonsmall());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.racesListIcon(), MEDIA_CSS.hideonsmall());
}
@Override
public AbstractWindDTO getValue(T object) {
return object.getWind();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, String> getCourseAreaColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getCourseArea();
}
};
return new SortableRaceListColumn<T, String>(I18N.courseArea(), cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getCourseArea();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, String> getCourseColumn() {
Cell<String> cell = new TextCell();
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getCourse();
}
};
return new SortableRaceListColumn<T, String>(I18N.course(), cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), MEDIA_CSS.showonlarge());
}
@Override
public String getValue(T object) {
return object.getCourse();
}
};
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, Number> getWindSourcesCountColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Integer>(new NullSafeComparableComparator<Integer>(false)) {
@Override
protected Integer getComparisonValue(T object) {
return object.getWindSourcesCount();
}
};
return new DataCountColumn<T>(DataCountColumn.ICON_WIND, comparator) {
@Override
public Number getValue(T object) {
return object.getWindSourcesCount();
}
};
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, Number> getVideoCountColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Integer>(new NullSafeComparableComparator<Integer>(false)) {
@Override
protected Integer getComparisonValue(T object) {
return object.getVideoCount();
}
};
return new DataCountColumn<T>(DataCountColumn.ICON_VIDEO, comparator) {
@Override
public Number getValue(T object) {
return object.getVideoCount();
}
};
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, Number> getAudioCountColumn() {
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, Integer>(new NullSafeComparableComparator<Integer>(false)) {
@Override
protected Integer getComparisonValue(T object) {
return object.getAudioCount();
}
};
return new DataCountColumn<T>(DataCountColumn.ICON_AUDIO, comparator) {
@Override
public Number getValue(T object) {
return object.getAudioCount();
}
};
}
public static <T extends LiveRaceDTO> SortableRaceListColumn<T, T> getRaceViewStateColumn() {
Cell<T> cell = new AbstractCell<T>() {
@Override
public void render(Context context, T value, SafeHtmlBuilder sb) {
RaceViewState state = value.getViewState();
RaceProgressDTO progress = value.getProgress();
if (state == RaceViewState.SCHEDULED) {
double min = MillisecondsTimePoint.now().until(new MillisecondsTimePoint(value.getStart())).asMinutes();
sb.appendEscaped(I18N.startingInMinutes((int) min));
} else if (state == RaceViewState.RUNNING && progress != null) {
SafeStyles width = SafeStylesUtils.forWidth(progress.getPercentageProgress(), Unit.PCT);
String text = I18N.currentOfTotalLegs(progress.getCurrentLeg(), progress.getTotalLegs());
sb.append(TEMPLATE.viewStateRunning(CSS.race_itemstatus_progressbar(),
CSS.race_itemstatus_progressbar_progress(), width, text));
} else {
sb.appendEscaped(state.getLabel());
}
}
};
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, RaceViewState>(new NullSafeComparableComparator<RaceViewState>()) {
@Override
protected RaceViewState getComparisonValue(T object) {
return object.getViewState();
}
};
return new SortableRaceListColumn<T, T>(I18N.status(), cell, comparator) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
@Override
public T getValue(T object) {
return object;
}
};
}
public static <T extends RaceListRaceDTO> SortableRaceListColumn<T, SimpleCompetitorDTO> getWinnerColumn() {
Cell<SimpleCompetitorDTO> cell = new AbstractCell<SimpleCompetitorDTO>() {
@Override
public void render(Context context, SimpleCompetitorDTO value, SafeHtmlBuilder sb) {
if (value != null) {
SafeUri flagImageUri = FlagImageResolver.getFlagImageUri(value.getFlagImageURL(), value.getTwoLetterIsoCountryCode());
sb.append(TEMPLATE.winner(CSS.race_item_flag(), CSS.race_item_winner(), flagImageUri, value.getName()));
}
}
};
InvertibleComparator<T> comparator = new InvertibleComparatorWrapper<T, String>(new NaturalComparator(false)) {
@Override
protected String getComparisonValue(T object) {
return object.getWinner() != null ? object.getWinner().getName() : null;
}
};
return new SortableRaceListColumn<T, SimpleCompetitorDTO>(I18N.winner(), cell, comparator) {
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemwinner());
}
@Override
public SimpleCompetitorDTO getValue(T object) {
return object.getWinner();
}
};
}
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, T> getRaceViewerButtonColumn(final EventView.Presenter presenter) {
Cell<T> cell = new AbstractCell<T>() {
private final String watchNowStyle = getButtonStyleNames(MAIN_CSS.buttonred());
private final String analyseRaceStyle = getButtonStyleNames(MAIN_CSS.buttonprimary());
@Override
public void render(Context context, T data, SafeHtmlBuilder sb) {
if (data.getTrackingState() != RaceTrackingState.TRACKED_VALID_DATA) {
SafeStylesBuilder styles = new SafeStylesBuilder().textTransform(TextTransform.UPPERCASE);
styles.trustedColor("#666").trustedNameAndValue("font-size", "0.933333333333333rem").toSafeStyles();
styles.trustedNameAndValue("padding", "0.714285714285714em 1.071428571428571em");
sb.append(TEMPLATE.raceNotTracked(styles.toSafeStyles(), I18N_UBI.eventRegattaRaceNotTracked()));
} else {
String styleNames = data.getViewState() == RaceViewState.FINISHED ? analyseRaceStyle : watchNowStyle;
String text = data.getViewState() == RaceViewState.FINISHED ? I18N.analyseRace() : I18N_UBI.watchNow();
String raceViewerURL = presenter.getRaceViewerURL(data.getRegattaName(), data.getTrackedRaceName());
sb.append(TEMPLATE.raceViewerLinkButton(styleNames, text, raceViewerURL));
}
}
private final String getButtonStyleNames(String buttonColor) {
return Util.join(" ", MAIN_CSS.button(), MAIN_CSS.buttonstrong(), buttonColor, MAIN_CSS.buttonarrowrightwhite());
}
};
InvertibleComparator<T> comparator = null;
return new SortableRaceListColumn<T, T>("", cell, comparator) {
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), CSS.raceslist_head_itembutton());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemright());
}
@Override
public T getValue(T object) {
return object;
}
};
}
public static class SortableRaceListStartTimeColumn<T extends RaceMetadataDTO<?>> extends SortableRaceListColumn<T, Date> {
protected SortableRaceListStartTimeColumn(InvertibleComparator<T> comparator) {
super(I18N.start(), new StartTimeCell(), comparator, SortingOrder.DESCENDING);
}
public void setShowTimeOnly(boolean showTimeOnly) {
((StartTimeCell) getCell()).showTimeOnly = showTimeOnly;
}
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
@Override
public Date getValue(T object) {
return object.getStart();
}
private static class StartTimeCell extends AbstractCell<Date> {
private static final DateTimeFormat DATE_FORMAT = DateTimeFormat.getFormat(PredefinedFormat.MONTH_NUM_DAY);
private static final DateTimeFormat TIME_FORMAT = DateTimeFormat.getFormat(PredefinedFormat.HOUR24_MINUTE);
private boolean showTimeOnly = true;
@Override
public void render(Context context, Date value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped((showTimeOnly ? "" : DATE_FORMAT.format(value) + " ") + TIME_FORMAT.format(value));
}
}
}
}
private static abstract class WindSpeedOrRangeColumn<T extends RaceMetadataDTO<?>> extends SortableRaceListColumn<T, String> {
protected WindSpeedOrRangeColumn(InvertibleComparator<T> comparator) {
super(I18N.wind(), new TextCell(), comparator);
}
@Override
public String getHeaderStyle() {
return CSS.raceslist_head_item();
}
@Override
public String getColumnStyle() {
return CSS.race_item();
}
}
private static abstract class DataCountColumn<T extends RaceListRaceDTO> extends SortableRaceListColumn<T, Number> {
private static final SafeUri ICON_WIND = UriUtils.fromTrustedString("images/home/icon-wind.png");
private static final SafeUri ICON_VIDEO = UriUtils.fromTrustedString("images/home/icon-video.png");
private static final SafeUri ICON_AUDIO = UriUtils.fromTrustedString("images/home/icon-audio.png");
private DataCountColumn(final SafeUri imageUri, InvertibleComparator<T> comparator) {
super(new SafeHtmlHeader(TEMPLATE.imageHeader(CSS.raceslist_head_itemflag(), imageUri)), new AbstractCell<Number>() {
@Override
public void render(Context context, Number value, SafeHtmlBuilder sb) {
if (value != null && value.longValue() > 0) {
sb.append(value.longValue());
} else {
sb.appendHtmlConstant("&mdash;");
}
}
}, comparator, SortingOrder.DESCENDING);
}
@Override
public String getHeaderStyle() {
return getStyleNamesString(CSS.raceslist_head_item(), CSS.raceslist_head_itemcenter(), MEDIA_CSS.showonlarge());
}
@Override
public String getColumnStyle() {
return getStyleNamesString(CSS.race_item(), CSS.race_itemcenter(), MEDIA_CSS.showonlarge());
}
}
}
@@ -0,0 +1,71 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import java.util.Collection;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.HeadingElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.ui.shared.dispatch.CollectionResult;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO;
public class RaceListContainer<T extends RaceMetadataDTO<?>> extends Composite implements RefreshableWidget<CollectionResult<T>> {
private static RaceListContainerUiBinder uiBinder = GWT.create(RaceListContainerUiBinder.class);
interface RaceListContainerUiBinder extends UiBinder<Widget, RaceListContainer<?>> {
}
@UiField HeadingElement titleUi;
@UiField DivElement infoUi;
@UiField DivElement noContentPlaceholderUi;
@UiField(provided = true) AbstractRaceList<T> raceListUi;
private String noContentPlaceholderText;
public RaceListContainer(String title, AbstractRaceList<T> raceList) {
this(title, null, raceList);
}
public RaceListContainer(String title, String noContentPlaceholderText, AbstractRaceList<T> raceList) {
this.noContentPlaceholderText = noContentPlaceholderText;
RacesListLiveResources.INSTANCE.css().ensureInjected();
this.raceListUi = raceList;
initWidget(uiBinder.createAndBindUi(this));
this.titleUi.setInnerText(title);
raceListUi.setVisible(false);
}
@Override
public void setData(CollectionResult<T> data, long nextUpdate, int updateNo) {
setRaceListData(data == null ? null : data.getValues());
}
public void setRaceListData(Collection<T> data) {
if(data == null || data.isEmpty()) {
if(noContentPlaceholderText == null) {
getElement().getStyle().setDisplay(Display.NONE);
} else {
noContentPlaceholderUi.setInnerText(noContentPlaceholderText);
noContentPlaceholderUi.getStyle().clearDisplay();
raceListUi.setVisible(false);
}
} else {
noContentPlaceholderUi.getStyle().setDisplay(Display.NONE);
getElement().getStyle().clearDisplay();
raceListUi.setVisible(true);
this.raceListUi.setTableData(data);
}
}
public void setInfoText(String infoText) {
this.infoUi.setInnerText(infoText);
this.infoUi.getStyle().clearDisplay();
}
}
@@ -0,0 +1,14 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
xmlns:r="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.racelist">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLiveResources" />
<g:HTMLPanel addStyleNames="{local_res.css.raceslistlive}">
<h3 ui:field="titleUi"></h3>
<div style="display: none;" ui:field="infoUi"></div>
<div style="display: none; font-weight: bold; font-style: italic;" ui:field="noContentPlaceholderUi"></div>
<r:AbstractRaceList ui:field="raceListUi"/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,142 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import java.util.Collection;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.SimpleCompetitorDTO;
import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO;
import com.sap.sailing.gwt.ui.shared.race.wind.AbstractWindDTO;
import com.sap.sse.common.Duration;
public class RaceListDataUtil {
private interface ValueProvider<T, V> {
V getValue(T object);
}
private static <T extends RaceMetadataDTO<?>> boolean hasValues(Collection<T> races, ValueProvider<T, ?> valueProvider) {
for (T race : races) {
if (valueProvider.getValue(race) != null) {
return true;
}
}
return false;
}
private static <T extends RaceMetadataDTO<?>> boolean hasNumberValues(Collection<T> races, ValueProvider<T, Number> valueProvider) {
for (T race : races) {
Number value = valueProvider.getValue(race);
if (value != null && value.longValue() > 0) {
return true;
}
}
return false;
}
private static <T extends RaceMetadataDTO<?>> boolean hasDifferentValues(Collection<T> races, ValueProvider<T, ?> valueProvider) {
Object compareValue = null;
for (T race : races) {
Object currentValue = valueProvider.getValue(race);
if (currentValue == null) {
continue;
} else if (compareValue == null) {
compareValue = currentValue;
} else if (!compareValue.equals(currentValue)) {
return true;
}
}
return false;
}
public static <T extends RaceMetadataDTO<?>> boolean hasFleets(Collection<T> data) {
return hasValues(data, new ValueProvider<T, FleetMetadataDTO>() {
@Override
public FleetMetadataDTO getValue(T object) {
return object.getFleet();
}
});
}
public static <T extends RaceListRaceDTO> boolean hasDurations(Collection<T> data) {
return hasValues(data, new ValueProvider<T, Duration>() {
@Override
public Duration getValue(T object) {
return object.getDuration();
}
});
}
public static <T extends RaceMetadataDTO<?>> boolean hasWind(Collection<T> data) {
return hasValues(data, new ValueProvider<T, AbstractWindDTO>() {
@Override
public AbstractWindDTO getValue(T object) {
return object.getWind();
}
});
}
public static <T extends RaceListRaceDTO> boolean hasWindSources(Collection<T> data) {
return hasNumberValues(data, new ValueProvider<T, Number>() {
@Override
public Number getValue(T object) {
return object.getWindSourcesCount();
}
});
}
public static <T extends RaceListRaceDTO> boolean hasVideos(Collection<T> data) {
return hasNumberValues(data, new ValueProvider<T, Number>() {
@Override
public Number getValue(T object) {
return object.getVideoCount();
}
});
}
public static <T extends RaceListRaceDTO> boolean hasAudios(Collection<T> data) {
return hasNumberValues(data, new ValueProvider<T, Number>() {
@Override
public Number getValue(T object) {
return object.getAudioCount();
}
});
}
public static <T extends RaceMetadataDTO<?>> boolean hasCourses(Collection<T> data) {
return hasValues(data, new ValueProvider<T, String>() {
@Override
public String getValue(T object) {
return object.getCourse();
}
});
}
public static <T extends RaceMetadataDTO<?>> boolean hasCourseAreas(Collection<T> data) {
return hasValues(data, new ValueProvider<T, String>() {
@Override
public String getValue(T object) {
return object.getCourseArea();
}
});
}
public static <T extends RaceListRaceDTO> boolean hasWinner(Collection<T> data) {
return hasValues(data, new ValueProvider<T, SimpleCompetitorDTO>() {
@Override
public SimpleCompetitorDTO getValue(T object) {
return object.getWinner();
}
});
}
private static final long DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
public static <T extends RaceMetadataDTO<?>> boolean hasDifferentStartDates(Collection<T> data) {
return hasDifferentValues(data, new ValueProvider<T, Long>() {
@Override
public Long getValue(T object) {
return object.getStart().getTime() / DAY_IN_MILLIS;
}
});
}
}
@@ -0,0 +1,57 @@
package com.sap.sailing.gwt.home.client.place.event.partials.racelist;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.cellview.client.TextHeader;
import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.SortingOrder;
import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn;
import com.sap.sse.common.Util;
public abstract class SortableRaceListColumn<T, C> extends SortableColumn<T, C> {
private final Header<?> header;
private final InvertibleComparator<T> comparator;
private boolean showDetails = true;
protected SortableRaceListColumn(String headerText, Cell<C> cell, InvertibleComparator<T> comparator) {
this(new TextHeader(headerText), cell, comparator);
}
protected SortableRaceListColumn(String headerText, Cell<C> cell, InvertibleComparator<T> comparator, SortingOrder preferredSortingOrder) {
this(new TextHeader(headerText), cell, comparator, preferredSortingOrder);
}
protected SortableRaceListColumn(Header<?> header, Cell<C> cell, InvertibleComparator<T> comparator) {
this(header, cell, comparator, SortingOrder.ASCENDING);
}
protected SortableRaceListColumn(Header<?> header, Cell<C> cell, InvertibleComparator<T> comparator, SortingOrder preferredSortingOrder) {
super(cell, preferredSortingOrder);
this.header = header;
this.comparator = comparator;
}
@Override
public final InvertibleComparator<T> getComparator() {
return comparator;
}
@Override
public final Header<?> getHeader() {
return header;
}
public void setShowDetails(boolean showDetails) {
this.showDetails = showDetails;
}
public boolean isShowDetails() {
return showDetails;
}
protected final String getStyleNamesString(String... styleNames) {
return Util.join(" ", styleNames);
}
}
@@ -1,79 +0,0 @@
/**
* The header of a regatta of an event
*/
.regattaheader {
font-size: 1rem;
margin-top: 2em;
padding: 0.666666666666667em;
overflow: hidden;
border-radius: 0.333333333333333em;
border: 1px solid #dedede;
background-color: #f2f2f2;
}
.regattaheaderlink {
display: block;
margin-top: 0;
border: none;
border-radius: 0;
color: #0a0a0a;
}
.regattaheader_logo {
float: left;
width: 4em;
height: 3.333333333333333em;
margin-right: 0.666666666666667em;
text-align: center;
line-height: 3.333333333333333em;
border-right: 1px solid #ccc;
padding-right: 0.666666666666667em;
}
.regattaheader_logo img {
display: inline-block;
text-align: center;
vertical-align: middle;
}
.regattaheader_content {
float: left;
width: 80%;
overflow: hidden;
}
.regattaheader_content_title {
font-size: 1.466666666666667em;
font-weight: 700;
height: 1.363636363636364em;
line-height: 1.363636363636364em;
}
.regattaheader_content_details {
height: 1.333333333333333em;
}
.regattaheader_content_details_item {
float: left;
font-size: 13px;
font-weight: 600;
color: #666;
padding: 0 0.666666666666667em;
border-right: 1px solid #ccc;
}
.regattaheader_content_details_item:first-of-type {
padding-left: 0;
}
.regattaheader_content_details_item:last-of-type {
border: none;
padding-right: 0;
}
.regattaheader_arrow {
float: right;
width: 5%;
line-height: 3.333333333333333em;
text-align: right;
}
.regattaheader_arrow:before {
content: '';
display: inline-block;
margin-left: 0.333333333333333em;
width: 0.8em;
height: 1.333333333333333em;
background-image: url("../images/home/breadcrumb-arrow.png");
background-size: contain;
background-repeat: no-repeat;
}
@@ -0,0 +1,125 @@
/**
* The header of a regatta of an event
*/
.regattaheader {
width: 100%;
float: left;
font-size: 1rem;
padding: 0.666666666666667em;
padding-right: 1em;
overflow: hidden;
color: #0a0a0a;
background-color: #f2f2f2;
border-bottom: 1px solid #ddd;
}
.regattaheaderpadding {
padding-right: 5em;
}
.regattaheader_logo {
float: left;
width: 3.333333333333333em;
height: 3.333333333333333em;
text-align: center;
line-height: 3.333333333333333em;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.regattaheader_logo img {
display: inline-block;
text-align: center;
vertical-align: middle;
}
.regattaheader_content {
float: left;
width: 60%;
overflow: hidden;
border-left: 1px solid #ccc;
margin-left: 0.666666666666667em;
padding-left: 1em;
}
.regattaheader_content_title {
font-size: 1.466666666666667em;
font-weight: 700;
height: 1.363636363636364em;
line-height: 1.363636363636364em;
}
.regattaheader_content_details {
height: 1.333333333333333em;
}
.regattaheader_content_details_item {
float: left;
font-size: 13px;
font-weight: 600;
color: #666;
padding: 0 0.666666666666667em;
border-right: 1px solid #ccc;
}
.regattaheader_content_details_item:first-of-type {
padding-left: 0;
}
.regattaheader_content_details_item:last-of-type {
border: none;
padding-right: 0;
}
.regattaheader_toggle {
float: right;
width: 4em;
cursor: pointer;
margin: 0.666666666666667em 0 0.666666666666667em -4em;
line-height: 3.333333333333333em;
text-align: center;
padding: 0 0.666666666666667em;
border-left: 1px solid #ccc;
}
.regattaheader_toggle_icon {
padding: 1em 0;
width: 1.333333333333333em;
height: 1.333333333333333em;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.standings_listhidden .regattaheader_toggle_icon {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
.regattaheader_arrow {
position: absolute;
top: 0;
right: 0;
bottom: 0;
text-align: right;
padding: 0.666666666666667em;
padding-right: 4.666666666666667em;
background-image: url("images/home/arrow-down-grey.png");
background-size: 1.333333333333333em 1.333333333333333em;
background-position: center;
background-repeat: no-repeat;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.regattaheader_update {
width: 20%;
float: right;
padding: 0.533333333333333em 0;
text-align: right;
font-weight: 600;
color: #666;
}
.regattaheader_update_title {
text-transform: uppercase;
}
img.regattaheader_update_title_icon {
height: 1.2em;
margin-right: 0.333333333333333em;
vertical-align: bottom;
}
.regattaheader_update_timestamp {
font-size: 12px;
}
@@ -1,26 +1,33 @@
package com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.eventview.RegattaReferenceDTO;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO;
public class RegattaHeader extends Composite {
private static EventHeaderUiBinder uiBinder = GWT.create(EventHeaderUiBinder.class);
interface EventHeaderUiBinder extends UiBinder<Widget, RegattaHeader> {
private static RegattaHeaderUiBinder uiBinder = GWT.create(RegattaHeaderUiBinder.class);
interface RegattaHeaderUiBinder extends UiBinder<Widget, RegattaHeader> {
}
@UiField StringMessages i18n;
@UiField AnchorElement headerBodyUi;
@UiField AnchorElement headerArrowUi;
public RegattaHeader(RegattaReferenceDTO regattaRefDTO) {
RegattaHeaderResources.INSTANCE.css().ensureInjected();
public RegattaHeader(RegattaMetadataDTO regattaMetadata) {
initWidget(uiBinder.createAndBindUi(this));
headerBodyUi.appendChild(new RegattaHeaderBody(regattaMetadata).getElement());
}
public void setRegattaNavigation(PlaceNavigation<?> placeNavigation) {
headerArrowUi.getStyle().clearDisplay();
placeNavigation.configureAnchorElement(headerBodyUi);
placeNavigation.configureAnchorElement(headerArrowUi);
}
}
@@ -1,30 +1,23 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.place.event.partials"
>
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader.RegattaHeaderResources" />
<g:HTMLPanel>
<!-- The regatta header contains basic regatta information-->
<div>
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<!-- IF isLink -->
<a href="<!-- linkToRegattaEvenPage -->" class="{local_res.css.regattaheader} {local_res.css.regattaheaderlink}">
<s:regattaHeader.RegattaHeaderBody ui:field='regatta'></s:regattaHeader.RegattaHeaderBody>
</a>
<!-- IFEND isLink -->
<!-- IF isLink == false -->
<div class="{local_res.css.regattaheader}">
<div class="{local_res.css.regattaheader_arrow}"></div>
</div>
<!-- IFEND isLink == false -->
</div>
</div>
</div>
</g:HTMLPanel>
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader.RegattaHeaderResources" />
<g:HTMLPanel>
<div>
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<a class="{local_res.css.regattaheader} {local_res.css.regattaheaderpadding}" ui:field="headerBodyUi"></a>
<!-- <a class="{local_res.css.regattaheader_toggle}"> -->
<!-- <img src="images/home/arrow-down-grey.png" class="{local_res.css.regattaheader_toggle_icon}"></img> -->
<!-- </a> -->
<a class="{local_res.css.regattaheader_arrow}" style="display:none;" ui:field="headerArrowUi"></a>
<!-- <div class="{local_res.css.regattaheader} {local_res.css.regattaheaderpadding}"></div> -->
<!-- <div class="{local_res.css.regattaheader_toggle}"></div> -->
<!-- <div class="{local_res.css.regattaheader_arrow}"></div> -->
</div>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,62 @@
package com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.UIObject;
import com.sap.sailing.gwt.common.client.BoatClassImageResolver;
import com.sap.sailing.gwt.home.client.shared.LabelTypeUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO;
public class RegattaHeaderBody extends UIObject {
private static final StringMessages I18N = StringMessages.INSTANCE;
private static RegattaHeaderBodyUiBinder uiBinder = GWT.create(RegattaHeaderBodyUiBinder.class);
interface RegattaHeaderBodyUiBinder extends UiBinder<Element, RegattaHeaderBody> {
}
@UiField protected DivElement logoUi;
@UiField protected SpanElement nameUi;
@UiField protected DivElement labelUi;
@UiField protected DivElement detailsItemContainerUi;
public RegattaHeaderBody(RegattaMetadataDTO regattaMetadata) {
RegattaHeaderResources.INSTANCE.css().ensureInjected();
setElement(uiBinder.createAndBindUi(this));
ImageResource logo = BoatClassImageResolver.getBoatClassIconResource(regattaMetadata.getBoatClass());
logoUi.getStyle().setBackgroundImage("url('" + logo.getSafeUri().asString() + "')");
nameUi.setInnerText(regattaMetadata.getDisplayName());
LabelTypeUtil.renderLabelTypeOrHide(labelUi, regattaMetadata.getState().getStateMarker());
addDetailsItem(regattaMetadata.getCompetitorsCount(), I18N.competitorsCount(regattaMetadata.getCompetitorsCount()));
addDetailsItem(regattaMetadata.getRaceCount(), I18N.racesCount(regattaMetadata.getRaceCount()));
addDetailsItem(regattaMetadata.getTrackedRacesCount(), I18N.trackedRacesCount(regattaMetadata.getTrackedRacesCount()));
String defaultCourseAreaName = regattaMetadata.getDefaultCourseAreaName();
if(defaultCourseAreaName != null) {
addDetailsItem(I18N.courseAreaName(defaultCourseAreaName));
}
addDetailsItem(regattaMetadata.getBoatCategory());
}
private void addDetailsItem(int count, String text) {
if (count > 0) {
addDetailsItem(text);
}
}
private void addDetailsItem(String text) {
if(text != null) {
DivElement detailsItem = DOM.createDiv().cast();
detailsItem.addClassName(RegattaHeaderResources.INSTANCE.css().regattaheader_content_details_item());
detailsItem.setInnerText(text);
detailsItemContainerUi.appendChild(detailsItem);
}
}
}
@@ -1,59 +1,24 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.place.event.ui"
>
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.ui.regattaHeader.RegattaHeaderResources" />
<g:HTMLPanel>
<div class="{local_res.css.regattaheader_logo}">
<img src="<!-- regatta.image -->" />
</div>
<div class="{local_res.css.regattaheader_content}">
<div class="{local_res.css.regattaheader_content_title}">
<!-- regatta.name -->
<!-- IF regatta.isLive -->
<div data-labeltype="live" class="{res.mainCss.label}">
<ui:text from='{i18n.playModeLive}' />
</div>
<!-- IFEND regatta.isLive -->
<!-- IF regatta.isFinished -->
<div data-labeltype="finished" class="{res.mainCss.label}">
<ui:text from='{i18n.raceIsFinished}' />
</div>
<!-- IFEND regatta.isFinished -->
<!-- IF regatta.isProgress -->
<div data-labeltype="progress" class="{res.mainCss.label}">
<ui:text from='{i18n.isProgress}' />
</div>
<!-- IFEND regatta.isProgress -->
<!-- IF regatta.isUpcoming -->
<div data-labeltype="upcoming" class="{res.mainCss.label}">
<ui:text from='{i18n.isUpcoming}' />
</div>
<!-- IFEND regatta.isUpcoming -->
</div>
<div class="{local_res.css.regattaheader_content_details}">
<div class="{local_res.css.regattaheader_content_details_item}">
<!-- regatta.competitorsCount -->
<ui:text from='{i18n.competitors}' />
</div>
<div class="{local_res.css.regattaheader_content_details_item}">
<!-- regatta.racesCount -->
<ui:text from='{i18n.regattaHeaderRacesCount}' />
</div>
<div class="{local_res.css.regattaheader_content_details_item}">
<!-- regatta.trackedCount -->
<ui:text from='{i18n.tracked}' />
</div>
<div class="{local_res.css.regattaheader_content_details_item}">
<!-- regatta.category -->
</div>
</div>
</div>
</g:HTMLPanel>
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.partials.regattaHeader.RegattaHeaderResources" />
<div>
<div class="{local_res.css.regattaheader_logo}" ui:field="logoUi"></div>
<div class="{local_res.css.regattaheader_content}">
<div class="{local_res.css.regattaheader_content_title}">
<span ui:field="nameUi"></span>
<div class="{res.mainCss.label}" ui:field="labelUi"></div>
</div>
<div class="{local_res.css.regattaheader_content_details}" ui:field="detailsItemContainerUi">
<!-- <div class="{local_res.css.regattaheader_content_details_item}"></div> -->
</div>
</div>
<!-- IF content.isLive <div class="{local_res.css.regattaheader_update}">
<div class="{local_res.css.regattaheader_update_title}"> <img src="images/home/reload-green.png"
class="{local_res.css.regattaheader_update_title_icon}"></img> <ui:text from='{i18n.lastUpdate}'
/> </div> <div class="{local_res.css.regattaheader_update_timestamp}"></div>
</div> IFEND content.isLive -->
</div>
</ui:UiBinder>
@@ -7,17 +7,24 @@ import com.google.gwt.resources.client.CssResource;
public interface RegattaHeaderResources extends ClientBundle {
public static final RegattaHeaderResources INSTANCE = GWT.create(RegattaHeaderResources.class);
@Source("RegattaHeader.css")
@Source("RegattaHeader.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String regattaheader();
String regattaheaderlink();
String regattaheaderpadding();
String regattaheader_logo();
String regattaheader_content();
String regattaheader_content_title();
String regattaheader_content_details();
String regattaheader_content_details_item();
String regattaheader_toggle();
String regattaheader_toggle_icon();
String standings_listhidden();
String regattaheader_arrow();
String regattaheader_update();
String regattaheader_update_title();
String regattaheader_update_title_icon();
String regattaheader_update_timestamp();
}
}
@@ -48,7 +48,7 @@ public class RegattaOverviewTabView extends Composite implements RegattaTabView<
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
stage.setupRefresh(refreshManager);
refreshManager.add(racesListLive, new GetLiveRacesForRegattaAction(currentPresenter.getCtx().getEventDTO()
refreshManager.add(racesListLive.getRefreshable(), new GetLiveRacesForRegattaAction(currentPresenter.getCtx().getEventDTO()
.getId(), currentPresenter.getCtx().getRegattaId()));
contentArea.setWidget(this);
@@ -1,23 +1,50 @@
package com.sap.sailing.gwt.home.client.place.event.regatta.tabs;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.ListNavigationPanel;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.ListNavigationPanel.ListNavigationAction;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.ListNavigationPanel.SelectionCallback;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.RaceStateLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListItem;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListStepsLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLive;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.AbstractRaceList;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListColumnFactory;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListContainer;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.RaceListDataUtil;
import com.sap.sailing.gwt.home.client.place.event.partials.racelist.SortableRaceListColumn;
import com.sap.sailing.gwt.home.client.place.event.partials.regattaraces.EventRegattaRaces;
import com.sap.sailing.gwt.home.client.place.event.regatta.EventRegattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.regatta.RegattaTabView;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshManager;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetFinishedRacesAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForRegattaAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaWithProgressAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
import com.sap.sse.common.Util.Triple;
/**
@@ -25,6 +52,31 @@ import com.sap.sse.common.Util.Triple;
*/
public class RegattaRacesTabView extends Composite implements RegattaTabView<RegattaRacesPlace> {
private static final StringMessages I18N = StringMessages.INSTANCE;
private enum Navigation implements ListNavigationAction {
SORT_LIST_FORMAT("Sortable list Format TODO", false),
COMPETITION_FORMAT("Competition Format TODO", true);
private final String displayName;
private final boolean showAdditionalWidget;
private Navigation(String displayName, boolean showAdditionalWidget) {
this.displayName = displayName;
this.showAdditionalWidget = showAdditionalWidget;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public boolean isShowAdditionalWidget() {
return showAdditionalWidget;
}
}
interface MyBinder extends UiBinder<HTMLPanel, RegattaRacesTabView> {
}
@@ -32,17 +84,28 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView<Reg
private Presenter currentPresenter;
@UiField(provided = true)
protected EventRegattaRaces regattaRaces;
@UiField MultiRegattaListStepsLegend regattaProgressLegendUi;
@UiField SimplePanel regattaInfoContainerUi;
@UiField(provided = true) ListNavigationPanel<Navigation> listNavigationPanelUi;
@UiField FlowPanel listFormatContainerUi;
@UiField FlowPanel compFormatContainerUi;
@UiField SimplePanel oldContentContainer;
private RacesListLive liveRacesList;
private RaceListContainer<RaceListRaceDTO> raceListContainer;
public RegattaRacesTabView() {
listNavigationPanelUi = new ListNavigationPanel<Navigation>(new RegattaRacesTabViewNavigationSelectionCallback());
listNavigationPanelUi.setAdditionalWidget(new RaceStateLegend());
initWidget(ourUiBinder.createAndBindUi(RegattaRacesTabView.this));
}
@Override
public void setPresenter(Presenter currentPresenter) {
this.currentPresenter = currentPresenter;
listFormatContainerUi.add(liveRacesList = new RacesListLive(currentPresenter, false));
raceListContainer = new RaceListContainer<>(I18N.finishedRaces(), I18N.noFinishedRaces(), new RaceListFinishedRaces(currentPresenter));
listFormatContainerUi.add(raceListContainer);
}
@Override
@@ -52,52 +115,56 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView<Reg
@Override
public void start(RegattaRacesPlace myPlace, final AcceptsOneWidget contentArea) {
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
if (ExperimentalFeatures.SHOW_NEW_RACES_LIST) {
listNavigationPanelUi.removeFromParent(); // TODO temporary removed
// listNavigationPanelUi.addAction(Navigation.SORT_LIST_FORMAT, true);
// listNavigationPanelUi.addAction(Navigation.COMPETITION_FORMAT, false);
// TODO: understand, and than move this into appropiate place (probably context)
final String selectedRegattaId = myPlace.getCtx().getRegattaId();
refreshManager.add(liveRacesList.getRefreshable(), new GetLiveRacesForRegattaAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
refreshManager.add(new RefreshableWidget<RegattaWithProgressDTO>() {
@Override
public void setData(RegattaWithProgressDTO data, long nextUpdate, int updateNo) {
regattaInfoContainerUi.setWidget(new MultiRegattaListItem(data));
}
}, new GetRegattaWithProgressAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
refreshManager.add(raceListContainer, new GetFinishedRacesAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId()));
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> regattaStructure = getRegattaStructure();
Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO> selectedRegatta = regattaStructure
.get(selectedRegattaId);
regattaRaces = new EventRegattaRaces(currentPresenter);
regattaRaces.setRaces(selectedRegatta.getC(), false, selectedRegatta.getB(),
selectedRegatta.getA());
// if (eventDTO.isRunning()) {
// // create update time for race states only for running events
// serverUpdateTimer.addTimeListener(new TimeListener() {
// @Override
// public void timeChanged(Date newTime, Date oldTime) {
// loadAndUpdateEventRaceStatesLog();
// }
// });
// }
initWidget(ourUiBinder.createAndBindUi(RegattaRacesTabView.this));
contentArea.setWidget(RegattaRacesTabView.this);
} else {
// createEventWithoutRegattasView(event, panel);
}
oldContentContainer.removeFromParent();
} else {
regattaProgressLegendUi.removeFromParent();
regattaInfoContainerUi.removeFromParent();
listFormatContainerUi.removeFromParent();
compFormatContainerUi.removeFromParent();
// TODO: understand, and than move this into appropiate place (probably context)
final String selectedRegattaId = myPlace.getCtx().getRegattaId();
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> rs = getRegattaStructure();
Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO> selectedRegatta = rs .get(selectedRegattaId);
EventRegattaRaces regattaRaces = new EventRegattaRaces(currentPresenter);
oldContentContainer.setWidget(regattaRaces);
regattaRaces.setRaces(selectedRegatta.getC(), false, selectedRegatta.getB(), selectedRegatta.getA());
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
contentArea.setWidget(RegattaRacesTabView.this);
}
@Override
public void stop() {
}
@Override
@@ -127,4 +194,62 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView<Reg
return result;
}
private class RegattaRacesTabViewNavigationSelectionCallback implements SelectionCallback<Navigation> {
@Override
public void onSelectAction(Navigation action) {
showWidget(listFormatContainerUi, action == Navigation.SORT_LIST_FORMAT);
showWidget(compFormatContainerUi, action == Navigation.COMPETITION_FORMAT);
}
private void showWidget(Widget widget, boolean show) {
widget.getElement().getStyle().setDisplay(show ? Display.BLOCK : Display.NONE);
}
}
private class RaceListFinishedRaces extends AbstractRaceList<RaceListRaceDTO> {
private final SortableRaceListColumn<RaceListRaceDTO, ?> durationColumn = RaceListColumnFactory.getDurationColumn();
private final SortableRaceListColumn<RaceListRaceDTO, ?> windSpeedColumn = RaceListColumnFactory.getWindRangeColumn();
private final SortableRaceListColumn<RaceListRaceDTO, ?> windSourcesCountColumn = RaceListColumnFactory.getWindSourcesCountColumn();
private final SortableRaceListColumn<RaceListRaceDTO, ?> videoCountColumn = RaceListColumnFactory.getVideoCountColumn();
private final SortableRaceListColumn<RaceListRaceDTO, ?> audioCountColumn = RaceListColumnFactory.getAudioCountColumn();
private final SortableRaceListColumn<RaceListRaceDTO, ?> winnerColumn = RaceListColumnFactory.getWinnerColumn();
public RaceListFinishedRaces(EventView.Presenter presenter) {
super(presenter);
}
@Override
protected void setTableData(Collection<RaceListRaceDTO> data) {
boolean hasFleets = RaceListDataUtil.hasFleets(data);
this.fleetCornerColumn.setShowDetails(hasFleets);
this.fleetNameColumn.setShowDetails(hasFleets);
this.startTimeColumn.setShowTimeOnly(!RaceListDataUtil.hasDifferentStartDates(data));
this.durationColumn.setShowDetails(RaceListDataUtil.hasDurations(data));
boolean hasWind = RaceListDataUtil.hasWind(data);
this.windSpeedColumn.setShowDetails(hasWind);
this.windDirectionColumn.setShowDetails(hasWind);
this.windSourcesCountColumn.setShowDetails(RaceListDataUtil.hasWindSources(data));
this.videoCountColumn.setShowDetails(RaceListDataUtil.hasVideos(data));
this.audioCountColumn.setShowDetails(RaceListDataUtil.hasAudios(data));
this.winnerColumn.setShowDetails(RaceListDataUtil.hasWinner(data));
super.setTableData(data);
}
@Override
protected void initTableColumns() {
add(fleetCornerColumn);
add(raceNameColumn);
add(fleetNameColumn);
add(startTimeColumn);
add(durationColumn);
add(windSpeedColumn);
add(windDirectionColumn);
add(windSourcesCountColumn);
add(videoCountColumn);
add(audioCountColumn);
add(winnerColumn);
add(raceViewerButtonColumn);
}
}
}
@@ -1,8 +1,26 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:p='urn:import:com.sap.sailing.gwt.home.client.place.event.partials'
>
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:p='urn:import:com.sap.sailing.gwt.home.client.place.event.partials'>
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
.listContainer > div {
margin-bottom: 2em;
}
.legend {
margin-top: 2em;
margin-bottom: -1.5em;
}
</ui:style>
<g:HTMLPanel ui:field="contentPanel">
<p:regattaraces.EventRegattaRaces ui:field="regattaRaces"/>
<div class="{res.mediaCss.grid}">
<p:multiRegattaList.MultiRegattaListStepsLegend addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns} {style.legend}" ui:field="regattaProgressLegendUi" />
<g:SimplePanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}" ui:field="regattaInfoContainerUi"/>
</div>
<p:listNavigation.ListNavigationPanel ui:field="listNavigationPanelUi"/>
<div class="{res.mediaCss.grid}">
<g:FlowPanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns} {style.listContainer}" ui:field="listFormatContainerUi" />
<g:FlowPanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns}" ui:field="compFormatContainerUi" />
</div>
<g:SimplePanel ui:field="oldContentContainer"/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -114,13 +114,13 @@ public class RefreshManager {
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public <D extends DTO, A extends Action<ResultWithTTL<D>>> void add(RefreshableWidget<D> widget,
public <D extends DTO, A extends Action<ResultWithTTL<D>>> void add(RefreshableWidget<? super D> widget,
ActionProvider<A> provider) {
refreshables.add(new RefreshHolder(widget, provider));
reschedule();
}
public <D extends DTO, A extends Action<ResultWithTTL<D>>> void add(RefreshableWidget<D> widget, A action) {
public <D extends DTO, A extends Action<ResultWithTTL<D>>> void add(RefreshableWidget<? super D> widget, A action) {
add(widget, new DefaultActionProvider<>(action));
}
@@ -112,6 +112,11 @@
.regattaleaderboard_meta_reload:hover {
background-color: #909090;
}
.regattaleaderboard_meta_reload_live:hover {
background-color: #ffa4a4;
}
.regattaleaderboard_meta_settings {
display: inline-block;
text-align: right;
@@ -47,7 +47,7 @@ public class EventHeader extends Composite {
}
LabelTypeUtil.renderLabelType(eventStateUi, event.getState().getStateMarker());
LogoUtil.setEventLogo(eventLogoUi, event);
eventDateUi.setInnerText(EventDatesFormatterUtil.formatDateRangeWithoutYear(event.getStartDate(), event.getEndDate()));
eventDateUi.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(event.getStartDate(), event.getEndDate()));
eventLocationUi.setInnerText(event.getLocationAndVenueAndCountry());
}
}
@@ -1,13 +1,15 @@
.sitefooter {
font-size: 0.8rem;
background: #333;
padding: 2.5em;
margin-top: -13.916666666666666em;
padding: 5em 3em;
margin-top: -10em;
color: #fff;
text-align: center;
font-size: 110%;
}
.sitefooter a {
color: #fff;
line-height: 2;
padding: 5px;
}
.sitefooter_language {
display: block;
@@ -20,5 +22,5 @@ a.sitefooter_language_linkactive {
}
.sitefooter_links {
font-weight: 600;
padding: 2.083333333333333em 0;
padding: 3em 0;
}
@@ -32,7 +32,7 @@
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgaGVpZ2h0PScxOHB4JyB3aWR0aD0nMTZweCc+PHRleHQgeD0nMCcgeT0nMTUnIGZpbGw9JyNlZmFhMDAnIGZvbnQtc2l6ZT0nMTYnPiYjOTY2MDs8L3RleHQ+PC9zdmc+");
background-position: right center;
background-repeat: no-repeat;
font-size: 0.8rem;
font-size: 110%;
}
</ui:style>
<g:HTMLPanel>
@@ -58,8 +58,8 @@
<a href="http://www.sap.com/about/legal/impressum.html"
title="{i18n.footerLegal}">
<ui:text from='{i18n.footerLegal}' />
|
</a>
|
<a href="http://www.sap.com/about/legal/privacy.html"
title="{i18n.footerPrivacy}">
<ui:text from='{i18n.footerPrivacy}' />
@@ -69,14 +69,14 @@
href="mailto:sailing_analytics%40sap.com?subject=[SAP Sailing] Feedback"
title="{i18n.footerFeedback}">
<ui:text from='{i18n.footerFeedback}' />
|
</a>
|
<a ui:field="desktopUi"
href="HomeDesktop.html"
title="Desktop">
Desktop
|
</a>
|
<g:Anchor
title="{i18n.whatsNew}"
@@ -26,11 +26,14 @@ public class MinileaderboardBox extends Composite implements RefreshableWidget<G
interface MyUiBinder extends UiBinder<Widget, MinileaderboardBox> {
}
private final StringMessages I18N = StringMessages.INSTANCE;
@UiField MobileSection itemContainerUi;
@UiField SectionHeaderContent headerUi;
public MinileaderboardBox() {
public MinileaderboardBox(boolean isOverall) {
initWidget(uiBinder.createAndBindUi(this));
headerUi.setSectionTitle(isOverall ? I18N.overallStandings() : I18N.results());
headerUi.setInfoText(StringMessages.INSTANCE.details());
@@ -9,7 +9,7 @@
<mp:section.MobileSection ui:field="itemContainerUi" edgeToEdgeContent="true">
<mp:header>
<mp:sectionHeader.SectionHeaderContent sectionTitle="{i18n.resultsStandings}" ui:field="headerUi" />
<mp:sectionHeader.SectionHeaderContent sectionTitle="{i18n.results}" ui:field="headerUi" />
</mp:header>
</mp:section.MobileSection>
@@ -34,8 +34,6 @@
margin: -1em 1em -1em 0;
background-size: contain;
background-position: center;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.sectionheader_item_image_seperator {
position: absolute;
@@ -81,7 +81,7 @@ public class EventViewImpl extends Composite implements EventView {
listContentUi.add(regattaStatus);
refreshManager.add(regattaStatus, new GetRegattasAndLiveRacesForEventAction(event.getId()));
} else {
MinileaderboardBox miniLeaderboard = new MinileaderboardBox();
MinileaderboardBox miniLeaderboard = new MinileaderboardBox(false);
miniLeaderboard.setAction(MSG.showAll(), currentPresenter.getRegattaMiniLeaderboardNavigation(regattaId));
listContentUi.add(miniLeaderboard);
refreshManager.add(miniLeaderboard, new GetMiniLeaderbordAction(event.getId(), regattaId, 3));
@@ -30,7 +30,7 @@ public class MiniLeaderboardViewImpl extends Composite implements MiniLeaderboar
private Presenter currentPresenter;
@UiField(provided = true)
EventHeader eventHeaderUi;
@UiField
@UiField(provided = true)
MinileaderboardBox minileaderboardUi;
@UiField
Quickfinder quickFinderUi;
@@ -41,6 +41,7 @@ public class MiniLeaderboardViewImpl extends Composite implements MiniLeaderboar
if(presenter.getCtx().getEventDTO().getType() == EventType.MULTI_REGATTA) {
regattaDisplayName = presenter.getCtx().getRegatta().getDisplayName();
}
minileaderboardUi = new MinileaderboardBox(false);
eventHeaderUi = new EventHeader(presenter.getCtx().getEventDTO(), regattaDisplayName);
initWidget(uiBinder.createAndBindUi(this));
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
@@ -29,7 +29,7 @@ public class SeriesViewImpl extends Composite implements SeriesView {
@UiField(provided = true) SeriesHeader eventHeaderUi;
@UiField Quickfinder quickFinderUi;
@UiField MinileaderboardBox leaderboardUi;
@UiField(provided = true) MinileaderboardBox leaderboardUi;
@UiField FlowPanel eventsUi;
// @UiField(provided = true) StatisticsBox statisticsBoxUi;
@@ -42,6 +42,7 @@ public class SeriesViewImpl extends Composite implements SeriesView {
EventSeriesViewDTO series = currentPresenter.getCtx().getSeriesDTO();
eventHeaderUi = new SeriesHeader(series);
// this.setupStatisticsBox(event);
leaderboardUi = new MinileaderboardBox(true);
initWidget(uiBinder.createAndBindUi(this));
this.setupListContent(series);
this.setupEventListContent(series);
@@ -29,11 +29,12 @@ public class SeriesMiniOverallLeaderboardViewImpl extends Composite implements S
@UiField(provided = true)
SeriesHeader eventHeaderUi;
@UiField Quickfinder quickFinderUi;
@UiField
@UiField(provided = true)
MinileaderboardBox minileaderboardUi;
public SeriesMiniOverallLeaderboardViewImpl(Presenter presenter) {
this.currentPresenter = presenter;
minileaderboardUi = new MinileaderboardBox(true);
eventHeaderUi = new SeriesHeader(presenter.getCtx().getSeriesDTO());
initWidget(uiBinder.createAndBindUi(this));
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
@@ -0,0 +1,18 @@
package com.sap.sailing.gwt.home.shared;
/**
* This class contains convenience boolean flags to enable/ disable features in experimental phase.
*/
public class ExperimentalFeatures {
/**
* Show new races list
*/
public static final boolean SHOW_NEW_RACES_LIST = true;
/**
* Show new regatta list
*/
public static final boolean SHOW_NEW_REGATTA_LIST = true;
}
@@ -152,7 +152,7 @@ public class SwitchingEntryPoint implements EntryPoint {
}
private void configureDesktopHeader() {
metaElement("viewport", "width=device-width,initial-scale=0.5,maximum-scale=1");
metaElement("viewport", "width=device-width,initial-scale=0.5,maximum-scale=2");
}
private void configureMobileHeader() {
@@ -28,6 +28,7 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
private final static String PARAM_ONLY_RACES_OF_SAME_DAY = "onlyracesofsameday";
private final static String PARAM_REGATTA = "regatta";
private final static String PARAM_COURSE_AREA = "coursearea";
private final static String PARAM_IGNORE_LOCAL_SETTINGS = "ignoreLocalSettings";
private DockLayoutPanel containerPanel;
private RaceDetailPanel detailPanel;
@@ -96,7 +97,8 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
private void createAndAddRegattaPanel(UUID eventId) {
RegattaRaceStatesSettings settings = createRegattaRaceStatesSettingsFromURL();
regattaPanel = new RegattaOverviewPanel(sailingService, this, getStringMessages(), eventId, settings, userAgent);
boolean ignoreLocalSettings = getIgnoreLocalSettingsFromURL();
regattaPanel = new RegattaOverviewPanel(sailingService, this, getStringMessages(), eventId, settings, userAgent, ignoreLocalSettings);
regattaPanel.addHandler(new EventDTOLoadedEvent.Handler() {
@Override
@@ -120,6 +122,10 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
containerPanel.add(scrollPanel);
}
private boolean getIgnoreLocalSettingsFromURL() {
return Boolean.parseBoolean(Window.Location.getParameter(PARAM_IGNORE_LOCAL_SETTINGS));
}
private void createAndAddDetailPanel() {
detailPanel = new RaceDetailPanel(getStringMessages(), new ClickHandler() {
@Override
@@ -81,7 +81,8 @@ public class RegattaOverviewPanel extends SimplePanel {
final StringMessages stringMessages,
UUID eventId,
RegattaRaceStatesSettings settings,
UserAgentDetails userAgent) {
UserAgentDetails userAgent,
boolean ignoreLocalSettings) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
@@ -102,7 +103,7 @@ public class RegattaOverviewPanel extends SimplePanel {
mainPanel.setWidth("100%");
mainPanel.addStyleName(style.contentWrapper());
regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventId, settings, uiUpdateTimer);
regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventId, settings, uiUpdateTimer, ignoreLocalSettings);
this.eventRaceGroupListeners.add(regattaRaceStatesComponent);
regattaRaceStatesComponent.setWidth("100%");
@@ -125,6 +125,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
private CellTable<RegattaOverviewEntryDTO> table;
boolean hasAnyRaceGroupASeries = false;
boolean hasAnyRaceGroupAFleet = false;
private final boolean ignoreLocalSettings;
public void setEntryClickedHandler(EntryHandler handler) {
this.entryClickedHandler = handler;
@@ -137,7 +138,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
*/
public RegattaRaceStatesComponent(final SailingServiceAsync sailingService, ErrorReporter errorReporter,
final StringMessages stringMessages, final UUID eventId, RegattaRaceStatesSettings settings,
Timer timerToSynchronize) {
Timer timerToSynchronize, boolean ignoreLocalSettings) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
this.eventId = eventId;
@@ -148,6 +149,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
this.localStorageRegattaOverviewEventKey = LOCAL_STORAGE_REGATTA_OVERVIEW_KEY + eventId.toString();
this.flagInterpreter = new RaceStateFlagsInterpreter(stringMessages);
this.settings = new RegattaRaceStatesSettings();
this.ignoreLocalSettings = ignoreLocalSettings;
loadAndSetSettings(settings);
mainPanel = new VerticalPanel();
mainPanel.getElement().getStyle().setWidth(100, Unit.PCT);
@@ -160,9 +162,11 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
}
private void loadAndSetSettings(RegattaRaceStatesSettings settings) {
RegattaRaceStatesSettings loadedSettings = loadRegattaRaceStatesSettings();
if (loadedSettings != null) {
settings = loadedSettings;
if(!ignoreLocalSettings) {
RegattaRaceStatesSettings loadedSettings = loadRegattaRaceStatesSettings();
if (loadedSettings != null) {
settings = loadedSettings;
}
}
updateSettings(settings);
}
@@ -897,11 +901,8 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
return null;
}
private String createRegattaLink(RegattaOverviewEntryDTO entryDTO) {
Map<String, String> leaderboardLinkParameters = new HashMap<String, String>();
leaderboardLinkParameters.put("name", entryDTO.regattaName);
leaderboardLinkParameters.put("showRaceDetails", String.valueOf(true));
leaderboardLinkParameters.put("displayName", entryDTO.regattaDisplayName);
String leaderboardLink = EntryPointLinkFactory.createLeaderboardLink(leaderboardLinkParameters);
Map<String, String> leaderboardLinkParameters = Collections.emptyMap();
String leaderboardLink = EntryPointLinkFactory.createLeaderboardTabLink(eventId.toString(), entryDTO.regattaName, leaderboardLinkParameters);
return leaderboardLink;
}
public void setRepeatedInfoLabel(FlowPanel repeatedInfoLabel) {
@@ -22,6 +22,7 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
@@ -37,8 +38,10 @@ import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO;
import com.sap.sailing.gwt.ui.shared.start.EventStageDTO;
import com.sap.sailing.gwt.ui.shared.start.StageEventType;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.ImageDescriptor;
import com.sap.sse.common.media.MediaDescriptor;
import com.sap.sse.common.media.MediaTagConstants;
@@ -429,18 +432,20 @@ public final class HomeServiceUtil {
return result;
}
public static RegattaMetadataDTO toRegattaMetadataDTO(LeaderboardGroup leaderboardGroup, Leaderboard leaderboard) {
public static RegattaMetadataDTO toRegattaMetadataDTO(EventBase event, LeaderboardGroup leaderboardGroup, Leaderboard leaderboard) {
RegattaMetadataDTO regattaDTO = new RegattaMetadataDTO();
fillRegattaFields(leaderboardGroup, leaderboard, regattaDTO);
fillRegattaFields(event, leaderboardGroup, leaderboard, regattaDTO);
return regattaDTO;
}
public static void fillRegattaFields(LeaderboardGroup leaderboardGroup, Leaderboard leaderboard,
public static void fillRegattaFields(EventBase event, LeaderboardGroup leaderboardGroup, Leaderboard leaderboard,
RegattaMetadataDTO regattaDTO) {
regattaDTO.setId(leaderboard.getName());
regattaDTO.setDisplayName(leaderboard.getDisplayName() != null ? leaderboard.getDisplayName() : leaderboard.getName());
regattaDTO.setBoatCategory(leaderboardGroup.getDisplayName() != null ? leaderboardGroup.getDisplayName() : leaderboardGroup.getName());
if(hasMultipleLeaderboardGroups(event)) {
regattaDTO.setBoatCategory(leaderboardGroup.getDisplayName() != null ? leaderboardGroup.getDisplayName() : leaderboardGroup.getName());
}
regattaDTO.setCompetitorsCount(calculateCompetitorsCount(leaderboard));
regattaDTO.setRaceCount(calculateRaceCount(leaderboard));
regattaDTO.setTrackedRacesCount(calculateTrackedRaceCount(leaderboard));
@@ -451,6 +456,11 @@ public final class HomeServiceUtil {
regattaDTO.setEndDate(regatta.getEndDate() != null ? regatta.getEndDate().asDate() : null);
}
regattaDTO.setState(calculateRegattaState(regattaDTO));
regattaDTO.setDefaultCourseAreaName(getCourseAreaNameForRegattaIdThereIsMoreThanOne(event, leaderboard));
}
private static boolean hasMultipleLeaderboardGroups(EventBase event) {
return Util.size(event.getLeaderboardGroups()) > 1;
}
public static boolean hasLiveRace(LeaderboardDTO leaderboard) {
@@ -458,9 +468,30 @@ public final class HomeServiceUtil {
return !liveRaces.isEmpty();
}
public static TimePoint getLiveTimePoint() {
return new MillisecondsTimePoint(getLiveTimePointInMillis());
}
private static long getLiveTimePointInMillis() {
// TODO better solution
long livePlayDelayInMillis = 15_000;
return System.currentTimeMillis() - livePlayDelayInMillis;
}
public static String getCourseAreaNameForRegattaIdThereIsMoreThanOne(EventBase event, Leaderboard leaderboard) {
/** The course area will not be shown if there is only one course area defined for the event */
if (Util.size(event.getVenue().getCourseAreas()) <= 1) {
return null;
}
CourseArea courseArea = null;
if (leaderboard instanceof FlexibleLeaderboard) {
courseArea = ((FlexibleLeaderboard) leaderboard).getDefaultCourseArea();
} else if(leaderboard instanceof RegattaLeaderboard) {
Regatta regatta = ((RegattaLeaderboard) leaderboard).getRegatta();
if (regatta != null) {
courseArea = regatta.getDefaultCourseArea();
}
}
return courseArea == null ? null : courseArea.getName();
}
}
@@ -9,7 +9,7 @@
<inherits name='com.google.gwt.debug.Debug'/>
<!-- Highcharts API -->
<inherits name='com.sap.sse.gwt.Highcharts_Autoinject' />
<inherits name='com.sap.sse.gwt.Highcharts' />
<!-- Google Maps API -->
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
Loaded 100 of 181 files, more files were not shown because too many files have changed in this diff. Show more