mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-16 10:48:47 +00:00
bug6275: UI changes
This commit is contained in:
+154
-61
@@ -9,6 +9,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.dom.client.Style;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||
import com.google.gwt.event.dom.client.KeyUpHandler;
|
||||
import com.google.gwt.event.logical.shared.SelectionEvent;
|
||||
import com.google.gwt.event.logical.shared.SelectionHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
@@ -17,8 +23,12 @@ import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
|
||||
import com.google.gwt.user.client.ui.SuggestBox;
|
||||
import com.google.gwt.user.client.ui.SuggestOracle;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.dto.CourseAreaDTO;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
@@ -55,49 +65,121 @@ public class CourseAreaTabComposite extends Composite {
|
||||
for (final EventDTO event : sortedExistingEvents) {
|
||||
eventDropDown.addItem(event.getName(), event.getId().toString());
|
||||
}
|
||||
final Button appendButton = new Button(stringMessages.appendCourseAreas());
|
||||
appendButton.setEnabled(false);
|
||||
appendButton.addStyleName("btn-secondary");
|
||||
final ListBox courseAreaDropDown = new ListBox();
|
||||
courseAreaDropDown.addItem(stringMessages.chooseWhatToAdd());
|
||||
courseAreaDropDown.setEnabled(false);
|
||||
courseAreaDropDown.setWidth("400px");
|
||||
final Button clearAllButton = new Button(stringMessages.clearAllCourseAreas());
|
||||
clearAllButton.addStyleName("btn-secondary");
|
||||
eventDropDown.addChangeHandler(e -> {
|
||||
final boolean hasSelection = eventDropDown.getSelectedIndex() > 0;
|
||||
appendButton.setEnabled(hasSelection);
|
||||
});
|
||||
appendButton.addClickHandler(e -> {
|
||||
final EventDTO selected = eventsCache.get(eventDropDown.getValue(eventDropDown.getSelectedIndex()));
|
||||
if (selected != null) {
|
||||
new CourseAreaSelectionDialog(selected.getVenue().getCourseAreas(), stringMessages,
|
||||
new DataEntryDialog.DialogCallback<List<CourseAreaDTO>>() {
|
||||
@Override
|
||||
public void ok(final List<CourseAreaDTO> result) {
|
||||
final List<CourseAreaDTO> updated = new ArrayList<>(courseAreaList.getValue());
|
||||
for (final CourseAreaDTO area : result) {
|
||||
updated.add(new CourseAreaDTO(UUID.randomUUID(), area.getName(), area.getCenterPosition(), area.getRadius()));
|
||||
}
|
||||
courseAreaList.setValue(updated);
|
||||
final int selectedIndex = eventDropDown.getSelectedIndex();
|
||||
courseAreaDropDown.clear();
|
||||
if (selectedIndex > 0) {
|
||||
final EventDTO selected = eventsCache.get(eventDropDown.getValue(selectedIndex));
|
||||
if (selected != null && selected.getVenue() != null) {
|
||||
courseAreaDropDown.addItem(stringMessages.chooseWhatToAdd());
|
||||
courseAreaDropDown.addItem(stringMessages.addAllCourseAreas());
|
||||
for (final CourseAreaDTO area : selected.getVenue().getCourseAreas()) {
|
||||
courseAreaDropDown.addItem(area.getName(), area.getId().toString());
|
||||
}
|
||||
@Override
|
||||
public void cancel() {}
|
||||
}).show();
|
||||
courseAreaDropDown.setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
courseAreaDropDown.addItem(stringMessages.chooseWhatToAdd());
|
||||
courseAreaDropDown.setEnabled(false);
|
||||
}
|
||||
});
|
||||
courseAreaDropDown.addChangeHandler(e -> {
|
||||
final int selectedIndex = courseAreaDropDown.getSelectedIndex();
|
||||
if (selectedIndex <= 0) {
|
||||
return;
|
||||
}
|
||||
final EventDTO selectedEvent = eventsCache.get(eventDropDown.getValue(eventDropDown.getSelectedIndex()));
|
||||
if (selectedEvent == null) {
|
||||
return;
|
||||
}
|
||||
final List<CourseAreaDTO> toAdd = new ArrayList<>();
|
||||
if (selectedIndex == 1) {
|
||||
for (final CourseAreaDTO area : selectedEvent.getVenue().getCourseAreas()) {
|
||||
toAdd.add(new CourseAreaDTO(UUID.randomUUID(), area.getName(), area.getCenterPosition(), area.getRadius()));
|
||||
}
|
||||
} else {
|
||||
final List<CourseAreaDTO> areas = selectedEvent.getVenue().getCourseAreas();
|
||||
if (selectedIndex - 2 < areas.size()) {
|
||||
final CourseAreaDTO area = areas.get(selectedIndex - 2);
|
||||
toAdd.add(new CourseAreaDTO(UUID.randomUUID(), area.getName(), area.getCenterPosition(), area.getRadius()));
|
||||
}
|
||||
}
|
||||
final List<CourseAreaDTO> updated = new ArrayList<>(courseAreaList.getValue());
|
||||
updated.addAll(toAdd);
|
||||
courseAreaList.setValue(updated);
|
||||
courseAreaDropDown.setSelectedIndex(0);
|
||||
});
|
||||
clearAllButton.addClickHandler(e -> courseAreaList.setValue(new ArrayList<>()));
|
||||
final TextBox remoteBaseUrlBox = new TextBox();
|
||||
remoteBaseUrlBox.setValue(SharedLandscapeConstants.DEFAULT_SAILING_SERVER_URL);
|
||||
remoteBaseUrlBox.setWidth("300px");
|
||||
remoteBaseUrlBox.getElement().setPropertyString("placeholder", stringMessages.remoteServerUrlPlaceholder());
|
||||
final TextBox bearerTokenOrNullBox = new TextBox();
|
||||
bearerTokenOrNullBox.setWidth("200px");
|
||||
bearerTokenOrNullBox.getElement().setPropertyString("placeholder", stringMessages.bearerTokenPlaceholder());
|
||||
final BusyIndicator remoteLoadBusyIndicator = new SimpleBusyIndicator();
|
||||
final Button loadRemoteEventsButton = new Button(stringMessages.loadRemoteEvents());
|
||||
loadRemoteEventsButton.addClickHandler(e -> {
|
||||
final String[] bearerTokenHolder = new String[1];
|
||||
final Button authenticateButton = new Button(stringMessages.authenticate());
|
||||
authenticateButton.addClickHandler(e -> {
|
||||
final TextBox tokenBox = new TextBox();
|
||||
tokenBox.setWidth("300px");
|
||||
tokenBox.getElement().setPropertyString("placeholder", stringMessages.bearerTokenPlaceholder());
|
||||
if (bearerTokenHolder[0] != null) {
|
||||
tokenBox.setValue(bearerTokenHolder[0]);
|
||||
}
|
||||
new DataEntryDialog<String>(stringMessages.authenticate(), null, stringMessages.ok(), stringMessages.cancel(), null,
|
||||
new DataEntryDialog.DialogCallback<String>() {
|
||||
@Override
|
||||
public void ok(final String result) {
|
||||
bearerTokenHolder[0] = result.trim().isEmpty() ? null : result.trim();
|
||||
}
|
||||
@Override
|
||||
public void cancel() {}
|
||||
}) {
|
||||
@Override
|
||||
protected String getResult() {
|
||||
return tokenBox.getValue();
|
||||
}
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
final VerticalPanel panel = new VerticalPanel();
|
||||
panel.setSpacing(3);
|
||||
final HorizontalPanel tokenRow = new HorizontalPanel();
|
||||
tokenRow.setSpacing(3);
|
||||
tokenRow.add(new Label(stringMessages.bearerTokenOrNullForRemoteEvents()));
|
||||
tokenRow.add(tokenBox);
|
||||
panel.add(tokenRow);
|
||||
final Label explanationLabel = new Label(stringMessages.helptextBearerToken());
|
||||
explanationLabel.setWidth("400px");
|
||||
explanationLabel.getElement().getStyle().setProperty("whiteSpace", "normal");
|
||||
explanationLabel.getElement().getStyle().setFontStyle(Style.FontStyle.ITALIC);
|
||||
explanationLabel.getElement().getStyle().setFontSize(11, Style.Unit.PX);
|
||||
panel.add(explanationLabel);
|
||||
return panel;
|
||||
}
|
||||
}.show();
|
||||
});
|
||||
final BusyIndicator remoteLoadBusyIndicator = new SimpleBusyIndicator(false, 0.7f) {
|
||||
@Override
|
||||
public void setBusy(final boolean busy) {
|
||||
super.setBusy(busy);
|
||||
getElement().getStyle().setDisplay(Style.Display.BLOCK);
|
||||
getElement().getStyle().setVisibility(busy ? Style.Visibility.VISIBLE : Style.Visibility.HIDDEN);
|
||||
}
|
||||
};
|
||||
remoteLoadBusyIndicator.setBusy(false);
|
||||
final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
|
||||
oracle.add(stringMessages.localEvents());
|
||||
oracle.add(SharedLandscapeConstants.DEFAULT_SAILING_SERVER_URL);
|
||||
oracle.add("http://localhost:8889");
|
||||
final SuggestBox sourceBox = new SuggestBox(oracle);
|
||||
sourceBox.setValue(stringMessages.localEvents());
|
||||
sourceBox.setWidth("300px");
|
||||
final Runnable loadEvents = () -> {
|
||||
eventDropDown.clear();
|
||||
eventDropDown.addItem(stringMessages.pleaseSelectAnEvent());
|
||||
eventsCache.clear();
|
||||
final String baseUrl = remoteBaseUrlBox.getValue().trim();
|
||||
if (baseUrl.isEmpty()) { // use local events
|
||||
final String source = sourceBox.getValue().trim();
|
||||
final boolean isLocal = source.isEmpty() || source.equals(stringMessages.localEvents());
|
||||
if (isLocal) {
|
||||
eventDropDown.addItem(stringMessages.pleaseSelectALocalEvent());
|
||||
final List<EventDTO> sorted = new ArrayList<>(existingEvents);
|
||||
sorted.sort(Comparator.comparing(EventDTO::getName));
|
||||
for (final EventDTO event : sorted) {
|
||||
@@ -105,15 +187,17 @@ public class CourseAreaTabComposite extends Composite {
|
||||
eventDropDown.addItem(event.getName(), event.getId().toString());
|
||||
}
|
||||
eventDropDown.setEnabled(true);
|
||||
} else { // load events from remote environment
|
||||
} else {
|
||||
eventDropDown.addItem(stringMessages.pleaseSelectAnEventFrom(source));
|
||||
remoteLoadBusyIndicator.setBusy(true);
|
||||
eventDropDown.setEnabled(false);
|
||||
final String bearerTokenOrNull = bearerTokenOrNullBox.getValue().trim().isEmpty() ? null : bearerTokenOrNullBox.getValue().trim();
|
||||
sailingServiceWrite.getRemoteEvents(baseUrl, bearerTokenOrNull,
|
||||
new AsyncCallback<List<EventDTO>>() {
|
||||
authenticateButton.setEnabled(false);
|
||||
final String bearerTokenOrNull = bearerTokenHolder[0];
|
||||
sailingServiceWrite.getRemoteEvents(source, bearerTokenOrNull,new AsyncCallback<List<EventDTO>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<EventDTO> result) {
|
||||
remoteLoadBusyIndicator.setBusy(false);
|
||||
authenticateButton.setEnabled(true);
|
||||
result.sort(Comparator.comparing(EventDTO::getName));
|
||||
for (final EventDTO event : result) {
|
||||
eventsCache.put(event.getId().toString(), event);
|
||||
@@ -124,38 +208,47 @@ public class CourseAreaTabComposite extends Composite {
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
remoteLoadBusyIndicator.setBusy(false);
|
||||
authenticateButton.setEnabled(true);
|
||||
eventDropDown.clear();
|
||||
eventDropDown.addItem(caught.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
sourceBox.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
|
||||
@Override
|
||||
public void onSelection(final SelectionEvent<SuggestOracle.Suggestion> event) {
|
||||
loadEvents.run();
|
||||
}
|
||||
});
|
||||
sourceBox.getValueBox().addKeyUpHandler(new KeyUpHandler() {
|
||||
@Override
|
||||
public void onKeyUp(final KeyUpEvent event) {
|
||||
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
|
||||
loadEvents.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
final VerticalPanel copyPanel = new VerticalPanel();
|
||||
copyPanel.setWidth("100%");
|
||||
copyPanel.setSpacing(3);
|
||||
final Grid remoteInputGrid = new Grid(2, 3);
|
||||
remoteInputGrid.setWidget(0, 0, new Label(stringMessages.copyCourseAreasFromAnotherUrl()));
|
||||
remoteInputGrid.setWidget(0, 1, remoteBaseUrlBox);
|
||||
final HorizontalPanel loadRow = new HorizontalPanel();
|
||||
loadRow.setSpacing(3);
|
||||
loadRow.add(loadRemoteEventsButton);
|
||||
loadRow.add(remoteLoadBusyIndicator);
|
||||
remoteInputGrid.setWidget(0, 2, loadRow);
|
||||
remoteInputGrid.setWidget(1, 0, new Label(stringMessages.bearerTokenOrNullForRemoteEvents()));
|
||||
remoteInputGrid.setWidget(1, 1, bearerTokenOrNullBox);
|
||||
eventDropDown.setWidth("100%");
|
||||
final HorizontalPanel actionButtons = new HorizontalPanel();
|
||||
actionButtons.setSpacing(3);
|
||||
actionButtons.add(appendButton);
|
||||
actionButtons.add(clearAllButton);
|
||||
final HorizontalPanel eventDropDownRow = new HorizontalPanel();
|
||||
eventDropDownRow.setSpacing(3);
|
||||
eventDropDownRow.setWidth("100%");
|
||||
eventDropDownRow.add(new Label(stringMessages.event() + ":"));
|
||||
eventDropDownRow.add(eventDropDown);
|
||||
eventDropDownRow.add(actionButtons);
|
||||
copyPanel.add(remoteInputGrid);
|
||||
copyPanel.add(eventDropDownRow);
|
||||
final Grid inputGrid = new Grid(3, 3);
|
||||
inputGrid.setWidget(0, 0, new Label(stringMessages.copyCourseAreasFromAnotherUrl()));
|
||||
sourceBox.setTitle(stringMessages.helptextCopySource());
|
||||
final HorizontalPanel sourceBoxRow = new HorizontalPanel();
|
||||
sourceBoxRow.setSpacing(3);
|
||||
sourceBoxRow.add(sourceBox);
|
||||
sourceBoxRow.add(remoteLoadBusyIndicator);
|
||||
inputGrid.setWidget(0, 1, sourceBoxRow);
|
||||
inputGrid.setWidget(0, 2, authenticateButton);
|
||||
eventDropDown.setWidth("400px");
|
||||
inputGrid.setWidget(1, 0, new Label(stringMessages.event() + ":"));
|
||||
inputGrid.setWidget(1, 1, eventDropDown);
|
||||
inputGrid.setWidget(1, 2, clearAllButton);
|
||||
courseAreaDropDown.setWidth("400px");
|
||||
inputGrid.setWidget(2, 0, new Label(stringMessages.courseAreas() + ":"));
|
||||
inputGrid.setWidget(2, 1, courseAreaDropDown);
|
||||
copyPanel.add(inputGrid);
|
||||
courseAreasPanel.add(copyPanel);
|
||||
courseAreasPanel.add(courseAreaList);
|
||||
initWidget(courseAreasPanel);
|
||||
|
||||
+8
@@ -1250,6 +1250,9 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String editSeries();
|
||||
String pleaseSelectAtLeastOneRegatta();
|
||||
String pleaseSelectAnEvent();
|
||||
String pleaseSelectALocalEvent();
|
||||
String pleaseSelectAnEventFrom(String source);
|
||||
String localEvents();
|
||||
String selectALeaderboard();
|
||||
String autoplayConfiguration();
|
||||
String startAutoplay();
|
||||
@@ -1474,8 +1477,13 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String bearerTokenOrNullForRemoteEvents();
|
||||
String remoteServerUrlPlaceholder();
|
||||
String bearerTokenPlaceholder();
|
||||
String authenticate();
|
||||
String helptextCopySource();
|
||||
String helptextBearerToken();
|
||||
String appendCourseAreas();
|
||||
String appendCourseAreasConfirm();
|
||||
String addAllCourseAreas();
|
||||
String chooseWhatToAdd();
|
||||
String clearAllCourseAreas();
|
||||
String selectCourseAreas();
|
||||
String resetCourseAreas();
|
||||
|
||||
+9
-1
@@ -1265,6 +1265,9 @@ filteredBy=filtered by
|
||||
editSeries=Edit Series
|
||||
pleaseSelectAtLeastOneRegatta=Please select at least one regatta
|
||||
pleaseSelectAnEvent=Please select an event
|
||||
pleaseSelectALocalEvent=Please select a local event
|
||||
pleaseSelectAnEventFrom=Please select an event from {0}
|
||||
localEvents=<Local Events>
|
||||
selectALeaderboard=Please select a leaderboard
|
||||
autoplayConfiguration=Autoplay configuration
|
||||
startAutoplay=Start autoplay
|
||||
@@ -1496,13 +1499,18 @@ registerBoats=Register Boats
|
||||
doYouWantToCreateADefaultRegattaLeaderboard=Do you want to create a default Regatta Leaderboard?
|
||||
copyCourse=Copy Course
|
||||
copyCourseAreasFromEvent=Copy course areas from event
|
||||
copyCourseAreasFromAnotherUrl=Copy course areas from another URL:
|
||||
copyCourseAreasFromAnotherUrl=Copy course areas from:
|
||||
helptextCopySource=Select where to load events from. Use "<Local Events>" for events on this server, a production URL such as https://www.sapsailing.com, or a local development server such as http://localhost:8889.
|
||||
helptextBearerToken=Needed only when the remote server has a different login system. Get it from browser dev tools (F12 -> Network -> any request -> Authorization header, copy the part after "Bearer ").
|
||||
loadRemoteEvents=Load
|
||||
bearerTokenOrNullForRemoteEvents=Bearer token for remote server:
|
||||
remoteServerUrlPlaceholder=Paste server URL (leave empty for local)
|
||||
bearerTokenPlaceholder=Leave empty for current user
|
||||
authenticate=Authenticate...
|
||||
appendCourseAreas=Pick...
|
||||
appendCourseAreasConfirm=Append
|
||||
addAllCourseAreas=Add all
|
||||
chooseWhatToAdd=Choose what to add...
|
||||
clearAllCourseAreas=Clear all
|
||||
selectCourseAreas=Select course areas
|
||||
resetCourseAreas=Reset
|
||||
|
||||
+9
-1
@@ -1241,6 +1241,9 @@ editSeries=Serie bearbeiten
|
||||
filteredBy=gefiltert nach
|
||||
pleaseSelectAtLeastOneRegatta=Bitte wenigstens eine Regatta auswählen
|
||||
pleaseSelectAnEvent=Bitte eine Veranstaltung auswählen
|
||||
pleaseSelectALocalEvent=Bitte eine lokale Veranstaltung auswählen
|
||||
pleaseSelectAnEventFrom=Bitte eine Veranstaltung von {0} auswählen
|
||||
localEvents=<Lokale Veranstaltungen>
|
||||
selectALeaderboard=Bitte eine Rangliste auswählen
|
||||
autoplayConfiguration=Automatisches Abspielen konfigurieren
|
||||
startAutoplay=Automatisches Abspielen starten
|
||||
@@ -1466,13 +1469,18 @@ registerBoats=Boote anmelden
|
||||
doYouWantToCreateADefaultRegattaLeaderboard=Möchten Sie eine Standardrangliste für die Regatta anlegen?
|
||||
copyCourse=Kurs kopieren
|
||||
copyCourseAreasFromEvent=Regattabahnen von Veranstaltung kopieren
|
||||
copyCourseAreasFromAnotherUrl=Regattabahnen von anderer URL kopieren:
|
||||
copyCourseAreasFromAnotherUrl=Regattabahnen kopieren von:
|
||||
helptextCopySource=Quelle auswählen, von der Veranstaltungen geladen werden. "<Lokale Veranstaltungen>" für lokale Veranstaltungen, eine Produktions-URL wie https://www.sapsailing.com, oder ein lokaler Entwicklungsserver wie http://localhost:8889.
|
||||
helptextBearerToken=Nur benötigt wenn der externe Server ein anderes Login-System hat. Browser-Entwicklertools öffnen (F12 -> Netzwerk -> beliebige Anfrage -> Authorization-Header, Teil nach "Bearer " kopieren).
|
||||
loadRemoteEvents=Laden
|
||||
bearerTokenOrNullForRemoteEvents=Bearer-Token für externen Server:
|
||||
remoteServerUrlPlaceholder=Server-URL einfügen (leer für lokal)
|
||||
bearerTokenPlaceholder=Leer lassen für aktuellen Benutzer
|
||||
authenticate=Authentifizieren...
|
||||
appendCourseAreas=Auswählen...
|
||||
appendCourseAreasConfirm=Anhängen
|
||||
addAllCourseAreas=Alle hinzufügen
|
||||
chooseWhatToAdd=Was hinzufügen?
|
||||
clearAllCourseAreas=Alle leeren
|
||||
selectCourseAreas=Regattabahnen auswählen
|
||||
resetCourseAreas=Zurücksetzen
|
||||
|
||||
Reference in New Issue
Block a user