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 de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
22 import java.io.Serializable;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Optional;
27 import org.apache.syncope.client.console.batch.BatchContent;
28 import org.apache.syncope.client.console.batch.BatchModal;
29 import org.apache.syncope.client.console.pages.BasePage;
30 import org.apache.syncope.client.console.panels.DirectoryPanel.EventDataWrapper;
31 import org.apache.syncope.client.console.rest.BaseRestClient;
32 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AjaxFallbackDataTable;
33 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
34 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
35 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
36 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
37 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
38 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
39 import org.apache.syncope.client.ui.commons.rest.RestClient;
40 import org.apache.wicket.AttributeModifier;
41 import org.apache.wicket.PageReference;
42 import org.apache.wicket.ajax.AjaxRequestTarget;
43 import org.apache.wicket.event.Broadcast;
44 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
45 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
46 import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
47 import org.apache.wicket.markup.html.WebMarkupContainer;
48 import org.apache.wicket.markup.html.form.CheckGroup;
49 import org.apache.wicket.markup.html.form.CheckGroupSelector;
50 import org.apache.wicket.markup.html.form.Form;
51 import org.apache.wicket.markup.html.panel.Fragment;
52 import org.apache.wicket.model.IModel;
53 import org.apache.wicket.model.ResourceModel;
54
55 public final class AjaxDataTablePanel<T extends Serializable, S> extends DataTablePanel<T, S> {
56
57 private static final long serialVersionUID = -7264400471578272966L;
58
59 public static class Builder<T extends Serializable, S> implements Serializable {
60
61 private static final long serialVersionUID = 8876232177473972722L;
62
63 private boolean checkBoxEnabled = true;
64
65 private final List<IColumn<T, S>> columns = new ArrayList<>();
66
67 private final ISortableDataProvider<T, S> dataProvider;
68
69 private int rowsPerPage = 10;
70
71 private final Collection<ActionLink.ActionType> batches = new ArrayList<>();
72
73 private RestClient batchExecutor;
74
75 private String itemKeyField;
76
77 private final PageReference pageRef;
78
79 private WebMarkupContainer container;
80
81 private MultilevelPanel multiLevelPanel;
82
83 public Builder(final ISortableDataProvider<T, S> provider, final PageReference pageRef) {
84 this.dataProvider = provider;
85 this.pageRef = pageRef;
86 }
87
88 public AjaxDataTablePanel<T, S> build(final String id) {
89 return new AjaxDataTablePanel<>(id, this);
90 }
91
92 public Builder<T, S> setContainer(final WebMarkupContainer container) {
93 this.container = container;
94 return this;
95 }
96
97 public Builder<T, S> addBatch(final ActionLink.ActionType actionType) {
98 batches.add(actionType);
99 return this;
100 }
101
102 public Builder<T, S> setBatchExecutor(final BaseRestClient batchExecutor) {
103 this.batchExecutor = batchExecutor;
104 return this;
105 }
106
107 public Builder<T, S> setItemKeyField(final String itemKeyField) {
108 this.itemKeyField = itemKeyField;
109 return this;
110 }
111
112 public Builder<T, S> setBatches(
113 final Collection<ActionLink.ActionType> batches,
114 final RestClient batchExecutor,
115 final String itemKeyField) {
116
117 this.batches.clear();
118 if (batches != null) {
119 this.batches.addAll(batches);
120 }
121 this.batchExecutor = batchExecutor;
122 this.itemKeyField = itemKeyField;
123 return this;
124 }
125
126 public Builder<T, S> addColumn(final IColumn<T, S> column) {
127 columns.add(column);
128 return this;
129 }
130
131 public Builder<T, S> setColumns(final List<IColumn<T, S>> columns) {
132 this.columns.clear();
133 if (columns != null) {
134 this.columns.addAll(columns);
135 }
136 return this;
137 }
138
139 public Builder<T, S> setRowsPerPage(final int rowsPerPage) {
140 this.rowsPerPage = rowsPerPage;
141 return this;
142 }
143
144 public Builder<T, S> disableCheckBoxes() {
145 this.checkBoxEnabled = false;
146 return this;
147 }
148
149 private boolean isBatchEnabled() {
150 return checkBoxEnabled && batchExecutor != null && !batches.isEmpty();
151 }
152
153 public void setMultiLevelPanel(final MultilevelPanel multiLevelPanel) {
154 this.multiLevelPanel = multiLevelPanel;
155 }
156
157 protected ActionsPanel<T> getActions(final IModel<T> model) {
158 return null;
159 }
160
161 protected ActionLinksTogglePanel<T> getTogglePanel() {
162 return null;
163 }
164 }
165
166 protected final BaseModal<T> batchModal;
167
168 private AjaxDataTablePanel(final String id, final Builder<T, S> builder) {
169 super(id);
170
171 batchModal = new BaseModal<>("batchModal");
172 batchModal.size(Modal.Size.Extra_large);
173 add(batchModal);
174
175 batchModal.setWindowClosedCallback(target -> {
176 batchModal.show(false);
177
178 EventDataWrapper data = new EventDataWrapper();
179 data.setTarget(target);
180 data.setRows(builder.rowsPerPage);
181
182 send(builder.pageRef.getPage(), Broadcast.BREADTH, data);
183 Optional.ofNullable((BasePage) findPage()).
184 ifPresent(page -> page.getNotificationPanel().refresh(target));
185 });
186
187 Fragment fragment = new Fragment("tablePanel", "batchAvailable", this);
188 add(fragment);
189
190 Form<T> groupForm = new Form<>("groupForm");
191 fragment.add(groupForm);
192
193 group = new CheckGroup<>("checkgroup", model);
194 group.add(new IndicatorAjaxFormChoiceComponentUpdatingBehavior() {
195
196 private static final long serialVersionUID = -151291731388673682L;
197
198 @Override
199 protected void onUpdate(final AjaxRequestTarget target) {
200 group.visitChildren(CheckGroupSelector.class, (selector, ivisit) -> {
201 target.focusComponent(selector);
202 ivisit.stop();
203 });
204 }
205 });
206 groupForm.add(group);
207
208 if (builder.checkBoxEnabled) {
209 builder.columns.add(0, new CheckGroupColumn<>(group));
210 }
211
212 dataTable = new AjaxFallbackDataTable<>(
213 "dataTable", builder.columns, builder.dataProvider, builder.rowsPerPage, builder.container) {
214
215 private static final long serialVersionUID = -7370603907251344224L;
216
217 @Override
218 protected ActionsPanel<T> getActions(final IModel<T> model) {
219 return builder.getActions(model);
220 }
221
222 @Override
223 protected ActionLinksTogglePanel<T> getTogglePanel() {
224 return builder.getTogglePanel();
225 }
226
227 };
228
229 dataTable.add(new AttributeModifier("class", "table table-bordered table-hover dataTable"));
230
231 group.add(dataTable);
232
233 fragment.add(new IndicatingAjaxButton("batchLink", groupForm) {
234
235 private static final long serialVersionUID = 382302811235019988L;
236
237 @Override
238 protected void onSubmit(final AjaxRequestTarget target) {
239
240 Optional.ofNullable(builder.getTogglePanel()).ifPresent(p -> p.close(target));
241
242 if (builder.multiLevelPanel == null) {
243 batchModal.header(new ResourceModel("batch"));
244 batchModal.changeCloseButtonLabel(getString("cancel", null, "Cancel"), target);
245
246 target.add(batchModal.setContent(new BatchModal<>(
247 batchModal,
248 builder.pageRef,
249 new ArrayList<>(group.getModelObject()),
250 builder.columns.size() == 1
251 ? builder.columns
252
253 : new ArrayList<>(builder.columns.subList(1, builder.columns.size())),
254 builder.batches,
255 builder.batchExecutor,
256 builder.itemKeyField)));
257
258 batchModal.show(true);
259 } else {
260 builder.multiLevelPanel.next(getString("batch"),
261 new BatchContent<>(
262 new ArrayList<>(group.getModelObject()),
263 builder.columns.size() == 1
264 ? builder.columns
265
266 : new ArrayList<>(builder.columns.subList(1, builder.columns.size())),
267 builder.batches,
268 builder.batchExecutor,
269 builder.itemKeyField),
270 target);
271 }
272 group.setModelObject(List.of());
273 target.add(group);
274 }
275 }.setEnabled(builder.isBatchEnabled()).setVisible(builder.isBatchEnabled()));
276 }
277 }