diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index 13a54d57d0d..377330433e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -302,7 +302,7 @@ public class CompetitorTableWrapper(new Label(getStringMessages().filterCompetitors()), - new ArrayList(), dataProvider, stringMessages) { + Collections.emptySet(), dataProvider, stringMessages) { @Override public Iterable getSearchableStrings(CompetitorDTO t) { List string = new ArrayList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupSelectorComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupSelectorComposite.java index 19a95938b18..4e9c9c50a1c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupSelectorComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupSelectorComposite.java @@ -98,7 +98,6 @@ public class LeaderboardGroupSelectorComposite extends Composite implements HasV selectedEventLeaderboardGroupsTable.setSelectionModel(selectedEventLeaderboardGroupsSelectionModel); selectedEventLeaderboardGroupsProvider = new ListDataProvider<>(); selectedEventLeaderboardGroupsProvider.addDataDisplay(selectedEventLeaderboardGroupsTable); - TextColumn leaderboardGroupNameColumn = new TextColumn() { @Override public String getValue(LeaderboardGroupDTO event) { @@ -160,7 +159,6 @@ public class LeaderboardGroupSelectorComposite extends Composite implements HasV }; availableLeaderboardGroupsSelectionModel = new RefreshableMultiSelectionModel<>( new EntityIdentityComparator() { - @Override public boolean representSameEntity(LeaderboardGroupDTO dto1, LeaderboardGroupDTO dto2) { return dto1.getName().equals(dto2.getName()); @@ -182,7 +180,6 @@ public class LeaderboardGroupSelectorComposite extends Composite implements HasV vp.add(availableLeaderboardGroupsFilterablePanel); vp.add(availableLeaderboardGroupsTable); result.add(vp); - TextColumn leaderboardGroupNameColumn = new TextColumn() { @Override public String getValue(LeaderboardGroupDTO event) { diff --git a/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java b/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java index 1af7aad55ec..3733d48ab9c 100755 --- a/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java +++ b/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java @@ -3,16 +3,21 @@ package com.sap.sailing.landscape.ui.client; import static com.sap.sse.common.HttpRequestHeaderConstants.HEADER_FORWARD_TO_MASTER; import java.util.ArrayList; +import java.util.Collections; +import java.util.Optional; import com.google.gwt.core.client.GWT; +import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.landscape.ui.client.i18n.StringMessages; +import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.celltable.TableWrapperWithSingleSelectionAndFilter; import com.sap.sse.security.ui.client.UserService; /** @@ -45,11 +50,29 @@ import com.sap.sse.security.ui.client.UserService; */ public class LandscapeManagementPanel extends VerticalPanel { private final LandscapeManagementWriteServiceAsync landscapeManagementService; + private final TableWrapperWithSingleSelectionAndFilter regionsTable; public LandscapeManagementPanel(StringMessages stringMessages, UserService userService, AdminConsoleTableResources tableResources, ErrorReporter errorReporter) { landscapeManagementService = initAndRegisterLandscapeManagementService(); add(new Label(stringMessages.explainNoConnectionsToMaster()+" "+stringMessages.region())); + regionsTable = new TableWrapperWithSingleSelectionAndFilter( + stringMessages, errorReporter, /* enablePager */ false, + /* entity identity comparator */ Optional.empty(), GWT.create(AdminConsoleTableResources.class), + /* checkbox filter function */ Optional.empty(), /* filter label */ Optional.empty(), + /* filter checkbox label */ null) { + @Override + protected Iterable getSearchableStrings(String t) { + return Collections.singleton(t); + } + }; + regionsTable.addColumn(new TextColumn() { + @Override + public String getValue(String s) { + return s; + } + }, stringMessages.region(), new NaturalComparator()); + add(regionsTable); landscapeManagementService.getRegions(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -58,9 +81,7 @@ public class LandscapeManagementPanel extends VerticalPanel { @Override public void onSuccess(ArrayList regions) { - for (final String region : regions) { - add(new Label(region)); - } + regionsTable.refresh(regions); } }); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapper.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapper.java index 6d0b0f2742f..f14a79e43fa 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapper.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapper.java @@ -1,5 +1,7 @@ package com.sap.sse.gwt.client.celltable; +import java.util.Comparator; + import com.google.gwt.core.client.GWT; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; @@ -19,7 +21,11 @@ import com.sap.sse.gwt.client.panels.AbstractFilterablePanel; /** * The {@link #getTable() table} created and wrapped by this object offers already a {@link ListHandler} for sorting. * Subclasses can obtain the table's default column sort handler created by this class's constructor by calling - * {@link #getColumnSortHandler}. The table is wrapped by a panel that can be obtained using {@link #asWidget()} + * {@link #getColumnSortHandler}. This may not even be necessary when adding sortable columns by using the + * {@link #addColumn(Column, String, Comparator)} method which provides the comparator and sets the column + * as {@link Column#setSortable(boolean) sortable}.

+ * + * The table is wrapped by a panel that can be obtained using {@link #asWidget()} * and which contains, if requested, the pager widget underneath the table. */ public abstract class TableWrapper, SM extends StringMessages, TR extends CellTableWithCheckboxResources> implements IsWidget { @@ -107,6 +113,18 @@ public abstract class TableWrapper, SM public void addColumn(Column column, String header) { table.addColumn(column, header); } + + /** + * Sets the {@code column} as {@link Column#setSortable(boolean) sortable}, assigns the comparator for the + * {@code column} in the {@link #getColumnSortHandler() sort handler} and {@link #addColumn(Column, String) adds the + * column}. + */ + public void addColumn(Column column, String header, Comparator comparator) { + ListHandler boatColumnListHandler = getColumnSortHandler(); + column.setSortable(true); + boatColumnListHandler.setComparator(column, comparator); + addColumn(column, header); + } public void setEmptyTableWidget(Widget widget) { table.setEmptyTableWidget(widget); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithFilter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithFilter.java new file mode 100644 index 00000000000..042ee868d0d --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithFilter.java @@ -0,0 +1,104 @@ +package com.sap.sse.gwt.client.celltable; + +import java.util.Collections; +import java.util.Optional; +import java.util.function.Function; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.cellview.client.AbstractCellTable; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; +import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; + +/** + * A {@link CellTable} wrapped in a {@link VerticalPanel}, with a {@link LabeledAbstractFilterablePanel} above it which + * may or may not have a filter checkbox enabled if a subclass + * {@link LabeledAbstractFilterablePanel#setUpdatePermissionFilterForCheckbox(java.util.function.Function) sets a filter + * function} to apply when the checkbox is activated.

+ * + * {@link #refresh(Iterable) Refreshing} the contents of the table displayed here will update the set of all + * objects underlying the filter. The filtering / sorting will then again be applied to update the model of the actual + * cell table displaying the filtered data set.

+ * + * The table starts out with an empty data set. + * + * @author Axel Uhl (d043530) + */ +public abstract class TableWrapperWithFilter, SM extends StringMessages, TR extends CellTableWithCheckboxResources> +extends TableWrapper { + private final LabeledAbstractFilterablePanel filterPanel; + + /** + * See + * {@link #TableWrapperWithFilter(StringMessages, ErrorReporter, boolean, boolean, Optional, CellTableWithCheckboxResources, Optional, Optional, String)} + * Default table resources of type {@link CellTableWithCheckboxResources} will be used by this constructor variant. + */ + public TableWrapperWithFilter(SM stringMessages, ErrorReporter errorReporter, boolean multiSelection, + boolean enablePager, Optional> entityIdentityComparator, + Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + this(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), updatePermissionFilterForCheckbox, filterLabel, + filterCheckboxLabel); + } + + /** + * @param multiSelection + * must fit the {@code S} selection model type; a {@link RefreshableSingleSelectionModel} shall be used + * if {@code multiSelection} is {@code false}, whereas a {@link RefreshableMultiSelectionModel} shall be + * used otherwise. + * @param entityIdentityComparator + * if provided, specifies how row objects of type {@code T} shall be compared with each other to + * determine whether the entities they represent are the same. For example, if two distinct DTOs have + * equal attribute values for an "ID" field they may be considered "identical" by this definition. If not + * provided, Java object identity will be used to determine "identity" and this will not allow you to + * replace one object for another while keeping selection even if the replacing object represents the + * same entity. + * @param updatePermissionFilterForCheckbox + * if provided, a checkbox will be shown next to the filter text box that will by default apply the + * filter condition encoded by this parameter's function; when the checkbox is un-ticked, all objects + * passing the text filter will be shown instead. + * @param filterLabel + * If provided, this replaces the regular (i18n-treated) "Filter by" label shown in front of the filter + * text box + * @param filterCheckboxLabel + * if a non-empty {@code updatePermissionFilterForCheckbox} is provided then this parameter must be + * non-{@code null}, providing the label text for the checkbox used to toggle the filter + */ + public TableWrapperWithFilter(SM stringMessages, ErrorReporter errorReporter, boolean multiSelection, + boolean enablePager, Optional> entityIdentityComparator, TR tableRes, + Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + super(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator.orElse(null), + tableRes); + filterPanel = new LabeledAbstractFilterablePanel(new Label(filterLabel.orElse(stringMessages.filterBy())), + Collections.emptySet(), dataProvider, stringMessages, filterCheckboxLabel) { + @Override + public Iterable getSearchableStrings(T t) { + return TableWrapperWithFilter.this.getSearchableStrings(t); + } + + @Override + public AbstractCellTable getCellTable() { + return TableWrapperWithFilter.this.getTable(); + } + }; + registerSelectionModelOnNewDataProvider(filterPanel.getAllListDataProvider()); + updatePermissionFilterForCheckbox.ifPresent(getFilterPanel()::setUpdatePermissionFilterForCheckbox); + mainPanel.insert(filterPanel, 0); + } + + @Override + public void refresh(Iterable newItems) { + getFilterPanel().updateAll(newItems); + } + + protected LabeledAbstractFilterablePanel getFilterPanel() { + return filterPanel; + } + + protected abstract Iterable getSearchableStrings(T t); +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithMultiSelectionAndFilter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithMultiSelectionAndFilter.java new file mode 100644 index 00000000000..65c6671991b --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithMultiSelectionAndFilter.java @@ -0,0 +1,37 @@ +package com.sap.sse.gwt.client.celltable; + +import java.util.Optional; +import java.util.function.Function; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; + +/** + * A {@link TableWrapperWithFilter} that supports multiple selection (selecting zero or more elements in the table). + * + * @author Axel Uhl (d043530) + * + * @param the object type represented by a row + * @param the {@link StringMessages} sub-type to use + * @param the table resources defining the styles for the elements shown + */ +public abstract class TableWrapperWithMultiSelectionAndFilter +extends TableWrapperWithFilter, SM, TR> { + public TableWrapperWithMultiSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, + Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + this(stringMessages, errorReporter, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), updatePermissionFilterForCheckbox, filterLabel, + filterCheckboxLabel); + } + + public TableWrapperWithMultiSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, + TR tableRes, Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + super(stringMessages, errorReporter, /* multiSelection */ true, enablePager, entityIdentityComparator, tableRes, + updatePermissionFilterForCheckbox, filterLabel, filterCheckboxLabel); + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithSingleSelectionAndFilter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithSingleSelectionAndFilter.java new file mode 100644 index 00000000000..93a2c0eda14 --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/celltable/TableWrapperWithSingleSelectionAndFilter.java @@ -0,0 +1,37 @@ +package com.sap.sse.gwt.client.celltable; + +import java.util.Optional; +import java.util.function.Function; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; + +/** + * A {@link TableWrapperWithFilter} that supports single selection (selecting at most one element in the table). + * + * @author Axel Uhl (d043530) + * + * @param the object type represented by a row + * @param the {@link StringMessages} sub-type to use + * @param the table resources defining the styles for the elements shown + */ +public abstract class TableWrapperWithSingleSelectionAndFilter +extends TableWrapperWithFilter, SM, TR> { + public TableWrapperWithSingleSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, + Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + this(stringMessages, errorReporter, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), updatePermissionFilterForCheckbox, filterLabel, + filterCheckboxLabel); + } + + public TableWrapperWithSingleSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, + TR tableRes, Optional> updatePermissionFilterForCheckbox, Optional filterLabel, + String filterCheckboxLabel) { + super(stringMessages, errorReporter, /* multiSelection */ false, enablePager, entityIdentityComparator, tableRes, + updatePermissionFilterForCheckbox, filterLabel, filterCheckboxLabel); + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/AbstractFilterablePanel.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/AbstractFilterablePanel.java index 73ca06eeac5..a7b1ee02bcb 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/AbstractFilterablePanel.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/AbstractFilterablePanel.java @@ -28,9 +28,9 @@ import com.sap.sse.gwt.client.StringMessages; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; /** - * This Panel contains a text box. Text entered into the text box filters the {@link CellTable} passed to the - * constructor by adjusting the cell table's {@link ListDataProvider}'s contents using the - * {@link AbstractListFilter#applyFilter(String, List)} and then sorting the table again according the the sorting + * This Panel contains a text box and optionally a check box. Text entered into the text box filters the + * {@link CellTable} passed to the constructor by adjusting the cell table's {@link ListDataProvider}'s contents using + * the {@link AbstractListFilter#applyFilter(String, List)} and then sorting the table again according the the sorting * criteria currently active (the sorting is the only reason why the {@link CellTable} actually needs to be known to an * instance of this class). To be initiated the method {@link #getSearchableStrings(Object)} has to be defined, which * gets those Strings from a T that should be considered when filtering, e.g. name or boatClass. The cell @@ -38,13 +38,23 @@ import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; * {@link #updateAll(Iterable)} which then runs the filter over the new selection. *

* + * If a filter function has been {@link #setUpdatePermissionFilterForCheckbox(Function) set}, an additional checkbox + * will be displayed which toggles the application of the filter function. It is intended to be used as a + * permission-based filter, toggling between showing only objects the user can change (UPDATE permission) and all + * objects the user can READ. This assumption is currently encoded in the default + * {@link StringMessages#hideElementsWithoutUpdateRights() text label used for the checkbox}, but there are currently no + * constraints regarding the actual implementation of the filter function. + *

+ * * Note that this panel does not contain the table that it filters. With this, this class's clients are free to * position the table wherever they want, not necessarily related to the text box provided by this panel in any specific - * way.

+ * way. + *

* * It is recommended to use the {@link #getAllListDataProvider()} as the data provider for the table's selection model. * This way, when the filter reduces the elements displayed in the table the selection will still refer to all elements * and will not be modified solely by the act of filtering. + *

* * Provides methods for filtering and selection of table items. * @@ -56,12 +66,15 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { protected ListDataProvider all; protected final ListDataProvider filtered; protected final TextBox textBox; - protected final CheckBox showOnlyObjectsWithUpdatePermissionCheckbox; + protected final CheckBox showOnlyObjectsWithUpdatePermissionCheckBox; private final Set> filters = new HashSet<>(); private final CheckboxEnablableFilter checkboxFilterForUpdatableObjectsOnly; - private boolean added = false; + /** + * Tells whether the {@link #showOnlyObjectsWithUpdatePermissionCheckBox} has already been added to this panel + */ + private boolean showOnlyObjectsWithUpdatePermissionCheckBoxAdded = false; private List select; private String selectExact; @@ -69,7 +82,6 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { private boolean executeSelect; static class CheckboxEnablableFilter implements Filter { - private final CheckBox checkbox; private Filter filterToApply; @@ -79,13 +91,15 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { @Override public boolean matches(T object) { + final boolean result; if (filterToApply == null) { - return true; + result = true; + } else if (!this.checkbox.getValue()) { + result = true; + } else { + result = filterToApply.matches(object); } - if (!this.checkbox.getValue()) { - return true; - } - return filterToApply.matches(object); + return result; } @Override @@ -96,7 +110,6 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { public void setFilterToApply(Filter filterToApply) { this.filterToApply = filterToApply; } - } protected final AbstractKeywordFilter filterer = new AbstractKeywordFilter() { @@ -128,12 +141,16 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { * This way, subclasses may choose to add other filter elements before the default text filter box. * Filtering will still use the text box contents, even if the box is ultimately not shown; but under * normal circumstances the text box will be empty in this case, not making filtering any stricter. - * @param executeSelectionOnRefresh - * Used for table items selection by URL-parameters. If true, the table items will wait to be selected + * @param executeSelectionOnRefresh + * Used for table items selection by URL-parameters. If true, the table items will wait to be selected * until the table list items have been refreshed. + * @param filterCheckboxLabel + * The text to use for the label of the filter checkbox which will be displayed if a + * {@link #setUpdatePermissionFilterForCheckbox(Function) filter is set}. */ public AbstractFilterablePanel(Iterable all, final ListDataProvider filtered, - boolean drawTextBox, final StringMessages stringMessages, boolean executeSelectOnRefresh) { + boolean drawTextBox, final StringMessages stringMessages, boolean executeSelectOnRefresh, + String filterCheckboxLabel) { this.executeSelectOnRefresh = executeSelectOnRefresh; filters.add(filterer); setSpacing(5); @@ -141,9 +158,9 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { this.filtered = filtered; this.textBox = new TextBox(); this.textBox.ensureDebugId("FilterTextBox"); - this.showOnlyObjectsWithUpdatePermissionCheckbox = new CheckBox(stringMessages.hideElementsWithoutUpdateRights()); - showOnlyObjectsWithUpdatePermissionCheckbox.setValue(true); - checkboxFilterForUpdatableObjectsOnly = new CheckboxEnablableFilter<>(showOnlyObjectsWithUpdatePermissionCheckbox); + this.showOnlyObjectsWithUpdatePermissionCheckBox = new CheckBox(filterCheckboxLabel); + showOnlyObjectsWithUpdatePermissionCheckBox.setValue(true); + checkboxFilterForUpdatableObjectsOnly = new CheckboxEnablableFilter<>(showOnlyObjectsWithUpdatePermissionCheckBox); filters.add(checkboxFilterForUpdatableObjectsOnly); this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); setAll(all); @@ -152,6 +169,15 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { } } + /** + * Like {@link #AbstractFilterablePanel(Iterable, ListDataProvider, boolean, StringMessages, boolean)}, but + * defaults the {@code filterCheckboxLabel} parameter to {@link StringMessages#hideElementsWithoutUpdateRights()}. + */ + public AbstractFilterablePanel(Iterable all, final ListDataProvider filtered, + boolean drawTextBox, final StringMessages stringMessages, boolean executeSelectOnRefresh) { + this(all, filtered, drawTextBox, stringMessages, executeSelectOnRefresh, stringMessages.hideElementsWithoutUpdateRights()); + } + public AbstractFilterablePanel(Iterable all, final ListDataProvider filtered, boolean drawTextBox, final StringMessages stringMessages) { this(all, filtered, drawTextBox, stringMessages, true); @@ -159,7 +185,7 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { public AbstractFilterablePanel(Iterable all, final ListDataProvider filtered, final StringMessages stringMessages) { - this(all, filtered, stringMessages, true); + this(all, filtered, stringMessages, /* selectOnRefresh */ true); } public AbstractFilterablePanel(Iterable all, final ListDataProvider filtered, @@ -167,6 +193,11 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { this(all, filtered, /* show default filter text box */ true, stringMessages, selectOnRefresh); } + public AbstractFilterablePanel(Iterable all, ListDataProvider filtered, StringMessages stringMessages, + String filterCheckboxLabel) { + this(all, filtered, /* draw text box */ true, stringMessages, /* selectOnRefresh */ true, filterCheckboxLabel); + } + private void setAll(Iterable all) { this.all.getList().clear(); if (all != null) { @@ -473,11 +504,11 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { }); } - public void addDefaultCheckBoxIfNecessary() { - if (!added) { - add(getCheckBox()); - getCheckBox().addClickHandler(e -> filter()); - added = true; + public void addShowOnlyObjectsWithUpdatePermissionCheckBoxIfNecessary() { + if (!showOnlyObjectsWithUpdatePermissionCheckBoxAdded) { + add(getShowOnlyObjectsWithUpdatePermissionCheckBox()); + getShowOnlyObjectsWithUpdatePermissionCheckBox().addClickHandler(e -> filter()); + showOnlyObjectsWithUpdatePermissionCheckBoxAdded = true; } } @@ -491,12 +522,12 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { return textBox; } - public CheckBox getCheckBox() { - return showOnlyObjectsWithUpdatePermissionCheckbox; + public CheckBox getShowOnlyObjectsWithUpdatePermissionCheckBox() { + return showOnlyObjectsWithUpdatePermissionCheckBox; } /** - * Defines the filter function to apply when the {@link #showOnlyObjectsWithUpdatePermissionCheckbox} checkbox is + * Defines the filter function to apply when the {@link #showOnlyObjectsWithUpdatePermissionCheckBox} checkbox is * ticked. */ public void setUpdatePermissionFilterForCheckbox(Function filterFunction) { @@ -511,7 +542,7 @@ public abstract class AbstractFilterablePanel extends HorizontalPanel { return "Update Permission Filter"; } }); - addDefaultCheckBoxIfNecessary(); + addShowOnlyObjectsWithUpdatePermissionCheckBoxIfNecessary(); } public Iterable getAll() { diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/LabeledAbstractFilterablePanel.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/LabeledAbstractFilterablePanel.java index ed66fd62775..5fdc1b622e7 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/LabeledAbstractFilterablePanel.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/LabeledAbstractFilterablePanel.java @@ -34,4 +34,10 @@ public abstract class LabeledAbstractFilterablePanel extends AbstractFilterab super(all, filtered, stringMessages); insert(label, 0); } + + public LabeledAbstractFilterablePanel(Label label, Iterable all, final ListDataProvider filtered, + StringMessages stringMessages, String filterCheckboxLabel) { + super(all, filtered, stringMessages, filterCheckboxLabel); + insert(label, 0); + } } \ No newline at end of file diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsRegion.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsRegion.java index ef571e0afd0..a079e9e9bde 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsRegion.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsRegion.java @@ -6,7 +6,7 @@ import com.sap.sse.landscape.SecurityGroup; import com.sap.sse.landscape.aws.AwsLandscape; public class AwsRegion implements Region { - private AwsLandscape landscape; + private AwsLandscape landscape; // FIXME this is broken; it shall be final and has to be initialized by the constructors if getAvailabilityZones and getSecurityGroups is expected to do anything useful private final String id; public AwsRegion(String id) { diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithFilterForSecuredDTOs.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithFilterForSecuredDTOs.java new file mode 100644 index 00000000000..0573a9f416e --- /dev/null +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithFilterForSecuredDTOs.java @@ -0,0 +1,42 @@ +package com.sap.sse.security.ui.client.component; + +import java.util.Optional; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; +import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.celltable.TableWrapperWithFilter; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.dto.SecuredDTO; +import com.sap.sse.security.ui.client.UserService; + +/** + * A {@link TableWrapperWithFilter} that displays {@link SecuredDTO} objects and uses the checkbox filter to display by default + * only those elements that the user can {@link DefaultActions#UPDATE update}. + * + * @author Axel Uhl (d043530) + * + * @param the object type represented by a row + * @param the selection model type to ues + * @param the {@link StringMessages} sub-type to use + * @param the table resources defining the styles for the elements shown + */ +public abstract class TableWrapperWithFilterForSecuredDTOs, SM extends StringMessages, TR extends CellTableWithCheckboxResources> +extends TableWrapperWithFilter { + public TableWrapperWithFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter, boolean multiSelection, + boolean enablePager, Optional> entityIdentityComparator, UserService userService, Optional filterLabel) { + this(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), userService, filterLabel); + } + + public TableWrapperWithFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter, boolean multiSelection, + boolean enablePager, Optional> entityIdentityComparator, TR tableRes, + UserService userService, Optional filterLabel) { + super(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator, tableRes, + Optional.of(t -> userService.hasPermission(t, DefaultActions.UPDATE)), filterLabel, + stringMessages.hideElementsWithoutUpdateRights()); + } +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithMultiSelectionAndFilterForSecuredDTO.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithMultiSelectionAndFilterForSecuredDTO.java new file mode 100644 index 00000000000..8ac1505e439 --- /dev/null +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithMultiSelectionAndFilterForSecuredDTO.java @@ -0,0 +1,39 @@ +package com.sap.sse.security.ui.client.component; + +import java.util.Optional; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; +import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; +import com.sap.sse.security.shared.dto.SecuredDTO; +import com.sap.sse.security.ui.client.UserService; + +/** + * A {@link TableWrapperWithFilterForSecuredDTOs} that supports multi selection (selecting zero or more elements in the table). + * + * @author Axel Uhl (d043530) + * + * @param the object type represented by a row + * @param the {@link StringMessages} sub-type to use + * @param the table resources defining the styles for the elements shown + */ +public abstract class TableWrapperWithMultiSelectionAndFilterForSecuredDTO + extends TableWrapperWithFilterForSecuredDTOs, SM, TR> { + public TableWrapperWithMultiSelectionAndFilterForSecuredDTO(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, UserService userService, + Optional filterLabel) { + this(stringMessages, errorReporter, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), userService, filterLabel); + } + + public TableWrapperWithMultiSelectionAndFilterForSecuredDTO(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, TR tableRes, + UserService userService, Optional filterLabel) { + super(stringMessages, errorReporter, /* multiSelection */ true, enablePager, entityIdentityComparator, tableRes, + userService, filterLabel); + } + +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithSingleSelectionAndFilterForSecuredDTOs.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithSingleSelectionAndFilterForSecuredDTOs.java new file mode 100644 index 00000000000..8861a76ffe8 --- /dev/null +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/TableWrapperWithSingleSelectionAndFilterForSecuredDTOs.java @@ -0,0 +1,39 @@ +package com.sap.sse.security.ui.client.component; + +import java.util.Optional; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.StringMessages; +import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; +import com.sap.sse.security.shared.dto.SecuredDTO; +import com.sap.sse.security.ui.client.UserService; + +/** + * A {@link TableWrapperWithFilterForSecuredDTOs} that supports single selection (selecting at most one element in the table). + * + * @author Axel Uhl (d043530) + * + * @param the object type represented by a row + * @param the {@link StringMessages} sub-type to use + * @param the table resources defining the styles for the elements shown + */ +public abstract class TableWrapperWithSingleSelectionAndFilterForSecuredDTOs + extends TableWrapperWithFilterForSecuredDTOs, SM, TR> { + public TableWrapperWithSingleSelectionAndFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, UserService userService, + Optional filterLabel) { + this(stringMessages, errorReporter, enablePager, entityIdentityComparator, + GWT.create(CellTableWithCheckboxResources.class), userService, filterLabel); + } + + public TableWrapperWithSingleSelectionAndFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter, + boolean enablePager, Optional> entityIdentityComparator, TR tableRes, + UserService userService, Optional filterLabel) { + super(stringMessages, errorReporter, /* multiSelection */ false, enablePager, entityIdentityComparator, + tableRes, userService, filterLabel); + } + +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserGroupTableWrapper.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserGroupTableWrapper.java index a3211b83adf..0b46ce8a797 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserGroupTableWrapper.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserGroupTableWrapper.java @@ -90,20 +90,16 @@ public class UserGroupTableWrapper extends }); } }); - final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog.create( userService.getUserManagementWriteService(), type, user -> refreshUserList(null), stringMessages); - final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementWriteService(), type, user -> user.getAccessControlList(), stringMessages); - actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_OWNERSHIP, DefaultActions.CHANGE_OWNERSHIP, configOwnership::openOwnershipDialog); actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL, u -> configACL.openDialog(u)); - filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterUserGroups()), new ArrayList(), dataProvider, stringMessages) { @Override @@ -120,7 +116,6 @@ public class UserGroupTableWrapper extends }; filterField.setUpdatePermissionFilterForCheckbox(userGroup -> userService.hasPermission(userGroup, DefaultActions.UPDATE)); registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider()); - mainPanel.insert(filterField, 0); table.addColumnSortHandler(userColumnListHandler); table.addColumn(UserGroupWithSecurityDTONameColumn, getStringMessages().groupName());