Merge branch 'bug4614' of ssh://sapsailing.com/home/trac/git into bug4614

This commit is contained in:
Alessandro Stoltenberg
2018-07-04 10:12:32 +02:00
19 changed files with 390 additions and 264 deletions
@@ -12,6 +12,8 @@ import com.google.gwt.user.client.ui.Anchor;
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.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
public class ErrorMessage extends Composite {
@@ -42,7 +44,7 @@ public class ErrorMessage extends Composite {
}
this.errorMessageDetail.setInnerText(errorMessageDetail);
Window.setStatus(errorMessageDetail);
Notification.notify(errorMessageDetail, NotificationType.WARNING);
}
public void addReloadPageButtonStyleNames(String styleNames) {
@@ -4,7 +4,6 @@ import java.util.Date;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
@@ -14,6 +13,8 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
/**
* A panel that has a race selection (inherited from {@link AbstractRaceManagementPanel}) and which adds a table
@@ -41,7 +42,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
@Override
public void onSuccess(Void result) {
Window.setStatus(stringMessages.successfullyUpdatedCourse());
Notification.notify(stringMessages.successfullyUpdatedCourse(), NotificationType.INFO);
refreshSelectedRaceData();
}
});
@@ -15,7 +15,6 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
@@ -30,6 +29,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
import com.sap.sailing.gwt.ui.shared.RemoteSailingServerReferenceDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
@@ -209,7 +210,7 @@ public class RemoteServerInstancesManagementPanel extends SimplePanel {
@Override
public void onSuccess(Void result) {
refreshSailingServerList();
Window.setStatus(stringMessages.successfullyUpdatedSailingServers());
Notification.notify(stringMessages.successfullyUpdatedSailingServers(), NotificationType.INFO);
}
});
}
@@ -230,8 +231,8 @@ public class RemoteServerInstancesManagementPanel extends SimplePanel {
@Override
public void onSuccess(RemoteSailingServerReferenceDTO result) {
filteredServerTablePanel.add(result);
Window.setStatus(stringMessages.successfullyUpdatedSailingServers());
filteredServerTablePanel.add(result);
Notification.notify(stringMessages.successfullyUpdatedSailingServers(), NotificationType.INFO);
}
});
}
@@ -8,7 +8,6 @@ import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
@@ -22,6 +21,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.TextfieldEntryDialog;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
@@ -163,7 +164,7 @@ public class ResultImportUrlsManagementPanel extends FlowPanel {
@Override
public void onSuccess(Void result) {
Window.setStatus(stringMessages.successfullyUpdatedResultImportUrls());
Notification.notify(stringMessages.successfullyUpdatedResultImportUrls(), NotificationType.INFO);
}
});
}
@@ -198,7 +199,7 @@ public class ResultImportUrlsManagementPanel extends FlowPanel {
@Override
public void onSuccess(Void result) {
urlListBox.addItem(url);
Window.setStatus(stringMessages.successfullyUpdatedResultImportUrls());
Notification.notify(stringMessages.successfullyUpdatedResultImportUrls(), NotificationType.INFO);
}
});
}
@@ -12,7 +12,6 @@ import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.Handler;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
@@ -35,15 +34,15 @@ import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.FlushableCellTable;
import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
/**
@@ -55,9 +54,11 @@ import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
*
*/
public class SwissTimingEventManagementPanel extends AbstractEventManagementPanel {
private static final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
private final LabeledAbstractFilterablePanel<SwissTimingRaceRecordDTO> filterablePanelEvents;
private final ListDataProvider<SwissTimingRaceRecordDTO> raceList;
private final CellTable<SwissTimingRaceRecordDTO> raceTable;
private final FlushableCellTable<SwissTimingRaceRecordDTO> raceTable;
private final Map<String, SwissTimingConfigurationDTO> previousConfigurations;
private final ListBox previousConfigurationsComboBox;
private final TextBox jsonUrlBox;
@@ -128,63 +129,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
fillRaces(sailingService);
}
});
TextColumn<SwissTimingRaceRecordDTO> raceNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.getName();
}
};
TextColumn<SwissTimingRaceRecordDTO> regattaNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.regattaName;
}
};
TextColumn<SwissTimingRaceRecordDTO> seriesNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.seriesName;
}
};
TextColumn<SwissTimingRaceRecordDTO> raceIdColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceId;
}
};
TextColumn<SwissTimingRaceRecordDTO> boatClassColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.boatClass != null ? object.boatClass : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> genderColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.gender != null ? object.gender : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> raceStatusColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceStatus != null ? object.raceStatus : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> raceStartTimeColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceStartTime==null?"":dateFormatter.render(object.raceStartTime) + " " + timeFormatter.render(object.raceStartTime);
}
};
HorizontalPanel racesSplitPanel = new HorizontalPanel();
mainPanel.add(racesSplitPanel);
@@ -236,7 +181,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
useInternalMarkPassingAlgorithmCheckbox.setWordWrap(false);
useInternalMarkPassingAlgorithmCheckbox.setValue(Boolean.FALSE);
trackableRacesPanel.add(useInternalMarkPassingAlgorithmCheckbox);
// text box for filtering the cell table
HorizontalPanel filterPanel = new HorizontalPanel();
filterPanel.setSpacing(5);
@@ -246,23 +191,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
filterPanel.add(lblFilterEvents);
filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE);
raceNameColumn.setSortable(true);
raceStartTimeColumn.setSortable(true);
boatClassColumn.setSortable(true);
raceIdColumn.setSortable(true);
genderColumn.setSortable(true);
raceStatusColumn.setSortable(true);
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
raceTable = new BaseCelltable<SwissTimingRaceRecordDTO>(/* pageSize */10000, tableRes);
raceTable.addColumn(regattaNameColumn, stringConstants.regatta());
raceTable.addColumn(seriesNameColumn, stringConstants.series());
raceTable.addColumn(raceNameColumn, stringConstants.name());
//raceTable.addColumn(raceIdColumn, stringConstants.id());
raceTable.addColumn(raceStatusColumn, stringConstants.status());
raceTable.addColumn(boatClassColumn, stringConstants.boatClass());
raceTable.addColumn(genderColumn, "Gender");
raceTable.addColumn(raceStartTimeColumn, stringConstants.startTime());
raceTable = new FlushableCellTable<SwissTimingRaceRecordDTO>(/* pageSize */10000, tableRes);
raceTable.setWidth("300px");
raceList = new ListDataProvider<SwissTimingRaceRecordDTO>();
filterablePanelEvents = new LabeledAbstractFilterablePanel<SwissTimingRaceRecordDTO>(lblFilterEvents,
@@ -282,19 +211,99 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
return strings;
}
};
raceTable.setSelectionModel(new RefreshableMultiSelectionModel<SwissTimingRaceRecordDTO>(
new EntityIdentityComparator<SwissTimingRaceRecordDTO>() {
@Override
public boolean representSameEntity(SwissTimingRaceRecordDTO dto1, SwissTimingRaceRecordDTO dto2) {
return dto1.raceId.equals(dto2.raceId);
}
@Override
public int hashCode(SwissTimingRaceRecordDTO t) {
return t.raceId.hashCode();
}
}, filterablePanelEvents.getAllListDataProvider()) {
});
final EntityIdentityComparator<SwissTimingRaceRecordDTO> entityIdentityComparator = new EntityIdentityComparator<SwissTimingRaceRecordDTO>() {
@Override
public boolean representSameEntity(SwissTimingRaceRecordDTO dto1, SwissTimingRaceRecordDTO dto2) {
return dto1.raceId.equals(dto2.raceId);
}
@Override
public int hashCode(SwissTimingRaceRecordDTO t) {
return t.raceId.hashCode();
}
};
TextColumn<SwissTimingRaceRecordDTO> raceNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.getName();
}
};
TextColumn<SwissTimingRaceRecordDTO> regattaNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.regattaName;
}
};
SelectionCheckboxColumn<SwissTimingRaceRecordDTO> selectionColumn = new SelectionCheckboxColumn<SwissTimingRaceRecordDTO>(
tableRes.cellTableStyle().cellTableCheckboxSelected(),
tableRes.cellTableStyle().cellTableCheckboxDeselected(),
tableRes.cellTableStyle().cellTableCheckboxColumnCell(), entityIdentityComparator, raceList, raceTable);
TextColumn<SwissTimingRaceRecordDTO> seriesNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.seriesName;
}
};
TextColumn<SwissTimingRaceRecordDTO> raceIdColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceId;
}
};
TextColumn<SwissTimingRaceRecordDTO> boatClassColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.boatClass != null ? object.boatClass : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> genderColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.gender != null ? object.gender : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> raceStatusColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceStatus != null ? object.raceStatus : "";
}
};
TextColumn<SwissTimingRaceRecordDTO> raceStartTimeColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.raceStartTime==null?"":dateFormatter.render(object.raceStartTime) + " " + timeFormatter.render(object.raceStartTime);
}
};
raceNameColumn.setSortable(true);
raceStartTimeColumn.setSortable(true);
boatClassColumn.setSortable(true);
raceIdColumn.setSortable(true);
genderColumn.setSortable(true);
raceStatusColumn.setSortable(true);
raceTable.addColumn(selectionColumn, selectionColumn.getHeader());
raceTable.addColumn(regattaNameColumn, stringConstants.regatta());
raceTable.addColumn(seriesNameColumn, stringConstants.series());
raceTable.addColumn(raceNameColumn, stringConstants.name());
//raceTable.addColumn(raceIdColumn, stringConstants.id());
raceTable.addColumn(raceStatusColumn, stringConstants.status());
raceTable.addColumn(boatClassColumn, stringConstants.boatClass());
raceTable.addColumn(genderColumn, stringConstants.gender());
raceTable.addColumn(raceStartTimeColumn, stringConstants.startTime());
raceTable.setSelectionModel(selectionColumn.getSelectionModel(), selectionColumn.getSelectionManager());
trackableRacesPanel.add(raceTable);
raceList.addDataDisplay(raceTable);
Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), regattaNameColumn, seriesNameColumn,
@@ -2078,4 +2078,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String multiUrlChangeExplain();
String lastEvent(String locationOrVenue);
String teaserOverallLinkToolTip();
String gender();
}
@@ -2071,4 +2071,5 @@ multiUrlChangeNewURL=new url
multiUrlNoPrefixWarning=No common prefix was found, this usually means that not all selected videos are hosted at the same location currently. Proceed at own risk!
multiUrlChangeExplain=This dialog will bulk replace common parts at the start of mediatrack urls. Make sure all urls start with the same prefix! Also please take a look at the new url column, and test the resulting urls before pressing save!
lastEvent=Last Event: {0}
teaserOverallLinkToolTip=To see the overall series, click the yellow corner
teaserOverallLinkToolTip=To see the overall series, click the yellow corner
gender=Gender
@@ -2067,4 +2067,5 @@ multiUrlChangeNewURL=Neue Url
multiUrlNoPrefixWarning=Es wurde kein gemeinsamer Präfix gefunden, dies deutet darauf hin, dass nicht alle ausgewählten Videos vom gleichen Host kommen. Auf eigene Gefahr fortsetzen!
multiUrlChangeExplain=Dieser Dialog ermöglicht es, mehrere URL-Anfänge gleichzeitig auszutauschen. Hierzu müssen diese den gleichen Präfix besitzen. Bitte unbedingt die Spalte mit den neuen URLs beachten und diese testen bevor gespeichert wird!
lastEvent=Letztes Event: {0}
teaserOverallLinkToolTip=Um die Serien-Übersicht zu sehen, in die gelbe Ecke klicken
teaserOverallLinkToolTip=Um die Serien-Übersicht zu sehen, in die gelbe Ecke klicken
gender=Geschlecht
@@ -9,11 +9,9 @@ import java.util.function.Function;
import java.util.function.Supplier;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.i18n.shared.DateTimeFormat.PredefinedFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
@@ -42,14 +40,11 @@ import com.sap.sailing.gwt.ui.actions.GetManeuversForCompetitorsAction;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.ManeuverTypeFormatter;
import com.sap.sailing.gwt.ui.client.NumberFormatterFactory;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractSortableColumnWithMinMax;
import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn;
import com.sap.sailing.gwt.ui.leaderboard.HasStringAndDoubleValue;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel.LeaderBoardStyle;
import com.sap.sailing.gwt.ui.leaderboard.MinMaxRenderer;
import com.sap.sailing.gwt.ui.leaderboard.SortedCellTableWithStylableHeaders;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sse.common.TimeRange;
@@ -82,8 +77,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
private final StringMessages stringMessages;
private final CompetitorSelectionProvider competitorSelectionModel;
private final NumberFormat towDigitAccuracy = NumberFormatterFactory.getDecimalFormat(2);
private final SimplePanel contentPanel = new SimplePanel();
private final Label importantMessageLabel = new Label();
private final SortedCellTableWithStylableHeaders<ManeuverTableData> maneuverCellTable;
@@ -167,153 +160,26 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
initWidget(rootPanel);
setVisible(false);
}
/**
* Creates a sortable column with the absolute value.
* Whereas {@link #createSortableMinMaxColumn()} creates a sortable column with signed values.
*/
/**
* Creates a sortable column with the absolute value. Whereas {@link #createSortableMinMaxColumn()} creates a
* sortable column with signed values.
*/
private SortableColumn<ManeuverTableData, String> createSortableAbsMinMaxColumn(
Function<ManeuverTableData, Double> extractor, String title, String unit) {
final SortableColumn<ManeuverTableData, String> col = new AbstractSortableColumnWithMinMax<ManeuverTableData, String>(
new TextCell(), SortingOrder.ASCENDING) {
final InvertibleComparator<ManeuverTableData> comparatorWithAbs = new InvertibleComparatorAdapter<ManeuverTableData>() {
@Override
public int compare(ManeuverTableData o1, ManeuverTableData o2) {
Double o1v = extractor.apply(o1);
Double o2v = extractor.apply(o2);
if (o1v == null && o2v == null) {
return 0;
}
if (o1v == null && o2v != null) {
return -1;
}
if (o1v != null && o2v == null) {
return 1;
}
return Double.compare(Math.abs(o1v), Math.abs(o2v));
}
};
final HasStringAndDoubleValue<ManeuverTableData> dataProvider = new HasStringAndDoubleValue<ManeuverTableData>() {
@Override
public String getStringValueToRender(ManeuverTableData row) {
Double value = extractor.apply(row);
if (value == null) {
return null;
}
return towDigitAccuracy.format(value);
}
@Override
public Double getDoubleValue(ManeuverTableData row) {
Double value = extractor.apply(row);
return value == null ? null : Math.abs(value);
}
};
final MinMaxRenderer<ManeuverTableData> renderer = new MinMaxRenderer<ManeuverTableData>(dataProvider, comparatorWithAbs);
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return comparatorWithAbs;
}
@Override
public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) {
renderer.render(context, object, title, sb);
}
@Override
public Header<?> getHeader() {
return new TextHeader(title + " [" + unit + "]");
}
@Override
public String getValue(ManeuverTableData object) {
return dataProvider.getStringValueToRender(object);
}
@Override
public void updateMinMax() {
renderer.updateMinMax(maneuverCellTable.getDataProvider().getList());
}
};
col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
return col;
return new SortableMinMaxColumn(extractor, title, unit, maneuverCellTable.getDataProvider(), /* absolute */ true);
}
/**
* Creates a sortable column with signed values.
*/
private SortableColumn<ManeuverTableData, String> createSortableMinMaxColumn(
Function<ManeuverTableData, Double> extractor, String title, String unit) {
final SortableColumn<ManeuverTableData, String> col = new AbstractSortableColumnWithMinMax<ManeuverTableData, String>(
new TextCell(), SortingOrder.ASCENDING) {
final InvertibleComparator<ManeuverTableData> comparator = new InvertibleComparatorAdapter<ManeuverTableData>() {
@Override
public int compare(ManeuverTableData o1, ManeuverTableData o2) {
Double o1v = extractor.apply(o1);
Double o2v = extractor.apply(o2);
if (o1v == null && o2v == null) {
return 0;
}
if (o1v == null && o2v != null) {
return -1;
}
if (o1v != null && o2v == null) {
return 1;
}
return Double.compare(o1v, o2v);
}
};
final HasStringAndDoubleValue<ManeuverTableData> dataProvider = new HasStringAndDoubleValue<ManeuverTableData>() {
@Override
public String getStringValueToRender(ManeuverTableData row) {
Double value = extractor.apply(row);
if (value == null) {
return null;
}
return towDigitAccuracy.format(value);
}
@Override
public Double getDoubleValue(ManeuverTableData row) {
Double value = extractor.apply(row);
return value == null ? null : value;
}
};
final MinMaxRenderer<ManeuverTableData> renderer = new MinMaxRenderer<ManeuverTableData>(dataProvider, comparator);
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return comparator;
}
@Override
public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) {
renderer.render(context, object, title, sb);
}
@Override
public Header<?> getHeader() {
return new TextHeader(title + " [" + unit + "]");
}
@Override
public String getValue(ManeuverTableData object) {
return dataProvider.getStringValueToRender(object);
}
@Override
public void updateMinMax() {
renderer.updateMinMax(maneuverCellTable.getDataProvider().getList());
}
};
col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
return col;
return new SortableMinMaxColumn(extractor, title, unit, maneuverCellTable.getDataProvider(), /* absolute */ false);
}
private SortableColumn<ManeuverTableData, String> createManeuverTypeColumn() {
return new SortableColumn<ManeuverTableData, String>(new TextCell(), SortingOrder.ASCENDING) {
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return new InvertibleComparatorAdapter<ManeuverTableData>() {
@@ -343,7 +209,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
return o1.getTimePoint().compareTo(o2.getTimePoint());
}
};
final SortableColumn<ManeuverTableData, Date> col = new SortableColumn<ManeuverTableData, Date>(
new DateCell(DateTimeFormat.getFormat(PredefinedFormat.TIME_LONG)), SortingOrder.ASCENDING) {
@Override
@@ -371,7 +236,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
return -Boolean.compare(o1.isMarkPassing(), o2.isMarkPassing());
}
};
final SortableColumn<ManeuverTableData, Boolean> column = new SortableColumn<ManeuverTableData, Boolean>(
new AbstractCell<Boolean>() {
@Override
@@ -406,9 +270,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
return o1.getCompetitorName().compareTo(o2.getCompetitorName());
}
};
return new SortableColumn<ManeuverTableData, String>(new TextCell(), SortingOrder.ASCENDING) {
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return comparator;
@@ -0,0 +1,94 @@
package com.sap.sailing.gwt.ui.client.shared.racemap.maneuver;
import java.util.Comparator;
import java.util.function.Function;
import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.cellview.client.TextHeader;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.view.client.ListDataProvider;
import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.SortingOrder;
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
import com.sap.sailing.gwt.ui.client.NumberFormatterFactory;
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractSortableColumnWithMinMax;
import com.sap.sailing.gwt.ui.leaderboard.HasStringAndDoubleValue;
import com.sap.sailing.gwt.ui.leaderboard.MinMaxRenderer;
public class SortableMinMaxColumn extends AbstractSortableColumnWithMinMax<ManeuverTableData, String> {
private final static NumberFormat TWO_DIGIT_ACCURACY = NumberFormatterFactory.getDecimalFormat(2);
private final String title;
private final String unit;
final InvertibleComparator<ManeuverTableData> comparator;
final HasStringAndDoubleValue<ManeuverTableData> dataProvider;
final MinMaxRenderer<ManeuverTableData> renderer;
final ListDataProvider<ManeuverTableData> maneuverTableListDataProvider;
public SortableMinMaxColumn(final Function<ManeuverTableData, Double> extractor, String title, String unit,
ListDataProvider<ManeuverTableData> maneuverTableListDataProvider, boolean absolute) {
super(new TextCell(), SortingOrder.ASCENDING);
this.title = title;
this.unit = unit;
this.maneuverTableListDataProvider = maneuverTableListDataProvider;
this.comparator = new InvertibleComparatorAdapter<ManeuverTableData>() {
@Override
public int compare(ManeuverTableData o1, ManeuverTableData o2) {
Double o1v = extractor.apply(o1);
Double o2v = extractor.apply(o2);
return Comparator.nullsFirst((Double v1, Double v2)->Double.compare(absolute?Math.abs(v1):v1, absolute?Math.abs(v2):v2)).compare(o1v, o2v);
}
};
this.dataProvider = new HasStringAndDoubleValue<ManeuverTableData>() {
@Override
public String getStringValueToRender(ManeuverTableData row) {
Double value = extractor.apply(row);
if (value == null) {
return null;
}
return TWO_DIGIT_ACCURACY.format(value);
}
@Override
public Double getDoubleValue(ManeuverTableData row) {
Double value = extractor.apply(row);
return value == null ? null : value;
}
};
this.renderer = new MinMaxRenderer<ManeuverTableData>(dataProvider, comparator);
this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
}
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return comparator;
}
@Override
public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) {
renderer.render(context, object, title, sb);
}
@Override
public Header<?> getHeader() {
return new TextHeader(title + " [" + unit + "]");
}
@Override
public String getValue(ManeuverTableData object) {
return dataProvider.getStringValueToRender(object);
}
@Override
public void updateMinMax() {
renderer.updateMinMax(maneuverTableListDataProvider.getList());
}
}
@@ -67,6 +67,8 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSortableColumnWithMinMax;
import com.sap.sailing.gwt.ui.leaderboard.MultiRaceLeaderboardPanel;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
@@ -708,7 +710,7 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel {
}
@Override
public void onSuccess(Void result) {
Window.setStatus("Successfully unsuppressed competitor "+object.getName());
Notification.notify("Successfully unsuppressed competitor "+object.getName(), NotificationType.INFO);
// force a reload of the entire editable leaderboard to hide the now suppressed competitor
loadCompleteLeaderboard(/* showProgress */ true);
}
@@ -16,7 +16,6 @@ import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
@@ -39,6 +38,8 @@ import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO.ScoreCorrectionEntryDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkScoreCorrectionDTO> {
@@ -433,7 +434,7 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
@Override
public void onSuccess(Void result) {
leaderboardPanel.removeBusyTask();
Window.setStatus(stringMessages.successfullyUpdatedScores());
Notification.notify(stringMessages.successfullyUpdatedScores(), NotificationType.INFO);
leaderboardPanel.loadCompleteLeaderboard(/* showProgress */ true); // reload leaderboard contents to reflect changes
}
});
@@ -15,7 +15,6 @@ import com.google.gwt.i18n.client.TimeZone;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.Point;
import com.google.gwt.maps.client.controls.ControlPosition;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.LegIdentifier;
import com.sap.sailing.domain.common.LegIdentifierImpl;
@@ -31,6 +30,8 @@ import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay;
import com.sap.sailing.gwt.ui.simulator.util.ColorPalette;
import com.sap.sailing.gwt.ui.simulator.util.ColorPaletteGenerator;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
@@ -338,8 +339,8 @@ public class RaceSimulationOverlay extends FullCanvasOverlay {
@Override
public void onFailure(Throwable caught) {
// TODO: add corresponding message to string-messages
// Window.setStatus(stringMessages.errorFetchingWindStreamletData(caught.getMessage()));
Window.setStatus(GET_SIMULATION_CATEGORY);
// Notification.error(stringMessages.errorFetchingWindStreamletData(caught.getMessage()));
Notification.notify(GET_SIMULATION_CATEGORY, NotificationType.WARNING);
}
@Override
@@ -13,7 +13,6 @@ import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.controls.ControlPosition;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
@@ -31,6 +30,8 @@ import com.sap.sailing.gwt.ui.simulator.streamlets.Swarm;
import com.sap.sailing.gwt.ui.simulator.streamlets.VectorField;
import com.sap.sailing.gwt.ui.simulator.streamlets.WindInfoForRaceVectorField;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.player.Timer;
@@ -217,7 +218,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
sailingService.getWindSourcesInfo(raceIdentifier, new MarkedAsyncCallback<>(new AsyncCallback<WindInfoForRaceDTO>() {
@Override
public void onFailure(Throwable caught) {
Window.setStatus(stringMessages.errorFetchingWindStreamletData(caught.getMessage()));
Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()),
NotificationType.WARNING);
}
@Override
@@ -256,7 +258,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay {
new MarkedAsyncCallback<>(new AsyncCallback<WindInfoForRaceDTO>() {
@Override
public void onFailure(Throwable caught) {
Window.setStatus(stringMessages.errorFetchingWindStreamletData(caught.getMessage()));
Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()),
NotificationType.WARNING);
}
@Override
@@ -126,12 +126,12 @@ public class RegattaByKeywordSearchService {
*
* @param leaderboard the leaderboard to get the matching events for
* @param leaderboardGroup the LeaderboardGroup hosting the leaderboard
* @param events all events hosting the LeaderboardGroup
* @param events all events hosting the LeaderboardGroup; may be {@code null}; if {@code null}, result will be {@code null}
* @return the best matching events for the given Leaderboard/LeaderboardGroup
*/
private Set<Event> filterEventsForLeaderboard(Leaderboard leaderboard, LeaderboardGroup leaderboardGroup, Set<Event> events) {
final Set<Event> result;
if (leaderboardGroup.hasOverallLeaderboard()) {
if (events != null && leaderboardGroup.hasOverallLeaderboard()) {
CourseArea defaultCourseArea = leaderboard.getDefaultCourseArea();
Set<Event> preResult = null;
if (defaultCourseArea != null) {
@@ -3,13 +3,13 @@ package com.sap.sse.gwt.client;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.gwt.client.Notification.NotificationType;
public class DefaultErrorReporter<S extends StringMessages> implements ErrorReporter {
private DialogBox errorDialogBox;
@@ -49,7 +49,7 @@ public class DefaultErrorReporter<S extends StringMessages> implements ErrorRepo
@Override
public void reportError(String message, boolean silentMode) {
if (silentMode) {
Window.setStatus(message);
Notification.notify(message, NotificationType.WARNING);
} else {
reportError(message);
}
@@ -0,0 +1,136 @@
package com.sap.sse.gwt.client;
import java.util.LinkedList;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Style.Cursor;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.sap.sse.common.Util.Pair;
/**
* Utility class to show non obstructive warning / info messages using a small notification at the bottom of the page. Clicking the notification will hide it. It will autohide after some time.
*/
public class Notification {
private static final int NOTIFICATION_TIME = 20000;
private static final double FADE_OUT_PERCENT = 0.98;
private static final double FADE_IN_PERCENT = 0.005;
interface NotificationResources extends ClientBundle {
@Source("notification.gss")
NotificationCSS css();
}
interface NotificationCSS extends CssResource {
String snackbar();
}
private final static FlowPanel snackBar = new FlowPanel();
private final static NotificationResources ress = GWT.create(NotificationResources.class);
private static Animation notificationAnimation;
static {
ress.css().ensureInjected();
snackBar.addStyleName(ress.css().snackbar());
snackBar.getElement().getStyle().setCursor(Cursor.POINTER);
notificationAnimation = new Animation() {
@Override
protected void onStart() {
super.onStart();
snackBar.getElement().getStyle().setOpacity(0);
snackBar.getElement().getStyle().setVisibility(Visibility.VISIBLE);
}
@Override
protected void onUpdate(double progress) {
if (progress < FADE_IN_PERCENT) {
double relPr = progress / FADE_IN_PERCENT;
double bottom = 60 * relPr - 30;
snackBar.getElement().getStyle().setOpacity(relPr);
snackBar.getElement().getStyle().setBottom(bottom, Unit.PX);
} else if (progress > FADE_OUT_PERCENT) {
double relPr = (progress - FADE_OUT_PERCENT) / (1 - FADE_OUT_PERCENT);
snackBar.getElement().getStyle().setOpacity(1 - relPr);
double bottom = 60 * (1 - relPr) - 30;
snackBar.getElement().getStyle().setBottom(bottom, Unit.PX);
} else {
snackBar.getElement().getStyle().setOpacity(1);
snackBar.getElement().getStyle().setBottom(30, Unit.PX);
}
}
@Override
protected void onComplete() {
snackBar.getElement().getStyle().setVisibility(Visibility.HIDDEN);
checkQueue(true);
}
@Override
protected void onCancel() {
snackBar.getElement().getStyle().setVisibility(Visibility.HIDDEN);
checkQueue(true);
}
};
}
private final static LinkedList<Pair<String, NotificationType>> QUEUE = new LinkedList<>();
private Notification() {
}
public enum NotificationType {
ERROR("\u2716", "RED", "WHITE"),
WARNING("\u26A0", "ORANGE", "WHITE"),
INFO("\u2139", "#008fcc", "WHITE");
private String decorator;
private String bgColor;
private String color;
NotificationType(String decorator, String bgColor, String color) {
this.decorator = decorator;
this.bgColor = bgColor;
this.color = color;
}
}
public static void notify(String message, NotificationType type) {
QUEUE.add(new Pair<>(message, type));
checkQueue(false);
}
/**
* Displays next message if non is displayed currently, else does nothing and will by called by currently displaying
* message TTL timer
*/
private static void checkQueue(boolean onAnimationFinish) {
if (!QUEUE.isEmpty()) {
if (!notificationAnimation.isRunning() || onAnimationFinish) {
RootPanel.get().add(snackBar);
Event.sinkEvents(snackBar.getElement(), Event.ONCLICK);
Event.setEventListener(snackBar.getElement(), new EventListener() {
@Override
public void onBrowserEvent(Event event) {
GWT.log("test");
notificationAnimation.cancel();
}
});
Pair<String, NotificationType> notification = QUEUE.pop();
snackBar.getElement().getStyle().setColor(notification.getB().color);
snackBar.getElement().getStyle().setBackgroundColor(notification.getB().bgColor);
snackBar.getElement().setInnerText(notification.getB().decorator + " " + notification.getA() + " "
+ notification.getB().decorator);
notificationAnimation.run(NOTIFICATION_TIME);
}
}
}
}
@@ -0,0 +1,10 @@
.snackbar {
visibility: hidden;
min-width: 250px;
margin-left: -125px;
text-align: center;
border-radius: 2px;
padding: 16px;
position: fixed;
left: 50%;
}
+3 -3
View File
@@ -8,7 +8,7 @@ First of all, make sure you've looked at http://www.amazon.de/Patterns-Elements-
#### Installations
1. Eclipse (Eclipse IDE for Eclipse Committers, e.g. version 4.7.2 "Oxygen SR2"), http://www.eclipse.org
1. Eclipse (Eclipse IDE for Eclipse Committers, version 4.7.2 ["Oxygen SR2"](http://www.eclipse.org/downloads/packages/eclipse-ide-eclipse-committers/oxygen2)), http://www.eclipse.org
2. Eclipse Extensions
* Install GWT Eclipse plugin for Eclipse (https://github.com/gwt-plugins/gwt-eclipse-plugin using http://storage.googleapis.com/gwt-eclipse-plugin/v3/release as the update site URL)
* Install Eclipse debugger for GWT SuperDevMode (master version: http://p2.sapsailing.com/p2/sdbg; public release: http://sdbg.github.io/p2)
@@ -71,7 +71,7 @@ The primary Git repository for the project is hosted on sapsailing.com. It is mi
* Install GWT SDK and add the SDK in Eclipse (Preferences -> GWT -> GWT Settings -> Add...)
* In "Window->Preferences->GWT->Errors/Warnings, set "Missing SDK" to "Ignore"
* In "Window->Preferences->General->Editors->TextEditors" check Insert Spaces for Tabs
* In "Window->Preferences->Web->HTML Files->Editor" indent using Spaces
* <del>In "Window->Preferences->Web->HTML Files->Editor" indent using Spaces</del>
* In "Window->Preferences->General->Content Types" select on the right side CSS, now add in the lower file association list *.gss to get limited syntax highlighting and content assist in GSS files
* Install Eclipse debugger for GWT SuperDevMode
* Install Eclipse eGit (optional)
@@ -79,7 +79,7 @@ The primary Git repository for the project is hosted on sapsailing.com. It is mi
* Check that the both JDKs are available (Windows->Preferences->Java->Installed JREs)
* Check that JDK 1.7 has been matched to JavaSE-1.7 and that JDK 1.8 has been matched to JavaSE-1.8 (...>Installed JREs>Execution Environments)
* It is also possible to match the SAPJVM 7 or 8 to JavaSE-1.7 / JavaSE-1.8 (for profiling purposes)
* Go to Windows->Preferences->Google->Errors/Warnings and set "Missing SDK" to "Ignore"
* <del>Go to Windows->Preferences->Google->Errors/Warnings and set "Missing SDK" to "Ignore"</del>
* Import all Race Analysis projects from the `java/` subdirectory of the git main folder (make sure to import via the wizard "Git->Projects from Git" in Eclipse, and additionally make sure to scan for nested projects!)
* Import all projects from the `mobile/` subdirectory of the git main folder; this in particular contains the race committee app projects
* Set the Eclipse target platform to race-analysis-p2-remote.target (located in com.sap.sailing.targetplatform/definitions)