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.wizards;
20
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Optional;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.syncope.client.console.SyncopeConsoleSession;
27 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
28 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
29 import org.apache.syncope.client.console.wizards.any.ResultPanel;
30 import org.apache.syncope.client.ui.commons.Constants;
31 import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
32 import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
33 import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
34 import org.apache.syncope.client.ui.commons.wizards.AbstractWizardMgtPanel;
35 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
36 import org.apache.syncope.client.ui.commons.wizards.ModalPanelBuilder;
37 import org.apache.wicket.Component;
38 import org.apache.wicket.MarkupContainer;
39 import org.apache.wicket.PageReference;
40 import org.apache.wicket.ajax.AjaxRequestTarget;
41 import org.apache.wicket.ajax.markup.html.AjaxLink;
42 import org.apache.wicket.event.Broadcast;
43 import org.apache.wicket.event.IEvent;
44 import org.apache.wicket.markup.html.WebMarkupContainer;
45 import org.apache.wicket.markup.html.basic.Label;
46 import org.apache.wicket.markup.html.list.ListItem;
47 import org.apache.wicket.markup.html.list.ListView;
48 import org.apache.wicket.markup.html.panel.Fragment;
49 import org.apache.wicket.markup.html.panel.Panel;
50 import org.apache.wicket.model.Model;
51 import org.apache.wicket.model.StringResourceModel;
52
53 public abstract class WizardMgtPanel<T extends Serializable> extends AbstractWizardMgtPanel<T> {
54
55 private static final long serialVersionUID = -4152438633429194882L;
56
57 private boolean readOnly = false;
58
59 protected final String actualId;
60
61 private final WebMarkupContainer container;
62
63 protected final Fragment initialFragment;
64
65 protected final boolean wizardInModal;
66
67 private boolean containerAutoRefresh = true;
68
69 protected PageReference pageRef;
70
71 protected final AjaxLink<?> addAjaxLink;
72
73 protected Label utilityIcon;
74
75 protected AjaxLink<?> utilityAjaxLink;
76
77 protected ModalPanelBuilder<T> newItemPanelBuilder;
78
79 protected NotificationPanel notificationPanel;
80
81 protected boolean footerVisibility = false;
82
83 protected boolean showResultPanel = false;
84
85 private final List<Component> outerObjects = new ArrayList<>();
86
87 protected final BaseModal<T> modal = new BaseModal<>(Constants.OUTER) {
88
89 private static final long serialVersionUID = 389935548143327858L;
90
91 @Override
92 protected void onConfigure() {
93 super.onConfigure();
94 setFooterVisible(footerVisibility);
95 }
96 };
97
98 protected WizardMgtPanel(final String id) {
99 this(id, false);
100 }
101
102 protected WizardMgtPanel(final String id, final boolean wizardInModal) {
103 super(id);
104 setOutputMarkupId(true);
105
106 this.actualId = wizardInModal ? BaseModal.CONTENT_ID : WIZARD_ID;
107 this.wizardInModal = wizardInModal;
108
109 outerObjects.add(modal);
110
111 container = new WebMarkupContainer("container");
112 container.setOutputMarkupPlaceholderTag(true).setOutputMarkupId(true);
113 add(container);
114
115 initialFragment = new Fragment("content", "default", this);
116 container.addOrReplace(initialFragment);
117
118 addAjaxLink = new AjaxLink<T>("add") {
119
120 private static final long serialVersionUID = -7978723352517770644L;
121
122 @Override
123 public void onClick(final AjaxRequestTarget target) {
124 send(WizardMgtPanel.this, Broadcast.BREADTH,
125 new ActionLinksTogglePanel.ActionLinkToggleCloseEventPayload(target));
126 send(WizardMgtPanel.this, Broadcast.EXACT,
127 new AjaxWizard.NewItemActionEvent<>(null, target));
128 }
129 };
130
131 addAjaxLink.setEnabled(false);
132 addAjaxLink.setVisible(false);
133 initialFragment.addOrReplace(addAjaxLink);
134
135 utilityAjaxLink = new AjaxLink<T>("utility") {
136
137 private static final long serialVersionUID = -7978723352517770644L;
138
139 @Override
140 public void onClick(final AjaxRequestTarget target) {
141 send(WizardMgtPanel.this, Broadcast.EXACT, new ExitEvent(target));
142 }
143 };
144
145 utilityAjaxLink.setEnabled(false);
146 utilityAjaxLink.setVisible(false);
147 initialFragment.addOrReplace(utilityAjaxLink);
148
149 utilityIcon = new Label("utilityIcon");
150 utilityAjaxLink.add(utilityIcon);
151
152 add(new ListView<>("outerObjectsRepeater", outerObjects) {
153
154 private static final long serialVersionUID = -9180479401817023838L;
155
156 @Override
157 protected void populateItem(final ListItem<Component> item) {
158 item.add(item.getModelObject());
159 }
160 });
161 }
162
163 public String getActualId() {
164 return actualId;
165 }
166
167 @Override
168 @SuppressWarnings("unchecked")
169 public void onEvent(final IEvent<?> event) {
170 if (event.getPayload() instanceof ExitEvent) {
171 AjaxRequestTarget target = ExitEvent.class.cast(event.getPayload()).getTarget();
172
173 modal.close(target);
174 } else if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
175 AjaxWizard.NewItemEvent<T> newItemEvent = AjaxWizard.NewItemEvent.class.cast(event.getPayload());
176 Optional<AjaxRequestTarget> target = newItemEvent.getTarget();
177 T item = newItemEvent.getItem();
178
179 boolean modalPanelAvailable = newItemEvent.getModalPanel() != null || newItemPanelBuilder != null;
180
181 if (event.getPayload() instanceof AjaxWizard.NewItemActionEvent && modalPanelAvailable) {
182 WizardModalPanel<?> modalPanel;
183 if (newItemEvent.getModalPanel() == null && newItemPanelBuilder != null) {
184 newItemPanelBuilder.setItem(item);
185
186 modalPanel = newItemPanelBuilder.build(
187 actualId,
188 ((AjaxWizard.NewItemActionEvent<T>) newItemEvent).getIndex(),
189 item != null
190 ? isReadOnly()
191 ? AjaxWizard.Mode.READONLY
192 : AjaxWizard.Mode.EDIT
193 : AjaxWizard.Mode.CREATE);
194 } else {
195 modalPanel = newItemEvent.getModalPanel();
196 }
197
198 if (wizardInModal) {
199 modal.setFormModel(item);
200
201 target.ifPresent(t -> t.add(modal.setContent(modalPanel)));
202
203 modal.header(Optional.ofNullable(newItemEvent.getTitleModel()).
204 orElse(new StringResourceModel(
205 String.format("any.%s", newItemEvent.getEventDescription()),
206 this,
207 Model.of(modalPanel.getItem()))));
208 modal.show(true);
209 } else {
210 Fragment fragment = new Fragment("content", "wizard", WizardMgtPanel.this);
211
212 fragment.add(new Label(
213 "title",
214 Optional.ofNullable(newItemEvent.getTitleModel()).orElse(Model.of(StringUtils.EMPTY))));
215
216 fragment.add(Component.class.cast(modalPanel));
217 container.addOrReplace(fragment);
218 }
219
220 target.ifPresent(this::customActionCallback);
221 } else if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
222 if (wizardInModal) {
223 target.ifPresent(modal::close);
224 } else {
225 container.addOrReplace(initialFragment);
226 }
227
228 target.ifPresent(this::customActionOnCancelCallback);
229 } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
230 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
231 target.ifPresent(t -> ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(t));
232
233 if (wizardInModal && showResultPanel) {
234 modal.setContent(new ResultPanel<>(
235 item,
236 AjaxWizard.NewItemFinishEvent.class.cast(newItemEvent).getResult()) {
237
238 private static final long serialVersionUID = -2630573849050255233L;
239
240 @Override
241 protected void closeAction(final AjaxRequestTarget target) {
242 modal.close(target);
243 }
244
245 @Override
246 protected Panel customResultBody(
247 final String panelId,
248 final T item,
249 final Serializable result) {
250
251 return WizardMgtPanel.this.customResultBody(panelId, item, result);
252 }
253 });
254 target.ifPresent(t -> t.add(modal.getForm()));
255 } else if (wizardInModal) {
256 target.ifPresent(modal::close);
257 } else {
258 container.addOrReplace(initialFragment);
259 }
260
261 target.ifPresent(this::customActionOnFinishCallback);
262 }
263
264 if (containerAutoRefresh) {
265 target.ifPresent(t -> t.add(container));
266 }
267 }
268 super.onEvent(event);
269 }
270
271 protected final WizardMgtPanel<T> disableContainerAutoRefresh() {
272 containerAutoRefresh = false;
273 return this;
274 }
275
276
277
278
279 protected Panel customResultBody(final String panelId, final T item, final Serializable result) {
280 return new Panel(panelId) {
281
282 private static final long serialVersionUID = 5538299138211283825L;
283
284 };
285 }
286
287
288
289
290
291
292 protected final WizardMgtPanel<T> enableUtilityButton() {
293 utilityAjaxLink.setEnabled(true);
294 utilityAjaxLink.setVisible(true);
295 return this;
296 }
297
298
299
300
301
302
303
304 public MarkupContainer addInnerObject(final Component... childs) {
305 return initialFragment.add(childs);
306 }
307
308
309
310
311
312
313
314 public MarkupContainer addOrReplaceInnerObject(final Component... childs) {
315 return initialFragment.addOrReplace(childs);
316 }
317
318
319
320
321
322
323
324
325
326 public final WizardMgtPanel<T> addOuterObject(final Component... childs) {
327 outerObjects.addAll(List.of(childs));
328 return this;
329 }
330
331 public <B extends ModalPanelBuilder<T>> WizardMgtPanel<T> setPageRef(final PageReference pageRef) {
332 this.pageRef = pageRef;
333 return this;
334 }
335
336 public <B extends ModalPanelBuilder<T>> WizardMgtPanel<T> setShowResultPanel(final boolean showResultPanel) {
337 this.showResultPanel = showResultPanel;
338 return this;
339 }
340
341 protected <B extends ModalPanelBuilder<T>> WizardMgtPanel<T> addNewItemPanelBuilder(
342 final B panelBuilder, final boolean newItemDefaultButtonEnabled) {
343
344 this.newItemPanelBuilder = panelBuilder;
345
346 if (this.newItemPanelBuilder != null) {
347 addAjaxLink.setEnabled(newItemDefaultButtonEnabled);
348 addAjaxLink.setVisible(newItemDefaultButtonEnabled);
349 this.newItemPanelBuilder.setEventSink(WizardMgtPanel.this);
350 }
351
352 return this;
353 }
354
355 protected WizardMgtPanel<T> addNotificationPanel(final NotificationPanel notificationPanel) {
356 this.notificationPanel = notificationPanel;
357 return this;
358 }
359
360 public WizardMgtPanel<T> setFooterVisibility(final boolean footerVisibility) {
361 this.footerVisibility = footerVisibility;
362 return this;
363 }
364
365
366
367
368
369
370 protected void setWindowClosedReloadCallback(final BaseModal<?> modal) {
371 modal.setWindowClosedCallback(target -> modal.show(false));
372 }
373
374
375
376
377
378
379 protected void customActionCallback(final AjaxRequestTarget target) {
380 }
381
382
383
384
385
386
387 protected void customActionOnFinishCallback(final AjaxRequestTarget target) {
388 }
389
390
391
392
393
394
395 protected void customActionOnCancelCallback(final AjaxRequestTarget target) {
396 }
397
398
399
400
401
402
403 public abstract static class Builder<T extends Serializable> implements Serializable {
404
405 private static final long serialVersionUID = 1908836274665387084L;
406
407 protected final PageReference pageRef;
408
409 private ModalPanelBuilder<T> newItemPanelBuilder;
410
411 private boolean newItemDefaultButtonEnabled = true;
412
413 private NotificationPanel notificationPanel;
414
415 private boolean showResultPage = false;
416
417 private boolean wizardInModal = false;
418
419 protected Builder(final PageReference pageRef) {
420 this.pageRef = pageRef;
421 }
422
423 protected abstract WizardMgtPanel<T> newInstance(String id, boolean wizardInModal);
424
425
426
427
428
429
430
431 public WizardMgtPanel<T> build(final String id) {
432 return newInstance(id, wizardInModal).
433 setPageRef(this.pageRef).
434 setShowResultPanel(this.showResultPage).
435 addNewItemPanelBuilder(this.newItemPanelBuilder, this.newItemDefaultButtonEnabled).
436 addNotificationPanel(this.notificationPanel);
437 }
438
439 public void setShowResultPage(final boolean showResultPage) {
440 this.showResultPage = showResultPage;
441 }
442
443 public Builder<T> addNewItemPanelBuilder(final ModalPanelBuilder<T> panelBuilder) {
444 this.newItemPanelBuilder = panelBuilder;
445 return this;
446 }
447
448
449
450
451
452
453
454
455 public Builder<T> addNewItemPanelBuilder(
456 final ModalPanelBuilder<T> panelBuilder, final boolean newItemDefaultButtonEnabled) {
457
458 this.newItemDefaultButtonEnabled = newItemDefaultButtonEnabled;
459 return addNewItemPanelBuilder(panelBuilder);
460 }
461
462
463
464
465
466
467
468 public Builder<T> addNotificationPanel(final NotificationPanel notificationPanel) {
469 this.notificationPanel = notificationPanel;
470 return this;
471 }
472
473
474
475
476
477
478
479 public Builder<T> setWizardInModal(final boolean wizardInModal) {
480 this.wizardInModal = wizardInModal;
481 return this;
482 }
483 }
484
485 public static class ExitEvent {
486
487 private final AjaxRequestTarget target;
488
489 public ExitEvent(final AjaxRequestTarget target) {
490 this.target = target;
491 }
492
493 public AjaxRequestTarget getTarget() {
494 return target;
495 }
496 }
497
498 public boolean isReadOnly() {
499 return readOnly;
500 }
501
502 public void setReadOnly(final boolean readOnly) {
503 this.readOnly = readOnly;
504 }
505 }