bug4811: introduced TableWrapper specializations aiming to reduce boiler-plate code for table construction

This commit is contained in:
Axel Uhl committed 2020-12-24 02:36:55 +01:00
1 parent 64baad725d
commit cc17e76fc3
14 files changed
+409 -43

No files matched your search

@@ -302,7 +302,7 @@ public class CompetitorTableWrapper<S extends RefreshableSelectionModel<Competit
}
});
filterField = new LabeledAbstractFilterablePanel<CompetitorDTO>(new Label(getStringMessages().filterCompetitors()),
new ArrayList<CompetitorDTO>(), dataProvider, stringMessages) {
Collections.emptySet(), dataProvider, stringMessages) {
@Override
public Iterable<String> getSearchableStrings(CompetitorDTO t) {
List<String> string = new ArrayList<String>();
@@ -98,7 +98,6 @@ public class LeaderboardGroupSelectorComposite extends Composite implements HasV
selectedEventLeaderboardGroupsTable.setSelectionModel(selectedEventLeaderboardGroupsSelectionModel);
selectedEventLeaderboardGroupsProvider = new ListDataProvider<>();
selectedEventLeaderboardGroupsProvider.addDataDisplay(selectedEventLeaderboardGroupsTable);
TextColumn<LeaderboardGroupDTO> leaderboardGroupNameColumn = new TextColumn<LeaderboardGroupDTO>() {
@Override
public String getValue(LeaderboardGroupDTO event) {
@@ -160,7 +159,6 @@ public class LeaderboardGroupSelectorComposite extends Composite implements HasV
};
availableLeaderboardGroupsSelectionModel = new RefreshableMultiSelectionModel<>(
new EntityIdentityComparator<LeaderboardGroupDTO>() {
@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<LeaderboardGroupDTO> leaderboardGroupNameColumn = new TextColumn<LeaderboardGroupDTO>() {
@Override
public String getValue(LeaderboardGroupDTO event) {
@@ -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<String, StringMessages, AdminConsoleTableResources> regionsTable;
public LandscapeManagementPanel(StringMessages stringMessages, UserService userService,
AdminConsoleTableResources tableResources, ErrorReporter errorReporter) {
landscapeManagementService = initAndRegisterLandscapeManagementService();
add(new Label(stringMessages.explainNoConnectionsToMaster()+" "+stringMessages.region()));
regionsTable = new TableWrapperWithSingleSelectionAndFilter<String, StringMessages, AdminConsoleTableResources>(
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<String> getSearchableStrings(String t) {
return Collections.singleton(t);
}
};
regionsTable.addColumn(new TextColumn<String>() {
@Override
public String getValue(String s) {
return s;
}
}, stringMessages.region(), new NaturalComparator());
add(regionsTable);
landscapeManagementService.getRegions(new AsyncCallback<ArrayList<String>>() {
@Override
public void onFailure(Throwable caught) {
@@ -58,9 +81,7 @@ public class LandscapeManagementPanel extends VerticalPanel {
@Override
public void onSuccess(ArrayList<String> regions) {
for (final String region : regions) {
add(new Label(region));
}
regionsTable.refresh(regions);
}
});
}
@@ -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}.<p>
*
* 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<T, S extends RefreshableSelectionModel<T>, SM extends StringMessages, TR extends CellTableWithCheckboxResources> implements IsWidget {
@@ -107,6 +113,18 @@ public abstract class TableWrapper<T, S extends RefreshableSelectionModel<T>, SM
public void addColumn(Column<T, ?> 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<T, ?> column, String header, Comparator<T> comparator) {
ListHandler<T> boatColumnListHandler = getColumnSortHandler();
column.setSortable(true);
boatColumnListHandler.setComparator(column, comparator);
addColumn(column, header);
}
public void setEmptyTableWidget(Widget widget) {
table.setEmptyTableWidget(widget);
@@ -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.<p>
*
* {@link #refresh(Iterable) Refreshing} the contents of the table displayed here will update the set of <em>all</em>
* 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.<p>
*
* The table starts out with an empty data set.
*
* @author Axel Uhl (d043530)
*/
public abstract class TableWrapperWithFilter<T, S extends RefreshableSelectionModel<T>, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapper<T, S, SM, TR> {
private final LabeledAbstractFilterablePanel<T> 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<T>> entityIdentityComparator,
Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> 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<T>> entityIdentityComparator, TR tableRes,
Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> filterLabel,
String filterCheckboxLabel) {
super(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator.orElse(null),
tableRes);
filterPanel = new LabeledAbstractFilterablePanel<T>(new Label(filterLabel.orElse(stringMessages.filterBy())),
Collections.emptySet(), dataProvider, stringMessages, filterCheckboxLabel) {
@Override
public Iterable<String> getSearchableStrings(T t) {
return TableWrapperWithFilter.this.getSearchableStrings(t);
}
@Override
public AbstractCellTable<T> getCellTable() {
return TableWrapperWithFilter.this.getTable();
}
};
registerSelectionModelOnNewDataProvider(filterPanel.getAllListDataProvider());
updatePermissionFilterForCheckbox.ifPresent(getFilterPanel()::setUpdatePermissionFilterForCheckbox);
mainPanel.insert(filterPanel, 0);
}
@Override
public void refresh(Iterable<T> newItems) {
getFilterPanel().updateAll(newItems);
}
protected LabeledAbstractFilterablePanel<T> getFilterPanel() {
return filterPanel;
}
protected abstract Iterable<String> getSearchableStrings(T t);
}
@@ -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 <T> the object type represented by a row
* @param <SM> the {@link StringMessages} sub-type to use
* @param <TR> the table resources defining the styles for the elements shown
*/
public abstract class TableWrapperWithMultiSelectionAndFilter<T, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapperWithFilter<T, RefreshableMultiSelectionModel<T>, SM, TR> {
public TableWrapperWithMultiSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator,
Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> 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<T>> entityIdentityComparator,
TR tableRes, Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> filterLabel,
String filterCheckboxLabel) {
super(stringMessages, errorReporter, /* multiSelection */ true, enablePager, entityIdentityComparator, tableRes,
updatePermissionFilterForCheckbox, filterLabel, filterCheckboxLabel);
}
}
@@ -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 <T> the object type represented by a row
* @param <SM> the {@link StringMessages} sub-type to use
* @param <TR> the table resources defining the styles for the elements shown
*/
public abstract class TableWrapperWithSingleSelectionAndFilter<T, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapperWithFilter<T, RefreshableSingleSelectionModel<T>, SM, TR> {
public TableWrapperWithSingleSelectionAndFilter(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator,
Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> 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<T>> entityIdentityComparator,
TR tableRes, Optional<Function<T, Boolean>> updatePermissionFilterForCheckbox, Optional<String> filterLabel,
String filterCheckboxLabel) {
super(stringMessages, errorReporter, /* multiSelection */ false, enablePager, entityIdentityComparator, tableRes,
updatePermissionFilterForCheckbox, filterLabel, filterCheckboxLabel);
}
}
@@ -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 <code>T</code> 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.
* <p>
*
* 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.
* <p>
*
* Note that this panel does <em>not</em> 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.<p>
* way.
* <p>
*
* 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.
* <p>
*
* Provides methods for filtering and selection of table items.
*
@@ -56,12 +66,15 @@ public abstract class AbstractFilterablePanel<T> extends HorizontalPanel {
protected ListDataProvider<T> all;
protected final ListDataProvider<T> filtered;
protected final TextBox textBox;
protected final CheckBox showOnlyObjectsWithUpdatePermissionCheckbox;
protected final CheckBox showOnlyObjectsWithUpdatePermissionCheckBox;
private final Set<Filter<T>> filters = new HashSet<>();
private final CheckboxEnablableFilter<T> checkboxFilterForUpdatableObjectsOnly;
private boolean added = false;
/**
* Tells whether the {@link #showOnlyObjectsWithUpdatePermissionCheckBox} has already been added to this panel
*/
private boolean showOnlyObjectsWithUpdatePermissionCheckBoxAdded = false;
private List<String> select;
private String selectExact;
@@ -69,7 +82,6 @@ public abstract class AbstractFilterablePanel<T> extends HorizontalPanel {
private boolean executeSelect;
static class CheckboxEnablableFilter<T> implements Filter<T> {
private final CheckBox checkbox;
private Filter<T> filterToApply;
@@ -79,13 +91,15 @@ public abstract class AbstractFilterablePanel<T> 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<T> extends HorizontalPanel {
public void setFilterToApply(Filter<T> filterToApply) {
this.filterToApply = filterToApply;
}
}
protected final AbstractKeywordFilter<T> filterer = new AbstractKeywordFilter<T>() {
@@ -128,12 +141,16 @@ public abstract class AbstractFilterablePanel<T> 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<T> all, final ListDataProvider<T> 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<T> 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<T> extends HorizontalPanel {
}
}
/**
* Like {@link #AbstractFilterablePanel(Iterable, ListDataProvider, boolean, StringMessages, boolean)}, but
* defaults the {@code filterCheckboxLabel} parameter to {@link StringMessages#hideElementsWithoutUpdateRights()}.
*/
public AbstractFilterablePanel(Iterable<T> all, final ListDataProvider<T> filtered,
boolean drawTextBox, final StringMessages stringMessages, boolean executeSelectOnRefresh) {
this(all, filtered, drawTextBox, stringMessages, executeSelectOnRefresh, stringMessages.hideElementsWithoutUpdateRights());
}
public AbstractFilterablePanel(Iterable<T> all, final ListDataProvider<T> filtered,
boolean drawTextBox, final StringMessages stringMessages) {
this(all, filtered, drawTextBox, stringMessages, true);
@@ -159,7 +185,7 @@ public abstract class AbstractFilterablePanel<T> extends HorizontalPanel {
public AbstractFilterablePanel(Iterable<T> all, final ListDataProvider<T> filtered,
final StringMessages stringMessages) {
this(all, filtered, stringMessages, true);
this(all, filtered, stringMessages, /* selectOnRefresh */ true);
}
public AbstractFilterablePanel(Iterable<T> all, final ListDataProvider<T> filtered,
@@ -167,6 +193,11 @@ public abstract class AbstractFilterablePanel<T> extends HorizontalPanel {
this(all, filtered, /* show default filter text box */ true, stringMessages, selectOnRefresh);
}
public AbstractFilterablePanel(Iterable<T> all, ListDataProvider<T> filtered, StringMessages stringMessages,
String filterCheckboxLabel) {
this(all, filtered, /* draw text box */ true, stringMessages, /* selectOnRefresh */ true, filterCheckboxLabel);
}
private void setAll(Iterable<? extends T> all) {
this.all.getList().clear();
if (all != null) {
@@ -473,11 +504,11 @@ public abstract class AbstractFilterablePanel<T> 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<T> 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<T, Boolean> filterFunction) {
@@ -511,7 +542,7 @@ public abstract class AbstractFilterablePanel<T> extends HorizontalPanel {
return "Update Permission Filter";
}
});
addDefaultCheckBoxIfNecessary();
addShowOnlyObjectsWithUpdatePermissionCheckBoxIfNecessary();
}
public Iterable<T> getAll() {
@@ -34,4 +34,10 @@ public abstract class LabeledAbstractFilterablePanel<T> extends AbstractFilterab
super(all, filtered, stringMessages);
insert(label, 0);
}
public LabeledAbstractFilterablePanel(Label label, Iterable<T> all, final ListDataProvider<T> filtered,
StringMessages stringMessages, String filterCheckboxLabel) {
super(all, filtered, stringMessages, filterCheckboxLabel);
insert(label, 0);
}
}
@@ -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) {
@@ -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 <T> the object type represented by a row
* @param <S> the selection model type to ues
* @param <SM> the {@link StringMessages} sub-type to use
* @param <TR> the table resources defining the styles for the elements shown
*/
public abstract class TableWrapperWithFilterForSecuredDTOs<T extends SecuredDTO, S extends RefreshableSelectionModel<T>, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapperWithFilter<T, S, SM, TR> {
public TableWrapperWithFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter, boolean multiSelection,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator, UserService userService, Optional<String> 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<T>> entityIdentityComparator, TR tableRes,
UserService userService, Optional<String> filterLabel) {
super(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator, tableRes,
Optional.of(t -> userService.hasPermission(t, DefaultActions.UPDATE)), filterLabel,
stringMessages.hideElementsWithoutUpdateRights());
}
}
@@ -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 <T> the object type represented by a row
* @param <SM> the {@link StringMessages} sub-type to use
* @param <TR> the table resources defining the styles for the elements shown
*/
public abstract class TableWrapperWithMultiSelectionAndFilterForSecuredDTO<T extends SecuredDTO, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapperWithFilterForSecuredDTOs<T, RefreshableMultiSelectionModel<T>, SM, TR> {
public TableWrapperWithMultiSelectionAndFilterForSecuredDTO(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator, UserService userService,
Optional<String> filterLabel) {
this(stringMessages, errorReporter, enablePager, entityIdentityComparator,
GWT.create(CellTableWithCheckboxResources.class), userService, filterLabel);
}
public TableWrapperWithMultiSelectionAndFilterForSecuredDTO(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator, TR tableRes,
UserService userService, Optional<String> filterLabel) {
super(stringMessages, errorReporter, /* multiSelection */ true, enablePager, entityIdentityComparator, tableRes,
userService, filterLabel);
}
}
@@ -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 <T> the object type represented by a row
* @param <SM> the {@link StringMessages} sub-type to use
* @param <TR> the table resources defining the styles for the elements shown
*/
public abstract class TableWrapperWithSingleSelectionAndFilterForSecuredDTOs<T extends SecuredDTO, SM extends StringMessages, TR extends CellTableWithCheckboxResources>
extends TableWrapperWithFilterForSecuredDTOs<T, RefreshableSingleSelectionModel<T>, SM, TR> {
public TableWrapperWithSingleSelectionAndFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator, UserService userService,
Optional<String> filterLabel) {
this(stringMessages, errorReporter, enablePager, entityIdentityComparator,
GWT.create(CellTableWithCheckboxResources.class), userService, filterLabel);
}
public TableWrapperWithSingleSelectionAndFilterForSecuredDTOs(SM stringMessages, ErrorReporter errorReporter,
boolean enablePager, Optional<EntityIdentityComparator<T>> entityIdentityComparator, TR tableRes,
UserService userService, Optional<String> filterLabel) {
super(stringMessages, errorReporter, /* multiSelection */ false, enablePager, entityIdentityComparator,
tableRes, userService, filterLabel);
}
}
@@ -90,20 +90,16 @@ public class UserGroupTableWrapper extends
});
}
});
final EditOwnershipDialog.DialogConfig<UserGroupDTO> configOwnership = EditOwnershipDialog.create(
userService.getUserManagementWriteService(), type,
user -> refreshUserList(null), stringMessages);
final EditACLDialog.DialogConfig<UserGroupDTO> 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<UserGroupDTO>(new Label(stringMessages.filterUserGroups()),
new ArrayList<UserGroupDTO>(), 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());