mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-10 21:02:40 +00:00
bug4104: Sharing of tags is now supported
This commit is contained in:
1 parent
f56e708848
commit
a5a512acc6
10 files changed
+205
-13
No files matched your search
+5
@@ -2113,6 +2113,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String tagAddTag();
|
||||
String tagEditTag();
|
||||
String tagDeleteTag();
|
||||
String tagShareTag();
|
||||
String tagAddTags();
|
||||
String tagSavedSuccessfully();
|
||||
String tagNotSaved();
|
||||
@@ -2157,4 +2158,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String close();
|
||||
String username();
|
||||
String tagPublicModificationPermissionMissing();
|
||||
String tagNotFound();
|
||||
String tagInvalidURL();
|
||||
String tagSharedDialog();
|
||||
String tagSharedURL();
|
||||
}
|
||||
+5
@@ -2109,6 +2109,7 @@ tagNoTagsFound=No tags found!
|
||||
tagAddTag=Add Tag
|
||||
tagEditTag=Edit Tag
|
||||
tagDeleteTag=Delete Tag
|
||||
tagShareTag=Share Tag
|
||||
tagAddTags=Add Tags
|
||||
tagSavedSuccessfully=Saved tag successfully
|
||||
tagNotSaved=Could not save tag!
|
||||
@@ -2153,3 +2154,7 @@ username=User name
|
||||
confirm=Confirm
|
||||
cancel=Cancel
|
||||
close=Close
|
||||
tagNotFound=Tag could not be found!
|
||||
tagInvalidURL=Invalid URL parameter
|
||||
tagSharedDialog=Shared tag
|
||||
tagSharedURL=URL:
|
||||
+5
@@ -2104,6 +2104,7 @@ tagNoTagsFound=Keine Tags gefunden!
|
||||
tagAddTag=Tag hinzufügen
|
||||
tagEditTag=Tag bearbeiten
|
||||
tagDeleteTag=Tag löschen
|
||||
tagShareTag=Tag teilen
|
||||
tagAddTags=Tags hinzufügen
|
||||
tagSavedSuccessfully=Tag erfolgreich gespeichert
|
||||
tagNotSaved=Tag konnte nicht gespeichert werden!
|
||||
@@ -2148,3 +2149,7 @@ username=Benutzername
|
||||
confirm=Fortfahren
|
||||
cancel=Abbrechen
|
||||
close=Schließen
|
||||
tagNotFound=Tag wurde nicht gefunden!
|
||||
tagInvalidURL=URL Parameter nicht gültig
|
||||
tagSharedDialog=Geteilter Tag
|
||||
tagSharedURL=URL:
|
||||
+8
-2
@@ -302,10 +302,16 @@ public class RaceBoardPanel
|
||||
raceMap.getRightHeaderPanel().add(userManagementMenuView);
|
||||
addChildComponent(raceMap);
|
||||
|
||||
// add panel for tagging functionality, hidden by default
|
||||
// add panel for tagging functionality, hidden if no url parameter "tags" is passed default
|
||||
taggingPanel = new TaggingPanel(parent, componentContext, stringMessages, sailingService, userService, timer, raceTimesInfoProvider);
|
||||
addChildComponent(taggingPanel);
|
||||
taggingPanel.setVisible(false);
|
||||
|
||||
if(Window.Location.getParameter("tag") != null) {
|
||||
taggingPanel.setVisible(true);
|
||||
}
|
||||
else {
|
||||
taggingPanel.setVisible(false);
|
||||
}
|
||||
|
||||
// Determine if the screen is large enough to initially display the leaderboard panel on the left side of the
|
||||
// map based on the initial screen width. Afterwards, the leaderboard panel visibility can be toggled as usual.
|
||||
|
||||
+26
-4
@@ -14,10 +14,13 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
|
||||
import com.google.gwt.safehtml.shared.SafeUri;
|
||||
import com.google.gwt.safehtml.shared.UriUtils;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.raceboard.tagging.TagPanelResources.TagPanelStyle;
|
||||
import com.sap.sailing.gwt.ui.raceboard.tagging.TaggingPanel.State;
|
||||
import com.sap.sse.gwt.client.Notification;
|
||||
import com.sap.sse.gwt.client.Notification.NotificationType;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
/**
|
||||
@@ -29,7 +32,7 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
* Contains different configurations for {@link TagCell}s. Used as {@link SafeHtmlTemplates template} for
|
||||
* {@link TagCell}s. <br/>
|
||||
* <br/>
|
||||
* <b>Notice:</b> CSS classes need to be provied as parameters as CSS classnames are context sensitive and can't be
|
||||
* <b>Notice:</b> CSS classes need to be provided as parameters as CSS classnames are context sensitive and can't be
|
||||
* hardcoded.
|
||||
*/
|
||||
protected interface TagCellTemplate extends SafeHtmlTemplates {
|
||||
@@ -49,11 +52,13 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
* @param content
|
||||
* available configurations are {@link #contentWithCommentWithImage},
|
||||
* {@link #contentWithCommentWithoutImage} and {@link #contentWithoutCommentWithImage}.
|
||||
* @param shareButton
|
||||
* @param content2
|
||||
* @return {@link SafeHtml HTML template}
|
||||
*/
|
||||
@Template("<div class='{0}'><div class='{1}'>{3}{4}{5}</div><div class='{2}'>{6}</div>{7}</div>")
|
||||
@Template("<div class='{0}'><div class='{1}'>{3}{4}{5}{8}</div><div class='{2}'>{6}</div>{7}</div>")
|
||||
SafeHtml cell(String classTag, String classTagHeading, String classTagCreated, SafeHtml icon, SafeHtml buttons,
|
||||
SafeHtml tag, SafeHtml created, SafeHtml content);
|
||||
SafeHtml tag, SafeHtml created, SafeHtml content, SafeHtml shareButtonHeader);
|
||||
|
||||
/**
|
||||
* Renders content with maximal configuration (comment and image).
|
||||
@@ -105,6 +110,14 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
SafeHtml headerButtonsDeletableAndModifyable(String classTagHeadingButtons, SafeHtml editButton,
|
||||
SafeHtml deleteButton);
|
||||
|
||||
/**
|
||||
* Renders part of heading holding a button to share a tag.
|
||||
*
|
||||
* @return {@link SafeHtml HTML template}
|
||||
*/
|
||||
@Template("<div class='{0}'>{1}</div>")
|
||||
SafeHtml shareButtonHeader(String classTagHeadingButtons, SafeHtml shareButton);
|
||||
|
||||
/**
|
||||
* Renders icon with given source.
|
||||
*
|
||||
@@ -185,6 +198,10 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
icon = tagCellTemplate.icon(safeIsPrivateImageUri);
|
||||
}
|
||||
|
||||
SafeHtml shareButton = tagCellTemplate.button(style.tagActionButton() + " " + style.tagShareButton(),
|
||||
stringMessages.tagShareTag(), tagCellTemplate.icon(resources.shareIcon().getSafeUri()));
|
||||
SafeHtml shareButtonHeader = tagCellTemplate.shareButtonHeader(style.tagCellHeadingButtons(), shareButton);
|
||||
|
||||
SafeHtml headingButtons = SafeHtmlUtils.EMPTY_SAFE_HTML;
|
||||
// preview cells do not show buttons
|
||||
if (!isPreviewCell) {
|
||||
@@ -213,7 +230,7 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
cellStyle = style.tagCell() + " " + style.tagCellActive();
|
||||
}
|
||||
SafeHtml cell = tagCellTemplate.cell(cellStyle, style.tagCellHeading(), style.tagCellCreated(), icon,
|
||||
headingButtons, safeTag, safeCreated, content);
|
||||
headingButtons, safeTag, safeCreated, content, shareButtonHeader);
|
||||
htmlBuilder.append(cell);
|
||||
}
|
||||
|
||||
@@ -251,6 +268,11 @@ public class TagCell extends AbstractCell<TagDTO> {
|
||||
});
|
||||
} else if (button.hasClassName(style.tagEditButton())) {
|
||||
taggingPanel.setCurrentState(State.EDIT_TAG);
|
||||
} else if (button.hasClassName(style.tagShareButton())) {
|
||||
String currentURL = Window.Location.getHref();
|
||||
String urlWithTagParam = currentURL
|
||||
.concat("&tag=" + tag.getRaceTimepoint().asMillis() + tag.getTag());
|
||||
new TagSharedURLDialog(taggingPanel, urlWithTagParam).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -11,6 +11,9 @@ import com.google.gwt.resources.client.ImageResource;
|
||||
public interface TagPanelResources extends ClientBundle {
|
||||
public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class);
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/share.png")
|
||||
ImageResource shareIcon();
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/edit.png")
|
||||
ImageResource editIcon();
|
||||
|
||||
@@ -62,6 +65,7 @@ public interface TagPanelResources extends ClientBundle {
|
||||
String tagActionButton();
|
||||
String tagEditButton();
|
||||
String tagDeleteButton();
|
||||
String tagShareButton();
|
||||
String tagCellCreated();
|
||||
String tagCellComment();
|
||||
String tagCellImage();
|
||||
@@ -100,6 +104,11 @@ public interface TagPanelResources extends ClientBundle {
|
||||
String tagFilterSearchBox();
|
||||
String tagFilterSearchInput();
|
||||
String tagFilterCurrentSelection();
|
||||
|
||||
//shared tag dialog
|
||||
String tagSharedURLLabel();
|
||||
String tagSharedURLTextBox();
|
||||
String tagSharedURLDialog();
|
||||
|
||||
// images
|
||||
String imageActiveFilter();
|
||||
@@ -108,6 +117,7 @@ public interface TagPanelResources extends ClientBundle {
|
||||
String imageClearSearch();
|
||||
String imageSettings();
|
||||
String imagePusTransparent();
|
||||
String imageShare();
|
||||
String imageEdit();
|
||||
String imageDelete();
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard.tagging;
|
||||
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Panel;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.raceboard.tagging.TagPanelResources.TagPanelStyle;
|
||||
|
||||
/**
|
||||
* A Dialog to show the URL of shared tags
|
||||
*/
|
||||
public class TagSharedURLDialog extends DialogBox {
|
||||
|
||||
private final TagPanelResources resources = TagPanelResources.INSTANCE;
|
||||
private final TagPanelStyle style = resources.style();
|
||||
|
||||
/**
|
||||
* Creates a Dialog which shows the user the URL of the tag he wants to share
|
||||
*
|
||||
* @param taggingPanel
|
||||
* {@link TaggingPanel} which creates this {@link TagSharedURLDialog}.
|
||||
* @param url
|
||||
* A URL which if called opens the {@link TaggingPanel} and selects the shared tag.
|
||||
*/
|
||||
public TagSharedURLDialog(TaggingPanel taggingPanel, String url) {
|
||||
StringMessages stringMessages = taggingPanel.getStringMessages();
|
||||
|
||||
Panel mainPanel = new FlowPanel();
|
||||
|
||||
Label descriptionLabel = new Label();
|
||||
descriptionLabel.setText(stringMessages.tagSharedURL());
|
||||
descriptionLabel.setStyleName(style.tagSharedURLLabel());
|
||||
descriptionLabel.addStyleName("gwt-Label");
|
||||
|
||||
TextBox urlTextBox = new TextBox();
|
||||
urlTextBox.setText(url);
|
||||
urlTextBox.setStyleName(style.tagSharedURLTextBox());
|
||||
urlTextBox.addStyleName("gwt-TextBox");
|
||||
|
||||
Panel buttonPanel = new FlowPanel();
|
||||
buttonPanel.setStyleName(style.buttonsPanel());
|
||||
|
||||
Button closeButton = new Button(stringMessages.close());
|
||||
closeButton.setStyleName(style.tagDialogButton());
|
||||
closeButton.addStyleName("gwt-Button");
|
||||
closeButton.addClickHandler(event -> {
|
||||
hide();
|
||||
});
|
||||
buttonPanel.add(closeButton);
|
||||
|
||||
mainPanel.add(descriptionLabel);
|
||||
mainPanel.add(urlTextBox);
|
||||
mainPanel.add(buttonPanel);
|
||||
|
||||
setGlassEnabled(true);
|
||||
setText(stringMessages.tagSharedDialog());
|
||||
addStyleName(style.tagSharedURLDialog());
|
||||
setWidget(mainPanel);
|
||||
center();
|
||||
}
|
||||
|
||||
}
|
||||
+55
-5
@@ -8,6 +8,7 @@ import java.util.Map;
|
||||
import com.google.gwt.core.shared.GWT;
|
||||
import com.google.gwt.user.cellview.client.CellList;
|
||||
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
|
||||
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;
|
||||
@@ -51,9 +52,9 @@ import com.sap.sse.security.ui.shared.UserDTO;
|
||||
* will be stored in the {@link com.sap.sse.security.UserStore UserStore}.<br/>
|
||||
* <br/>
|
||||
* The TaggingPanel is also used as a data provider for all of its subcomponents like header, footer and content
|
||||
* section. Therefor the TaggingPanel provides references to important services, string messages, its current state ando
|
||||
* section. Therefore the TaggingPanel provides references to important services, string messages, its current state ando
|
||||
* so on.
|
||||
* Best practise: The constructor of subcomponents of the TaggingPanel contains only the TaggingPanel as a parameter.
|
||||
* Best practice: The constructor of subcomponents of the TaggingPanel contains only the TaggingPanel as a parameter.
|
||||
* Every other required shared resource (string messages, service references, ...) can be requested from the
|
||||
* TaggingPanel itself.
|
||||
*/
|
||||
@@ -100,6 +101,11 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
|
||||
// current state of the Tagging-Panel
|
||||
private State currentState;
|
||||
|
||||
//Needed for sharing Tags
|
||||
private boolean firstTimePublicTagsLoaded = true;
|
||||
private final TimePoint sharedTimePoint;
|
||||
private final String sharedTag;
|
||||
|
||||
public TaggingPanel(Component<?> parent, ComponentContext<?> context, StringMessages stringMessages,
|
||||
SailingServiceAsync sailingService, UserService userService, Timer timer,
|
||||
@@ -132,6 +138,26 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(this);
|
||||
|
||||
setCurrentState(State.VIEW);
|
||||
|
||||
//Get the url parameter "tag" and divide it into the logical timepoint and the tag title
|
||||
String urlParameter = Window.Location.getParameter("tag");
|
||||
if(urlParameter != null) {
|
||||
if(urlParameter.length() > 13) {
|
||||
String timeMillisString = urlParameter.substring(0, 13);//Works till "Nov 20 2286", afterwards timeMillis length increases from 13 to 14 chars
|
||||
String tagString = urlParameter.substring(13, urlParameter.length());
|
||||
sharedTimePoint = new MillisecondsTimePoint(Long.parseLong(timeMillisString));
|
||||
sharedTag = tagString;
|
||||
}
|
||||
else {
|
||||
Notification.notify(stringMessages.tagInvalidURL(), NotificationType.WARNING);
|
||||
sharedTimePoint = null;
|
||||
sharedTag = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sharedTimePoint = null;
|
||||
sharedTag = null;
|
||||
}
|
||||
|
||||
initializePanel();
|
||||
}
|
||||
@@ -236,7 +262,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
NotificationType.WARNING);
|
||||
|
||||
} else if (!isLoggedInAndRaceLogAvailable()) {
|
||||
// User is not logged in or race can not be identifed because regatta, race column or fleet are missing.
|
||||
// User is not logged in or race can not be identified because regatta, race column or fleet are missing.
|
||||
Notification.notify(stringMessages.tagNotSaved(), NotificationType.ERROR);
|
||||
|
||||
} else if (tag.isEmpty()) {
|
||||
@@ -540,7 +566,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
for (TagDTO tag : raceInfo.getTags()) {
|
||||
if (tag.getRevokedAt() != null) {
|
||||
// received tag is revoked => latestReceivedTagTime will be revokedAt if revoke event
|
||||
// occured before latestReceivedTagTime
|
||||
// occurred before latestReceivedTagTime
|
||||
currentTags.remove(tag);
|
||||
modifiedTags = true;
|
||||
if (latestReceivedTagTime == null || (latestReceivedTagTime != null
|
||||
@@ -550,7 +576,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
}
|
||||
} else if (!currentTags.contains(tag)) {
|
||||
// received tag is NOT revoked => latestReceivedTagTime will be createdAt if tag event
|
||||
// occured before latestReceivedTagTime
|
||||
// occurred before latestReceivedTagTime
|
||||
currentTags.add(tag);
|
||||
modifiedTags = true;
|
||||
if (latestReceivedTagTime == null || (latestReceivedTagTime != null
|
||||
@@ -569,6 +595,30 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
if (modifiedTags) {
|
||||
updateContent();
|
||||
}
|
||||
//After tags were added for the first time, find tag which matches the URL Parameter "tag", hightlight it and jump to its logical timepoint
|
||||
if(firstTimePublicTagsLoaded && raceInfo.getTags() != null) {
|
||||
firstTimePublicTagsLoaded = false;
|
||||
if(sharedTimePoint != null) {
|
||||
timer.setTime(sharedTimePoint.asMillis());
|
||||
if(sharedTag != null) {
|
||||
TagDTO matchingTag = null;
|
||||
for(TagDTO tag: tagListProvider.getAllTags()) {
|
||||
if(tag.getRaceTimepoint().equals(sharedTimePoint) && tag.getTag().equals(sharedTag)) {
|
||||
matchingTag = tag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(matchingTag != null) {
|
||||
tagSelectionModel.clear();
|
||||
tagSelectionModel.setSelected(matchingTag, true);
|
||||
}
|
||||
else {
|
||||
Notification.notify(stringMessages.tagNotFound(), NotificationType.WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -70,6 +70,7 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/**************************** Tag-Cells ****************************/
|
||||
.tagCell {
|
||||
box-shadow: 1px 2px 3px lightgrey;
|
||||
@@ -380,6 +381,20 @@
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/**************************** SharedTag Dialog ****************************/
|
||||
.tagSharedURLLabel{
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.tagSharedURLTextBox{
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.tagSharedURLDialog{
|
||||
|
||||
}
|
||||
|
||||
/**************************** Disabled tags (during editing) ****************************/
|
||||
.taggingPanelDisabled .tagCell {
|
||||
background-color: lightgrey;
|
||||
@@ -389,19 +404,28 @@
|
||||
.taggingPanelDisabled .tagCell.tagCellActive {
|
||||
background-color: #e5f2f9;
|
||||
}
|
||||
|
||||
.taggingPanelDisabled .tagCellHeadingButtons,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagEditButton,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagEditButton:hover,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagEditButton:focus,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagDeleteButton,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagDeleteButton:hover,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagDeleteButton:focus {
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagDeleteButton:focus,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagShareButton,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagShareButton:hover,
|
||||
.taggingPanelDisabled .tagCellHeadingButtons .tagShareButton:focus{
|
||||
cursor: not-allowed;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/**************************** Images ****************************/
|
||||
.imageShare {
|
||||
gwt-sprite: "shareIcon";
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.imageEdit {
|
||||
gwt-sprite: "editIcon";
|
||||
width: 2em;
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 312 B |
Reference in new issue
Block a user