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.reports;
20
21 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
22 import java.time.Duration;
23 import java.time.temporal.ChronoUnit;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.List;
28 import org.apache.commons.lang3.SerializationUtils;
29 import org.apache.syncope.client.console.SyncopeConsoleSession;
30 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
31 import org.apache.syncope.client.console.commons.IdRepoConstants;
32 import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
33 import org.apache.syncope.client.console.pages.BasePage;
34 import org.apache.syncope.client.console.panels.DirectoryPanel;
35 import org.apache.syncope.client.console.panels.MultilevelPanel;
36 import org.apache.syncope.client.console.rest.ImplementationRestClient;
37 import org.apache.syncope.client.console.rest.ReportRestClient;
38 import org.apache.syncope.client.console.wicket.ajax.IndicatorAjaxTimerBehavior;
39 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
40 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
41 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
42 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
43 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
44 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
45 import org.apache.syncope.client.console.widgets.JobActionPanel;
46 import org.apache.syncope.client.ui.commons.Constants;
47 import org.apache.syncope.client.ui.commons.MIMETypesLoader;
48 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
49 import org.apache.syncope.common.lib.SyncopeClientException;
50 import org.apache.syncope.common.lib.to.JobTO;
51 import org.apache.syncope.common.lib.to.ReportTO;
52 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
53 import org.apache.wicket.Component;
54 import org.apache.wicket.PageReference;
55 import org.apache.wicket.ajax.AjaxRequestTarget;
56 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
57 import org.apache.wicket.event.Broadcast;
58 import org.apache.wicket.event.IEvent;
59 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
60 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
61 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
62 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
63 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
64 import org.apache.wicket.markup.html.WebPage;
65 import org.apache.wicket.markup.html.basic.Label;
66 import org.apache.wicket.markup.repeater.Item;
67 import org.apache.wicket.model.CompoundPropertyModel;
68 import org.apache.wicket.model.IModel;
69 import org.apache.wicket.model.Model;
70 import org.apache.wicket.model.StringResourceModel;
71 import org.apache.wicket.spring.injection.annot.SpringBean;
72
73
74
75
76 public abstract class ReportDirectoryPanel
77 extends DirectoryPanel<ReportTO, ReportTO, DirectoryDataProvider<ReportTO>, ReportRestClient> {
78
79 private static final long serialVersionUID = 4984337552918213290L;
80
81 protected final ReportStartAtTogglePanel startAt;
82
83 @SpringBean
84 protected ImplementationRestClient implementationRestClient;
85
86 @SpringBean
87 protected ReportRestClient reportRestClient;
88
89 @SpringBean
90 protected MIMETypesLoader mimeTypesLoader;
91
92 protected ReportDirectoryPanel(final ReportRestClient restClient, final PageReference pageRef) {
93 super(MultilevelPanel.FIRST_LEVEL_ID, restClient, pageRef, true);
94
95 addNewItemPanelBuilder(new ReportWizardBuilder(
96 new ReportTO(), implementationRestClient, reportRestClient, mimeTypesLoader, pageRef), true);
97 MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, IdRepoEntitlement.REPORT_CREATE);
98
99 modal.size(Modal.Size.Large);
100 initResultTable();
101
102 container.add(new IndicatorAjaxTimerBehavior(Duration.of(10, ChronoUnit.SECONDS)) {
103
104 private static final long serialVersionUID = -4661303265651934868L;
105
106 @Override
107 protected void onTimer(final AjaxRequestTarget target) {
108 container.modelChanged();
109 target.add(container);
110 }
111 });
112
113 startAt = new ReportStartAtTogglePanel(container, pageRef);
114 addInnerObject(startAt);
115 }
116
117 @Override
118 protected List<IColumn<ReportTO, String>> getColumns() {
119 List<IColumn<ReportTO, String>> columns = new ArrayList<>();
120
121 columns.add(new KeyPropertyColumn<>(
122 new StringResourceModel(Constants.KEY_FIELD_NAME, this), Constants.KEY_FIELD_NAME));
123 columns.add(new PropertyColumn<>(new StringResourceModel(Constants.NAME_FIELD_NAME, this),
124 Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME));
125
126 columns.add(new PropertyColumn<>(
127 new StringResourceModel("mimeType", this), "mimeType", "mimeType"));
128
129 columns.add(new DatePropertyColumn<>(
130 new StringResourceModel("lastExec", this), null, "lastExec"));
131
132 columns.add(new DatePropertyColumn<>(
133 new StringResourceModel("nextExec", this), null, "nextExec"));
134
135 columns.add(new DatePropertyColumn<>(
136 new StringResourceModel("start", this), "start", "start"));
137
138 columns.add(new DatePropertyColumn<>(
139 new StringResourceModel("end", this), "end", "end"));
140
141 columns.add(new PropertyColumn<>(
142 new StringResourceModel("latestExecStatus", this), "latestExecStatus", "latestExecStatus"));
143
144 columns.add(new BooleanPropertyColumn<>(
145 new StringResourceModel("active", this), "active", "active"));
146
147 columns.add(new AbstractColumn<>(new Model<>(""), "running") {
148
149 private static final long serialVersionUID = 4209532514416998046L;
150
151 @Override
152 public void populateItem(
153 final Item<ICellPopulator<ReportTO>> cellItem,
154 final String componentId,
155 final IModel<ReportTO> rowModel) {
156
157 Component panel;
158 try {
159 JobTO jobTO = restClient.getJob(rowModel.getObject().getKey());
160 panel = new JobActionPanel(componentId, jobTO, false, ReportDirectoryPanel.this);
161 MetaDataRoleAuthorizationStrategy.authorize(panel, WebPage.ENABLE,
162 String.format("%s,%s",
163 IdRepoEntitlement.REPORT_EXECUTE,
164 IdRepoEntitlement.REPORT_UPDATE));
165 } catch (Exception e) {
166 LOG.error("Could not get job for report {}", rowModel.getObject().getKey(), e);
167 panel = new Label(componentId, Model.of());
168 }
169 cellItem.add(panel);
170 }
171
172 @Override
173 public String getCssClass() {
174 return "running-col";
175 }
176 });
177
178 return columns;
179 }
180
181 @Override
182 public void onEvent(final IEvent<?> event) {
183 if (event.getPayload() instanceof JobActionPanel.JobActionPayload) {
184 container.modelChanged();
185 JobActionPanel.JobActionPayload.class.cast(event.getPayload()).getTarget().add(container);
186 } else {
187 super.onEvent(event);
188 }
189 }
190
191 @Override
192 public ActionsPanel<ReportTO> getActions(final IModel<ReportTO> model) {
193 ActionsPanel<ReportTO> panel = super.getActions(model);
194
195 panel.add(new ActionLink<>() {
196
197 private static final long serialVersionUID = -3722207913631435501L;
198
199 @Override
200 public void onClick(final AjaxRequestTarget target, final ReportTO ignore) {
201 viewReportExecs(model.getObject(), target);
202 }
203 }, ActionLink.ActionType.VIEW_EXECUTIONS, IdRepoEntitlement.REPORT_READ);
204
205 panel.add(new ActionLink<>() {
206
207 private static final long serialVersionUID = -3722207913631435501L;
208
209 @Override
210 public void onClick(final AjaxRequestTarget target, final ReportTO ignore) {
211 send(ReportDirectoryPanel.this, Broadcast.EXACT,
212 new AjaxWizard.EditItemActionEvent<>(restClient.read(model.getObject().getKey()), target));
213 }
214 }, ActionLink.ActionType.EDIT, IdRepoEntitlement.REPORT_UPDATE);
215
216 panel.add(new ActionLink<>() {
217
218 private static final long serialVersionUID = -3722207913631435501L;
219
220 @Override
221 public void onClick(final AjaxRequestTarget target, final ReportTO ignore) {
222 final ReportTO clone = SerializationUtils.clone(model.getObject());
223 clone.setKey(null);
224 send(ReportDirectoryPanel.this, Broadcast.EXACT,
225 new AjaxWizard.EditItemActionEvent<>(clone, target));
226 }
227 }, ActionLink.ActionType.CLONE, IdRepoEntitlement.REPORT_CREATE);
228
229 panel.add(new ActionLink<>() {
230
231 private static final long serialVersionUID = -3722207913631435501L;
232
233 @Override
234 public void onClick(final AjaxRequestTarget target, final ReportTO ignore) {
235 startAt.setExecutionDetail(
236 model.getObject().getKey(), model.getObject().getName(), target);
237 startAt.toggle(target, true);
238 }
239 }, ActionLink.ActionType.EXECUTE, IdRepoEntitlement.REPORT_EXECUTE);
240
241 panel.add(new ActionLink<>() {
242
243 private static final long serialVersionUID = -3722207913631435501L;
244
245 @Override
246 public void onClick(final AjaxRequestTarget target, final ReportTO ignore) {
247 final ReportTO reportTO = model.getObject();
248 try {
249 restClient.delete(reportTO.getKey());
250
251 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
252 target.add(container);
253 } catch (SyncopeClientException e) {
254 LOG.error("While deleting {}", reportTO.getKey(), e);
255 SyncopeConsoleSession.get().onException(e);
256 }
257 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
258 }
259 }, ActionLink.ActionType.DELETE, IdRepoEntitlement.REPORT_DELETE, true);
260
261 return panel;
262 }
263
264 @Override
265 protected Collection<ActionType> getBatches() {
266 List<ActionType> batches = new ArrayList<>();
267 batches.add(ActionType.EXECUTE);
268 batches.add(ActionType.DELETE);
269 return batches;
270 }
271
272 @Override
273 protected ReportDataProvider dataProvider() {
274 return new ReportDataProvider(rows);
275 }
276
277 @Override
278 protected String paginatorRowsKey() {
279 return IdRepoConstants.PREF_REPORT_PAGINATOR_ROWS;
280 }
281
282 protected abstract void viewReportExecs(ReportTO reportTO, AjaxRequestTarget target);
283
284 protected class ReportDataProvider extends DirectoryDataProvider<ReportTO> {
285
286 private static final long serialVersionUID = 4725679400450513556L;
287
288 private final SortableDataProviderComparator<ReportTO> comparator;
289
290 public ReportDataProvider(final int paginatorRows) {
291 super(paginatorRows);
292
293 setSort(Constants.NAME_FIELD_NAME, SortOrder.ASCENDING);
294 comparator = new SortableDataProviderComparator<>(this);
295 }
296
297 @Override
298 public Iterator<ReportTO> iterator(final long first, final long count) {
299 List<ReportTO> list = restClient.list();
300 list.sort(comparator);
301 return list.subList((int) first, (int) first + (int) count).iterator();
302 }
303
304 @Override
305 public long size() {
306 return restClient.list().size();
307 }
308
309 @Override
310 public IModel<ReportTO> model(final ReportTO report) {
311 return new CompoundPropertyModel<>(report);
312 }
313 }
314 }