1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.panels;
20
21 import com.fasterxml.jackson.databind.json.JsonMapper;
22 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
23 import java.io.Serializable;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Optional;
27 import org.apache.syncope.client.console.PreferenceManager;
28 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
29 import org.apache.syncope.client.console.pages.BasePage;
30 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
31 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
32 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
33 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
34 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
35 import org.apache.syncope.client.ui.commons.Constants;
36 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
37 import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
38 import org.apache.syncope.client.ui.commons.rest.RestClient;
39 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
40 import org.apache.wicket.PageReference;
41 import org.apache.wicket.ajax.AjaxRequestTarget;
42 import org.apache.wicket.event.Broadcast;
43 import org.apache.wicket.event.IEvent;
44 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
45 import org.apache.wicket.markup.html.WebMarkupContainer;
46 import org.apache.wicket.markup.html.form.DropDownChoice;
47 import org.apache.wicket.markup.html.form.Form;
48 import org.apache.wicket.model.IModel;
49 import org.apache.wicket.model.Model;
50 import org.apache.wicket.model.PropertyModel;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public abstract class DirectoryPanel<
55 T extends Serializable, W extends Serializable, DP extends DirectoryDataProvider<T>, E extends RestClient>
56 extends WizardMgtPanel<W> {
57
58 private static final long serialVersionUID = -9170191461250434024L;
59
60 protected static final Logger LOG = LoggerFactory.getLogger(DirectoryPanel.class);
61
62 protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
63
64 protected E restClient;
65
66
67
68
69 protected Integer rows;
70
71
72
73
74 protected final WebMarkupContainer container;
75
76
77
78
79
80 protected final boolean filtered;
81
82 private boolean checkBoxEnabled;
83
84 private boolean showPaginator;
85
86
87
88
89 protected AjaxDataTablePanel<T, String> resultTable;
90
91
92
93
94 protected DP dataProvider;
95
96
97
98
99 protected final BasePage page;
100
101 protected String itemKeyFieldName = Constants.KEY_FIELD_NAME;
102
103 protected final BaseModal<W> altDefaultModal = new BaseModal<>(Constants.OUTER);
104
105 protected final BaseModal<W> displayAttributeModal = new BaseModal<>(Constants.OUTER);
106
107 protected final ActionLinksTogglePanel<T> actionTogglePanel;
108
109
110
111
112
113
114
115
116
117 public DirectoryPanel(final String id, final E restClient, final PageReference pageRef) {
118 this(id, restClient, pageRef, true);
119 }
120
121 public DirectoryPanel(
122 final String id,
123 final E restClient,
124 final PageReference pageRef,
125 final boolean wizardInModal) {
126
127 this(id, restClient, pageRef, true, wizardInModal);
128 }
129
130 public DirectoryPanel(
131 final String id,
132 final E restClient,
133 final PageReference pageRef,
134 final boolean showPaginator,
135 final boolean wizardInModal) {
136
137 this(id, new Builder<T, W, E>(restClient, pageRef) {
138
139 private static final long serialVersionUID = -8424727765826509309L;
140
141 @Override
142 protected WizardMgtPanel<W> newInstance(final String id, final boolean wizardInModal) {
143 throw new UnsupportedOperationException("Not supported yet.");
144 }
145 }.setFiltered(false), wizardInModal);
146 setPageRef(pageRef);
147 this.showPaginator = showPaginator;
148 }
149
150 protected DirectoryPanel(final String id, final Builder<T, W, E> builder) {
151 this(id, builder, true);
152 }
153
154 protected DirectoryPanel(final String id, final Builder<T, W, E> builder, final boolean wizardInModal) {
155 super(id, wizardInModal);
156 setOutputMarkupId(true);
157
158 actionTogglePanel = actionTogglePanel();
159 addOuterObject(actionTogglePanel);
160
161 addOuterObject(altDefaultModal);
162 addOuterObject(displayAttributeModal);
163
164 setPageRef(builder.getPageRef());
165 this.page = (BasePage) builder.getPageRef().getPage();
166
167 this.filtered = builder.filtered;
168 this.checkBoxEnabled = builder.checkBoxEnabled;
169 this.showPaginator = builder.showPaginator;
170
171 this.restClient = builder.restClient;
172
173
174 container = new WebMarkupContainer("searchContainer");
175 container.setOutputMarkupId(true);
176 addInnerObject(container);
177
178 rows = PreferenceManager.getPaginatorRows(paginatorRowsKey());
179
180 modal.setWindowClosedCallback(target -> {
181 if (actionTogglePanel.isVisibleInHierarchy() && modal.getContent() instanceof WizardModalPanel) {
182 actionTogglePanel.updateHeader(target, WizardModalPanel.class.cast(modal.getContent()).getItem());
183 }
184 modal.show(false);
185 });
186
187 setWindowClosedReloadCallback(altDefaultModal);
188 altDefaultModal.size(Modal.Size.Default);
189
190 displayAttributeModal.setWindowClosedCallback(target -> {
191 EventDataWrapper data = new EventDataWrapper();
192 data.setTarget(target);
193 data.setRows(rows);
194
195 send(DirectoryPanel.this, Broadcast.EXACT, data);
196
197 displayAttributeModal.size(Modal.Size.Default);
198 modal.show(false);
199 });
200 displayAttributeModal.size(Modal.Size.Default);
201 displayAttributeModal.addSubmitButton();
202 }
203
204 protected abstract DP dataProvider();
205
206 protected abstract String paginatorRowsKey();
207
208 protected abstract List<IColumn<T, String>> getColumns();
209
210 protected void initResultTable() {
211
212
213
214 updateResultTable(false);
215
216
217
218
219
220 Form<?> paginatorForm = new Form<>("paginator");
221 paginatorForm.setOutputMarkupPlaceholderTag(true);
222 paginatorForm.setVisible(showPaginator);
223 container.add(paginatorForm);
224
225 DropDownChoice<Integer> rowsChooser = new DropDownChoice<>(
226 "rowsChooser", new PropertyModel<>(this, "rows"), PreferenceManager.getPaginatorChoices());
227 rowsChooser.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
228
229 private static final long serialVersionUID = -1107858522700306810L;
230
231 @Override
232 protected void onUpdate(final AjaxRequestTarget target) {
233 PreferenceManager.set(paginatorRowsKey(), String.valueOf(rows));
234
235 EventDataWrapper data = new EventDataWrapper();
236 data.setTarget(target);
237 data.setRows(rows);
238
239 send(getParent(), Broadcast.BREADTH, data);
240 }
241 });
242 paginatorForm.add(rowsChooser);
243
244
245
246
247
248 container.add(getHeader("tablehandling"));
249
250 }
251
252 protected ActionsPanel<Serializable> getHeader(final String componentId) {
253 final ActionsPanel<Serializable> panel = new ActionsPanel<>(componentId, null);
254
255 panel.add(new ActionLink<>() {
256
257 private static final long serialVersionUID = -7978723352517770644L;
258
259 @Override
260 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
261 if (target != null) {
262 target.add(container);
263 }
264 }
265 }, ActionLink.ActionType.RELOAD, IdRepoEntitlement.USER_SEARCH).hideLabel();
266 return panel;
267 }
268
269 public void search(final AjaxRequestTarget target) {
270 target.add(container);
271 }
272
273 public void updateResultTable(final AjaxRequestTarget target) {
274 updateResultTable(false);
275 if (container.isVisibleInHierarchy()) {
276 target.add(container);
277 }
278 }
279
280 protected void updateResultTable(final boolean create) {
281 updateResultTable(create, rows);
282 }
283
284 protected void updateResultTable(final boolean create, final int rows) {
285 if (dataProvider == null) {
286 dataProvider = dataProvider();
287 }
288 dataProvider.setPaginatorRows(rows);
289
290 int currentPage = Optional.ofNullable(resultTable).
291 map(table -> (create ? (int) table.getPageCount() - 1 : (int) table.getCurrentPage())).orElse(0);
292
293
294 AjaxDataTablePanel.Builder<T, String> resultTableBuilder = new AjaxDataTablePanel.Builder<>(
295 dataProvider, page.getPageReference()) {
296
297 private static final long serialVersionUID = 2205322679547329123L;
298
299 @Override
300 protected ActionsPanel<T> getActions(final IModel<T> model) {
301 return DirectoryPanel.this.getActions(model);
302 }
303
304 @Override
305 protected ActionLinksTogglePanel<T> getTogglePanel() {
306 return DirectoryPanel.this.getTogglePanel();
307 }
308
309 }.setColumns(getColumns()).
310 setRowsPerPage(rows).
311 setBatches(getBatches(), restClient, itemKeyFieldName).
312 setContainer(container);
313
314 if (!checkBoxEnabled) {
315 resultTableBuilder.disableCheckBoxes();
316 }
317
318 resultTableCustomChanges(resultTableBuilder);
319 resultTable = resultTableBuilder.build("resultTable");
320
321 resultTable.setCurrentPage(currentPage);
322 resultTable.setOutputMarkupId(true);
323 container.addOrReplace(resultTable);
324 }
325
326
327
328
329
330
331 protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<T, String> resultTableBuilder) {
332 }
333
334 public DirectoryPanel<T, W, DP, E> disableCheckBoxes() {
335 checkBoxEnabled = false;
336 return this;
337 }
338
339 @Override
340 public void onEvent(final IEvent<?> event) {
341 if (event.getPayload() instanceof EventDataWrapper) {
342 EventDataWrapper data = (EventDataWrapper) event.getPayload();
343
344 if (data.getRows() < 1) {
345 updateResultTable(data.isCreate());
346 } else {
347 updateResultTable(data.isCreate(), data.getRows());
348 }
349
350 if (container.isVisibleInHierarchy()) {
351 data.getTarget().add(container);
352 }
353 }
354 super.onEvent(event);
355 }
356
357 @Override
358 protected void customActionOnFinishCallback(final AjaxRequestTarget target) {
359 EventDataWrapper data = new EventDataWrapper();
360 data.setTarget(target);
361 data.setRows(rows);
362 send(getParent(), Broadcast.BREADTH, data);
363 }
364
365 protected ActionsPanel<T> getActions(final IModel<T> model) {
366 return new ActionsPanel<>("actions", model == null ? new Model<>() : model);
367 }
368
369 protected ActionLinksTogglePanel<T> actionTogglePanel() {
370 return new ActionLinksTogglePanel<>(Constants.OUTER, pageRef);
371 }
372
373 protected ActionLinksTogglePanel<T> getTogglePanel() {
374 return actionTogglePanel;
375 }
376
377 public static class EventDataWrapper {
378
379 private AjaxRequestTarget target;
380
381 private boolean create;
382
383 private int rows;
384
385 public AjaxRequestTarget getTarget() {
386 return target;
387 }
388
389 public void setTarget(final AjaxRequestTarget target) {
390 this.target = target;
391 }
392
393 public boolean isCreate() {
394 return create;
395 }
396
397 public void setCreate(final boolean create) {
398 this.create = create;
399 }
400
401 public int getRows() {
402 return rows;
403 }
404
405 public void setRows(final int rows) {
406 this.rows = rows;
407 }
408 }
409
410 protected abstract Collection<ActionLink.ActionType> getBatches();
411
412 public abstract static class Builder<T extends Serializable, W extends Serializable, E extends RestClient>
413 extends WizardMgtPanel.Builder<W> {
414
415 private static final long serialVersionUID = 5088962796986706805L;
416
417
418
419
420
421 protected boolean filtered = false;
422
423 protected boolean checkBoxEnabled = true;
424
425 protected boolean showPaginator = true;
426
427
428
429
430 protected String fiql;
431
432 protected final E restClient;
433
434 protected Builder(final E restClient, final PageReference pageRef) {
435 super(pageRef);
436 this.restClient = restClient;
437 }
438
439 public Builder<T, W, E> setFiltered(final boolean filtered) {
440 this.filtered = filtered;
441 return this;
442 }
443
444 public Builder<T, W, E> disableCheckBoxes() {
445 this.checkBoxEnabled = false;
446 return this;
447 }
448
449 public Builder<T, W, E> hidePaginator() {
450 this.showPaginator = false;
451 return this;
452 }
453
454 public Builder<T, W, E> setFiql(final String fiql) {
455 this.fiql = fiql;
456 return this;
457 }
458
459 private PageReference getPageRef() {
460 return pageRef;
461 }
462 }
463 }