Bug 4104: Added Javadoc comments in com.sap.sailing.gwt.ui.raceboard.tagging package.

This commit is contained in:
Henri Kohlberg committed 2018-09-04 16:13:07 +02:00
1 parent 08a685fee0
commit be3392b498
18 files changed
+727 -235

No files matched your search

@@ -12,13 +12,24 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.raceboard.tagging.TagPanelResources.TagPanelStyle;
/**
* Used to show generic confirmation dialog to ask user for explicit confirmation of an action.
* Used to show generic confirmation dialog to ask user for explicit confirmation of an action. Can be used to make sure
* the user wants to delete something.
*/
public class ConfirmationDialog extends DialogBox {
private final TagPanelResources resources = TagPanelResources.INSTANCE;
private final TagPanelStyle style = resources.style();
/**
* Shows a centered dialog popup wich asks the user if the given action (<code>text</code>) should be confirmed.
*
* @param title
* title of dialog popup
* @param text
* question shown to user which needs confirmation
* @param consumer
* returns <code>true</code> if user clicks the confirm-button, otherwise <code>false</code>.
*/
public ConfirmationDialog(StringMessages stringMessages, String title, String text, Consumer<Boolean> consumer) {
Panel mainPanel = new FlowPanel();
mainPanel.setStyleName(style.confirmationDialogPanel());
@@ -6,7 +6,9 @@ import com.google.gwt.user.client.ui.Button;
import com.sap.sailing.gwt.ui.raceboard.tagging.TagPanelResources.TagPanelStyle;
/**
* Used to store tag button data and creates new tag event when clicking the button.
* Used to store preset {@link com.sap.sailing.gwt.ui.shared.TagDTO tags} which will be rendered in {@link TaggingPanel}
* as buttons for quick and easy access. Clicking on tag-buttons does not have any effect until click listener gets
* added manually! See example at {@link TaggingPanel#addTagButton(TagButton) addTagButton()}.
*/
public class TagButton extends Button implements Serializable {
@@ -17,8 +19,21 @@ public class TagButton extends Button implements Serializable {
private String tag, imageURL, comment;
private boolean visibleForPublic;
public TagButton(String buttonName, String tag, String imageURL, String comment,
boolean visibleForPublic) {
/**
* Creates tag button with given attributes.
*
* @param buttonName
* Usually equal with title
* @param tag
* title of corresponding tag
* @param imageURL
* URL to optional image of corresponding tag, may be <code>null</code> in case of missing image
* @param comment
* optional comment of corresponding tag, may be <code>null</code> in case of missing comment
* @param visibleForPublic
* should be <code>true</code> if everybody should see the generated tag, otherwise <code>false</code>
*/
protected TagButton(String buttonName, String tag, String imageURL, String comment, boolean visibleForPublic) {
super(buttonName);
setStyleName(style.tagDialogButton());
@@ -30,35 +45,79 @@ public class TagButton extends Button implements Serializable {
addStyleName("gwt-Button");
}
public String getTag() {
/**
* Returns title of corresponding tag.
*
* @return title of tag
*/
protected String getTag() {
return tag;
}
public String getImageURL() {
/**
* Returns image URL of corresponding tag.
*
* @return image URL of tag
*/
protected String getImageURL() {
return imageURL;
}
public String getComment() {
/**
* Returns comment of corresponding tag.
*
* @return comment of tag
*/
protected String getComment() {
return comment;
}
public boolean isVisibleForPublic() {
/**
* Returns visibility of corresponding tag.
*
* @return <code>true</code> if tag is visible for public, otherwise <code>false</code>
*/
protected boolean isVisibleForPublic() {
return visibleForPublic;
}
public void setTag(String tag) {
/**
* Sets title of corresponding tag.
*
* @param tag
* title, must not be <code>null</code>
*/
protected void setTag(String tag) {
this.tag = tag;
}
public void setImageURL(String imageURL) {
/**
* Sets optional image URL of corresponding tag.
*
* @param imageURL
* image URL, may be <code>null</code>
*/
protected void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
public void setComment(String comment) {
/**
* Sets optional comment of corresponding tag.
*
* @param comment
* comment, may be <code>null</code>
*/
protected void setComment(String comment) {
this.comment = comment;
}
public void setVisibleForPublic(boolean visibleForPublic) {
/**
* Sets visibility of corresponding tag.
*
* @param visibleForPublic
* should be <code>true</code> if tag is visible for public, otherwise <code>false</code>
*/
protected void setVisibleForPublic(boolean visibleForPublic) {
this.visibleForPublic = visibleForPublic;
}
}
@@ -3,6 +3,9 @@ package com.sap.sailing.gwt.ui.raceboard.tagging;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.cellview.client.CellTable;
/**
* Interface for styling cell table containing {@link TagButton} at {@link TagButtonDialog}.
*/
public interface TagButtonCellTableResources extends CellTable.Resources {
public static final TagButtonCellTableResources INSTANCE = GWT.create(TagCellListResources.class);
@@ -25,10 +25,14 @@ import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
/**
* Dialog for modifying tag buttons
* Dialog which allows users to modify their personal {@link TagButton tag-buttons}.
*/
public class TagButtonDialog extends DialogBox {
/**
* Preset layout for action column at the {@link TagButtonDialog#createTable tag button table} used in the
* {@link TagButtonDialog}.
*/
private class EditTagButtonsImagesBarCell extends ImagesBarCell {
public static final String ACTION_REMOVE = "ACTION_REMOVE";
public static final String ACTION_EDIT = "ACTION_EDIT";
@@ -57,6 +61,14 @@ public class TagButtonDialog extends DialogBox {
private Button closeButton, saveButton, cancelButton, addTagButtonButton;
private TagButton selectedTagButton;
/**
* Centered dialog wich allows users to edit their personal {@link TagButton tag-buttons}.
*
* @param taggingPanel
* {@link TaggingPanel} which creates this {@link TagButtonDialog}.
* @param footerPanel
* footer panel of {@link TaggingPanel}
*/
public TagButtonDialog(TaggingPanel taggingPanel, TagFooterPanel footerPanel) {
this.taggingPanel = taggingPanel;
this.stringMessages = taggingPanel.getStringMessages();
@@ -87,6 +99,18 @@ public class TagButtonDialog extends DialogBox {
center();
}
/**
* Creates table which shows tag buttons as a compact overview in form of a table.
*
* @param footerPanel
* footer panel of {@link TaggingPanel}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
* @return {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton tag-buttons}
*/
private CellTable<TagButton> createTable(TagFooterPanel footerPanel, TagInputPanel inputPanel,
TagPreviewPanel tagPreviewPanel) {
CellTable<TagButton> tagButtonTable = new CellTable<TagButton>(15, buttonTableResources);
@@ -175,6 +199,22 @@ public class TagButtonDialog extends DialogBox {
return tagButtonTable;
}
/**
* Creates a {@link Panel} containing all action buttons of the {@link TagButtonDialog} to create {@link TagButton
* tag-buttons}, save changes, discard changes and close the {@link TagButtonDialog}.
*
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
* @param footerPanel
* footer panel of {@link TaggingPanel}
* @return {@link Panel} containing all action buttons
*/
private Panel createButtonPanel(CellTable<TagButton> tagButtonTable, TagInputPanel inputPanel,
TagPreviewPanel tagPreviewPanel, TagFooterPanel footerPanel) {
addSaveButton(footerPanel, tagButtonTable, inputPanel, tagPreviewPanel);
@@ -192,6 +232,20 @@ public class TagButtonDialog extends DialogBox {
return controlButtonPanel;
}
/**
* Creates a button allowing users to save their changes on a {@link TagButton}.
*
* @param footerPanel
* footer panel of {@link TaggingPanel}
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
*/
private void addSaveButton(TagFooterPanel footerPanel, CellTable<TagButton> tagButtonTable,
TagInputPanel inputPanel, TagPreviewPanel tagPreviewPanel) {
saveButton = new Button(stringMessages.save());
@@ -223,6 +277,18 @@ public class TagButtonDialog extends DialogBox {
});
}
/**
* Creates a button allowing users to discard their changes on a {@link TagButton}.
*
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
*/
private void addCancelButton(TagInputPanel inputPanel, TagPreviewPanel tagPreviewPanel,
CellTable<TagButton> tagButtonTable) {
cancelButton = new Button(stringMessages.cancel());
@@ -242,6 +308,18 @@ public class TagButtonDialog extends DialogBox {
});
}
/**
* Creates a button allowing users to close the {@link TagButtonDialog}.
*
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
*/
private void addCloseButton(TagFooterPanel footerPanel, TagPreviewPanel tagPreviewPanel) {
closeButton = new Button(stringMessages.close());
closeButton.setStyleName(style.tagDialogButton());
@@ -249,6 +327,20 @@ public class TagButtonDialog extends DialogBox {
closeButton.addClickHandler(event -> hide());
}
/**
* Creates a button allowing users to add a new {@link TagButton}.
*
* @param footerPanel
* footer panel of {@link TaggingPanel}
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param inputPanel
* input fields of {@link TagButtonDialog} which allow to create new and modify existing {@link TagButton
* tag-buttons}
* @param tagPreviewPanel
* renders {@link TagPreviewPanel} preview of current input fields
*/
private void addTagButtonButton(TagFooterPanel footerPanel, CellTable<TagButton> tagButtonTable,
TagInputPanel inputPanel, TagPreviewPanel tagPreviewPanel) {
addTagButtonButton = new Button(stringMessages.tagAddCustomTagButton());
@@ -271,6 +363,17 @@ public class TagButtonDialog extends DialogBox {
});
}
/**
* Sets the given <code>buttons</code> as value for the given <code>tagButtonTable</code>. If <code>buttons</code>
* is empty, <code>tagButtonTable</code> will be hidden.
*
* @param tagButtonTable
* {@link com.google.gwt.user.cellview.client.CellTable CellTable} containing {@link TagButton
* tag-buttons}
* @param buttons
* List of {@link TagButton tag-buttons} which represents the local version of the current users
* {@link TagButton tag-buttons}.
*/
private void setRowData(CellTable<TagButton> tagButtonTable, List<TagButton> buttons) {
tagButtonTable.setRowData(buttons);
tagButtonTable.setVisible(!buttons.isEmpty());
@@ -10,7 +10,8 @@ import com.google.gwt.json.client.JSONString;
import com.sap.sailing.gwt.ui.client.GwtJsonDeSerializer;
/**
* Serializes and deserializes TagButtons to save them in User Storage.
* Serializes and deserializes {@link TagButton tag-buttons} to save them in the {@link com.sap.sse.security.UserStore
* UserStore}.
*/
public class TagButtonJsonDeSerializer implements GwtJsonDeSerializer<List<TagButton>> {
@@ -14,7 +14,7 @@ import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.security.ui.client.UserService;
/**
* Displays tag buttons of current user.
* Panel used to show the {@link TagButton tag-buttons} of {@link UserService#getCurrentUser() current user}.
*/
public class TagButtonPanel extends FlowPanel {
@@ -30,7 +30,11 @@ public class TagButtonPanel extends FlowPanel {
private final Label heading;
private final Panel tagButtonsPanel;
public TagButtonPanel(TagFooterPanel footerPanel, TaggingPanel taggingPanel) {
/**
* Displays {@link TagButton tag-buttons} of {@link UserService#getCurrentUser() current user} at the footer of the
* {@link TaggingPanel}.
*/
protected TagButtonPanel(TaggingPanel taggingPanel, TagFooterPanel footerPanel) {
this.footerPanel = footerPanel;
this.taggingPanel = taggingPanel;
this.stringMessages = taggingPanel.getStringMessages();
@@ -47,25 +51,8 @@ public class TagButtonPanel extends FlowPanel {
}
/**
* Stores local copy of tag buttons from current user in user storage.
*/
protected void storeAllTagButtons() {
TagButtonJsonDeSerializer serializer = new TagButtonJsonDeSerializer();
JSONObject jsonObject = serializer.serialize(taggingPanel.getTagButtons());
userService.setPreference(USER_STORAGE_TAG_BUTTONS_KEY, jsonObject.toString(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Notification.notify(stringMessages.tagButtonNotSavable(), NotificationType.WARNING);
}
@Override
public void onSuccess(Void result) {
}
});
}
/**
* Loads all tag buttons from current user from user storage and displays them.
* Loads all {@link TagButton tag-buttons} of {@link UserService#getCurrentUser() current user} from
* {@link com.sap.sse.security.UserStore UserStore} and displays them.
*/
protected void loadAllTagButtons() {
tagButtonsPanel.clear();
@@ -100,9 +87,31 @@ public class TagButtonPanel extends FlowPanel {
}
/**
* If the height of the tagButtonsPanel has changed after deleting all tag buttons (delta not equals 0 ), the
* footerWidget of the TaggingPanel has a different height, which in this case might cause the contentWidget to be
* to small. In case no tag buttons are available for the current user, tag button panel will be hidden.
* Stores {@link TaggingPanel#getTagButtons() local copy} of {@link TagButton tag-buttons} of the
* {@link UserService#getCurrentUser() current user} in {@link com.sap.sse.security.UserStore UserStore}.
*/
protected void storeAllTagButtons() {
TagButtonJsonDeSerializer serializer = new TagButtonJsonDeSerializer();
JSONObject jsonObject = serializer.serialize(taggingPanel.getTagButtons());
userService.setPreference(USER_STORAGE_TAG_BUTTONS_KEY, jsonObject.toString(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Notification.notify(stringMessages.tagButtonNotSavable(), NotificationType.WARNING);
}
@Override
public void onSuccess(Void result) {
}
});
}
/**
* If the height of the {@link #tagButtonsPanel} has changed after deleting all {@link TagButton tag-buttons} (delta
* height does not equal 0), the {@link TaggingPanel}s
* {@link com.google.gwt.user.client.ui.HeaderPanel#getFooterWidget() footer widget} has a different height, which
* in this case might cause the {@link TaggingPanel#contentPanel contentWidget} to be to small. In case no
* {@link TagButton tag-buttons} are available for the {@link UserService#getCurrentUser() current user},
* {@link TagButtonPanel} will be hidden.
*/
protected void recalculateHeight() {
if (taggingPanel.getTagButtons().size() == 0) {
@@ -23,30 +23,108 @@ import com.sap.sse.security.ui.client.UserService;
*/
public class TagCell extends AbstractCell<TagDTO> {
public interface TagCellTemplate extends SafeHtmlTemplates {
/**
* 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
* hardcoded.
*/
protected interface TagCellTemplate extends SafeHtmlTemplates {
/**
* Renders public, non-removable cell with different content configurations
*
* @param tag
* title
* @param createdAt
* contains author name and createdAt time
* @param content
* available configurations are {@link #contentWithCommentWithImage},
* {@link #contentWithCommentWithoutImage} and {@link #contentWithoutCommentWithImage}.
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><div class='{1}'>{3}</div><div class='{2}'>{4}</div>{5}</div>")
SafeHtml cell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt,
SafeHtml content);
/**
* Renders public, removable cell with different content configurations
*
* @param tag
* title
* @param createdAt
* contains author name and createdAt time
* @param content
* available configurations are {@link #contentWithCommentWithImage},
* {@link #contentWithCommentWithoutImage} and {@link #contentWithoutCommentWithImage}.
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><div class='{1}'>{3}<div style=\"position: relative\"><button>X</button></div></div><div class='{2}'>{4}</div>{5}</div>")
SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag,
SafeHtml createdAt, SafeHtml content);
/**
* Renders private, non-removable cell with different content configurations
*
* @param tag
* title
* @param createdAt
* contains author name and createdAt time
* @param content
* available configurations are {@link #contentWithCommentWithImage},
* {@link #contentWithCommentWithoutImage} and {@link #contentWithoutCommentWithImage}.
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><div class='{1}'><img src='{6}'>{3}</div><div class='{2}'>{4}</div>{5}</div>")
SafeHtml privateCell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag,
SafeHtml createdAt, SafeHtml content, SafeUri safeUri);
/**
* Renders private, removable cell with different content configurations
*
* @param tag
* title
* @param createdAt
* contains author name and createdAt time
* @param content
* available configurations are {@link #contentWithCommentWithImage},
* {@link #contentWithCommentWithoutImage} and {@link #contentWithoutCommentWithImage}.
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><div class='{1}'><img src='{6}'>{3}<div style=\"position: relative\"><button>X</button></div></div><div class='{2}'>{4}</div>{5}</div>")
SafeHtml privateCellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag,
SafeHtml createdAt, SafeHtml content, SafeUri safeUri);
/**
* Renders content with maximal configuration (comment and image).
*
* @param imageURL
* image URL
* @param comment
* comment
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><img src='{2}'/></div><div class='{1}'>{3}</div>")
SafeHtml contentWithCommentWithImage(String styleTagImage, String styleTagComment, SafeUri imageURL,
SafeHtml comment);
/**
* Renders content with mixed configuration (comment, no image).
*
* @param comment
* comment
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'>{1}</div>")
SafeHtml contentWithCommentWithoutImage(String styleTagComment, SafeHtml comment);
/**
* Renders content with mixed configuration (image, no comment).
*
* @param imageURL
* image URL
* @return {@link SafeHtml HTML template}
*/
@Template("<div class='{0}'><img src='{1}'/></div>")
SafeHtml contentWithoutCommentWithImage(String styleTagImage, SafeUri imageURL);
}
@@ -60,6 +138,15 @@ public class TagCell extends AbstractCell<TagDTO> {
private final UserService userService;
private final boolean isPreviewCell;
/**
* Displays the content of a {@link TagDTO tag} by using {@link SafeHtmlTemplates}.
*
* @param taggingPanel
* instance of {@link TaggingPanel}
* @param isPreviewCell
* should be <code>true</code> if {@link TagCell cell} is used as {@link TagPreviewPanel preview cell},
* otherwise <code>false</code>
*/
public TagCell(TaggingPanel taggingPanel, boolean isPreviewCell) {
super("click");
this.taggingPanel = taggingPanel;
@@ -68,6 +155,10 @@ public class TagCell extends AbstractCell<TagDTO> {
this.isPreviewCell = isPreviewCell;
}
/**
* Renders {@link TagDTO tag} and appends it to given {@link SafeHtmlBuilder html builder}. Checks tag for available
* attributes and chooses suitable {@link TagCellTemplate rendering template}.
*/
@Override
public void render(Context context, TagDTO tag, SafeHtmlBuilder htmlBuilder) {
if (tag == null) {
@@ -121,6 +212,12 @@ public class TagCell extends AbstractCell<TagDTO> {
htmlBuilder.append(cell);
}
/**
* Asks user for confirmation if user presses the delete button on the {@link TagCell}. If user confirms deletion,
* {@link TagDTO tag} will be deleted from {@link TaggingPanel} including
* {@link com.sap.sailing.domain.abstractlog.race.RaceLog RaceLog} or {@link com.sap.sse.security.UserStore
* UserStore}, depending on where the tag is saved.
*/
@Override
public void onBrowserEvent(Context context, Element parent, TagDTO tag, NativeEvent event,
ValueUpdater<TagDTO> valueUpdater) {
@@ -3,6 +3,10 @@ package com.sap.sailing.gwt.ui.raceboard.tagging;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.cellview.client.CellList;
/**
* Interface for styling {@link TaggingPanel#tagCellList cell list} containing {@link TagCell} at
* {@link TaggingPanel#contentPanel TaggingPanel}.
*/
public interface TagCellListResources extends CellList.Resources {
public static final TagCellListResources INSTANCE = GWT.create(TagCellListResources.class);
@@ -9,7 +9,8 @@ import com.sap.sailing.gwt.ui.raceboard.tagging.TagPanelResources.TagPanelStyle;
import com.sap.sailing.gwt.ui.raceboard.tagging.TaggingPanel.State;
/**
* Panel used to create tags and tag buttons in side menu of RaceBoard.
* Panel used to create tags and {@link TagButton tag-buttons} at the {@link TaggingPanel#footerPanel footer} of the
* {@link TaggingPanel}.
*/
public class TagCreationPanel extends FlowPanel {
@@ -17,7 +18,15 @@ public class TagCreationPanel extends FlowPanel {
private final StringMessages stringMessages;
public TagCreationPanel(TagFooterPanel tagFooterPanel, TaggingPanel taggingPanel) {
/**
* Creates panel used to create tags and {@link TagButton tag-buttons}.
*
* @param taggingPanel
* provides reference to {@link StringMessages}
* @param tagFooterPanel
* required for creation of {@link TagButton tag-buttons}
*/
protected TagCreationPanel(TaggingPanel taggingPanel, TagFooterPanel tagFooterPanel) {
this.stringMessages = taggingPanel.getStringMessages();
setStyleName(style.tagCreationPanel());
@@ -12,7 +12,7 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* Serializes and deserializes TagDTOs.
* Serializes and deserializes {@link TagDTO}.
*/
public class TagDTOJsonDeSerializer {
@@ -26,6 +26,13 @@ public class TagDTOJsonDeSerializer {
private static final String FIELD_CREATED_AT = "createdAt";
private static final String FIELD_REVOKED_AT = "revokedAt";
/**
* Serializes list of {@link TagDTO tags} to {@link JSONObject json}.
*
* @param tags
* list to be seriaized
* @return {@link JSONObject json object}
*/
public JSONObject serialize(List<TagDTO> tags) {
JSONObject result = new JSONObject();
@@ -41,18 +48,25 @@ public class TagDTOJsonDeSerializer {
tagObject.put(FIELD_IMAGE_URL, new JSONString(tag.getImageURL()));
tagObject.put(FIELD_USERNAME, new JSONString(tag.getUsername()));
tagObject.put(FIELD_VISIBLE_FOR_PUBLIC, JSONBoolean.getInstance(tag.isVisibleForPublic()));
tagObject.put(FIELD_RACE_TIMEPOINT, timePointToString(tag.getRaceTimepoint()));
tagObject.put(FIELD_CREATED_AT, timePointToString(tag.getCreatedAt()));
tagObject.put(FIELD_REVOKED_AT, timePointToString(tag.getRevokedAt()));
tagObject.put(FIELD_RACE_TIMEPOINT, serializeTimePoint(tag.getRaceTimepoint()));
tagObject.put(FIELD_CREATED_AT, serializeTimePoint(tag.getCreatedAt()));
tagObject.put(FIELD_REVOKED_AT, serializeTimePoint(tag.getRevokedAt()));
}
return result;
}
public List<TagDTO> deserialize(JSONObject rootObject) {
/**
* Deserializes {@link JSONObject json} to list of {@link TagDTO tags}.
*
* @param jsonObject
* {@link JSONObject json} to be deserialized
* @return {@link TagDTO list of tags}
*/
public List<TagDTO> deserialize(JSONObject jsonObject) {
List<TagDTO> result = null;
if (rootObject != null) {
if (jsonObject != null) {
result = new ArrayList<TagDTO>();
JSONArray tagsArray = (JSONArray) rootObject.get(FIELD_TAGS);
JSONArray tagsArray = (JSONArray) jsonObject.get(FIELD_TAGS);
for (int i = 0; i < tagsArray.size(); i++) {
JSONObject tagValue = (JSONObject) tagsArray.get(i);
JSONString tag = (JSONString) tagValue.get(FIELD_TAG);
@@ -75,7 +89,14 @@ public class TagDTOJsonDeSerializer {
return result;
}
private JSONString timePointToString(TimePoint timepoint) {
/**
* Serializes given {@link TimePoint} to {@link JSONString json}.
*
* @param timepoint
* {@link TimePoint} to be serialized
* @return {@link JSONString json}
*/
private JSONString serializeTimePoint(TimePoint timepoint) {
if (timepoint != null) {
return new JSONString(Long.toString(timepoint.asMillis()));
} else {
@@ -83,6 +104,13 @@ public class TagDTOJsonDeSerializer {
}
}
/**
* Deserializes {@link String timepoint-string} to {@link TimePoint}.
*
* @param timepoint
* {@link String timepoint} to be deserialized
* @return {@link TimePoint}
*/
private TimePoint deserilizeTimePoint(String timepoint) {
if (!timepoint.isEmpty()) {
return new MillisecondsTimePoint(Long.parseLong(timepoint));
@@ -91,11 +119,35 @@ public class TagDTOJsonDeSerializer {
}
}
public String createIdenticalKeyFromThreeStrings(String racecolumn, String fleet, String leaderboard) {
/**
* Combines <code>leaderboard</code>, <code>racecolumn</code> and <code>fleet</code> to a unique key. Used to store
* private tags in {@link com.sap.sse.security.UserStore UserStore}.
*
* @param leaderboard
* leaderboard name
* @param racecolumn
* race column name
* @param fleet
* fleet name
* @return unique key for given race
*/
public String createIdenticalKeyFromThreeStrings(String leaderboard, String racecolumn, String fleet) {
return "Private tags:" + escape(racecolumn) + "+" + escape(fleet) + "+" + escape(leaderboard);
}
/**
* Escapes given string by replacing every occurence of '/' by '//' and '+' by '/p'.
*
* @param string
* string to be escaped
* @return escaped string
*/
private String escape(String string) {
// '+' needs to be escaped as method replaceAll() expects the first parameter to be a regular expression and not
// a
// simple string. As '+' has a different meaning in context of a regex it needs to be escaped by '\+' which
// again
// needs to be escaped by '\\+'.
return string.replaceAll("/", "//").replaceAll("\\+", "/p");
}
}
@@ -8,7 +8,8 @@ import com.sap.sse.common.filter.Filter;
import com.sap.sse.common.filter.FilterSet;
/**
* Shows current selected filter.
* Shows current selected filter used at {@link TagFilterPanel}. Observes {@link TagListProvider} for changes of the
* selected filter.
*/
public class TagFilterLabel extends Label {
@@ -17,6 +18,12 @@ public class TagFilterLabel extends Label {
private final TaggingPanel taggingPanel;
private final StringMessages stringMessages;
/**
* Creates {@link Label} and adds it as observer at the {@link TagListProvider}.
*
* @param taggingPanel
* provides reference to {@link TagListProvider} and {@link StringMessages}.
*/
public TagFilterLabel(TaggingPanel taggingPanel) {
this.taggingPanel = taggingPanel;
this.stringMessages = taggingPanel.getStringMessages();
@@ -26,9 +33,16 @@ public class TagFilterLabel extends Label {
taggingPanel.getTagListProvider().addObserveringLabel(this);
}
public void update(FilterSet<TagDTO, Filter<TagDTO>> tagsFilterSet) {
if (tagsFilterSet != null && !tagsFilterSet.getName().isEmpty()) {
setText(stringMessages.tagCurrentFilter() + " " + tagsFilterSet.getName());
/**
* Updates label text to match given <code>tagFilterSet</code>. Hides label if no filter is applied, otherwise label
* is shown.
*
* @param tagFilterSet
* current selected filter
*/
public void update(FilterSet<TagDTO, Filter<TagDTO>> tagFilterSet) {
if (tagFilterSet != null && !tagFilterSet.getName().isEmpty()) {
setText(stringMessages.tagCurrentFilter() + " " + tagFilterSet.getName());
removeStyleName(style.hidden());
} else {
setText("");
@@ -54,7 +54,13 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
private FilterSet<TagDTO, FilterWithUI<TagDTO>> lastActiveTagFilterSet;
private final TagFilterLabel currentFilter;
public TagFilterPanel(TaggingPanel taggingPanel) {
/**
* Creates panel which allows filtering of tags and shows current selected filter.
*
* @param taggingPanel
* provides reference to {@link StringMessages}, {@link UserService} and {@link TagListProvider}.
*/
protected TagFilterPanel(TaggingPanel taggingPanel) {
this.taggingPanel = taggingPanel;
this.stringMessages = taggingPanel.getStringMessages();
this.userService = taggingPanel.getUserSerivce();
@@ -80,6 +86,9 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
initializeUI();
}
/**
* Initializes UI.
*/
private void initializeUI() {
setStyleName(style.tagFilterPanel());
@@ -122,9 +131,16 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
add(currentFilter);
}
/**
* Opens up filter dialog to configure filters.
*/
private void showFilterDialog() {
TagFilterSetsDialog tagsFilterSetsDialog = new TagFilterSetsDialog(tagFilterSets, stringMessages,
new DialogCallback<TagFilterSets>() {
@Override
public void cancel() {
}
@Override
public void ok(final TagFilterSets newTagFilterSets) {
tagFilterSets.getFilterSets().clear();
@@ -141,18 +157,14 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
taggingPanel.updateContent();
}
@Override
public void cancel() {
}
}, userService);
tagsFilterSetsDialog.show();
}
/**
* Updates the tags filter checkbox state by setting its check mark and updating its label according to the current
* filter selected
* Updates the {@link #filterSettingsButton tag filter checkbox} state by setting its check mark and updating its
* title according to the {@link #lastActiveTagFilterSet current selected filter}.
*/
private void updateTagFilterControlState(TagFilterSets filterSets) {
String tagsFilterTitle = stringMessages.tagsFilter();
@@ -178,8 +190,8 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
}
/*
* loads users Tag Filter Sets from server and stores it into tagFilterSets
/**
* Loads the users {@link TagFilterSets} from {@link UserService} and saves it into {@link #tagFilterSets}.
*/
protected void loadTagFilterSets() {
if (userService.getCurrentUser() != null) {
@@ -213,6 +225,12 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
}
/**
* Stores <code>newTagsFilterSets</code> via {@link UserService}.
*
* @param newTagsFilterSets
* filter sets to be stored
*/
private void storeTagFilterSets(TagFilterSets newTagsFilterSets) {
TagFilterSetsJsonDeSerializer serializer = new TagFilterSetsJsonDeSerializer();
JSONObject jsonObject = serializer.serialize(newTagsFilterSets);
@@ -228,12 +246,18 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
});
}
/**
* Clears searchbox and removes key-up-listener.
*/
private void clearSelection() {
searchTextBox.setText("");
clearTextBoxButton.addStyleName(style.tagFilterHiddenButton());
onKeyUp(null);
}
/**
* Adds {@link TagFilterPanel} to applied filters at {@link TagListProvider} to apply searchbox filter.
*/
private void ensureSetSearchFilter() {
if (tagListProvider.getTagFilterSet() == null
|| !Util.contains(tagListProvider.getTagFilterSet().getFilters(), this)) {
@@ -248,6 +272,9 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
}
/**
* Removes {@link TagFilterPanel} from applied filters at {@link TagListProvider} to remove searchbox filter.
*/
private void removeSearchFilter() {
if (tagListProvider.getTagFilterSet() != null
&& Util.contains(tagListProvider.getTagFilterSet().getFilters(), this)) {
@@ -262,6 +289,13 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
}
/**
* Checks if given <code>tag</code> matches the current filter.
*
* @param tag
* tag to be compared to
* @return <code>true</code> if tag matches filter, otherwise <code>false</code>
*/
@Override
public boolean matches(TagDTO tag) {
final Iterable<String> lowercaseKeywords = Util
@@ -300,6 +334,8 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit
}
/**
* Applies filter entered by using search textbox to filterset.
*
* @param event
* ignored; may be <code>null</code>
*/
@@ -3,7 +3,8 @@ package com.sap.sailing.gwt.ui.raceboard.tagging;
import com.google.gwt.user.client.ui.FlowPanel;
/**
* Panel containg TagCreationPanel and TagButtonPanel which is used as footer in TaggingPanel.
* Panel containg {@link TagCreationPanel} and {@link TagButtonPanel} which is used as {@link TaggingPanel#footerPanel
* footer} in {@link TaggingPanel}.
*/
public class TagFooterPanel extends FlowPanel {
@@ -12,13 +13,20 @@ public class TagFooterPanel extends FlowPanel {
private final TagCreationPanel tagCreationPanel;
private final TagButtonPanel tagButtonPanel;
public TagFooterPanel(TaggingPanel taggingPanel) {
/**
* Creates footer panel and loads {@link TagButton tag-buttons} from {@link com.sap.sse.security.UserStore
* UserStore}.
*
* @param taggingPanel
* required to instantiate {@link TagCreationPanel} and {@link TagButtonPanel}
*/
protected TagFooterPanel(TaggingPanel taggingPanel) {
this.taggingPanel = taggingPanel;
tagCreationPanel = new TagCreationPanel(this, taggingPanel);
tagButtonPanel = new TagButtonPanel(this, taggingPanel);
tagCreationPanel = new TagCreationPanel(taggingPanel, this);
tagButtonPanel = new TagButtonPanel(taggingPanel, this);
// Tag buttons are only shown if amount of tag buttons is greater then 0!
// Tag-buttons are only shown if amount of tag-buttons is greater then 0!
setTagButtonsVisibility(true);
// input fields are hidden by default
@@ -28,11 +36,13 @@ public class TagFooterPanel extends FlowPanel {
}
/**
* Sets visibility of input fields for new tag and "Edit Tag-Buttons"-button. Input fields will not be hidden but
* removed completly from DOM in case parameter visible is set to false!
* Sets visibility of {@link TagCreationPanel input fields} for new tag and {@link TaggingPanel#createTagsButton
* "Edit Tag-Buttons"-button}. {@link TagCreationPanel Input fields} will not be hidden but removed completly from
* DOM in case <code>visible</code> is set to <code>false</code>!
*
* @param visible
* should be true when user is logged in and tagging panel is in EDIT-mode, otherwise false
* should be <code>true</code> when user is logged in and {@link TaggingPanel} is in
* {@link TaggingPanel#currentState EDIT-mode}, otherwise <code>false</code>
*/
protected void setInputFieldsVisibility(boolean visible) {
if (visible) {
@@ -45,10 +55,11 @@ public class TagFooterPanel extends FlowPanel {
}
/**
* Sets visibility of tag buttons. Tag buttons panel will only be shown if amount of tag buttons is greater then 0!
* Sets visibility of {@link TagButtonPanel tagButtonPanel}. {@link TagButtonPanel tagButtonPanel} will only be
* shown if amount of {@link TaggingPanel#getTagButtons() tag-buttons} is greater then <code>0</code>!
*
* @param visible
* should be true when user is logged in, otherwise false
* should be <code>true</code> when user is logged in, otherwise <code>false</code>
*/
protected void setTagButtonsVisibility(boolean visible) {
if (taggingPanel.getTagButtons().size() > 0) {
@@ -61,22 +72,23 @@ public class TagFooterPanel extends FlowPanel {
}
/**
* If the height of the tagButtonPanel has changed after deleting (delta not equals 0 ), the footerWidget of the
* TaggingPanel has a different height, which in this case might cause the contentWidget to be to small.
* If height of the {@link TagButtonPanel tagButtonPanel} has changed after deleting (delta height does not equal
* 0), the {@link TaggingPanel#footerPanel footer widget} of the {@link TaggingPanel} has a different height, which
* in this case might cause the {@link TaggingPanel#contentPanel content widget} to be to small.
*/
protected void recalculateHeight() {
tagButtonPanel.recalculateHeight();
}
/**
* Loads all tag buttons from user storage and displays them.
* Loads all {@link TagButton tag-buttons} from {@link com.sap.sse.security.UserStore UserStore} and displays them.
*/
protected void loadAllTagButtons() {
tagButtonPanel.loadAllTagButtons();
}
/**
* Stores all tag buttons into user storage.
* Stores all {@link TagButton tag-buttons} into {@link com.sap.sse.security.UserStore UserStore}.
*/
protected void storeAllTagButtons() {
tagButtonPanel.storeAllTagButtons();
@@ -23,7 +23,10 @@ public class TagInputPanel extends FlowPanel {
private final TextArea commentTextArea;
private final CheckBox visibleForPublicCheckBox;
public TagInputPanel(StringMessages stringMessages) {
/**
* Creates view allowing users to input values for tags and {@link TagButton tag-buttons}.
*/
protected TagInputPanel(StringMessages stringMessages) {
setStyleName(style.tagInputPanel());
tagTextBox = new TextBox();
@@ -56,58 +59,61 @@ public class TagInputPanel extends FlowPanel {
add(checkboxWrapper);
}
public TextBox getTagTextBox() {
return tagTextBox;
}
public TextBox getImageURLTextBox() {
return imageURLTextBox;
}
public TextArea getCommentTextArea() {
return commentTextArea;
}
public CheckBox getVisibleForPublicCheckBox() {
return visibleForPublicCheckBox;
}
public String getTag() {
return tagTextBox.getValue();
}
public String getComment() {
return commentTextArea.getValue();
}
public String getImageURL() {
return imageURLTextBox.getValue();
}
public boolean isVisibleForPublic() {
return visibleForPublicCheckBox.getValue();
}
public void setTag(String tag) {
tagTextBox.setValue(tag);
}
public void setComment(String comment) {
commentTextArea.setValue(comment);
}
public void setImageURL(String imageURL) {
imageURLTextBox.setValue(imageURL);
}
public void setVisibleForPublic(boolean visibleForPublic) {
visibleForPublicCheckBox.setValue(visibleForPublic);
}
public void clearAllValues() {
/**
* Clears all input fields.
*/
protected void clearAllValues() {
tagTextBox.setText("");
imageURLTextBox.setText("");
commentTextArea.setText("");
setVisibleForPublic(DEFAULT_VISIBLE_FOR_PUBLIC);
}
protected String getTag() {
return tagTextBox.getValue();
}
protected String getComment() {
return commentTextArea.getValue();
}
protected String getImageURL() {
return imageURLTextBox.getValue();
}
protected boolean isVisibleForPublic() {
return visibleForPublicCheckBox.getValue();
}
protected void setTag(String tag) {
tagTextBox.setValue(tag);
}
protected void setComment(String comment) {
commentTextArea.setValue(comment);
}
protected void setImageURL(String imageURL) {
imageURLTextBox.setValue(imageURL);
}
protected void setVisibleForPublic(boolean visibleForPublic) {
visibleForPublicCheckBox.setValue(visibleForPublic);
}
protected TextBox getTagTextBox() {
return tagTextBox;
}
protected TextBox getImageURLTextBox() {
return imageURLTextBox;
}
protected TextArea getCommentTextArea() {
return commentTextArea;
}
protected CheckBox getVisibleForPublicCheckBox() {
return visibleForPublicCheckBox;
}
}
@@ -7,12 +7,12 @@ import java.util.List;
import com.google.gwt.view.client.ListDataProvider;
import com.sap.sailing.gwt.ui.shared.TagDTO;
import com.sap.sse.common.Util;
import com.sap.sse.common.filter.Filter;
import com.sap.sse.common.filter.FilterSet;
/**
* Used to store tags and filter sets and to apply these filters on the tags
* Provides list of {@link TagDTO tags} and is able to filter theses {@link TagDTO tags} with the current selected
* {@link FilterSet}.
*/
public class TagListProvider extends ListDataProvider<TagDTO> {
@@ -20,26 +20,45 @@ public class TagListProvider extends ListDataProvider<TagDTO> {
private FilterSet<TagDTO, Filter<TagDTO>> currentFilterSet;
private TagFilterLabel observingLabel;
public TagListProvider() {
/**
* Creates instance without tags or filters.
*/
protected TagListProvider() {
allTags = new ArrayList<TagDTO>();
}
public void addObserveringLabel(TagFilterLabel tagFilterLabel) {
/**
* Used by {@link TagFilterLabel} to inform {@link TagFilterLabel} about changes of the {@link #currentFilterSet
* current filter set}.
*
* @param tagFilterLabel
*/
protected void addObserveringLabel(TagFilterLabel tagFilterLabel) {
observingLabel = tagFilterLabel;
}
public List<TagDTO> getAllTags() {
/**
* Returns list of all {@link TagDTO tags} ignoring the {@link #currentFilterSet current filter set}.
*
* @return list of all {@link TagDTO tags}
*/
protected List<TagDTO> getAllTags() {
return allTags;
}
public List<TagDTO> getFilteredTags() {
/**
* Returns list of all {@link TagDTO tags} which are filtered by {@link #currentFilterSet current filter set}.
*
* @return list of filtered {@link TagDTO tags}
*/
protected List<TagDTO> getFilteredTags() {
return getList();
}
/**
* filter all tags by tagsFilterSet
* Updates {@link #getList() list} of filtered {@link TagDTO tags} by applying {@link #currentFilterSet}.
*/
public void updateFilteredTags() {
protected void updateFilteredTags() {
List<TagDTO> currentFilteredList = new ArrayList<TagDTO>(getAllTags());
if (currentFilterSet != null) {
for (Filter<TagDTO> filter : currentFilterSet.getFilters()) {
@@ -63,20 +82,27 @@ public class TagListProvider extends ListDataProvider<TagDTO> {
setList(currentFilteredList);
}
public FilterSet<TagDTO, Filter<TagDTO>> getTagFilterSet() {
/**
* Returns {@link #currentFilterSet current filter set}.
*
* @return current selected filter set
*/
protected FilterSet<TagDTO, Filter<TagDTO>> getTagFilterSet() {
return currentFilterSet;
}
public void setCurrentFilterSet(FilterSet<TagDTO, Filter<TagDTO>> tagsFilterSet) {
currentFilterSet = tagsFilterSet;
/**
* Sets {@link #currentFilterSet current selected filter set} to given <code>tagFilterSet</code>.
*
* @param tagFilterSet
* selected filter set
*/
protected void setCurrentFilterSet(FilterSet<TagDTO, Filter<TagDTO>> tagFilterSet) {
currentFilterSet = tagFilterSet;
if (observingLabel != null) {
observingLabel.update(tagsFilterSet);
observingLabel.update(tagFilterSet);
}
updateFilteredTags();
refresh();
}
public int getFilteredTagsListSize() {
return Util.size(getFilteredTags());
}
}
@@ -5,10 +5,12 @@ import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
/**
* Interface for styling {@link TaggingPanel} and its content.
*/
public interface TagPanelResources extends ClientBundle {
public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class);
// TODO image is stored in wrong folder
@Source("com/sap/sailing/gwt/ui/client/images/edit.png")
ImageResource editIcon();
@@ -3,8 +3,6 @@ package com.sap.sailing.gwt.ui.raceboard.tagging;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
@@ -14,7 +12,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.security.ui.client.UserService;
/**
* Panel used to preview a tag.
* Panel showing {@link TagCell} as preview used at {@link TagButtonDialog}.
*/
public class TagPreviewPanel extends FlowPanel {
@@ -27,7 +25,16 @@ public class TagPreviewPanel extends FlowPanel {
private final CellList<TagDTO> tagPreviewCellList;
private List<TagDTO> listContainingPreviewTag;
public TagPreviewPanel(TaggingPanel taggingPanel, TagInputPanel inputPanel) {
/**
* Creates panel showing preview of tag when creating a {@link TagButton}. Adds change listener on input fields to
* be able to rerender the {@link TagCell preview cell} whenever user changes values of the input fields.
*
* @param taggingPanel
* references {@link UserService}
* @param inputPanel
* references input fields used to get current user input
*/
protected TagPreviewPanel(TaggingPanel taggingPanel, TagInputPanel inputPanel) {
this.taggingPanel = taggingPanel;
this.userService = taggingPanel.getUserSerivce();
@@ -39,37 +46,28 @@ public class TagPreviewPanel extends FlowPanel {
add(new Label(taggingPanel.getStringMessages().tagPreview()));
add(tagPreviewCellList);
inputPanel.getTagTextBox().addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
renderPreview(inputPanel);
}
inputPanel.getTagTextBox().addValueChangeHandler(event -> {
renderPreview(inputPanel);
});
inputPanel.getImageURLTextBox().addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
renderPreview(inputPanel);
}
inputPanel.getImageURLTextBox().addValueChangeHandler(event -> {
renderPreview(inputPanel);
});
inputPanel.getCommentTextArea().addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
renderPreview(inputPanel);
}
inputPanel.getCommentTextArea().addValueChangeHandler(event -> {
renderPreview(inputPanel);
});
inputPanel.getVisibleForPublicCheckBox().addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
renderPreview(inputPanel);
}
inputPanel.getVisibleForPublicCheckBox().addValueChangeHandler(event -> {
renderPreview(inputPanel);
});
renderPreview(inputPanel);
}
public void renderPreview(TagInputPanel inputPanel) {
/**
* Renders preview of tag by getting data from the input fields.
*
* @param inputPanel
* used to get input values from user
*/
protected void renderPreview(TagInputPanel inputPanel) {
listContainingPreviewTag.removeAll(listContainingPreviewTag);
listContainingPreviewTag.add(new TagDTO(inputPanel.getTag(), inputPanel.getComment(), inputPanel.getImageURL(),
userService.getCurrentUser().getName(), inputPanel.isVisibleForPublic(),
@@ -42,11 +42,18 @@ import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.shared.SuccessInfo;
import com.sap.sse.security.ui.shared.UserDTO;
/**
* A view showing tags which are connected to a specific race and allowing users to add own tags to a race. This view is
* shown at the {@link com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel RaceBoard}. Tags consist of a heading and
* optional a comment and/or image. Tag-Buttons allow to preset tags which are used more frequently by an user. Public
* tags will be stored as an {@link com.sap.sailing.domain.abstractlog.race.RaceLogEvent RaceLogEvent}, private tags
* will be stored in the {@link com.sap.sse.security.UserStore UserStore}.
*/
public class TaggingPanel extends ComponentWithoutSettings
implements RaceTimesInfoProviderListener, UserStatusEventHandler {
/**
* Describes the current state of the Tagging-Panel.
* Describes the {@link TaggingPanel#currentState current state} of the {@link TaggingPanel}.
*/
protected enum State {
VIEW, // default
@@ -122,7 +129,7 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Initializes UI of Tagging-Panel.
* Initializes UI of {@link TaggingPanel}.
*/
private void initializePanel() {
taggingPanel.setStyleName(style.taggingPanel());
@@ -162,7 +169,8 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Updates parameters required to save to/revoke from race log.
* Updates parameters required to save/revoke {@link com.sap.sailing.domain.abstractlog.race.RaceLogEvent events}
* to/from {@link com.sap.sailing.domain.abstractlog.race.RaceLog RaceLog}.
*/
public void updateRace(String leaderboardName, RaceColumnDTO raceColumn, FleetDTO fleet) {
if (leaderboardName != null && !leaderboardName.equals(this.leaderboardName)) {
@@ -189,8 +197,21 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Sends request to SailingService to add the given tag to the race log if the parameter
* <code>isVisibleForPublic</code> is set to true. Otherwise tag will be stored in the user storage.
* Checks if {@link UserService#getCurrentUser() current user} is non-<code>null</code> and if
* {@link #leaderboardName}, {@link #raceColumn} and {@link #fleet} are non-<code>null</code>.
*
* @return <code>true</code> if current user, {@link #leaderboardName}, {@link #raceColumn} and {@link #fleet} are
* non-<code>null</code>, otherwise <code>false</code>.
*/
protected boolean isLoggedInAndRaceLogAvailable() {
return userService.getCurrentUser() != null && leaderboardName != null && raceColumn != null && fleet != null;
}
/**
* Sends request to {@link SailingServiceAsync SailingService} to add the given tag to the
* {@link com.sap.sailing.domain.abstractlog.race.RaceLog RaceLog} if the parameter <code>isVisibleForPublic</code>
* is set to <code>true</code>. Otherwise tag will be stored in the {@link com.sap.sse.security.UserStore
* UserStore}.
*/
protected void saveTag(String tag, String comment, String imageURL, boolean isVisibleForPublic) {
if (!isLoggedInAndRaceLogAvailable()) {
@@ -241,8 +262,8 @@ public class TaggingPanel extends ComponentWithoutSettings
// store list of loaded private tags also containing the new tag
TagDTOJsonDeSerializer serializer = new TagDTOJsonDeSerializer();
JSONObject jsonObject = serializer.serialize(loadedPrivateTags);
userService.setPreference(serializer.createIdenticalKeyFromThreeStrings(leaderboardName,
raceColumn.getName(), fleet.getName()), jsonObject.toString(), new AsyncCallback<Void>() {
userService.setPreference(serializer.createIdenticalKeyFromThreeStrings(fleet.getName(),
leaderboardName, raceColumn.getName()), jsonObject.toString(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Notification.notify(stringMessages.tagButtonNotSavable(), NotificationType.WARNING);
@@ -262,9 +283,11 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* If the parameter <code>tag</code> is visible for the public a request to the SailingService is sent to revoke the
* given tag in race log. Otherwise the parameter <code>tag</code> is private and so the tag must be removed from
* the user storage.
* If attribute <code>isVisibleForPublic</code> of given tag is set to true, a request to the
* {@link SailingServiceAsync SailingService} is sent to revoke the given
* {@link com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent RaceLogTagEvent} in
* {@link com.sap.sailing.domain.abstractlog.race.RaceLog RaceLog}. Otherwise the given tag is private and must be
* removed from the {@link com.sap.sse.security.UserStore UserStore}.
*/
protected void removeTag(TagDTO tagToRemove) {
if (tagToRemove.isVisibleForPublic()) {
@@ -305,8 +328,8 @@ public class TaggingPanel extends ComponentWithoutSettings
// store list in user storage
TagDTOJsonDeSerializer serializer = new TagDTOJsonDeSerializer();
JSONObject jsonObject = serializer.serialize(privateTags);
userService.setPreference(serializer.createIdenticalKeyFromThreeStrings(leaderboardName,
raceColumn.getName(), fleet.getName()), jsonObject.toString(), new AsyncCallback<Void>() {
userService.setPreference(serializer.createIdenticalKeyFromThreeStrings(fleet.getName(),
leaderboardName, raceColumn.getName()), jsonObject.toString(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Notification.notify(stringMessages.tagNotRemoved(), NotificationType.ERROR);
@@ -327,57 +350,49 @@ public class TaggingPanel extends ComponentWithoutSettings
}
}
private void removePrivateTagsFromProvider() {
tagListProvider.getAllTags().removeIf(tag -> !tag.isVisibleForPublic());
}
/**
* Adds a list of {@link TagDTO tags} to the {@link TagListProvider}.
*/
private void addTagsToProvider(List<TagDTO> tags) {
tags.forEach(tag -> tagListProvider.getAllTags().add(tag));
}
/**
* Checks if currentUser (read from UserService) is non-<code>null</code> and if leaderboardName, fleet and
* raceColumn are not <code>null</code>.
*
* @return true if current user, leaderboardName, raceColumn and fleet are non-<code>null</code>, otherwise false.
* Removes all private tags from {@link TagListProvider}.
*/
protected boolean isLoggedInAndRaceLogAvailable() {
return userService.getCurrentUser() != null && leaderboardName != null && raceColumn != null && fleet != null;
private void removePrivateTagsFromProvider() {
tagListProvider.getAllTags().removeIf(tag -> !tag.isVisibleForPublic());
}
/**
* Controls the visibility of UI elements in case the content or current state changes.
* Controls the visibility of UI elements in case the content or {@link #currentState} changes.
*/
protected void updateContent() {
setFooterPanelVisibility(currentState == State.EDIT);
setCreateTagsButtonVisibility(currentState == State.VIEW);
tagListProvider.updateFilteredTags();
tagCellList.setVisibleRange(0, tagListProvider.getFilteredTagsListSize());
tagCellList.setVisibleRange(0, tagListProvider.getFilteredTags().size());
tagListProvider.refresh();
}
/**
* Forces tagging panel to rerender content.
* Forces {@link #contentPanel} to rerender.
*/
protected void refreshContentPanel() {
taggingPanel.setContentWidget(contentPanel);
}
/**
* Forces tagging panel to rerender footer.
* Forces {@link #footerPanel} to rerender.
*/
protected void refreshFooterPanel() {
taggingPanel.setFooterWidget(footerPanel);
}
protected Date getTimerTime() {
return timer.getTime();
}
protected List<TagButton> getTagButtons() {
return tagButtons;
}
/**
* Adds {@link TagButton} to {@link #tagButtons list} of all {@link TagButton tag-buttons} and applies
* {@link com.google.gwt.event.dom.client.ClickHandler ClickHandler} on it which allows saving of tags.
*/
protected void addTagButton(TagButton tagButton) {
tagButton.addClickHandler(event -> {
saveTag(tagButton.getTag(), tagButton.getComment(), tagButton.getImageURL(),
@@ -386,26 +401,18 @@ public class TaggingPanel extends ComponentWithoutSettings
tagButtons.add(tagButton);
}
protected TagListProvider getTagListProvider() {
return tagListProvider;
}
protected UserService getUserSerivce() {
return userService;
}
protected StringMessages getStringMessages() {
return stringMessages;
}
/**
* Loads private tags of {@link UserService#getCurrentUser() current user} from
* {@link com.sap.sse.security.UserStore UserStore}. Callback will be triggered if receiving of tags was successful.
*/
private void loadAllPrivateTags(AsyncCallback<List<TagDTO>> callback) {
// only reload tags if user is logged in
if (userService.getCurrentUser() != null) {
TagDTOJsonDeSerializer tagDTODeSerializer = new TagDTOJsonDeSerializer();
// load all private tags from user storage
userService.getPreference(tagDTODeSerializer.createIdenticalKeyFromThreeStrings(leaderboardName,
raceColumn.getName(), fleet.getName()), new AsyncCallback<String>() {
userService.getPreference(tagDTODeSerializer.createIdenticalKeyFromThreeStrings(fleet.getName(),
leaderboardName, raceColumn.getName()), new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
// TODO: Add error handling
@@ -432,7 +439,46 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Sets the current state and updates the UI.
* Returns time of {@link #timer}.
*/
protected Date getTimerTime() {
return timer.getTime();
}
/**
* Returns {@link #tagButtons list} of all {@link TagButton tag-buttons} of the {@link UserService#getCurrentUser()
* current user}.
*/
protected List<TagButton> getTagButtons() {
return tagButtons;
}
/**
* Returns instance of {@link TagListProvider} so it does not have to be a constructor parameter of every sub
* component of the {@link TaggingPanel}.
*/
protected TagListProvider getTagListProvider() {
return tagListProvider;
}
/**
* Returns instance of {@link UserService} so it does not have to be a constructor parameter of every sub component
* of the {@link TaggingPanel}.
*/
protected UserService getUserSerivce() {
return userService;
}
/**
* Returns instance of {@link StringMessages} so it does not have to be a constructor parameter of every sub
* component of the {@link TaggingPanel}.
*/
protected StringMessages getStringMessages() {
return stringMessages;
}
/**
* Sets the {@link #currentState} to the given {@link State state} and updates the UI.
*
* @param state
* new state
@@ -443,9 +489,10 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Updates the visibility of the footer and it's components. Input fields will NOT get displayed if user is not
* logged in, even if showInputFields is set to true! Tag buttons can't be hidden and will get displayed
* automatically when user is logged in.
* Updates the visibility of the {@link #footerPanel} and it's components. Input fields will NOT get displayed if
* user is not logged in, even if <code>showInputFields</code> is set to <code>true</code>! {@link TagButton}s can't
* be hidden and will get displayed automatically when {@link UserService#getCurrentUser() current user} is logged
* in.
*/
private void setFooterPanelVisibility(boolean showInputFields) {
// Setting footerPanel.setVisible(false) is not sufficient as panel would still be
@@ -461,19 +508,20 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Updates the visibility of the "Add Tags"-button. Button will NOT get displayed if user is not logged in, even if
* showButton is set to true!
* Updates the visibility of the {@link #createTagsButton "Add Tags"-button}. {@link #createTagsButton Button} will
* NOT get displayed if {@link UserService#getCurrentUser() current user} is not logged in, even if
* <code>showButton</code> is set to <code>true</code>!
*/
private void setCreateTagsButtonVisibility(boolean showButton) {
createTagsButton.setVisible(userService.getCurrentUser() != null && showButton);
}
/**
* Update local list of tags when response of server gets dispatched to all listeners by RaceTimesInfoProvider.
* Server sends only difference of tags in comparison based on the createdAt-timestamp of the latest received tag
* event.
* Updates {@link TagListProvider#getAllTags() local list of tags} when response of {@link SailingServiceAsync
* SailingService} gets dispatched to all listeners by {@link RaceTimesInfoProvider}. {@link SailingServiceAsync
* SailingService} sends only difference of tags in comparison based on the <code>createdAt</code>-timestamp of the
* {@link RaceTimesInfoProvider#latestReceivedTagTimes latest received tag events}.
*/
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo,
long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
@@ -526,9 +574,11 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* When the user logs in or out the content needs to be reset to hide private tags of the previous user. This gets
* achieved by resetting the local list of tags and resetting all latest received tag times at the
* RaceTimesInfoProvider.
* When the {@link UserService#getCurrentUser() current user} logs in or out the {@link #contentPanel content} needs
* to be reset to hide private tags of the previous {@link UserService#getCurrentUser() current user}. This gets
* achieved by resetting the {@link TagListProvider#getAllTags() local list of tags} and resetting all
* {@link RaceTimesInfoProvider#latestReceivedTagTimes latest received tag events} at the
* {@link RaceTimesInfoProvider}.
*/
@Override
public void onUserStatusChange(UserDTO user, boolean preAuthenticated) {
@@ -575,7 +625,7 @@ public class TaggingPanel extends ComponentWithoutSettings
}
/**
* Only request tags from server if Tagging-Panel is visible.
* Only request tags from server if {@link TaggingPanel} is visible.
*/
@Override
public void setVisible(boolean visible) {