bug6239: refactored enabling/disabling of REMOVE/UPDATE buttons for adminconsole panels

This commit is contained in:
masha.kashirina
2026-04-17 15:38:53 +02:00
parent 486efe3bbe
commit 447a8e7caf
9 changed files with 28 additions and 79 deletions
@@ -14,7 +14,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.gwt.cell.client.AbstractCell;
@@ -40,7 +39,6 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.sap.sailing.domain.common.dto.CourseAreaDTO;
import com.sap.sailing.gwt.common.client.help.HelpButton;
import com.sap.sailing.gwt.common.client.help.HelpButtonResources;
@@ -180,19 +178,6 @@ public class EventListComposite extends Composite {
final Button remove = buttonPanel.addRemoveAction(stringMessages.remove(), refreshableEventSelectionModel, true,
() -> removeEvents(refreshableEventSelectionModel.getSelectedSet()));
remove.ensureDebugId("RemoveEventsButton");
this.refreshableEventSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
final Set<EventDTO> selectedEvents = refreshableEventSelectionModel.getSelectedSet();
boolean canDeleteAll = true;
for (EventDTO eventDTO : selectedEvents) {
if (!userService.hasPermission(eventDTO, DefaultActions.DELETE)) {
canDeleteAll = false;
}
}
remove.setEnabled(!selectedEvents.isEmpty() && canDeleteAll);
}
});
buttonPanel.addUnsecuredWidget(new HelpButton(HelpButtonResources.INSTANCE,
stringMessages.videoGuide(), "https://sapsailing-documentation.s3-eu-west-1.amazonaws.com/adminconsole/CreatingYourFirstEvent.mp4"));
panel.add(filterTextbox);
@@ -183,7 +183,7 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv
devicesControlsPanel.add(busyIndicator);
buttonPanel.addUnsecuredAction(stringMessages.refresh(), () -> refreshDevices());
// setup controls
final Button removeDeviceButton = buttonPanel.addRemoveAction(stringMessages.remove(), refreshableDevicesSelectionModel,
buttonPanel.addRemoveAction(stringMessages.remove(), refreshableDevicesSelectionModel,
/* with confirmation */ true, () -> {
if (refreshableDevicesSelectionModel.getSelectedSet().size() > 0) {
if (Window.confirm(stringMessages.doYouReallyWantToRemoveTheSelectedIgtimiDevices())) {
@@ -193,7 +193,6 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv
}
}
});
removeDeviceButton.setEnabled(false);
devicesCaptionPanelContents.add(devicesControlsPanel);
devicesCaptionPanelContents.add(devicesTable);
add(devicesCaptionPanel);
@@ -230,7 +229,7 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv
dawControlsPanel.add(dawButtonPanel);
dawButtonPanel.addUnsecuredAction(stringMessages.refresh(), () -> refreshDataAccessWindows());
// setup controls
final Button removeDAWButton = dawButtonPanel.addRemoveAction(stringMessages.remove(), refreshableDataAccessWindowsSelectionModel,
dawButtonPanel.addRemoveAction(stringMessages.remove(), refreshableDataAccessWindowsSelectionModel,
/* with confirmation */ true, () -> {
if (refreshableDataAccessWindowsSelectionModel.getSelectedSet().size() > 0) {
if (Window.confirm(stringMessages.doYouReallyWantToRemoveTheSelectedIgtimiDataAccessWindows())) {
@@ -240,10 +239,8 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv
}
}
});
removeDAWButton.setEnabled(false);
refreshableDevicesSelectionModel.addSelectionChangeHandler(
e -> {
removeDeviceButton.setEnabled(refreshableDevicesSelectionModel.getSelectedSet().size() > 0);
final boolean exactlyOneDeviceSelected = refreshableDevicesSelectionModel.getSelectedSet().size() == 1;
dawTable.setVisible(exactlyOneDeviceSelected);
dawControlsPanel.setVisible(exactlyOneDeviceSelected);
@@ -251,10 +248,6 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv
filterDataAccessWindowPanel.search(refreshableDevicesSelectionModel.getSelectedSet().iterator().next().getSerialNumber());
}
});
refreshableDataAccessWindowsSelectionModel.addSelectionChangeHandler(
e -> {
removeDAWButton.setEnabled(refreshableDataAccessWindowsSelectionModel.getSelectedSet().size() > 0);
});
dataAccessWindowsCaptionPanelContents.add(dawControlsPanel);
dataAccessWindowsCaptionPanelContents.add(dawTable);
add(dataAccessWindowsCaptionPanel);
@@ -865,14 +865,6 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel
@Override
protected void leaderboardSelectionChanged() {
Set<StrippedLeaderboardDTO> selectedLeaderboards = leaderboardSelectionModel.getSelectedSet();
boolean canDeleteAllSelected = true;
for (StrippedLeaderboardDTO leaderboard : selectedLeaderboards) {
if (!userService.hasPermission(leaderboard, DefaultActions.DELETE)) {
canDeleteAllSelected = false;
}
}
leaderboardRemoveButton.setEnabled(!selectedLeaderboards.isEmpty() && canDeleteAllSelected);
final StrippedLeaderboardDTO selectedLeaderboard = getSelectedLeaderboard();
if (leaderboardSelectionModel.getSelectedSet().size() == 1 && selectedLeaderboard != null) {
raceColumnTable.getDataProvider().getList().clear();
@@ -835,15 +835,8 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel
}
private void groupSelectionChanged() {
Set<LeaderboardGroupDTO> selectedLeaderboardGroups = refreshableGroupsSelectionModel.getSelectedSet();
final Set<LeaderboardGroupDTO> selectedLeaderboardGroups = refreshableGroupsSelectionModel.getSelectedSet();
isSingleGroupSelected = selectedLeaderboardGroups.size() == 1;
boolean canDeleteAllSelected = true;
for (LeaderboardGroupDTO group : selectedLeaderboardGroups) {
if (!userService.hasPermission(group, DefaultActions.DELETE)) {
canDeleteAllSelected = false;
}
}
removeButton.setEnabled(!selectedLeaderboardGroups.isEmpty() && canDeleteAllSelected);
splitPanel.setVisible(isSingleGroupSelected);
if (isSingleGroupSelected) {
LeaderboardGroupDTO selectedGroup = selectedLeaderboardGroups.iterator().next();
@@ -32,12 +32,9 @@ import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.common.media.MediaTrackWithSecurityDTO;
@@ -177,7 +174,7 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med
}).center();
}
});
final Button multiUrlChange = buttonAndFilterPanel.addUpdateAction(stringMessages.multiUrlChangeMediaTrack(),
buttonAndFilterPanel.addUpdateAction(stringMessages.multiUrlChangeMediaTrack(),
refreshableSelectionModel,
new Command() {
@Override
@@ -195,7 +192,7 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med
}
}
});
final Button remove = buttonAndFilterPanel.addRemoveAction(stringMessages.remove(), refreshableSelectionModel,
buttonAndFilterPanel.addRemoveAction(stringMessages.remove(), refreshableSelectionModel,
/* with confirmation */ true, new Command() {
@Override
public void execute() {
@@ -204,24 +201,6 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med
}
}
});
refreshableSelectionModel.addSelectionChangeHandler(new Handler() {
@Override
public void onSelectionChange(final SelectionChangeEvent event) {
final Set<MediaTrackWithSecurityDTO> selected = refreshableSelectionModel.getSelectedSet();
boolean canDeleteAllSelected = true;
boolean canUpdateAllSelected = true;
for (final MediaTrackWithSecurityDTO track : selected) {
if (!userService.hasPermission(track, DefaultActions.DELETE)) {
canDeleteAllSelected = false;
}
if (!userService.hasPermission(track, DefaultActions.UPDATE)) {
canUpdateAllSelected = false;
}
}
remove.setEnabled(!selected.isEmpty() && canDeleteAllSelected);
multiUrlChange.setEnabled(!selected.isEmpty() && canUpdateAllSelected);
}
});
buttonAndFilterPanel.addUnsecuredWidget(lblFilterRaces);
createMediaTracksTable(userService);
filterableMediaTracks.getTextBox().ensureDebugId("MediaTracksFilterTextBox");
@@ -15,7 +15,6 @@ import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.gwt.common.client.help.HelpButton;
import com.sap.sailing.gwt.common.client.help.HelpButtonResources;
@@ -29,7 +28,6 @@ import com.sap.sse.gwt.adminconsole.FilterablePanelProvider;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
@@ -79,7 +77,7 @@ public class RegattaManagementPanel extends SimplePanel implements FilterablePan
update.ensureDebugId("UpdateRegattaButton");
final Button create = buttonPanel.addCreateAction(stringMessages.addRegatta(), this::openCreateRegattaDialog);
create.ensureDebugId("AddRegattaButton");
final Button remove = buttonPanel.addRemoveAction(stringMessages.remove(),
buttonPanel.addRemoveAction(stringMessages.remove(),
refreshableRegattaMultiSelectionModel, true, () -> {
// unmodifiable collection can't be sent to the server.
final Collection<RegattaIdentifier> regattas = createModifiableCollection();
@@ -88,10 +86,10 @@ public class RegattaManagementPanel extends SimplePanel implements FilterablePan
buttonPanel.addUnsecuredWidget(new HelpButton(HelpButtonResources.INSTANCE,
stringMessages.videoGuide(), "https://sapsailing-documentation.s3-eu-west-1.amazonaws.com/adminconsole/Advanced+Topics/Setting+up+Events+with+multiple+Regattas+or+Classes.mp4"));
regattasContentPanel.add(buttonPanel);
refreshableRegattaMultiSelectionModel.addSelectionChangeHandler(new Handler() {
refreshableRegattaMultiSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
List<RegattaDTO> selectedRegattas = new ArrayList<>(
final List<RegattaDTO> selectedRegattas = new ArrayList<>(
refreshableRegattaMultiSelectionModel.getSelectedSet());
final RegattaIdentifier selectedRegatta;
if (selectedRegattas.size() == 1) {
@@ -109,13 +107,6 @@ public class RegattaManagementPanel extends SimplePanel implements FilterablePan
regattaDetailsComposite.setRegatta(null);
regattaDetailsComposite.setVisible(false);
}
boolean canDeleteAllSelected = true;
for (RegattaDTO regatta : refreshableRegattaMultiSelectionModel.getSelectedSet()) {
if (!userService.hasPermission(regatta, DefaultActions.DELETE)) {
canDeleteAllSelected = false;
}
}
remove.setEnabled(!selectedRegattas.isEmpty() && canDeleteAllSelected);
}
});
regattasContentPanel.add(regattaListComposite);
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.sap.sailing.domain.common.security.SecuredDomainType;
import com.sap.sse.common.Named;
import com.sap.sse.common.TimePoint;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
@@ -12,7 +13,7 @@ import com.sap.sse.security.shared.dto.OwnershipDTO;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
public class IgtimiDataAccessWindowWithSecurityDTO implements SecuredDTO {
public class IgtimiDataAccessWindowWithSecurityDTO implements SecuredDTO, Named {
private static final long serialVersionUID = 176992188692729118L;
private SecurityInformationDTO securityInformation = new SecurityInformationDTO();
@@ -1,6 +1,7 @@
package com.sap.sailing.gwt.ui.shared;
import com.sap.sailing.domain.common.security.SecuredDomainType;
import com.sap.sse.common.Named;
import com.sap.sse.common.Position;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Pair;
@@ -12,7 +13,7 @@ import com.sap.sse.security.shared.dto.OwnershipDTO;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
public class IgtimiDeviceWithSecurityDTO implements SecuredDTO {
public class IgtimiDeviceWithSecurityDTO implements SecuredDTO, Named {
private static final long serialVersionUID = 176992188692729118L;
private SecurityInformationDTO securityInformation = new SecurityInformationDTO();
@@ -16,6 +16,8 @@ import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SetSelectionModel;
import com.sap.sse.common.Named;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.i18n.StringMessages;
@@ -30,6 +32,7 @@ public class AccessControlledButtonPanel extends Composite {
private final HorizontalPanel panel = new HorizontalPanel();
private final Map<Button, Supplier<Boolean>> buttonToPermissions = new HashMap<>();
private final UserService userService;
private final Supplier<Boolean> createPermissionCheck, createPermissionCheckWithoutServerCreateObjectCheck,
removePermissionCheck, updatePermissionCheck;
private final BiConsumer<Button, Supplier<Boolean>> visibilityUpdater = (btn, check) -> btn.setVisible(check.get());
@@ -44,6 +47,7 @@ public class AccessControlledButtonPanel extends Composite {
* the {@link HasPermissions} representing the type of objects to be secured by this panel
*/
public AccessControlledButtonPanel(final UserService userService, final HasPermissions type) {
this.userService = userService;
this.createPermissionCheck = () -> userService.hasCurrentUserPermissionToCreateObjectOfType(type);
this.createPermissionCheckWithoutServerCreateObjectCheck = () -> userService
.hasCurrentUserPermissionToCreateObjectOfTypeWithoutServerCreateObjectPermissionCheck(type);
@@ -136,7 +140,7 @@ public class AccessControlledButtonPanel extends Composite {
*
* @return the created {@link SelectedElementsCountingButton} instance with optional confirmation
*/
public <T extends Named> Button addRemoveAction(final String text, final SetSelectionModel<T> selectionModel,
public <T extends Named & SecuredDTO> Button addRemoveAction(final String text, final SetSelectionModel<T> selectionModel,
boolean withConfirmation, final Command callback) {
if (selectionModel == null) {
throw new IllegalArgumentException("Selection model for a remove action must not be null");
@@ -146,6 +150,11 @@ public class AccessControlledButtonPanel extends Composite {
? new SelectedElementsCountingButton<T>(text, selectionModel, StringMessages.INSTANCE::doYouReallyWantToRemoveSelectedElements,
handler)
: new SelectedElementsCountingButton<T>(text, selectionModel, handler);
selectionModel.addSelectionChangeHandler(event -> {
final boolean canActOnAllSelected = selectionModel.getSelectedSet().stream()
.allMatch(item -> userService.hasPermission(item, DefaultActions.DELETE));
button.setEnabled(!selectionModel.getSelectedSet().isEmpty() && canActOnAllSelected);
});
return resolveButtonVisibility(removePermissionCheck, button);
}
@@ -180,13 +189,18 @@ public class AccessControlledButtonPanel extends Composite {
*
* @return the created {@link SelectedElementsCountingButton} instance with optional confirmation
*/
public <T extends Named> Button addUpdateAction(final String text, final SetSelectionModel<T> selectionModel,
public <T extends Named & SecuredDTO> Button addUpdateAction(final String text, final SetSelectionModel<T> selectionModel,
final Command callback) {
if (selectionModel == null) {
throw new IllegalArgumentException("Selection model for an update action must not be null");
}
final ClickHandler handler = wrap(updatePermissionCheck, callback);
final Button button = new SelectedElementsCountingButton<T>(text, selectionModel, handler);
selectionModel.addSelectionChangeHandler(event -> {
final boolean canActOnAllSelected = selectionModel.getSelectedSet().stream()
.allMatch(item -> userService.hasPermission(item, DefaultActions.UPDATE));
button.setEnabled(!selectionModel.getSelectedSet().isEmpty() && canActOnAllSelected);
});
return resolveButtonVisibility(updatePermissionCheck, button);
}