You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2016/04/28 18:40:40 UTC

[3/4] syncope git commit: [SYNCOPE-745] report management + refactoring ModalPanel interface; still missing reportlets

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
new file mode 100644
index 0000000..7866000
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.reports;
+
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.ReportRestClient;
+import org.apache.syncope.client.console.tasks.ExecutionsDirectoryPanel;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+/**
+ * Modal window with report executions.
+ */
+public class ReportExecutionDetails extends MultilevelPanel.SecondLevel {
+
+    private static final long serialVersionUID = -4110576026663173545L;
+
+    public ReportExecutionDetails(final ReportTO reportTO, final PageReference pageRef) {
+        super();
+
+        final MultilevelPanel mlp = new MultilevelPanel("executions");
+        add(mlp);
+
+        mlp.setFirstLevel(new ExecutionsDirectoryPanel(mlp, reportTO.getKey(), new ReportRestClient(), pageRef) {
+
+            private static final long serialVersionUID = 5691719817252887541L;
+
+            @Override
+            protected void next(
+                    final String title,
+                    final MultilevelPanel.SecondLevel slevel,
+                    final AjaxRequestTarget target) {
+                mlp.next(title, slevel, target);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportStartAtTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportStartAtTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportStartAtTogglePanel.java
new file mode 100644
index 0000000..04022fa
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportStartAtTogglePanel.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.reports;
+
+import org.apache.syncope.client.console.panels.StartAtTogglePanel;
+import org.apache.syncope.client.console.rest.ExecutionRestClient;
+import org.apache.syncope.client.console.rest.ReportRestClient;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+
+public class ReportStartAtTogglePanel extends StartAtTogglePanel {
+
+    private static final long serialVersionUID = -3195479265440591519L;
+
+    public ReportStartAtTogglePanel(final WebMarkupContainer container) {
+        super(container);
+    }
+
+    @Override
+    protected ExecutionRestClient getRestClient() {
+        return new ReportRestClient();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
new file mode 100644
index 0000000..497a4bd
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.reports;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.notifications.TemplateContentModal;
+import org.apache.syncope.client.console.notifications.TemplateModal;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ReportTemplateTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.syncope.client.console.panels.WizardModalPanel;
+import org.apache.syncope.client.console.reports.ReportTemplateDirectoryPanel.ReportTemplateProvider;
+import org.apache.syncope.client.console.rest.ReportRestClient;
+import org.apache.syncope.common.lib.types.ReportTemplateFormat;
+
+public class ReportTemplateDirectoryPanel
+        extends DirectoryPanel<ReportTemplateTO, ReportTemplateTO, ReportTemplateProvider, ReportRestClient> {
+
+    private static final long serialVersionUID = -3789392431954221446L;
+
+    protected final BaseModal<Serializable> utilityModal = new BaseModal<>("outer");
+
+    public ReportTemplateDirectoryPanel(final String id, final PageReference pageReference) {
+        super(id, pageReference, true);
+        disableCheckBoxes();
+
+        modal.size(Modal.Size.Small);
+        modal.addSubmitButton();
+        setFooterVisibility(true);
+
+        addOuterObject(utilityModal);
+        setWindowClosedReloadCallback(utilityModal);
+        utilityModal.size(Modal.Size.Large);
+        utilityModal.addSubmitButton();
+
+        restClient = new ReportRestClient();
+        addNewItemPanelBuilder(new AbstractModalPanelBuilder<ReportTemplateTO>(new ReportTemplateTO(), pageRef) {
+
+            private static final long serialVersionUID = 1995192603527154740L;
+
+            @Override
+            public WizardModalPanel<ReportTemplateTO> build(
+                    final String id, final int index, final AjaxWizard.Mode mode) {
+                return new TemplateModal<ReportTemplateTO, ReportTemplateFormat>(
+                        modal, restClient, new ReportTemplateTO(), pageReference);
+            }
+        }, true);
+
+        initResultTable();
+
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, ENABLE, StandardEntitlement.MAIL_TEMPLATE_CREATE);
+    }
+
+    @Override
+    protected List<IColumn<ReportTemplateTO, String>> getColumns() {
+        List<IColumn<ReportTemplateTO, String>> columns = new ArrayList<>();
+        columns.add(new PropertyColumn<ReportTemplateTO, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+
+        columns.add(new ActionColumn<ReportTemplateTO, String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public ActionLinksPanel<ReportTemplateTO> getActions(
+                    final String componentId, final IModel<ReportTemplateTO> model) {
+
+                final ActionLinksPanel.Builder<ReportTemplateTO> panel = ActionLinksPanel.builder();
+
+                panel.add(new ActionLink<ReportTemplateTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770645L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final ReportTemplateTO ignore) {
+                        TemplateContentModal.TemplateContent<ReportTemplateFormat> content
+                                = new TemplateContentModal.TemplateContent<ReportTemplateFormat>(
+                                        model.getObject().getKey(), ReportTemplateFormat.FO);
+                        content.setContent(
+                                restClient.readTemplateFormat(model.getObject().getKey(), ReportTemplateFormat.FO));
+
+                        utilityModal.header(new ResourceModel("report.template.fo", "FO Content"));
+                        utilityModal.setContent(new TemplateContentModal<ReportTemplateTO, ReportTemplateFormat>(
+                                utilityModal, restClient, content, pageRef));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionLink.ActionType.FO_EDIT, StandardEntitlement.MAIL_TEMPLATE_UPDATE);
+
+                panel.add(new ActionLink<ReportTemplateTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770645L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final ReportTemplateTO ignore) {
+                        TemplateContentModal.TemplateContent<ReportTemplateFormat> content
+                                = new TemplateContentModal.TemplateContent<ReportTemplateFormat>(
+                                        model.getObject().getKey(), ReportTemplateFormat.HTML);
+                        content.setContent(
+                                restClient.readTemplateFormat(model.getObject().getKey(), ReportTemplateFormat.HTML));
+
+                        utilityModal.header(new ResourceModel("report.template.html", "HTML Content"));
+                        utilityModal.setContent(new TemplateContentModal<ReportTemplateTO, ReportTemplateFormat>(
+                                utilityModal, restClient, content, pageRef));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionLink.ActionType.HTML_EDIT, StandardEntitlement.MAIL_TEMPLATE_UPDATE);
+
+                panel.add(new ActionLink<ReportTemplateTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770645L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final ReportTemplateTO ignore) {
+                        TemplateContentModal.TemplateContent<ReportTemplateFormat> content
+                                = new TemplateContentModal.TemplateContent<ReportTemplateFormat>(
+                                        model.getObject().getKey(), ReportTemplateFormat.CSV);
+                        content.setContent(
+                                restClient.readTemplateFormat(model.getObject().getKey(), ReportTemplateFormat.CSV));
+
+                        utilityModal.setFormModel(content);
+                        utilityModal.header(new ResourceModel("report.template.text", "TEXT Content"));
+                        utilityModal.setContent(new TemplateContentModal<ReportTemplateTO, ReportTemplateFormat>(
+                                utilityModal, restClient, content, pageRef));
+                        utilityModal.show(true);
+                        target.add(utilityModal);
+                    }
+                }, ActionLink.ActionType.TEXT_EDIT, StandardEntitlement.MAIL_TEMPLATE_UPDATE);
+
+                panel.add(new ActionLink<ReportTemplateTO>() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final ReportTemplateTO ignore) {
+                        try {
+                            restClient.deleteTemplate(model.getObject().getKey());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                            target.add(container);
+                        } catch (SyncopeClientException e) {
+                            LOG.error("While deleting object {}", model.getObject().getKey(), e);
+                            error(StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage());
+                        }
+                        SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                    }
+                }, ActionLink.ActionType.DELETE, StandardEntitlement.MAIL_TEMPLATE_DELETE);
+
+                return panel.build(componentId);
+            }
+        });
+        return columns;
+    }
+
+    @Override
+    protected ReportTemplateProvider dataProvider() {
+        return new ReportTemplateProvider(rows);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_MAIL_TEMPLATE_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        return Collections.<ActionLink.ActionType>emptyList();
+    }
+
+    public class ReportTemplateProvider extends DirectoryDataProvider<ReportTemplateTO> {
+
+        private static final long serialVersionUID = -276043813563988590L;
+
+        private final SortableDataProviderComparator<ReportTemplateTO> comparator;
+
+        public ReportTemplateProvider(final int paginatorRows) {
+            super(paginatorRows);
+            setSort("key", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<ReportTemplateTO> iterator(final long first, final long count) {
+            final List<ReportTemplateTO> list = restClient.getAllAvailableTemplates();
+            Collections.sort(list, comparator);
+            return list.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return restClient.getAllAvailableTemplates().size();
+        }
+
+        @Override
+        public IModel<ReportTemplateTO> model(final ReportTemplateTO reportTemplateTO) {
+            return new AbstractReadOnlyModel<ReportTemplateTO>() {
+
+                private static final long serialVersionUID = 774694801558497248L;
+
+                @Override
+                public ReportTemplateTO getObject() {
+                    return reportTemplateTO;
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
new file mode 100644
index 0000000..6a12244
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.reports;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.client.console.rest.ReportRestClient;
+import org.apache.syncope.client.console.tasks.CrontabPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.to.ReportTemplateTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.model.PropertyModel;
+
+public class ReportWizardBuilder extends AjaxWizardBuilder<ReportTO> {
+
+    private static final long serialVersionUID = 5945391813567245081L;
+
+    private final ReportRestClient restClient = new ReportRestClient();
+
+    public ReportWizardBuilder(final ReportTO reportTO, final PageReference pageRef) {
+        super(reportTO, pageRef);
+    }
+
+    @Override
+    protected Serializable onApplyInternal(final ReportTO modelObject) {
+        if (modelObject.getKey() == null) {
+            restClient.create(modelObject);
+        } else {
+            restClient.update(modelObject);
+        }
+        return modelObject;
+    }
+
+    @Override
+    protected WizardModel buildModelSteps(final ReportTO modelObject, final WizardModel wizardModel) {
+        wizardModel.add(new Profile(modelObject));
+        wizardModel.add(new Schedule(modelObject));
+        return wizardModel;
+    }
+
+    public class Profile extends WizardStep {
+
+        private static final long serialVersionUID = -3043839139187792810L;
+
+        public Profile(final ReportTO reportTO) {
+
+            AjaxTextFieldPanel name = new AjaxTextFieldPanel(
+                    "name", "name", new PropertyModel<String>(reportTO, "name"), false);
+            name.addRequiredLabel();
+            name.setEnabled(true);
+            add(name);
+
+            final AjaxDropDownChoicePanel<String> template = new AjaxDropDownChoicePanel<>(
+                    "template", getString("template"),
+                    new PropertyModel<String>(reportTO, "template"));
+            template.setChoices(CollectionUtils.collect(
+                    restClient.getAllAvailableTemplates(), new Transformer<ReportTemplateTO, String>() {
+
+                @Override
+                public String transform(final ReportTemplateTO input) {
+                    return input.getKey();
+                }
+            }, new ArrayList<String>()));
+
+            template.addRequiredLabel();
+            add(template);
+
+            AjaxCheckBoxPanel active = new AjaxCheckBoxPanel(
+                    "active", "active", new PropertyModel<Boolean>(reportTO, "active"), false);
+            add(active);
+        }
+    }
+
+    public class Schedule extends WizardStep {
+
+        private static final long serialVersionUID = -785981096328637758L;
+
+        public Schedule(final ReportTO reportTO) {
+            add(new CrontabPanel(
+                    "schedule", new PropertyModel<String>(reportTO, "cronExpression"), reportTO.getCronExpression()));
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
index 83a0951..9eaa65d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import java.io.Serializable;
 import java.net.URI;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
@@ -31,7 +30,7 @@ import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class BaseRestClient implements Serializable {
+public abstract class BaseRestClient implements RestClient {
 
     protected static final Logger LOG = LoggerFactory.getLogger(BaseRestClient.class);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
index 1bb0ad9..aa0d59a 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
@@ -22,11 +22,15 @@ import java.util.Date;
 import java.util.List;
 import org.apache.syncope.common.lib.to.ExecTO;
 
-public interface ExecutionRestClient {
+public interface ExecutionRestClient extends RestClient {
 
     void startExecution(String executionCollectorKey, Date start);
 
     void deleteExecution(String executionKey);
 
     List<ExecTO> listRecentExecutions(final int max);
+
+    List<ExecTO> listExecutions(final String taskKey, final int page, final int size);
+
+    int countExecutions(final String taskKey);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/NotificationRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/NotificationRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/NotificationRestClient.java
index eb7d160..eab0a17 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/NotificationRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/NotificationRestClient.java
@@ -29,7 +29,8 @@ import org.apache.syncope.common.lib.types.MailTemplateFormat;
 import org.apache.syncope.common.rest.api.service.MailTemplateService;
 import org.apache.syncope.common.rest.api.service.NotificationService;
 
-public class NotificationRestClient extends BaseRestClient {
+public class NotificationRestClient extends BaseRestClient
+        implements TemplateRestClient<MailTemplateTO, MailTemplateFormat> {
 
     private static final long serialVersionUID = 6328933265096511690L;
 
@@ -53,22 +54,27 @@ public class NotificationRestClient extends BaseRestClient {
         getService(NotificationService.class).delete(key);
     }
 
+    @Override
     public List<MailTemplateTO> getAllAvailableTemplates() {
         return getService(MailTemplateService.class).list();
     }
 
+    @Override
     public void createTemplate(final MailTemplateTO mailTemplateTO) {
         getService(MailTemplateService.class).create(mailTemplateTO);
     }
 
+    @Override
     public void deleteTemplate(final String key) {
         getService(MailTemplateService.class).delete(key);
     }
 
+    @Override
     public MailTemplateTO readTemplate(final String key) {
         return getService(MailTemplateService.class).read(key);
     }
 
+    @Override
     public String readTemplateFormat(final String key, final MailTemplateFormat format) {
         try {
             return IOUtils.toString(InputStream.class.cast(
@@ -80,6 +86,7 @@ public class NotificationRestClient extends BaseRestClient {
         }
     }
 
+    @Override
     public void updateTemplateFormat(final String key, final String content, final MailTemplateFormat format) {
         getService(MailTemplateService.class).setFormat(
                 key, format, IOUtils.toInputStream(content, SyncopeConstants.DEFAULT_CHARSET));

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index 743ebfb..1c59d09 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@ -18,16 +18,27 @@
  */
 package org.apache.syncope.client.console.rest;
 
+import static org.apache.syncope.client.console.rest.BaseRestClient.getService;
+
+import java.io.InputStream;
 import java.util.Date;
 import java.util.List;
 import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.to.ReportTemplateTO;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.apache.syncope.common.lib.types.ReportTemplateFormat;
+import org.apache.syncope.common.rest.api.beans.ExecQuery;
 import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
 import org.apache.syncope.common.rest.api.service.ReportService;
+import org.apache.syncope.common.rest.api.service.ReportTemplateService;
 
-public class ReportRestClient extends BaseRestClient implements ExecutionRestClient {
+public class ReportRestClient extends BaseRestClient
+        implements ExecutionRestClient, TemplateRestClient<ReportTemplateTO, ReportTemplateFormat> {
 
     private static final long serialVersionUID = 1644689667998953604L;
 
@@ -74,4 +85,54 @@ public class ReportRestClient extends BaseRestClient implements ExecutionRestCli
     public Response exportExecutionResult(final String executionKey, final ReportExecExportFormat fmt) {
         return getService(ReportService.class).exportExecutionResult(executionKey, fmt);
     }
+
+    @Override
+    public List<ExecTO> listExecutions(final String taskKey, final int page, final int size) {
+        return getService(ReportService.class).
+                listExecutions(new ExecQuery.Builder().key(taskKey).page(page).size(size).build()).getResult();
+    }
+
+    @Override
+    public int countExecutions(final String taskKey) {
+        return getService(ReportService.class).
+                listExecutions(new ExecQuery.Builder().key(taskKey).page(1).size(1).build()).getTotalCount();
+    }
+
+    @Override
+    public List<ReportTemplateTO> getAllAvailableTemplates() {
+        return getService(ReportTemplateService.class).list();
+    }
+
+    @Override
+    public void createTemplate(final ReportTemplateTO reportTemplateTO) {
+        getService(ReportTemplateService.class).create(reportTemplateTO);
+    }
+
+    @Override
+    public void deleteTemplate(final String key) {
+        getService(ReportTemplateService.class).delete(key);
+    }
+
+    @Override
+    public ReportTemplateTO readTemplate(final String key) {
+        return getService(ReportTemplateService.class).read(key);
+    }
+
+    @Override
+    public String readTemplateFormat(final String key, final ReportTemplateFormat format) {
+        try {
+            return IOUtils.toString(InputStream.class.cast(
+                    getService(ReportTemplateService.class).getFormat(key, format).getEntity()),
+                    SyncopeConstants.DEFAULT_CHARSET);
+        } catch (Exception e) {
+            LOG.error("Error retrieving mail template {} as {}", key, format, e);
+            return StringUtils.EMPTY;
+        }
+    }
+
+    @Override
+    public void updateTemplateFormat(final String key, final String content, final ReportTemplateFormat format) {
+        getService(ReportTemplateService.class).setFormat(
+                key, format, IOUtils.toInputStream(content, SyncopeConstants.DEFAULT_CHARSET));
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/RestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/RestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/RestClient.java
new file mode 100644
index 0000000..4ac954c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/RestClient.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.rest;
+
+import java.io.Serializable;
+
+public interface RestClient extends Serializable {
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index abc62a6..0c70c44 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -61,6 +61,7 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
                 build()).getTotalCount();
     }
 
+    @Override
     public int countExecutions(final String taskKey) {
         return getService(TaskService.class).
                 listExecutions(new ExecQuery.Builder().key(taskKey).page(1).size(1).build()).getTotalCount();
@@ -139,6 +140,7 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
                 getResult();
     }
 
+    @Override
     public List<ExecTO> listExecutions(final String taskKey, final int page, final int size) {
         return getService(TaskService.class).
                 listExecutions(new ExecQuery.Builder().key(taskKey).page(page).size(size).build()).getResult();

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
new file mode 100644
index 0000000..9bb62b6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.rest;
+
+import java.util.List;
+
+public interface TemplateRestClient<T, F> extends RestClient {
+
+    List<T> getAllAvailableTemplates();
+
+    void createTemplate(final T templateTO);
+
+    void deleteTemplate(final String key);
+
+    T readTemplate(final String key);
+
+    String readTemplateFormat(final String key, final F format);
+
+    void updateTemplateFormat(final String key, final String content, final F format);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
index f61e4ee..835e478 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
@@ -44,21 +44,19 @@ import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.StringResourceModel;
 
 public class StatusDirectoryPanel
         extends DirectoryPanel<StatusBean, StatusBean, AttributableStatusProvider, AbstractAnyRestClient<?>>
-        implements ModalPanel<StatusBean> {
+        implements ModalPanel {
 
     private static final long serialVersionUID = -9148734710505211261L;
 
@@ -110,21 +108,6 @@ public class StatusDirectoryPanel
     }
 
     @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void onError(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public StatusBean getItem() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
     protected List<IColumn<StatusBean, String>> getColumns() {
         final List<IColumn<StatusBean, String>> columns = new ArrayList<>();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
index d2cf748..da05b49 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
@@ -21,14 +21,11 @@ package org.apache.syncope.client.console.status;
 import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.panel.Panel;
 
-public class StatusModal<T extends AnyTO> extends Panel implements ModalPanel<AnyWrapper<T>> {
+public class StatusModal<T extends AnyTO> extends Panel implements ModalPanel {
 
     private static final long serialVersionUID = 1066124171682570080L;
 
@@ -39,19 +36,4 @@ public class StatusModal<T extends AnyTO> extends Panel implements ModalPanel<An
         final MultilevelPanel mlp = new MultilevelPanel("status");
         add(mlp.setFirstLevel(new StatusDirectoryPanel(baseModal, mlp, pageReference, anyTO, statusOnly)));
     }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void onError(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public AnyWrapper<T> getItem() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
index 93b2a2a..dc947f2 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
@@ -18,32 +18,14 @@
  */
 package org.apache.syncope.client.console.tasks;
 
-import java.io.Serializable;
 import org.apache.syncope.client.console.panels.ModalPanel;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.panel.Panel;
 
-public abstract class AbstractTasks extends Panel implements ModalPanel<Serializable> {
+public abstract class AbstractTasks extends Panel implements ModalPanel {
 
     private static final long serialVersionUID = -4013796607157549641L;
 
     public AbstractTasks(final String id) {
         super(id);
     }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void onError(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public Serializable getItem() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/ExecutionsDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/ExecutionsDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/ExecutionsDirectoryPanel.java
new file mode 100644
index 0000000..10545f1
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/ExecutionsDirectoryPanel.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.tasks;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel.SecondLevel;
+import org.apache.syncope.client.console.rest.ExecutionRestClient;
+import org.apache.syncope.client.console.tasks.ExecutionsDirectoryPanel.ExecProvider;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ExecTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public abstract class ExecutionsDirectoryPanel
+        extends DirectoryPanel<ExecTO, ExecTO, ExecProvider, ExecutionRestClient> {
+
+    private static final long serialVersionUID = 2039393934721149162L;
+
+    private final BaseModal<?> baseModal;
+
+    private final MultilevelPanel multiLevelPanelRef;
+
+    private final String key;
+
+    public ExecutionsDirectoryPanel(
+            final MultilevelPanel multiLevelPanelRef,
+            final String key,
+            final ExecutionRestClient executionRestClient,
+            final PageReference pageRef) {
+        this(null, multiLevelPanelRef, key, executionRestClient, pageRef);
+    }
+
+    public ExecutionsDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final String key,
+            final ExecutionRestClient executionRestClient,
+            final PageReference pageRef) {
+        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef, false);
+        this.baseModal = baseModal;
+        this.multiLevelPanelRef = multiLevelPanelRef;
+        restClient = executionRestClient;
+        setOutputMarkupId(true);
+        this.key = key;
+        initResultTable();
+    }
+
+    @Override
+    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<ExecTO, String> resultTableBuilder) {
+        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
+    }
+
+    protected abstract void next(final String title, final SecondLevel secondLevel, final AjaxRequestTarget target);
+
+    @Override
+    protected List<IColumn<ExecTO, String>> getColumns() {
+        final List<IColumn<ExecTO, String>> columns = new ArrayList<>();
+
+        columns.add(new KeyPropertyColumn<ExecTO>(new ResourceModel("key"), "key", "key"));
+
+        columns.add(new DatePropertyColumn<ExecTO>(new ResourceModel("start"), "start", "start"));
+
+        columns.add(new DatePropertyColumn<ExecTO>(new ResourceModel("end"), "end", "end"));
+
+        columns.add(new PropertyColumn<ExecTO, String>(new ResourceModel("status"), "status", "status"));
+
+        columns.add(new ActionColumn<ExecTO, String>(new ResourceModel("actions")) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public ActionLinksPanel<ExecTO> getActions(final String componentId, final IModel<ExecTO> model) {
+                final ExecTO taskExecutionTO = model.getObject();
+
+                final ActionLinksPanel.Builder<ExecTO> panel = ActionLinksPanel.builder();
+
+                panel.
+                        add(new ActionLink<ExecTO>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final ExecTO ignore) {
+                                next(new StringResourceModel("execution.view", ExecutionsDirectoryPanel.this, model).
+                                        getObject(), new ExecMessage(model.getObject().getMessage()), target);
+                            }
+                        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).
+                        add(new ActionLink<ExecTO>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final ExecTO ignore) {
+                                try {
+                                    restClient.deleteExecution(taskExecutionTO.getKey());
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                } catch (SyncopeClientException scce) {
+                                    error(scce.getMessage());
+                                }
+                                target.add(ExecutionsDirectoryPanel.this);
+                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE);
+
+                return panel.build(componentId, model.getObject());
+            }
+
+            @Override
+            public ActionLinksPanel<Serializable> getHeader(final String componentId) {
+                final ActionLinksPanel.Builder<Serializable> panel = ActionLinksPanel.builder();
+
+                return panel.add(new ActionLink<Serializable>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
+                        if (target != null) {
+                            target.add(container);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected ExecProvider dataProvider() {
+        return new ExecProvider(key, rows);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_TASK_EXECS_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
+        bulkActions.add(ActionLink.ActionType.DELETE);
+        return bulkActions;
+    }
+
+    protected class ExecProvider extends DirectoryDataProvider<ExecTO> {
+
+        private static final long serialVersionUID = 8943636537120648961L;
+
+        private final SortableDataProviderComparator<ExecTO> comparator;
+
+        private final String taskKey;
+
+        public ExecProvider(final String taskKey, final int paginatorRows) {
+            super(paginatorRows);
+            this.taskKey = taskKey;
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        public SortableDataProviderComparator<ExecTO> getComparator() {
+            return comparator;
+        }
+
+        @Override
+        public Iterator<ExecTO> iterator(final long first, final long count) {
+            final int page = ((int) first / paginatorRows);
+            List<ExecTO> list = restClient.listExecutions(taskKey, (page < 0 ? 0 : page) + 1, paginatorRows);
+            Collections.sort(list, comparator);
+            return list.iterator();
+        }
+
+        @Override
+        public long size() {
+            return restClient.countExecutions(taskKey);
+        }
+
+        @Override
+        public IModel<ExecTO> model(final ExecTO taskExecution) {
+
+            return new AbstractReadOnlyModel<ExecTO>() {
+
+                private static final long serialVersionUID = 7485475149862342421L;
+
+                @Override
+                public ExecTO getObject() {
+                    return taskExecution;
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
index 03d62e7..6d8d6c7 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
@@ -50,7 +50,7 @@ import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 
 public abstract class NotificationTaskDirectoryPanel
-        extends TaskDirectoryPanel<NotificationTaskTO> implements ModalPanel<NotificationTaskTO> {
+        extends TaskDirectoryPanel<NotificationTaskTO> implements ModalPanel {
 
     private static final long serialVersionUID = 4984337552918213290L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
index da36a28..2e83e6e 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
@@ -53,7 +53,7 @@ import org.apache.wicket.model.StringResourceModel;
  * Tasks page.
  */
 public abstract class PropagationTaskDirectoryPanel
-        extends TaskDirectoryPanel<PropagationTaskTO> implements ModalPanel<PropagationTaskTO> {
+        extends TaskDirectoryPanel<PropagationTaskTO> implements ModalPanel {
 
     private static final long serialVersionUID = 4984337552918213290L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
index 709205a..14fc503 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
@@ -62,7 +62,7 @@ import org.apache.wicket.model.StringResourceModel;
  * @param <T> Sched task type.
  */
 public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
-        extends TaskDirectoryPanel<T> implements ModalPanel<T> {
+        extends TaskDirectoryPanel<T> implements ModalPanel {
 
     private static final long serialVersionUID = 4984337552918213290L;
 
@@ -70,7 +70,7 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
 
     protected T schedTaskTO;
 
-    private final StartAtTogglePanel startAt;
+    private final TaskStartAtTogglePanel startAt;
 
     protected SchedTaskDirectoryPanel(
             final BaseModal<?> baseModal,
@@ -92,7 +92,7 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
 
         initResultTable();
 
-        startAt = new StartAtTogglePanel(container);
+        startAt = new TaskStartAtTogglePanel(container);
         addInnerObject(startAt);
     }
 
@@ -202,7 +202,8 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
 
                             @Override
                             public void onClick(final AjaxRequestTarget target, final T ignore) {
-                                startAt.setTaskTO(target, model.getObject());
+                                startAt.setExecutionDetail(
+                                        model.getObject().getKey(), model.getObject().getName(), target);
                                 startAt.toggle(target, true);
                             }
                         }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE).

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
index 1f2e693..a85a248 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
@@ -115,8 +115,8 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
             }
         };
 
-        private final IModel<List<String>> reconciliationFilterBuilderClasses =
-                new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> reconciliationFilterBuilderClasses
+                = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
@@ -147,8 +147,8 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
         };
 
         public Profile(final SchedTaskTO taskTO) {
-            AjaxTextFieldPanel name =
-                    new AjaxTextFieldPanel("name", "name", new PropertyModel<String>(taskTO, "name"), false);
+            AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name", new PropertyModel<String>(taskTO, "name"),
+                    false);
             name.addRequiredLabel();
             name.setEnabled(true);
             add(name);
@@ -158,8 +158,8 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
             description.setEnabled(true);
             add(description);
 
-            AjaxCheckBoxPanel active =
-                    new AjaxCheckBoxPanel("active", "active", new PropertyModel<Boolean>(taskTO, "active"), false);
+            AjaxCheckBoxPanel active = new AjaxCheckBoxPanel("active", "active", new PropertyModel<Boolean>(taskTO,
+                    "active"), false);
             add(active);
 
             AjaxDropDownChoicePanel<String> jobDelegateClassName = new AjaxDropDownChoicePanel<>(

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/StartAtTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/StartAtTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/StartAtTogglePanel.java
deleted file mode 100644
index 912fd5c..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/StartAtTogglePanel.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.tasks;
-
-import java.io.Serializable;
-import java.util.Date;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.panels.TogglePanel;
-import org.apache.syncope.client.console.rest.TaskRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.DateTimeFieldPanel;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.SchedTaskTO;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.model.Model;
-
-public class StartAtTogglePanel extends TogglePanel<Serializable> {
-
-    private static final long serialVersionUID = -3195479265440591519L;
-
-    private SchedTaskTO taskTO;
-
-    public StartAtTogglePanel(final WebMarkupContainer container) {
-        super("startAt");
-
-        final Form<?> form = new Form<>("startAtForm");
-        addInnerObject(form);
-
-        final Model<Date> startAtDateModel = new Model<>();
-
-        final DateTimeFieldPanel startAtDate = new DateTimeFieldPanel(
-                "startAtDate", "startAtDate", startAtDateModel, SyncopeConstants.DATE_PATTERNS[3]);
-
-        startAtDate.setReadOnly(true).hideLabel();
-        form.add(startAtDate);
-
-        final AjaxCheckBoxPanel startAtCheck = new AjaxCheckBoxPanel(
-                "startAtCheck", "startAtCheck", new Model<>(false), false);
-
-        form.add(startAtCheck);
-
-        startAtCheck.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-            private static final long serialVersionUID = -1107858522700306810L;
-
-            @Override
-            protected void onUpdate(final AjaxRequestTarget target) {
-                target.add(startAtDate.setModelObject(null).setReadOnly(!startAtCheck.getModelObject()));
-            }
-        });
-
-        form.add(new AjaxSubmitLink("startAt", form) {
-
-            private static final long serialVersionUID = -7978723352517770644L;
-
-            @Override
-            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-                try {
-                    new TaskRestClient().startExecution(taskTO.getKey(), startAtDateModel.getObject());
-                    info(getString(Constants.OPERATION_SUCCEEDED));
-                    toggle(target, false);
-                    target.add(container);
-                } catch (SyncopeClientException e) {
-                    error(StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage());
-                    LOG.error("While running propagation task {}", taskTO.getKey(), e);
-                }
-                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
-            }
-
-            @Override
-            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
-                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
-            }
-
-        });
-    }
-
-    public void setTaskTO(final AjaxRequestTarget target, final SchedTaskTO taskTO) {
-        this.taskTO = taskTO;
-        setHeader(target, taskTO.getName());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
index 5484b8b..081d2dd 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
@@ -32,7 +32,6 @@ import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
-import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 
@@ -42,7 +41,7 @@ import org.apache.wicket.model.IModel;
  * @param <T> task type.
  */
 public abstract class TaskDirectoryPanel<T extends AbstractTaskTO>
-        extends DirectoryPanel<T, T, TaskDataProvider<T>, TaskRestClient> implements ModalPanel<T> {
+        extends DirectoryPanel<T, T, TaskDataProvider<T>, TaskRestClient> implements ModalPanel {
 
     private static final long serialVersionUID = 4984337552918213290L;
 
@@ -64,22 +63,7 @@ public abstract class TaskDirectoryPanel<T extends AbstractTaskTO>
         resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
     }
 
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void onError(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public T getItem() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    protected abstract void viewTask(T taskTO, AjaxRequestTarget target);
+    protected abstract void viewTask(final T taskTO, final AjaxRequestTarget target);
 
     protected abstract class TasksProvider<T extends AbstractTaskTO> extends DirectoryDataProvider<T> {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutionDetails.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutionDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutionDetails.java
index e02e6c5..eb2254f 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutionDetails.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutionDetails.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.tasks;
 
 import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.TaskRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.common.lib.to.AbstractTaskTO;
 import org.apache.wicket.PageReference;
@@ -39,7 +40,7 @@ public class TaskExecutionDetails<T extends AbstractTaskTO> extends MultilevelPa
         final MultilevelPanel mlp = new MultilevelPanel("executions");
         add(mlp);
 
-        mlp.setFirstLevel(new TaskExecutions(baseModal, mlp, taskTO, pageRef) {
+        mlp.setFirstLevel(new ExecutionsDirectoryPanel(baseModal, mlp, taskTO.getKey(), new TaskRestClient(), pageRef) {
 
             private static final long serialVersionUID = 5691719817252887541L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutions.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutions.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutions.java
deleted file mode 100644
index 84025e0..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskExecutions.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.tasks;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
-import org.apache.syncope.client.console.panels.DirectoryPanel;
-import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.panels.MultilevelPanel.SecondLevel;
-import org.apache.syncope.client.console.rest.TaskRestClient;
-import org.apache.syncope.client.console.tasks.TaskExecutions.TaskExecProvider;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.AbstractTaskTO;
-import org.apache.syncope.common.lib.to.ExecTO;
-import org.apache.syncope.common.lib.types.StandardEntitlement;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.model.AbstractReadOnlyModel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.model.StringResourceModel;
-
-public abstract class TaskExecutions
-        extends DirectoryPanel<ExecTO, ExecTO, TaskExecProvider, TaskRestClient> {
-
-    private static final long serialVersionUID = 2039393934721149162L;
-
-    private final BaseModal<?> baseModal;
-
-    private final MultilevelPanel multiLevelPanelRef;
-
-    protected TaskRestClient taskRestClient = new TaskRestClient();
-
-    private final AbstractTaskTO taskTO;
-
-    public TaskExecutions(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final AbstractTaskTO taskTO,
-            final PageReference pageRef) {
-        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef, false);
-        this.baseModal = baseModal;
-        this.multiLevelPanelRef = multiLevelPanelRef;
-        restClient = taskRestClient;
-        setOutputMarkupId(true);
-        this.taskTO = taskTO;
-        initResultTable();
-    }
-
-    @Override
-    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<ExecTO, String> resultTableBuilder) {
-        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
-    }
-
-    protected abstract void next(final String title, final SecondLevel secondLevel, final AjaxRequestTarget target);
-
-    @Override
-    protected List<IColumn<ExecTO, String>> getColumns() {
-        final List<IColumn<ExecTO, String>> columns = new ArrayList<>();
-
-        columns.add(new KeyPropertyColumn<ExecTO>(new ResourceModel("key"), "key", "key"));
-
-        columns.add(new DatePropertyColumn<ExecTO>(new ResourceModel("start"), "start", "start"));
-
-        columns.add(new DatePropertyColumn<ExecTO>(new ResourceModel("end"), "end", "end"));
-
-        columns.add(new PropertyColumn<ExecTO, String>(new ResourceModel("status"), "status", "status"));
-
-        columns.add(new ActionColumn<ExecTO, String>(new ResourceModel("actions")) {
-
-            private static final long serialVersionUID = -3503023501954863131L;
-
-            @Override
-            public ActionLinksPanel<ExecTO> getActions(final String componentId, final IModel<ExecTO> model) {
-                final ExecTO taskExecutionTO = model.getObject();
-
-                final ActionLinksPanel.Builder<ExecTO> panel = ActionLinksPanel.builder();
-
-                panel.
-                        add(new ActionLink<ExecTO>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final ExecTO ignore) {
-                                next(new StringResourceModel("execution.view", TaskExecutions.this, model).getObject(),
-                                        new ExecMessage(model.getObject().getMessage()), target);
-                            }
-                        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).
-                        add(new ActionLink<ExecTO>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final ExecTO ignore) {
-                                try {
-                                    restClient.deleteExecution(taskExecutionTO.getKey());
-                                    taskTO.getExecutions().remove(taskExecutionTO);
-                                    info(getString(Constants.OPERATION_SUCCEEDED));
-                                } catch (SyncopeClientException scce) {
-                                    error(scce.getMessage());
-                                }
-                                target.add(TaskExecutions.this);
-                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
-                            }
-                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE);
-
-                return panel.build(componentId, model.getObject());
-            }
-
-            @Override
-            public ActionLinksPanel<Serializable> getHeader(final String componentId) {
-                final ActionLinksPanel.Builder<Serializable> panel = ActionLinksPanel.builder();
-
-                return panel.add(new ActionLink<Serializable>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
-                        if (target != null) {
-                            target.add(container);
-                        }
-                    }
-                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
-            }
-        });
-
-        return columns;
-    }
-
-    @Override
-    protected TaskExecProvider dataProvider() {
-        return new TaskExecProvider(taskTO.getKey(), rows);
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return Constants.PREF_TASK_EXECS_PAGINATOR_ROWS;
-    }
-
-    @Override
-    protected Collection<ActionLink.ActionType> getBulkActions() {
-        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
-        bulkActions.add(ActionLink.ActionType.DELETE);
-        return bulkActions;
-    }
-
-    protected class TaskExecProvider extends DirectoryDataProvider<ExecTO> {
-
-        private static final long serialVersionUID = 8943636537120648961L;
-
-        private final SortableDataProviderComparator<ExecTO> comparator;
-
-        private final String taskKey;
-
-        public TaskExecProvider(final String taskKey, final int paginatorRows) {
-            super(paginatorRows);
-            this.taskKey = taskKey;
-            comparator = new SortableDataProviderComparator<>(this);
-        }
-
-        public SortableDataProviderComparator<ExecTO> getComparator() {
-            return comparator;
-        }
-
-        @Override
-        public Iterator<ExecTO> iterator(final long first, final long count) {
-            final int page = ((int) first / paginatorRows);
-            List<ExecTO> list = taskRestClient.listExecutions(taskKey, (page < 0 ? 0 : page) + 1, paginatorRows);
-            Collections.sort(list, comparator);
-            return list.iterator();
-        }
-
-        @Override
-        public long size() {
-            return taskRestClient.countExecutions(taskKey);
-        }
-
-        @Override
-        public IModel<ExecTO> model(final ExecTO taskExecution) {
-
-            return new AbstractReadOnlyModel<ExecTO>() {
-
-                private static final long serialVersionUID = 7485475149862342421L;
-
-                @Override
-                public ExecTO getObject() {
-                    return taskExecution;
-                }
-            };
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskStartAtTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskStartAtTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskStartAtTogglePanel.java
new file mode 100644
index 0000000..5e250e2
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/TaskStartAtTogglePanel.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.tasks;
+
+import org.apache.syncope.client.console.panels.StartAtTogglePanel;
+import org.apache.syncope.client.console.rest.ExecutionRestClient;
+import org.apache.syncope.client.console.rest.TaskRestClient;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+
+public class TaskStartAtTogglePanel extends StartAtTogglePanel {
+
+    private static final long serialVersionUID = -3195479265440591519L;
+
+    public TaskStartAtTogglePanel(final WebMarkupContainer container) {
+        super(container);
+    }
+
+    @Override
+    protected ExecutionRestClient getRestClient() {
+        return new TaskRestClient();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
index 0025f79..bc62538 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
@@ -44,6 +44,7 @@ import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.syncope.client.console.panels.SubmitableModalPanel;
 
 public class BaseModal<T extends Serializable> extends Modal<T> {
 
@@ -123,21 +124,21 @@ public class BaseModal<T extends Serializable> extends Modal<T> {
         return form.getModelObject();
     }
 
-    public ModalPanel<T> getContent() {
+    public ModalPanel getContent() {
         if (content instanceof ModalPanel) {
-            return (ModalPanel<T>) content;
+            return (ModalPanel) content;
         }
         throw new IllegalStateException();
     }
 
-    public BaseModal<T> setContent(final ModalPanel<T> component) {
+    public BaseModal<T> setContent(final ModalPanel component) {
         if (component instanceof Panel) {
             return setInternalContent(Panel.class.cast(component));
         }
         throw new IllegalArgumentException("Panel instance is required");
     }
 
-    public BaseModal<T> setContent(final ModalPanel<T> component, final AjaxRequestTarget target) {
+    public BaseModal<T> setContent(final ModalPanel component, final AjaxRequestTarget target) {
         setContent(component);
         target.add(content);
         return this;
@@ -178,18 +179,22 @@ public class BaseModal<T extends Serializable> extends Modal<T> {
     }
 
     public AjaxSubmitLink addSubmitButton() {
+        if (!(BaseModal.this.getContent() instanceof SubmitableModalPanel)) {
+            throw new IllegalStateException();
+        }
+
         AjaxSubmitLink submit = new AjaxSubmitLink(SUBMIT, form) {
 
             private static final long serialVersionUID = -5783994974426198290L;
 
             @Override
             protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-                BaseModal.this.getContent().onSubmit(target, form);
+                SubmitableModalPanel.class.cast(BaseModal.this.getContent()).onSubmit(target, form);
             }
 
             @Override
             protected void onError(final AjaxRequestTarget target, final Form<?> form) {
-                BaseModal.this.getContent().onError(target, form);
+                SubmitableModalPanel.class.cast(BaseModal.this.getContent()).onError(target, form);
             }
         };
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ae52b12e/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
index 730bf9c..0d9c074 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
@@ -47,6 +47,7 @@ public abstract class ActionLink<T extends Serializable> implements Serializable
         CREATE("create"),
         EDIT("read"),
         TYPE_EXTENSIONS("read"),
+        FO_EDIT("read"),
         HTML_EDIT("read"),
         TEXT_EDIT("read"),
         LAYOUT_EDIT("read"),