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