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