651c7d639c1885180d43213498edce343ed92696
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java
| ... | ... | @@ -191,7 +191,6 @@ public class EventListComposite extends Composite { |
| 191 | 191 | } |
| 192 | 192 | } |
| 193 | 193 | remove.setEnabled(!selectedEvents.isEmpty() && canDeleteAll); |
| 194 | - |
|
| 195 | 194 | } |
| 196 | 195 | }); |
| 197 | 196 | buttonPanel.addUnsecuredWidget(new HelpButton(HelpButtonResources.INSTANCE, |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java
| ... | ... | @@ -21,25 +21,20 @@ import com.google.gwt.cell.client.FieldUpdater; |
| 21 | 21 | import com.google.gwt.cell.client.TextCell; |
| 22 | 22 | import com.google.gwt.cell.client.ValueUpdater; |
| 23 | 23 | import com.google.gwt.core.client.GWT; |
| 24 | -import com.google.gwt.dom.client.BrowserEvents; |
|
| 25 | 24 | import com.google.gwt.dom.client.Element; |
| 26 | 25 | import com.google.gwt.dom.client.NativeEvent; |
| 27 | 26 | import com.google.gwt.dom.client.Style.Unit; |
| 28 | 27 | import com.google.gwt.event.dom.client.KeyCodes; |
| 29 | -import com.google.gwt.safehtml.shared.SafeHtmlUtils; |
|
| 30 | 28 | import com.google.gwt.user.cellview.client.AbstractCellTable; |
| 31 | -import com.google.gwt.user.cellview.client.CellTable; |
|
| 32 | 29 | import com.google.gwt.user.cellview.client.Column; |
| 33 | 30 | import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; |
| 31 | +import com.google.gwt.user.cellview.client.Header; |
|
| 34 | 32 | import com.google.gwt.user.client.Command; |
| 35 | 33 | import com.google.gwt.user.client.Window; |
| 36 | 34 | import com.google.gwt.user.client.rpc.AsyncCallback; |
| 37 | 35 | import com.google.gwt.user.client.ui.Button; |
| 38 | 36 | import com.google.gwt.user.client.ui.FlowPanel; |
| 39 | 37 | import com.google.gwt.user.client.ui.Label; |
| 40 | -import com.google.gwt.view.client.CellPreviewEvent; |
|
| 41 | -import com.google.gwt.view.client.DefaultSelectionEventManager; |
|
| 42 | -import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction; |
|
| 43 | 38 | import com.google.gwt.view.client.ListDataProvider; |
| 44 | 39 | import com.google.gwt.view.client.SelectionChangeEvent; |
| 45 | 40 | import com.google.gwt.view.client.SelectionChangeEvent.Handler; |
| ... | ... | @@ -69,10 +64,10 @@ import com.sap.sse.gwt.client.ErrorReporter; |
| 69 | 64 | import com.sap.sse.gwt.client.Notification; |
| 70 | 65 | import com.sap.sse.gwt.client.Notification.NotificationType; |
| 71 | 66 | import com.sap.sse.gwt.client.async.MarkedAsyncCallback; |
| 72 | -import com.sap.sse.gwt.client.celltable.BaseCelltable; |
|
| 73 | 67 | import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; |
| 68 | +import com.sap.sse.gwt.client.celltable.FlushableCellTable; |
|
| 74 | 69 | import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; |
| 75 | -import com.sap.sse.gwt.client.controls.BetterCheckboxCell; |
|
| 70 | +import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn; |
|
| 76 | 71 | import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; |
| 77 | 72 | import com.sap.sse.gwt.client.panels.AbstractFilterablePanel; |
| 78 | 73 | import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; |
| ... | ... | @@ -103,11 +98,12 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 103 | 98 | private final ErrorReporter errorReporter; |
| 104 | 99 | private final StringMessages stringMessages; |
| 105 | 100 | private final UserService userService; |
| 106 | - private CellTable<MediaTrackWithSecurityDTO> mediaTracksTable; |
|
| 101 | + private FlushableCellTable<MediaTrackWithSecurityDTO> mediaTracksTable; |
|
| 107 | 102 | private ListDataProvider<MediaTrackWithSecurityDTO> mediaTrackListDataProvider = new ListDataProvider<>(); |
| 108 | 103 | private Date latestDate; |
| 109 | 104 | private RefreshableMultiSelectionModel<MediaTrackWithSecurityDTO> refreshableSelectionModel; |
| 110 | 105 | private final FileStorageServiceConnectionTestObservable storageServiceAvailable; |
| 106 | + private final SelectionCheckboxColumn<MediaTrackWithSecurityDTO> checkColumn; |
|
| 111 | 107 | |
| 112 | 108 | public MediaPanel(Presenter presenter, StringMessages stringMessages) { |
| 113 | 109 | this.sailingServiceWrite = presenter.getSailingService(); |
| ... | ... | @@ -117,6 +113,43 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 117 | 113 | this.stringMessages = stringMessages; |
| 118 | 114 | this.errorReporter = presenter.getErrorReporter(); |
| 119 | 115 | this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(presenter.getSailingService()); |
| 116 | + Label lblFilterRaces = new Label(stringMessages.filterMediaByName() + ":"); |
|
| 117 | + lblFilterRaces.setWordWrap(false); |
|
| 118 | + this.filterableMediaTracks = new LabeledAbstractFilterablePanel<MediaTrackWithSecurityDTO>(lblFilterRaces, |
|
| 119 | + allMediaTracks, mediaTrackListDataProvider, stringMessages) { |
|
| 120 | + @Override |
|
| 121 | + public List<String> getSearchableStrings(MediaTrackWithSecurityDTO t) { |
|
| 122 | + List<String> strings = new ArrayList<String>(); |
|
| 123 | + strings.add(t.title); |
|
| 124 | + strings.add(t.url); |
|
| 125 | + if (t.startTime == null) { |
|
| 126 | + GWT.log("startTime of media track " + t.title + " undefined"); |
|
| 127 | + } else { |
|
| 128 | + strings.add(t.startTime.toString()); |
|
| 129 | + } |
|
| 130 | + return strings; |
|
| 131 | + } |
|
| 132 | + |
|
| 133 | + @Override |
|
| 134 | + public AbstractCellTable<MediaTrackWithSecurityDTO> getCellTable() { |
|
| 135 | + return mediaTracksTable; |
|
| 136 | + } |
|
| 137 | + }; |
|
| 138 | + checkColumn = new SelectionCheckboxColumn<>( |
|
| 139 | + tableResources.cellTableStyle().cellTableCheckboxSelected(), |
|
| 140 | + tableResources.cellTableStyle().cellTableCheckboxDeselected(), |
|
| 141 | + tableResources.cellTableStyle().cellTableCheckboxColumnCell(), |
|
| 142 | + new EntityIdentityComparator<MediaTrackWithSecurityDTO>() { |
|
| 143 | + @Override |
|
| 144 | + public boolean representSameEntity(MediaTrackWithSecurityDTO dto1, MediaTrackWithSecurityDTO dto2) { |
|
| 145 | + return dto1.dbId.equals(dto2.dbId); |
|
| 146 | + } |
|
| 147 | + @Override |
|
| 148 | + public int hashCode(MediaTrackWithSecurityDTO t) { |
|
| 149 | + return t.dbId.hashCode(); |
|
| 150 | + } |
|
| 151 | + }, filterableMediaTracks.getAllListDataProvider()); |
|
| 152 | + refreshableSelectionModel = checkColumn.getSelectionModel(); |
|
| 120 | 153 | AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, |
| 121 | 154 | SecuredDomainType.MEDIA_TRACK); |
| 122 | 155 | add(buttonAndFilterPanel); |
| ... | ... | @@ -144,12 +177,12 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 144 | 177 | }).center(); |
| 145 | 178 | } |
| 146 | 179 | }); |
| 147 | - |
|
| 148 | - Button multiURLChange = buttonAndFilterPanel.addUnsecuredAction(stringMessages.multiUrlChangeMediaTrack(), |
|
| 180 | + final Button multiUrlChange = buttonAndFilterPanel.addUpdateAction(stringMessages.multiUrlChangeMediaTrack(), |
|
| 181 | + refreshableSelectionModel, |
|
| 149 | 182 | new Command() { |
| 150 | 183 | @Override |
| 151 | 184 | public void execute() { |
| 152 | - Set<MediaTrackWithSecurityDTO> selected = refreshableSelectionModel.getSelectedSet(); |
|
| 185 | + final Set<MediaTrackWithSecurityDTO> selected = refreshableSelectionModel.getSelectedSet(); |
|
| 153 | 186 | if (selected.isEmpty()) { |
| 154 | 187 | Notification.notify(stringMessages.noSelection(), NotificationType.ERROR); |
| 155 | 188 | } else { |
| ... | ... | @@ -162,48 +195,39 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 162 | 195 | } |
| 163 | 196 | } |
| 164 | 197 | }); |
| 165 | - multiURLChange.setEnabled(false); |
|
| 166 | - Label lblFilterRaces = new Label(stringMessages.filterMediaByName() + ":"); |
|
| 167 | - lblFilterRaces.setWordWrap(false); |
|
| 168 | - buttonAndFilterPanel.addUnsecuredWidget(lblFilterRaces); |
|
| 169 | - this.filterableMediaTracks = new LabeledAbstractFilterablePanel<MediaTrackWithSecurityDTO>(lblFilterRaces, |
|
| 170 | - allMediaTracks, mediaTrackListDataProvider, stringMessages) { |
|
| 198 | + final Button remove = buttonAndFilterPanel.addRemoveAction(stringMessages.remove(), refreshableSelectionModel, |
|
| 199 | + /* with confirmation */ true, new Command() { |
|
| 171 | 200 | @Override |
| 172 | - public List<String> getSearchableStrings(MediaTrackWithSecurityDTO t) { |
|
| 173 | - List<String> strings = new ArrayList<String>(); |
|
| 174 | - strings.add(t.title); |
|
| 175 | - strings.add(t.url); |
|
| 176 | - if (t.startTime == null) { |
|
| 177 | - GWT.log("startTime of media track " + t.title + " undefined"); |
|
| 178 | - } else { |
|
| 179 | - strings.add(t.startTime.toString()); |
|
| 201 | + public void execute() { |
|
| 202 | + for (final MediaTrackWithSecurityDTO track : refreshableSelectionModel.getSelectedSet()) { |
|
| 203 | + removeMediaTrack(track); |
|
| 180 | 204 | } |
| 181 | - return strings; |
|
| 182 | 205 | } |
| 183 | - |
|
| 184 | - @Override |
|
| 185 | - public AbstractCellTable<MediaTrackWithSecurityDTO> getCellTable() { |
|
| 186 | - return mediaTracksTable; |
|
| 187 | - } |
|
| 188 | - }; |
|
| 189 | - createMediaTracksTable(userService); |
|
| 190 | - filterableMediaTracks.getTextBox().ensureDebugId("MediaTracksFilterTextBox"); |
|
| 191 | - filterableMediaTracks |
|
| 192 | - .setUpdatePermissionFilterForCheckbox(mediaTrack -> userService.hasPermission(mediaTrack, DefaultActions.UPDATE)); |
|
| 193 | - buttonAndFilterPanel.addUnsecuredWidget(filterableMediaTracks); |
|
| 194 | - |
|
| 206 | + }); |
|
| 195 | 207 | refreshableSelectionModel.addSelectionChangeHandler(new Handler() { |
| 196 | 208 | @Override |
| 197 | - public void onSelectionChange(SelectionChangeEvent event) { |
|
| 198 | - boolean canUpdateAll = true; |
|
| 199 | - for (MediaTrackWithSecurityDTO track : refreshableSelectionModel.getSelectedSet()) { |
|
| 209 | + public void onSelectionChange(final SelectionChangeEvent event) { |
|
| 210 | + final Set<MediaTrackWithSecurityDTO> selected = refreshableSelectionModel.getSelectedSet(); |
|
| 211 | + boolean canDeleteAllSelected = true; |
|
| 212 | + boolean canUpdateAllSelected = true; |
|
| 213 | + for (final MediaTrackWithSecurityDTO track : selected) { |
|
| 214 | + if (!userService.hasPermission(track, DefaultActions.DELETE)) { |
|
| 215 | + canDeleteAllSelected = false; |
|
| 216 | + } |
|
| 200 | 217 | if (!userService.hasPermission(track, DefaultActions.UPDATE)) { |
| 201 | - canUpdateAll = false; |
|
| 218 | + canUpdateAllSelected = false; |
|
| 202 | 219 | } |
| 203 | 220 | } |
| 204 | - multiURLChange.setEnabled(!refreshableSelectionModel.getSelectedSet().isEmpty() && canUpdateAll); |
|
| 221 | + remove.setEnabled(!selected.isEmpty() && canDeleteAllSelected); |
|
| 222 | + multiUrlChange.setEnabled(!selected.isEmpty() && canUpdateAllSelected); |
|
| 205 | 223 | } |
| 206 | 224 | }); |
| 225 | + buttonAndFilterPanel.addUnsecuredWidget(lblFilterRaces); |
|
| 226 | + createMediaTracksTable(userService); |
|
| 227 | + filterableMediaTracks.getTextBox().ensureDebugId("MediaTracksFilterTextBox"); |
|
| 228 | + filterableMediaTracks |
|
| 229 | + .setUpdatePermissionFilterForCheckbox(mediaTrack -> userService.hasPermission(mediaTrack, DefaultActions.UPDATE)); |
|
| 230 | + buttonAndFilterPanel.addUnsecuredWidget(filterableMediaTracks); |
|
| 207 | 231 | } |
| 208 | 232 | |
| 209 | 233 | private final Displayer<MediaTrackWithSecurityDTO> mediaTracksDisplayer = new Displayer<MediaTrackWithSecurityDTO>() { |
| ... | ... | @@ -226,58 +250,10 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 226 | 250 | } |
| 227 | 251 | |
| 228 | 252 | private void createMediaTracksTable(final UserService userService) { |
| 229 | - // Create a CellTable. |
|
| 230 | - // Set a key provider that provides a unique key for each contact. If key is |
|
| 231 | - // used to identify contacts when fields (such as the name and address) |
|
| 232 | - // change. |
|
| 233 | - mediaTracksTable = new BaseCelltable<>(1000, tableResources); |
|
| 253 | + mediaTracksTable = new FlushableCellTable<>(1000, tableResources); |
|
| 234 | 254 | mediaTracksTable.setWidth("100%"); |
| 235 | - // Attach a column sort handler to the ListDataProvider to sort the list. |
|
| 236 | - ListHandler<MediaTrackWithSecurityDTO> sortHandler = new ListHandler<>(mediaTrackListDataProvider.getList()); |
|
| 255 | + final ListHandler<MediaTrackWithSecurityDTO> sortHandler = new ListHandler<>(mediaTrackListDataProvider.getList()); |
|
| 237 | 256 | mediaTracksTable.addColumnSortHandler(sortHandler); |
| 238 | - // Add a selection model so we can select cells. |
|
| 239 | - refreshableSelectionModel = new RefreshableMultiSelectionModel<>( |
|
| 240 | - new EntityIdentityComparator<MediaTrackWithSecurityDTO>() { |
|
| 241 | - @Override |
|
| 242 | - public boolean representSameEntity(MediaTrackWithSecurityDTO dto1, MediaTrackWithSecurityDTO dto2) { |
|
| 243 | - return dto1.dbId.equals(dto2.dbId); |
|
| 244 | - } |
|
| 245 | - @Override |
|
| 246 | - public int hashCode(MediaTrackWithSecurityDTO t) { |
|
| 247 | - return t.dbId.hashCode(); |
|
| 248 | - } |
|
| 249 | - }, filterableMediaTracks.getAllListDataProvider()); |
|
| 250 | - mediaTracksTable.setSelectionModel(refreshableSelectionModel, |
|
| 251 | - DefaultSelectionEventManager.createCustomManager( |
|
| 252 | - new DefaultSelectionEventManager.CheckboxEventTranslator<MediaTrackWithSecurityDTO>() { |
|
| 253 | - @Override |
|
| 254 | - public boolean clearCurrentSelection(CellPreviewEvent<MediaTrackWithSecurityDTO> event) { |
|
| 255 | - return !isCheckboxColumn(event.getColumn()); |
|
| 256 | - } |
|
| 257 | - |
|
| 258 | - @Override |
|
| 259 | - public SelectAction translateSelectionEvent( |
|
| 260 | - CellPreviewEvent<MediaTrackWithSecurityDTO> event) { |
|
| 261 | - NativeEvent nativeEvent = event.getNativeEvent(); |
|
| 262 | - if (BrowserEvents.CLICK.equals(nativeEvent.getType())) { |
|
| 263 | - if (nativeEvent.getCtrlKey()) { |
|
| 264 | - MediaTrackWithSecurityDTO value = event.getValue(); |
|
| 265 | - refreshableSelectionModel.setSelected(value, !refreshableSelectionModel.isSelected(value)); |
|
| 266 | - return SelectAction.IGNORE; |
|
| 267 | - } |
|
| 268 | - if (!refreshableSelectionModel.getSelectedSet().isEmpty() && !isCheckboxColumn(event.getColumn())) { |
|
| 269 | - return SelectAction.DEFAULT; |
|
| 270 | - } |
|
| 271 | - } |
|
| 272 | - return SelectAction.TOGGLE; |
|
| 273 | - } |
|
| 274 | - |
|
| 275 | - private boolean isCheckboxColumn(int columnIndex) { |
|
| 276 | - return columnIndex == 0; |
|
| 277 | - } |
|
| 278 | - })); |
|
| 279 | - |
|
| 280 | - // Initialize the columns. |
|
| 281 | 257 | initTableColumns(sortHandler, userService); |
| 282 | 258 | mediaTrackListDataProvider.addDataDisplay(mediaTracksTable); |
| 283 | 259 | add(mediaTracksTable); |
| ... | ... | @@ -290,17 +266,10 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 290 | 266 | */ |
| 291 | 267 | private void initTableColumns(final ListHandler<MediaTrackWithSecurityDTO> sortHandler, |
| 292 | 268 | final UserService userService) { |
| 293 | - Column<MediaTrackWithSecurityDTO, Boolean> checkColumn = new Column<MediaTrackWithSecurityDTO, Boolean>( |
|
| 294 | - new BetterCheckboxCell(tableResources.cellTableStyle().cellTableCheckboxSelected(), |
|
| 295 | - tableResources.cellTableStyle().cellTableCheckboxDeselected())) { |
|
| 296 | - @Override |
|
| 297 | - public Boolean getValue(MediaTrackWithSecurityDTO object) { |
|
| 298 | - // Get the value from the selection model. |
|
| 299 | - return refreshableSelectionModel.isSelected(object); |
|
| 300 | - } |
|
| 301 | - }; |
|
| 302 | - mediaTracksTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>")); |
|
| 269 | + final Header<Boolean> selectAllHeader = checkColumn.createHeader(); |
|
| 270 | + mediaTracksTable.addColumn(checkColumn, selectAllHeader); |
|
| 303 | 271 | mediaTracksTable.setColumnWidth(checkColumn, 40, Unit.PX); |
| 272 | + mediaTracksTable.setSelectionModel(refreshableSelectionModel, checkColumn.getSelectionManager()); |
|
| 304 | 273 | // db id |
| 305 | 274 | Column<MediaTrackWithSecurityDTO, String> dbIdColumn = new Column<MediaTrackWithSecurityDTO, String>( |
| 306 | 275 | new TextCell()) { |
| ... | ... | @@ -715,4 +684,4 @@ public class MediaPanel extends FlowPanel implements FilterablePanelProvider<Med |
| 715 | 684 | public AbstractFilterablePanel<MediaTrackWithSecurityDTO> getFilterablePanel() { |
| 716 | 685 | return filterableMediaTracks; |
| 717 | 686 | } |
| 718 | -} |
|
| 687 | +} |
|
| ... | ... | \ No newline at end of file |
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 |