diff --git a/TODO b/TODO index 216f0cc6ff4..c8eb7c60db1 100755 --- a/TODO +++ b/TODO @@ -4,8 +4,6 @@ Axel - Refresh button in leaderboard panel doesn't properly add expand/collapse buttons for race columns which since the last refresh obtained their expansion enablement - - Separate column for competitor name, next to flag+sailID - - Finish a first draft version of a GWT admin and leaderboard UI * implement a smart incremental update capability for leaderboard diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java index ddb85b29122..0fc3d67694d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java @@ -59,7 +59,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel { public EditableRaceColumn(String raceName, boolean medalRace, List> cellList) { super(raceName, medalRace, /* expandable */ false, // we don't want leg expansion when editing scores - new CompositeCell(new ArrayList>(cellList)), RACE_COLUMN_HEADER_STYLE); + new CompositeCell(new ArrayList>(cellList)), + RACE_COLUMN_HEADER_STYLE, RACE_COLUMN_STYLE); for (RowUpdateWhiteboardProducer rowUpdateWhiteboardProducer : cellList) { rowUpdateWhiteboardProducer.setWhiteboardOwner(this); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/FormattedDoubleLegDetailColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/FormattedDoubleLegDetailColumn.java index bd572bf693d..022d7bfa016 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/FormattedDoubleLegDetailColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/FormattedDoubleLegDetailColumn.java @@ -12,8 +12,8 @@ public class FormattedDoubleLegDetailColumn extends LegDetailColumn field, - int decimals, CellTable leaderboardTable, String headerStyle) { - super(title, field, new TextCell(), leaderboardTable, headerStyle); + int decimals, CellTable leaderboardTable, String headerStyle, String columnStyle) { + super(title, field, new TextCell(), leaderboardTable, headerStyle, columnStyle); StringBuilder patternBuilder = new StringBuilder("0"); if (decimals > 0) { patternBuilder.append('.'); @@ -39,7 +39,7 @@ public class FormattedDoubleLegDetailColumn extends LegDetailColumn"). + percent+"% 25px; \">"). appendEscaped(getValue(row)).appendHtmlConstant(""); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java index 89d659bb143..03732db2717 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java @@ -81,9 +81,15 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro protected final String RACE_COLUMN_HEADER_STYLE; protected final String LEG_DETAIL_COLUMN_HEADER_STYLE; + + protected final String LEG_DETAIL_COLUMN_STYLE; protected final String LEG_COLUMN_HEADER_STYLE; + protected final String RACE_COLUMN_STYLE; + + protected final String LEG_COLUMN_STYLE; + private class SettingsClickHandler implements ClickHandler { private final StringConstants stringConstants; @@ -135,6 +141,21 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro */ String cellTableLegDetailColumnHeader(); + /** + * Applied to detail columns + */ + String cellTableLegDetailColumn(); + + /** + * Applied to race columns + */ + String cellTableRaceColumn(); + + /** + * Applied to leg columns + */ + String cellTableLegColumn(); + } @Override @Source ({CellTable.Style.DEFAULT_CSS, "LeaderboardTable.css"}) @@ -227,19 +248,26 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro private final String raceName; private final boolean medalRace; private final String headerStyle; + private final String columnStyle; - public RaceColumn(String raceName, boolean medalRace, boolean enableExpansion, Cell cell, String headerStyle) { + public RaceColumn(String raceName, boolean medalRace, boolean enableExpansion, Cell cell, String headerStyle, String columnStyle) { super(LeaderboardPanel.this, enableExpansion, cell); setHorizontalAlignment(ALIGN_CENTER); this.raceName = raceName; this.medalRace = medalRace; this.headerStyle = headerStyle; + this.columnStyle = columnStyle; } public String getRaceName() { return raceName; } + @Override + public String getColumnStyle() { + return columnStyle; + } + @Override public void render(Context context, LeaderboardRowDAO object, SafeHtmlBuilder html) { LeaderboardEntryDAO entry = object.fieldsByRaceName.get(raceName); @@ -294,8 +322,8 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro } private class TextRaceColumn extends RaceColumn { - public TextRaceColumn(String raceName, boolean medalRace, boolean expandable, String headerStyle) { - super(raceName, medalRace, expandable, new TextCell(), headerStyle); + public TextRaceColumn(String raceName, boolean medalRace, boolean expandable, String headerStyle, String columnStyle) { + super(raceName, medalRace, expandable, new TextCell(), headerStyle, columnStyle); } @Override @@ -331,7 +359,7 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro List> result = new ArrayList>(); for (int i=0; i(/* pageSize */ 100, resources); getLeaderboardTable().setWidth("100%"); getLeaderboardTable().setSelectionModel(new MultiSelectionModel() {}); @@ -505,11 +536,19 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro protected void addColumn(SortableColumn column) { getLeaderboardTable().addColumn(column, column.getHeader()); listHandler.setComparator(column, column.getComparator()); + String columnStyle = column.getColumnStyle(); + if (columnStyle != null) { + getLeaderboardTable().addColumnStyleName(getLeaderboardTable().getColumnCount()-1, columnStyle); + } } protected void insertColumn(int beforeIndex, SortableColumn column) { getLeaderboardTable().insertColumn(beforeIndex, column, column.getHeader()); listHandler.setComparator(column, column.getComparator()); + String columnStyle = column.getColumnStyle(); + if (columnStyle != null) { + getLeaderboardTable().addColumnStyleName(beforeIndex, columnStyle); + } } private void loadCompleteLeaderboard(Date date) { @@ -603,18 +642,25 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro // first remove race columns no longer needed: removeUnusedRaceColumns(leaderboard); if (leaderboard != null) { - createMissingRaceColumns(leaderboard); + createMissingAndAdjustExistingRaceColumns(leaderboard); ensureTotalsColumn(); } } - private void createMissingRaceColumns(LeaderboardDAO leaderboard) { + /** + * Existing and matching race columns may still need to be removed, re-created and inserted because the + * "tracked" property may have changed, changing the columns expandability. + */ + private void createMissingAndAdjustExistingRaceColumns(LeaderboardDAO leaderboard) { for (Map.Entry> raceNameAndMedalRaceAndTracked : leaderboard.raceNamesAndMedalRaceAndTracked.entrySet()) { boolean foundRaceColumn = false; for (int i=0; !foundRaceColumn && i c = getLeaderboardTable().getColumn(i); - if (c instanceof RaceColumn && ((RaceColumn) c).getRaceName().equals(raceNameAndMedalRaceAndTracked.getKey())) { - foundRaceColumn = true; + if (c instanceof RaceColumn) { + RaceColumn raceColumn = (RaceColumn) c; + if (raceColumn.getRaceName().equals(raceNameAndMedalRaceAndTracked.getKey())) { + foundRaceColumn = true; + } } } if (!foundRaceColumn) { @@ -625,7 +671,7 @@ public class LeaderboardPanel extends FormPanel implements LegDetailSelectionPro protected RaceColumn createRaceColumn(Map.Entry> raceNameAndMedalRaceAndTracked) { return new TextRaceColumn(raceNameAndMedalRaceAndTracked.getKey(), raceNameAndMedalRaceAndTracked.getValue().getA(), - raceNameAndMedalRaceAndTracked.getValue().getB(), RACE_COLUMN_HEADER_STYLE); + raceNameAndMedalRaceAndTracked.getValue().getB(), RACE_COLUMN_HEADER_STYLE, RACE_COLUMN_STYLE); } private void removeUnusedRaceColumns(LeaderboardDAO leaderboard) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardTable.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardTable.css index 250e2b563e0..9b28f703664 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardTable.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardTable.css @@ -48,7 +48,8 @@ .cellTableEvenRow { border-bottom: 1px solid #e5e5e5; - background-color: #FFFFFF; + background-color: none; +/* background-color: #FFFFFF; */ } .cellTableEvenRowCell { @@ -61,7 +62,8 @@ .cellTableOddRow { border-bottom: 1px solid #e5e5e5; - background-color: #f2f2f2; + background-color: none; + /* background-color: #f2f2f2; */ } .cellTableOddRowCell { @@ -113,4 +115,16 @@ .cellTableLegDetailColumnHeader { background-color: #f5f5f5; padding: 3px 12px; -} \ No newline at end of file +} + +.cellTableRaceColumn { + background-color: #ff0000 !important; +} + +.cellTableLegColumn { + background-color: #00ff00 !important; +} + +.cellTableLegDetailColumn { + background-color: #0000ff !important; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegColumn.java index 9be35135d07..6184bfc44bc 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegColumn.java @@ -26,7 +26,9 @@ public class LegColumn extends ExpandableSortableColumn { private final StringConstants stringConstants; private final LegDetailSelectionProvider legDetailSelectionProvider; private final String headerStyle; + private final String columnStyle; private final String detailHeaderStyle; + private final String detailColumnStyle; private abstract class AbstractLegDetailField> implements LegDetailField { public T get(LeaderboardRowDAO row) { @@ -105,7 +107,7 @@ public class LegColumn extends ExpandableSortableColumn { } public LegColumn(LeaderboardPanel leaderboardPanel, String raceName, int legIndex, StringConstants stringConstants, - LegDetailSelectionProvider legDetailSelectionProvider, String headerStyle, String detailHeaderStyle) { + LegDetailSelectionProvider legDetailSelectionProvider, String headerStyle, String columnStyle, String detailHeaderStyle, String detailColumnStyle) { super(leaderboardPanel, /* expandable */ true /* all legs have details */, new TextCell()); setHorizontalAlignment(ALIGN_CENTER); this.raceName = raceName; @@ -113,13 +115,20 @@ public class LegColumn extends ExpandableSortableColumn { this.stringConstants = stringConstants; this.legDetailSelectionProvider = legDetailSelectionProvider; this.headerStyle = headerStyle; + this.columnStyle = columnStyle; this.detailHeaderStyle = detailHeaderStyle; + this.detailColumnStyle = detailColumnStyle; } private int getLegIndex() { return legIndex; } + @Override + public String getColumnStyle() { + return columnStyle; + } + @Override public String getHeaderStyle() { return headerStyle; @@ -181,28 +190,28 @@ public class LegColumn extends ExpandableSortableColumn { for (LegDetailColumnType type : legDetailSelectionProvider.getLegDetailsToShow()) { switch (type) { case DISTANCE_TRAVELED: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.distanceInMeters(), new DistanceTraveledInMeters(), 0, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.distanceInMeters(), new DistanceTraveledInMeters(), 0, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case AVERAGE_SPEED_OVER_GROUND_IN_KNOTS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.averageSpeedInKnots(), new AverageSpeedOverGroundInKnots(), 2, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.averageSpeedInKnots(), new AverageSpeedOverGroundInKnots(), 2, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case RANK_GAIN: - result.add(new RankGainColumn(stringConstants.rankGain(), new RankGain(), getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new RankGainColumn(stringConstants.rankGain(), new RankGain(), getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case CURRENT_SPEED_OVER_GROUND_IN_KNOTS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.currentSpeedOverGroundInKnots(), new CurrentSpeedOverGroundInKnots(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.currentSpeedOverGroundInKnots(), new CurrentSpeedOverGroundInKnots(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case ESTIMATED_TIME_TO_NEXT_WAYPOINT_IN_SECONDS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.estimatedTimeToNextWaypointInSeconds(), new EstimatedTimeToNextWaypointInSeconds(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.estimatedTimeToNextWaypointInSeconds(), new EstimatedTimeToNextWaypointInSeconds(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case GAP_TO_LEADER_IN_SECONDS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.gapToLeaderInSeconds(), new GapToLeaderInSeconds(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.gapToLeaderInSeconds(), new GapToLeaderInSeconds(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case VELOCITY_MADE_GOOD_IN_KNOTS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.velocityMadeGoodInKnots(), new VelocityMadeGoodInKnots(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.velocityMadeGoodInKnots(), new VelocityMadeGoodInKnots(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; case WINDWARD_DISTANCE_TO_GO_IN_METERS: - result.add(new FormattedDoubleLegDetailColumn(stringConstants.windwardDistanceToGoInMeters(), new WindwardDistanceToGoInMeters(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle)); + result.add(new FormattedDoubleLegDetailColumn(stringConstants.windwardDistanceToGoInMeters(), new WindwardDistanceToGoInMeters(), 1, getLeaderboardPanel().getLeaderboardTable(), detailHeaderStyle, detailColumnStyle)); break; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegDetailColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegDetailColumn.java index ba6f45c80df..41ebb07423e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegDetailColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegDetailColumn.java @@ -16,19 +16,21 @@ public abstract class LegDetailColumn, Rendering private FieldType minimum; private FieldType maximum; private final String headerStyle; + private final String columnStyle; public interface LegDetailField> { T get(LeaderboardRowDAO row); } protected LegDetailColumn(String title, LegDetailField field, Cell cell, CellTable leaderboardTable, - String headerStyle) { + String headerStyle, String columnStyle) { super(cell); setHorizontalAlignment(ALIGN_CENTER); this.title = title; this.field = field; this.leaderboardTable = leaderboardTable; this.headerStyle = headerStyle; + this.columnStyle = columnStyle; } protected String getTitle() { @@ -44,6 +46,11 @@ public abstract class LegDetailColumn, Rendering return field; } + @Override + public String getColumnStyle() { + return columnStyle; + } + @Override public Comparator getComparator() { return new Comparator() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RankGainColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RankGainColumn.java index 2a09237d7e9..909f6996769 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RankGainColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RankGainColumn.java @@ -8,8 +8,9 @@ import com.google.gwt.user.cellview.client.CellTable; import com.sap.sailing.gwt.ui.shared.LeaderboardRowDAO; public class RankGainColumn extends LegDetailColumn { - public RankGainColumn(String title, LegDetailField field, CellTable leaderboardTable, String headerStyle) { - super(title, field, new RankGainCell(), leaderboardTable, headerStyle); + public RankGainColumn(String title, LegDetailField field, CellTable leaderboardTable, + String headerStyle, String columnStyle) { + super(title, field, new RankGainCell(), leaderboardTable, headerStyle, columnStyle); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SortableColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SortableColumn.java index 44d672b372e..f1a4732802b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SortableColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SortableColumn.java @@ -40,4 +40,13 @@ public abstract class SortableColumn extends Column { public String getHeaderStyle() { return null; } + + /** + * Allows a column to specify a style/CSS class to use to format the <col> element. + * This default implementation returns null, meaning that no additional style other + * than the GWT-provided default styles will be used. + */ + public String getColumnStyle() { + return null; + } } diff --git a/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.AdminConsole/rpcPolicyManifest/manifest.txt b/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.AdminConsole/rpcPolicyManifest/manifest.txt index a7c70f9012d..7fce3ee6e43 100755 --- a/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.AdminConsole/rpcPolicyManifest/manifest.txt +++ b/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.AdminConsole/rpcPolicyManifest/manifest.txt @@ -1,3 +1,2 @@ # Module com.sap.sailing.gwt.ui.AdminConsole # RPC service class, partial path of RPC policy file -com.sap.sailing.gwt.ui.client.SailingService, B8E9FCF9DD8EE2E8179A1AEA7AB5145A.gwt.rpc diff --git a/java/com.sap.sailing.gwt.ui/war/crossdomain.xml b/java/com.sap.sailing.gwt.ui/war/crossdomain.xml new file mode 100755 index 00000000000..8802ac20b4e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/war/crossdomain.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/xcelsius/RankPerLeg.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/xcelsius/RankPerLeg.java index 99a07850261..32dfb3656a5 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/xcelsius/RankPerLeg.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/xcelsius/RankPerLeg.java @@ -1,6 +1,9 @@ package com.sap.sailing.server.xcelsius; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -55,16 +58,16 @@ public class RankPerLeg extends Action { /* * Get Legs data */ + int i=0; + NumberFormat numberFormat = new DecimalFormat("00"); for (final TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) { final Leg leg = trackedLeg.getLeg(); - final String legId = "" + leg.getFrom().getId(); + final String legId = numberFormat.format(++i); final String markName = leg.getFrom().getName(); final String upOrDownwinLeg = trackedLeg.isUpOrDownwindLeg(time) ? "U" : "D"; - - /* - * Get competitor data - */ - for (final Competitor competitor : race.getCompetitors()) { + LinkedHashMap ranks = trackedLeg.getRanks(time); + // Get competitor data + for (final Competitor competitor : ranks.keySet()) { if (competitorNameSet == null || competitorNameSet.contains(competitor.getName())) { /* * Get data