514187fcd40f4e6dfe0aa859075e2f337b4400ae
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java
| ... | ... | @@ -32,12 +32,9 @@ import com.google.gwt.user.cellview.client.Header; |
| 32 | 32 | import com.google.gwt.user.client.Command; |
| 33 | 33 | import com.google.gwt.user.client.Window; |
| 34 | 34 | import com.google.gwt.user.client.rpc.AsyncCallback; |
| 35 | -import com.google.gwt.user.client.ui.Button; |
|
| 36 | 35 | import com.google.gwt.user.client.ui.FlowPanel; |
| 37 | 36 | import com.google.gwt.user.client.ui.Label; |
| 38 | 37 | import com.google.gwt.view.client.ListDataProvider; |
| 39 | -import com.google.gwt.view.client.SelectionChangeEvent; |
|
| 40 | -import com.google.gwt.view.client.SelectionChangeEvent.Handler; |
|
| 41 | 38 | import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; |
| 42 | 39 | import com.sap.sailing.domain.common.media.MediaTrack; |
| 43 | 40 | import com.sap.sailing.domain.common.media.MediaTrackWithSecurityDTO; |
| ... | ... | @@ -103,6 +100,7 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 103 | 100 | private Date latestDate; |
| 104 | 101 | private RefreshableMultiSelectionModel<MediaTrackWithSecurityDTO> refreshableSelectionModel; |
| 105 | 102 | private final FileStorageServiceConnectionTestObservable storageServiceAvailable; |
| 103 | + private final SelectionCheckboxColumn<MediaTrackWithSecurityDTO> checkColumn; |
|
| 106 | 104 | |
| 107 | 105 | public MediaPanel(Presenter presenter, StringMessages stringMessages) { |
| 108 | 106 | this.sailingServiceWrite = presenter.getSailingService(); |
| ... | ... | @@ -112,6 +110,43 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 112 | 110 | this.stringMessages = stringMessages; |
| 113 | 111 | this.errorReporter = presenter.getErrorReporter(); |
| 114 | 112 | this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(presenter.getSailingService()); |
| 113 | + Label lblFilterRaces = new Label(stringMessages.filterMediaByName() + ":"); |
|
| 114 | + lblFilterRaces.setWordWrap(false); |
|
| 115 | + this.filterableMediaTracks = new LabeledAbstractFilterablePanel<MediaTrackWithSecurityDTO>(lblFilterRaces, |
|
| 116 | + allMediaTracks, mediaTrackListDataProvider, stringMessages) { |
|
| 117 | + @Override |
|
| 118 | + public List<String> getSearchableStrings(MediaTrackWithSecurityDTO t) { |
|
| 119 | + List<String> strings = new ArrayList<String>(); |
|
| 120 | + strings.add(t.title); |
|
| 121 | + strings.add(t.url); |
|
| 122 | + if (t.startTime == null) { |
|
| 123 | + GWT.log("startTime of media track " + t.title + " undefined"); |
|
| 124 | + } else { |
|
| 125 | + strings.add(t.startTime.toString()); |
|
| 126 | + } |
|
| 127 | + return strings; |
|
| 128 | + } |
|
| 129 | + |
|
| 130 | + @Override |
|
| 131 | + public AbstractCellTable<MediaTrackWithSecurityDTO> getCellTable() { |
|
| 132 | + return mediaTracksTable; |
|
| 133 | + } |
|
| 134 | + }; |
|
| 135 | + checkColumn = new SelectionCheckboxColumn<>( |
|
| 136 | + tableResources.cellTableStyle().cellTableCheckboxSelected(), |
|
| 137 | + tableResources.cellTableStyle().cellTableCheckboxDeselected(), |
|
| 138 | + tableResources.cellTableStyle().cellTableCheckboxColumnCell(), |
|
| 139 | + new EntityIdentityComparator<MediaTrackWithSecurityDTO>() { |
|
| 140 | + @Override |
|
| 141 | + public boolean representSameEntity(MediaTrackWithSecurityDTO dto1, MediaTrackWithSecurityDTO dto2) { |
|
| 142 | + return dto1.dbId.equals(dto2.dbId); |
|
| 143 | + } |
|
| 144 | + @Override |
|
| 145 | + public int hashCode(MediaTrackWithSecurityDTO t) { |
|
| 146 | + return t.dbId.hashCode(); |
|
| 147 | + } |
|
| 148 | + }, filterableMediaTracks.getAllListDataProvider()); |
|
| 149 | + refreshableSelectionModel = checkColumn.getSelectionModel(); |
|
| 115 | 150 | AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, |
| 116 | 151 | SecuredDomainType.MEDIA_TRACK); |
| 117 | 152 | add(buttonAndFilterPanel); |
| ... | ... | @@ -139,8 +174,8 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 139 | 174 | }).center(); |
| 140 | 175 | } |
| 141 | 176 | }); |
| 142 | - |
|
| 143 | - Button multiURLChange = buttonAndFilterPanel.addUnsecuredAction(stringMessages.multiUrlChangeMediaTrack(), |
|
| 177 | + buttonAndFilterPanel.addUpdateAction(stringMessages.multiUrlChangeMediaTrack(), |
|
| 178 | + refreshableSelectionModel, |
|
| 144 | 179 | new Command() { |
| 145 | 180 | @Override |
| 146 | 181 | public void execute() { |
| ... | ... | @@ -157,8 +192,8 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 157 | 192 | } |
| 158 | 193 | } |
| 159 | 194 | }); |
| 160 | - multiURLChange.setEnabled(false); |
|
| 161 | - final Button removeButton = buttonAndFilterPanel.addRemoveAction(stringMessages.remove(), new Command() { |
|
| 195 | + buttonAndFilterPanel.addRemoveAction(stringMessages.remove(), refreshableSelectionModel, |
|
| 196 | + /* with confirmation */ true, new Command() { |
|
| 162 | 197 | @Override |
| 163 | 198 | public void execute() { |
| 164 | 199 | for (final MediaTrackWithSecurityDTO track : refreshableSelectionModel.getSelectedSet()) { |
| ... | ... | @@ -166,62 +201,12 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 166 | 201 | } |
| 167 | 202 | } |
| 168 | 203 | }); |
| 169 | - removeButton.setEnabled(false); |
|
| 170 | - Label lblFilterRaces = new Label(stringMessages.filterMediaByName() + ":"); |
|
| 171 | - lblFilterRaces.setWordWrap(false); |
|
| 172 | 204 | buttonAndFilterPanel.addUnsecuredWidget(lblFilterRaces); |
| 173 | - this.filterableMediaTracks = new LabeledAbstractFilterablePanel<MediaTrackWithSecurityDTO>(lblFilterRaces, |
|
| 174 | - allMediaTracks, mediaTrackListDataProvider, stringMessages) { |
|
| 175 | - @Override |
|
| 176 | - public List<String> getSearchableStrings(MediaTrackWithSecurityDTO t) { |
|
| 177 | - List<String> strings = new ArrayList<String>(); |
|
| 178 | - strings.add(t.title); |
|
| 179 | - strings.add(t.url); |
|
| 180 | - if (t.startTime == null) { |
|
| 181 | - GWT.log("startTime of media track " + t.title + " undefined"); |
|
| 182 | - } else { |
|
| 183 | - strings.add(t.startTime.toString()); |
|
| 184 | - } |
|
| 185 | - return strings; |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - @Override |
|
| 189 | - public AbstractCellTable<MediaTrackWithSecurityDTO> getCellTable() { |
|
| 190 | - return mediaTracksTable; |
|
| 191 | - } |
|
| 192 | - }; |
|
| 193 | 205 | createMediaTracksTable(userService); |
| 194 | 206 | filterableMediaTracks.getTextBox().ensureDebugId("MediaTracksFilterTextBox"); |
| 195 | 207 | filterableMediaTracks |
| 196 | 208 | .setUpdatePermissionFilterForCheckbox(mediaTrack -> userService.hasPermission(mediaTrack, DefaultActions.UPDATE)); |
| 197 | 209 | buttonAndFilterPanel.addUnsecuredWidget(filterableMediaTracks); |
| 198 | - |
|
| 199 | - refreshableSelectionModel.addSelectionChangeHandler(new Handler() { |
|
| 200 | - @Override |
|
| 201 | - public void onSelectionChange(SelectionChangeEvent event) { |
|
| 202 | - final Set<MediaTrackWithSecurityDTO> selected = refreshableSelectionModel.getSelectedSet(); |
|
| 203 | - final int count = selected.size(); |
|
| 204 | - boolean canUpdateAll = true; |
|
| 205 | - boolean canDeleteAll = true; |
|
| 206 | - for (MediaTrackWithSecurityDTO track : selected) { |
|
| 207 | - if (!userService.hasPermission(track, DefaultActions.UPDATE)) { |
|
| 208 | - canUpdateAll = false; |
|
| 209 | - } |
|
| 210 | - if (!userService.hasPermission(track, DefaultActions.DELETE)) { |
|
| 211 | - canDeleteAll = false; |
|
| 212 | - } |
|
| 213 | - } |
|
| 214 | - final boolean multiUrlEnabled = count > 0 && canUpdateAll; |
|
| 215 | - multiURLChange.setEnabled(multiUrlEnabled); |
|
| 216 | - multiURLChange.setText(count > 0 |
|
| 217 | - ? stringMessages.multiUrlChangeMediaTrack() + " (" + count + ")" |
|
| 218 | - : stringMessages.multiUrlChangeMediaTrack()); |
|
| 219 | - removeButton.setEnabled(count > 0 && canDeleteAll); |
|
| 220 | - removeButton.setText(count > 0 |
|
| 221 | - ? stringMessages.remove() + " (" + count + ")" |
|
| 222 | - : stringMessages.remove()); |
|
| 223 | - } |
|
| 224 | - }); |
|
| 225 | 210 | } |
| 226 | 211 | |
| 227 | 212 | private final Displayer<MediaTrackWithSecurityDTO> mediaTracksDisplayer = new Displayer<MediaTrackWithSecurityDTO>() { |
| ... | ... | @@ -260,21 +245,6 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 260 | 245 | */ |
| 261 | 246 | private void initTableColumns(final ListHandler<MediaTrackWithSecurityDTO> sortHandler, |
| 262 | 247 | final UserService userService) { |
| 263 | - final SelectionCheckboxColumn<MediaTrackWithSecurityDTO> checkColumn = new SelectionCheckboxColumn<>( |
|
| 264 | - tableResources.cellTableStyle().cellTableCheckboxSelected(), |
|
| 265 | - tableResources.cellTableStyle().cellTableCheckboxDeselected(), |
|
| 266 | - tableResources.cellTableStyle().cellTableCheckboxColumnCell(), |
|
| 267 | - new EntityIdentityComparator<MediaTrackWithSecurityDTO>() { |
|
| 268 | - @Override |
|
| 269 | - public boolean representSameEntity(MediaTrackWithSecurityDTO dto1, MediaTrackWithSecurityDTO dto2) { |
|
| 270 | - return dto1.dbId.equals(dto2.dbId); |
|
| 271 | - } |
|
| 272 | - @Override |
|
| 273 | - public int hashCode(MediaTrackWithSecurityDTO t) { |
|
| 274 | - return t.dbId.hashCode(); |
|
| 275 | - } |
|
| 276 | - }, filterableMediaTracks.getAllListDataProvider()); |
|
| 277 | - refreshableSelectionModel = checkColumn.getSelectionModel(); |
|
| 278 | 248 | final Header<Boolean> selectAllHeader = checkColumn.createHeader(); |
| 279 | 249 | mediaTracksTable.addColumn(checkColumn, selectAllHeader); |
| 280 | 250 | mediaTracksTable.setColumnWidth(checkColumn, 40, Unit.PX); |
java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/AccessControlledButtonPanel.java
| ... | ... | @@ -165,6 +165,32 @@ public class AccessControlledButtonPanel extends Composite { |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | /** |
| 168 | + * Adds a secured action button, which is only visible if the current user has any |
|
| 169 | + * {@link UserService#hasCurrentUserPermissionToDeleteAnyObjectOfType(HasPermissions) update permission} for the |
|
| 170 | + * {@link HasPermissions type} provided in this {@link AccessControlledButtonPanel}'s constructor. |
|
| 171 | + * |
|
| 172 | + * @param text |
|
| 173 | + * the {@link String text} to show on the button |
|
| 174 | + * @param selectionModel |
|
| 175 | + * the {@link SetSelectionModel<T> selection model} of the table; used to enable/disable the remove |
|
| 176 | + * button when the selection becomes non-empty/empty, respectively and to display the number of elements |
|
| 177 | + * selected in case the selection contains more than one element |
|
| 178 | + * @param callback |
|
| 179 | + * the {@link Command callback} to execute on button click, if permission is granted |
|
| 180 | + * |
|
| 181 | + * @return the created {@link SelectedElementsCountingButton} instance with optional confirmation |
|
| 182 | + */ |
|
| 183 | + public <T extends Named> Button addUpdateAction(final String text, final SetSelectionModel<T> selectionModel, |
|
| 184 | + final Command callback) { |
|
| 185 | + if (selectionModel == null) { |
|
| 186 | + throw new IllegalArgumentException("Selection model for an update action must not be null"); |
|
| 187 | + } |
|
| 188 | + final ClickHandler handler = wrap(updatePermissionCheck, callback); |
|
| 189 | + final Button button = new SelectedElementsCountingButton<T>(text, selectionModel, handler); |
|
| 190 | + return resolveButtonVisibility(updatePermissionCheck, button); |
|
| 191 | + } |
|
| 192 | + |
|
| 193 | + /** |
|
| 168 | 194 | * Adds an action button, which's visibility depends on the provided {@link Supplier permission check}. |
| 169 | 195 | * |
| 170 | 196 | * @param text |