[SYNCOPE-765] providing TODO features

Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/9014cf28
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/9014cf28
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/9014cf28

Branch: refs/heads/master
Commit: 9014cf2873b522d9fdd7dfe7afa5bdc8be3c9677
Parents: 762178b
Author: fmartelli <fabio.marte...@gmail.com>
Authored: Thu Mar 24 16:59:31 2016 +0100
Committer: fmartelli <fabio.marte...@gmail.com>
Committed: Thu Mar 24 17:19:54 2016 +0100

----------------------------------------------------------------------
 client/console/pom.xml                          |   4 +
 .../client/console/commons/Constants.java       |   2 +
 .../console/commons/MapChoiceRenderer.java      |  55 ++++
 .../syncope/client/console/pages/BasePage.java  |  19 +-
 .../syncope/client/console/pages/TODOs.java     |  41 +++
 .../panels/AbstractSearchResultPanel.java       |   4 +
 .../console/panels/AnyTypeClassesPanel.java     |   2 +-
 .../client/console/panels/AnyTypesPanel.java    |   4 +-
 .../panels/ParametersCreateModalPanel.java      |   3 +-
 .../client/console/panels/ParametersPanel.java  |   3 +-
 .../console/panels/RelationshipTypesPanel.java  |   2 +-
 .../client/console/panels/SchemaTypePanel.java  |   4 +-
 .../console/panels/SecurityQuestionsPanel.java  |   6 +-
 .../syncope/client/console/todos/Approval.java  | 208 ++++++++++++++
 .../client/console/todos/ApprovalDetails.java   |  48 ++++
 .../client/console/todos/ApprovalModal.java     |  83 ++++++
 .../console/todos/TODOSearchResultPanel.java    | 217 ++++++++++++++
 .../client/console/widgets/TODOsWidget.java     | 283 +++++++++++++++++++
 .../wizards/AbstractModalPanelBuilder.java      |   2 +-
 .../client/console/wizards/AjaxWizard.java      |  32 ++-
 .../console/wizards/AjaxWizardBuilder.java      |   8 +-
 .../console/wizards/AjaxWizardMgtButtonBar.java |  37 ++-
 .../client/console/wizards/WizardMgtPanel.java  |   5 +-
 .../client/console/wizards/any/PlainAttrs.java  |   2 +-
 .../META-INF/resources/css/syncopeConsole.css   |   6 +-
 .../syncope/client/console/pages/BasePage.html  |  13 +-
 .../client/console/pages/BasePage.properties    |   1 +
 .../client/console/pages/BasePage_it.properties |   1 +
 .../console/pages/BasePage_pt_BR.properties     |   1 +
 .../syncope/client/console/pages/Realms.html    |  12 +-
 .../syncope/client/console/pages/TODOs.html     |  35 +++
 .../client/console/pages/TODOs.properties       |  32 +++
 .../client/console/pages/TODOs_it.properties    |  32 +++
 .../client/console/pages/TODOs_pt_BR.properties |  32 +++
 .../syncope/client/console/todos/Approval.html  |  34 +++
 .../client/console/todos/Approval.properties    |  17 ++
 .../client/console/todos/ApprovalDetails.html   |  26 ++
 .../client/console/todos/ApprovalModal.html     |  26 ++
 .../console/todos/ApprovalModal.properties      |  17 ++
 .../client/console/todos/Approval_it.properties |  17 ++
 .../console/todos/Approval_pt_BR.properties     |  17 ++
 .../markup/html/form/ActionLinksPanel.html      |   2 +-
 .../client/console/widgets/TODOsWidget.html     |  48 ++++
 .../console/widgets/TODOsWidget.properties      |  21 ++
 .../console/widgets/TODOsWidget_it.properties   |  21 ++
 .../widgets/TODOsWidget_pt_BR.properties        |  21 ++
 .../console/wizards/any/DerAttrs.properties     |   2 +-
 .../console/wizards/any/DerAttrs_it.properties  |   2 +-
 .../wizards/any/DerAttrs_pt_BR.properties       |   2 +-
 .../console/wizards/any/UserDetails.properties  |   2 +-
 .../wizards/any/UserDetails_it.properties       |   2 +-
 .../wizards/any/UserDetails_pt_BR.properties    |   2 +-
 .../client/console/panels/CamelRoutesPanel.java |   2 +-
 pom.xml                                         |   6 +
 54 files changed, 1447 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/pom.xml
----------------------------------------------------------------------
diff --git a/client/console/pom.xml b/client/console/pom.xml
index 6f4ebcf..c143ee7 100644
--- a/client/console/pom.xml
+++ b/client/console/pom.xml
@@ -134,6 +134,10 @@ under the License.
       <groupId>org.webjars</groupId>
       <artifactId>jquery-ui</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>jQuery-slimScroll</artifactId>
+    </dependency>
     
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
index 3e0d4a4..8f9c250 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
@@ -88,6 +88,8 @@ public final class Constants {
 
     public static final String PREF_ROLE_PAGINATOR_ROWS = 
"role.paginator.rows";
 
+    public static final String PREF_WORKFLOW_FORM_PAGINATOR_ROWS = 
"role.paginator.workflow.form";
+
     public static final String PREF_RESOURCES_PAGINATOR_ROWS = 
"resources.paginator.rows";
 
     public static final String PREF_CONNECTORS_PAGINATOR_ROWS = 
"connectors.paginator.rows";

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
new file mode 100644
index 0000000..2845105
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
@@ -0,0 +1,55 @@
+/*
+ * 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.commons;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+
+public class MapChoiceRenderer<T, K> implements IChoiceRenderer<T> {
+
+    private static final long serialVersionUID = -7452881117778186644L;
+
+    private final Map<T, K> map;
+
+    public MapChoiceRenderer(final Map<T, K> map) {
+        this.map = map;
+    }
+
+    @Override
+    public Object getDisplayValue(final T key) {
+        return map.get(key);
+    }
+
+    @Override
+    public String getIdValue(final T key, final int index) {
+        return key.toString();
+    }
+
+    @Override
+    public T getObject(final String id, final IModel<? extends List<? extends 
T>> choices) {
+        for (Map.Entry<T, K> entry : map.entrySet()) {
+            if (entry.getValue() != null && 
entry.getValue().toString().equals(id)) {
+                return entry.getKey();
+            }
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index a860bfe..44fc786 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -27,10 +27,10 @@ import 
org.apache.syncope.client.console.annotations.ExtPage;
 import 
org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.init.ConsoleInitializer;
 import org.apache.syncope.client.console.panels.NotificationPanel;
-import org.apache.syncope.client.console.rest.UserWorkflowRestClient;
 import org.apache.syncope.client.console.topology.Topology;
 import org.apache.syncope.client.console.wicket.markup.head.MetaHeaderItem;
 import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.widgets.TODOsWidget;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
@@ -84,8 +84,7 @@ public class BasePage extends WebPage implements 
IAjaxIndicatorAware {
         super(parameters);
 
         body = new WebMarkupContainer("body");
-        Serializable leftMenuCollapse =
-                
SyncopeConsoleSession.get().getAttribute(SyncopeConsoleSession.MENU_COLLAPSE);
+        Serializable leftMenuCollapse = 
SyncopeConsoleSession.get().getAttribute(SyncopeConsoleSession.MENU_COLLAPSE);
         if ((leftMenuCollapse instanceof Boolean) && ((Boolean) 
leftMenuCollapse)) {
             body.add(new AttributeAppender("class", " sidebar-collapse"));
         }
@@ -97,15 +96,7 @@ public class BasePage extends WebPage implements 
IAjaxIndicatorAware {
         body.add(new Label("version", 
SyncopeConsoleApplication.get().getVersion()));
         body.add(new Label("username", 
SyncopeConsoleSession.get().getSelfTO().getUsername()));
 
-        WebMarkupContainer todosContainer = new 
WebMarkupContainer("todosContainer");
-        body.add(todosContainer);
-        Label todos = new Label("todos", "0");
-        todosContainer.add(todos);
-        if 
(SyncopeConsoleSession.get().owns(StandardEntitlement.WORKFLOW_FORM_LIST)) {
-            todos.setDefaultModelObject(new 
UserWorkflowRestClient().getForms().size());
-        }
-        MetaDataRoleAuthorizationStrategy.authorize(
-                todosContainer, WebPage.ENABLE, 
StandardEntitlement.WORKFLOW_FORM_LIST);
+        body.add(new TODOsWidget("todosWidget", 
getPageReference()).setRenderBodyOnly(true));
 
         // menu
         WebMarkupContainer liContainer = new 
WebMarkupContainer(getLIContainerId("dashboard"));
@@ -248,8 +239,8 @@ public class BasePage extends WebPage implements 
IAjaxIndicatorAware {
         }
 
         // Extensions
-        ClassPathScanImplementationLookup classPathScanImplementationLookup =
-                (ClassPathScanImplementationLookup) 
SyncopeConsoleApplication.get().
+        ClassPathScanImplementationLookup classPathScanImplementationLookup
+                = (ClassPathScanImplementationLookup) 
SyncopeConsoleApplication.get().
                 
getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP);
         List<Class<? extends BaseExtPage>> extPageClasses = 
classPathScanImplementationLookup.getExtPageClasses();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/pages/TODOs.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/TODOs.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/TODOs.java
new file mode 100644
index 0000000..ac51ba0
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/TODOs.java
@@ -0,0 +1,41 @@
+/*
+ * 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.pages;
+
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.todos.TODOSearchResultPanel;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class TODOs extends BasePage {
+
+    private static final long serialVersionUID = -1100228004207271271L;
+
+    public TODOs(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", 
Dashboard.class));
+
+        WebMarkupContainer content = new WebMarkupContainer("content");
+        content.setOutputMarkupId(true);
+        body.add(content);
+
+        content.add(new TODOSearchResultPanel("wfPanel", getPageReference()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
index 50b1539..66de748 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
@@ -145,6 +146,9 @@ public abstract class AbstractSearchResultPanel<
         setWindowClosedReloadCallback(modal);
         setWindowClosedReloadCallback(altDefaultModal);
         setWindowClosedReloadCallback(displayAttributeModal);
+
+        altDefaultModal.size(Modal.Size.Medium);
+        displayAttributeModal.size(Modal.Size.Medium);
     }
 
     protected abstract DP dataProvider();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
index 8fa1b5a..5c2b446 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
@@ -66,7 +66,7 @@ public class AnyTypeClassesPanel extends 
AbstractTypesPanel<AnyTypeClassTO, AnyT
             private static final long serialVersionUID = -6388405037134399367L;
 
             @Override
-            public ModalPanel<AnyTypeClassTO> build(final int index, final 
boolean edit) {
+            public ModalPanel<AnyTypeClassTO> build(final int index, final 
AjaxWizard.Mode mode) {
                 final AnyTypeClassTO modelObject = newModelObject();
                 return new AnyTypeClassModalPanel(modal, modelObject, pageRef) 
{
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
index 978c299..93d19b6 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
@@ -67,7 +67,7 @@ public class AnyTypesPanel extends 
AbstractTypesPanel<AnyTypeTO, AnyTypeProvider
             private static final long serialVersionUID = -6388405037134399367L;
 
             @Override
-            public ModalPanel<AnyTypeTO> build(final int index, final boolean 
edit) {
+            public ModalPanel<AnyTypeTO> build(final int index, final 
AjaxWizard.Mode mode) {
                 final AnyTypeTO modelObject = newModelObject();
                 return new AnyTypeModalPanel(modal, modelObject, pageRef) {
 
@@ -184,7 +184,7 @@ public class AnyTypesPanel extends 
AbstractTypesPanel<AnyTypeTO, AnyTypeProvider
                                     target.add(container);
                                 } catch (Exception e) {
                                     LOG.error("While deleting {}", 
model.getObject(), e);
-                                    error(StringUtils.isBlank(e.getMessage()) 
+                                    error(StringUtils.isBlank(e.getMessage())
                                             ? e.getClass().getName() : 
e.getMessage());
                                 }
                                 
SyncopeConsoleSession.get().getNotificationPanel().refresh(target);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
index 4f73fab..6e71a2b 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.panels;
 
 import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.wicket.PageReference;
 
@@ -35,7 +36,7 @@ public class ParametersCreateModalPanel extends 
AbstractModalPanel<AttrTO> {
         super(modal, pageRef);
         this.attrTO = attrTO;
         add(new ParametersCreateWizardPanel("parametersCreateWizardPanel",
-                new ParametersCreateWizardPanel.ParametersForm(), 
pageRef).build(false));
+                new ParametersCreateWizardPanel.ParametersForm(), 
pageRef).build(AjaxWizard.Mode.CREATE));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
index 6ee4ae0..60540d9 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
@@ -36,6 +36,7 @@ import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 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.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -100,7 +101,7 @@ public class ParametersPanel extends 
AbstractSearchResultPanel<
             private static final long serialVersionUID = 1995192603527154740L;
 
             @Override
-            public ModalPanel<AttrTO> build(final int index, final boolean 
edit) {
+            public ModalPanel<AttrTO> build(final int index, final 
AjaxWizard.Mode mode) {
                 return new ParametersCreateModalPanel(modal, newModelObject(), 
pageRef);
             }
         }, true);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
index 81df00e..a2fa48f 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
@@ -67,7 +67,7 @@ public class RelationshipTypesPanel extends 
AbstractTypesPanel<RelationshipTypeT
             private static final long serialVersionUID = -6388405037134399367L;
 
             @Override
-            public ModalPanel<RelationshipTypeTO> build(final int index, final 
boolean edit) {
+            public ModalPanel<RelationshipTypeTO> build(final int index, final 
AjaxWizard.Mode mode) {
                 final RelationshipTypeTO modelObject = newModelObject();
                 return new RelationshipTypeModalPanel(modal, modelObject, 
pageRef) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
index b06318d..dd0c3aa 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
@@ -95,7 +95,7 @@ public class SchemaTypePanel extends 
AbstractTypesPanel<AbstractSchemaTO, Schema
                 private static final long serialVersionUID = 
-6388405037134399367L;
 
                 @Override
-                public ModalPanel<AbstractSchemaTO> build(final int index, 
final boolean edit) {
+                public ModalPanel<AbstractSchemaTO> build(final int index, 
final AjaxWizard.Mode mode) {
                     final AbstractSchemaTO modelObject = newModelObject();
                     return new SchemaModalPanel(modal, modelObject, pageRef) {
 
@@ -223,7 +223,7 @@ public class SchemaTypePanel extends 
AbstractTypesPanel<AbstractSchemaTO, Schema
                                     target.add(container);
                                 } catch (Exception e) {
                                     LOG.error("While deleting {}", 
model.getObject(), e);
-                                    error(StringUtils.isBlank(e.getMessage()) 
+                                    error(StringUtils.isBlank(e.getMessage())
                                             ? e.getClass().getName() : 
e.getMessage());
                                 }
                                 
SyncopeConsoleSession.get().getNotificationPanel().refresh(target);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
index bac8481..beb15d4 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
@@ -76,7 +76,7 @@ public class SecurityQuestionsPanel extends 
AbstractSearchResultPanel<
             private static final long serialVersionUID = -6388405037134399367L;
 
             @Override
-            public ModalPanel<SecurityQuestionTO> build(final int index, final 
boolean edit) {
+            public ModalPanel<SecurityQuestionTO> build(final int index, final 
AjaxWizard.Mode mode) {
                 final SecurityQuestionTO modelObject = newModelObject();
                 return new SecurityQuestionsModalPanel(modal, modelObject, 
pageRef);
             }
@@ -223,8 +223,8 @@ public class SecurityQuestionsPanel extends 
AbstractSearchResultPanel<
 
         @Override
         public Iterator<SecurityQuestionTO> iterator(final long first, final 
long count) {
-            final List<SecurityQuestionTO> list =
-                    
SyncopeConsoleSession.get().getService(SecurityQuestionService.class).list();
+            final List<SecurityQuestionTO> list = 
SyncopeConsoleSession.get().getService(SecurityQuestionService.class).
+                    list();
             Collections.sort(list, comparator);
             return list.subList((int) first, (int) first + (int) 
count).iterator();
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/todos/Approval.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/todos/Approval.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/Approval.java
new file mode 100644
index 0000000..616e49c
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/Approval.java
@@ -0,0 +1,208 @@
+/*
+ * 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.todos;
+
+import static org.apache.wicket.Component.ENABLE;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.syncope.client.console.commons.MapChoiceRenderer;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.DateTimeFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class Approval extends Panel {
+
+    private static final long serialVersionUID = -8847854414429745216L;
+
+    protected static final Logger LOG = 
LoggerFactory.getLogger(Approval.class);
+
+    public Approval(final PageReference pageRef, final WorkflowFormTO formTO) {
+        super(MultilevelPanel.FIRST_LEVEL_ID);
+
+        IModel<List<WorkflowFormPropertyTO>> formProps = new 
LoadableDetachableModel<List<WorkflowFormPropertyTO>>() {
+
+            private static final long serialVersionUID = 3169142472626817508L;
+
+            @Override
+            protected List<WorkflowFormPropertyTO> load() {
+                return formTO.getProperties();
+            }
+        };
+
+        final ListView<WorkflowFormPropertyTO> propView = new 
ListView<WorkflowFormPropertyTO>("propView", formProps) {
+
+            private static final long serialVersionUID = 9101744072914090143L;
+
+            @Override
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            protected void populateItem(final ListItem<WorkflowFormPropertyTO> 
item) {
+                final WorkflowFormPropertyTO prop = item.getModelObject();
+
+                String label = StringUtils.isBlank(prop.getName()) ? 
prop.getId() : prop.getName();
+
+                FieldPanel field;
+                switch (prop.getType()) {
+                    case Boolean:
+                        field = new AjaxDropDownChoicePanel("value", label, 
new PropertyModel<String>(prop, "value") {
+
+                            private static final long serialVersionUID = 
-3743432456095828573L;
+
+                            @Override
+                            public String getObject() {
+                                return StringUtils.isBlank(prop.getValue())
+                                        ? null
+                                        : prop.getValue().equals("true") ? 
"Yes" : "No";
+                            }
+
+                            @Override
+                            public void setObject(final String object) {
+                                
prop.setValue(String.valueOf(object.equalsIgnoreCase("yes")));
+                            }
+
+                        }, false).setChoices(Arrays.asList(new String[] { 
"Yes", "No" }));
+                        break;
+
+                    case Date:
+                        final FastDateFormat formatter = 
FastDateFormat.getInstance(prop.getDatePattern());
+                        field = new DateTimeFieldPanel("value", label, new 
PropertyModel<Date>(prop, "value") {
+
+                            private static final long serialVersionUID = 
-3743432456095828573L;
+
+                            @Override
+                            public Date getObject() {
+                                try {
+                                    if (StringUtils.isBlank(prop.getValue())) {
+                                        return null;
+                                    } else {
+                                        return 
formatter.parse(prop.getValue());
+                                    }
+                                } catch (ParseException e) {
+                                    LOG.error("Unparsable date: {}", 
prop.getValue(), e);
+                                    return null;
+                                }
+                            }
+
+                            @Override
+                            public void setObject(final Date object) {
+                                prop.setValue(formatter.format(object));
+                            }
+
+                        }, prop.getDatePattern());
+                        break;
+
+                    case Enum:
+                        MapChoiceRenderer<String, String> enumCR = new 
MapChoiceRenderer<>(prop.getEnumValues());
+                        final Map<String, String> map = 
MapUtils.invertMap(prop.getEnumValues());
+
+                        field = new AjaxDropDownChoicePanel(
+                                "value", label, new 
PropertyModel<String>(prop, "value"), false).
+                                setChoiceRenderer(enumCR).setChoices(new 
Model<ArrayList<String>>() {
+
+                            private static final long serialVersionUID = 
-858521070366432018L;
+
+                            @Override
+                            public ArrayList<String> getObject() {
+                                return new 
ArrayList<String>(prop.getEnumValues().keySet());
+                            }
+                        });
+                        break;
+
+                    case Long:
+                        field = new 
AjaxSpinnerFieldPanel.Builder<Long>().build(
+                                "value",
+                                label,
+                                Long.class,
+                                new PropertyModel<Long>(prop, "value") {
+
+                            private static final long serialVersionUID = 
-7688359318035249200L;
+
+                            @Override
+                            public Long getObject() {
+                                return StringUtils.isBlank(prop.getValue())
+                                        ? null
+                                        : NumberUtils.toLong(prop.getValue());
+                            }
+
+                            @Override
+                            public void setObject(final Long object) {
+                                prop.setValue(String.valueOf(object));
+                            }
+                        });
+                        break;
+
+                    case String:
+                    default:
+                        field = new AjaxTextFieldPanel("value", label, new 
PropertyModel<String>(prop, "value"), false);
+                        break;
+                }
+
+                field.setReadOnly(!prop.isWritable());
+                if (prop.isRequired()) {
+                    field.addRequiredLabel();
+                }
+
+                item.add(field);
+            }
+        };
+
+        final AjaxLink<String> userDetails = new 
AjaxLink<String>("userDetails") {
+
+            private static final long serialVersionUID = -4804368561204623354L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                viewDetails(formTO, target);
+            }
+        };
+        MetaDataRoleAuthorizationStrategy.authorize(userDetails, ENABLE, 
StandardEntitlement.USER_READ);
+
+        add(propView);
+        add(userDetails);
+    }
+
+    protected abstract void viewDetails(final WorkflowFormTO formTO, final 
AjaxRequestTarget target);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalDetails.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalDetails.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalDetails.java
new file mode 100644
index 0000000..20613d9
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalDetails.java
@@ -0,0 +1,48 @@
+/*
+ * 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.todos;
+
+import java.util.List;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.console.wizards.any.AnyHandler;
+import org.apache.syncope.client.console.wizards.any.UserWizardBuilder;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.wicket.PageReference;
+
+public class ApprovalDetails extends MultilevelPanel.SecondLevel {
+
+    private static final long serialVersionUID = -8847854414429745216L;
+
+    public ApprovalDetails(final PageReference pageRef, final WorkflowFormTO 
formTO) {
+        super(MultilevelPanel.SECOND_LEVEL_ID);
+
+        final UserTO userTO = new UserRestClient().read(formTO.getUserKey());
+        final List<String> anyTypeClasses = new 
AnyTypeRestClient().get(AnyTypeKind.USER.name()).getClasses();
+
+        final AjaxWizard<AnyHandler<UserTO>> wizard
+                = new UserWizardBuilder("wizard", userTO, anyTypeClasses, 
pageRef).build(AjaxWizard.Mode.READONLY);
+
+        add(wizard);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalModal.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalModal.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalModal.java
new file mode 100644
index 0000000..a4fa1b5
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/ApprovalModal.java
@@ -0,0 +1,83 @@
+/*
+ * 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.todos;
+
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.UserWorkflowRestClient;
+import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+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 ApprovalModal extends Panel implements ModalPanel<WorkflowFormTO> 
{
+
+    private static final long serialVersionUID = -8847854414429745216L;
+
+    private final BaseModal<?> modal;
+
+    private final WorkflowFormTO formTO;
+
+    public ApprovalModal(final BaseModal<?> modal, final PageReference 
pageRef, final WorkflowFormTO formTO) {
+        super(BaseModal.CONTENT_ID);
+        this.modal = modal;
+        this.formTO = formTO;
+
+        final MultilevelPanel mlp = new MultilevelPanel("approval");
+        add(mlp);
+
+        mlp.setFirstLevel(new Approval(pageRef, formTO) {
+
+            private static final long serialVersionUID = -2195387360323687302L;
+
+            @Override
+            protected void viewDetails(final WorkflowFormTO formTO, final 
AjaxRequestTarget target) {
+                mlp.next(getString("approval.details"), new 
ApprovalDetails(pageRef, formTO), target);
+            }
+        });
+    }
+
+    @Override
+    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+        try {
+            new UserWorkflowRestClient().submitForm(formTO);
+            this.modal.show(false);
+            this.modal.close(target);
+            
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+        } catch (SyncopeClientException e) {
+            SyncopeConsoleSession.get().error(getString(Constants.ERROR) + ": 
" + e.getMessage());
+        }
+        SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+    }
+
+    @Override
+    public void onError(final AjaxRequestTarget target, final Form<?> form) {
+        SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+    }
+
+    @Override
+    public WorkflowFormTO getItem() {
+        return this.formTO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/todos/TODOSearchResultPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/todos/TODOSearchResultPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/TODOSearchResultPanel.java
new file mode 100644
index 0000000..fa14859
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/todos/TODOSearchResultPanel.java
@@ -0,0 +1,217 @@
+/*
+ * 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.todos;
+
+import static org.apache.wicket.Component.ENABLE;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+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.SearchableDataProvider;
+import 
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.AbstractSearchResultPanel;
+import org.apache.syncope.client.console.rest.UserWorkflowRestClient;
+import 
org.apache.syncope.client.console.todos.TODOSearchResultPanel.ApprovalProvider;
+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.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.WorkflowFormTO;
+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.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+
+public class TODOSearchResultPanel
+        extends AbstractSearchResultPanel<WorkflowFormTO, WorkflowFormTO, 
ApprovalProvider, UserWorkflowRestClient> {
+
+    private static final long serialVersionUID = -7122136682275797903L;
+
+    public TODOSearchResultPanel(final String id, final PageReference 
pageReference) {
+        super(id, pageReference, false);
+        disableCheckBoxes();
+
+        setFooterVisibility(true);
+        modal.addSumbitButton();
+        modal.size(Modal.Size.Large);
+
+        restClient = new UserWorkflowRestClient();
+
+        initResultTable();
+
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, ENABLE, 
StandardEntitlement.WORKFLOW_FORM_SUBMIT);
+    }
+
+    @Override
+    protected List<IColumn<WorkflowFormTO, String>> getColumns() {
+
+        List<IColumn<WorkflowFormTO, String>> columns = new 
ArrayList<IColumn<WorkflowFormTO, String>>();
+        columns.add(new PropertyColumn<WorkflowFormTO, String>(
+                new ResourceModel("taskId"), "taskId", "taskId"));
+        columns.add(new PropertyColumn<WorkflowFormTO, String>(
+                new ResourceModel("key"), "key", "key"));
+        columns.add(new PropertyColumn<WorkflowFormTO, String>(
+                new ResourceModel("description"), "description", 
"description"));
+        columns.add(new DatePropertyColumn<WorkflowFormTO>(
+                new ResourceModel("createTime"), "createTime", "createTime"));
+        columns.add(new DatePropertyColumn<WorkflowFormTO>(
+                new ResourceModel("dueDate"), "dueDate", "dueDate"));
+        columns.add(new PropertyColumn<WorkflowFormTO, String>(new 
ResourceModel("owner"), "owner", "owner"));
+        columns.add(new ActionColumn<WorkflowFormTO, String>(new 
ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = -3503023501954863133L;
+
+            @Override
+            public ActionLinksPanel<WorkflowFormTO> getActions(
+                    final String componentId, final IModel<WorkflowFormTO> 
model) {
+                final ActionLinksPanel.Builder<WorkflowFormTO> panel = 
ActionLinksPanel.builder();
+
+                panel.add(new ActionLink<WorkflowFormTO>() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final 
WorkflowFormTO ignore) {
+                        try {
+                            
restClient.claimForm(model.getObject().getTaskId());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scee) {
+                            error(getString(Constants.ERROR) + ": " + 
scee.getMessage());
+                        }
+                        
SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                        target.add(container);
+                    }
+                }, ActionLink.ActionType.CLAIM, 
StandardEntitlement.WORKFLOW_FORM_CLAIM);
+
+                panel.add(new ActionLink<WorkflowFormTO>() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final 
WorkflowFormTO ignore) {
+                        final IModel<WorkflowFormTO> formModel = new 
CompoundPropertyModel<>(model.getObject());
+                        modal.setFormModel(formModel);
+
+                        target.add(modal.setContent(new ApprovalModal(modal, 
pageRef, model.getObject())));
+                        modal.header(new Model<>(getString("approval.edit", 
new Model<>(model.getObject()))));
+
+                        modal.show(true);
+                    }
+
+                    @Override
+                    protected boolean statusCondition(final WorkflowFormTO 
modelObject) {
+                        return 
SyncopeConsoleSession.get().getSelfTO().getUsername().
+                                equals(model.getObject().getOwner());
+                    }
+
+                }, ActionLink.ActionType.EDIT, 
StandardEntitlement.WORKFLOW_FORM_READ);
+
+                return panel.build(componentId);
+            }
+
+            @Override
+            public ActionLinksPanel<WorkflowFormTO> getHeader(final String 
componentId) {
+                final ActionLinksPanel.Builder<WorkflowFormTO> panel = 
ActionLinksPanel.builder();
+
+                return panel.add(new ActionLink<WorkflowFormTO>() {
+
+                    private static final long serialVersionUID = 
-7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final 
WorkflowFormTO ignore) {
+                        if (target != null) {
+                            target.add(container);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, 
StandardEntitlement.WORKFLOW_FORM_LIST).build(componentId);
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected ApprovalProvider dataProvider() {
+        return new ApprovalProvider(rows);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_WORKFLOW_FORM_PAGINATOR_ROWS;
+    }
+
+    public static class ApprovalProvider extends 
SearchableDataProvider<WorkflowFormTO> {
+
+        private static final long serialVersionUID = -2311716167583335852L;
+
+        private final SortableDataProviderComparator<WorkflowFormTO> 
comparator;
+
+        private final UserWorkflowRestClient restClient = new 
UserWorkflowRestClient();
+
+        public ApprovalProvider(final int paginatorRows) {
+            super(paginatorRows);
+            setSort("createTime", SortOrder.DESCENDING);
+            this.comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<WorkflowFormTO> iterator(final long first, final long 
count) {
+            final List<WorkflowFormTO> list = restClient.getForms();
+            Collections.sort(list, comparator);
+            return list.subList((int) first, (int) first + (int) 
count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return restClient.getForms().size();
+        }
+
+        @Override
+        public IModel<WorkflowFormTO> model(final WorkflowFormTO 
configuration) {
+            return new AbstractReadOnlyModel<WorkflowFormTO>() {
+
+                private static final long serialVersionUID = 
-2566070996511906708L;
+
+                @Override
+                public WorkflowFormTO getObject() {
+                    return configuration;
+                }
+            };
+        }
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        return Collections.<ActionLink.ActionType>emptyList();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/widgets/TODOsWidget.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/widgets/TODOsWidget.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/widgets/TODOsWidget.java
new file mode 100644
index 0000000..8b50826
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/widgets/TODOsWidget.java
@@ -0,0 +1,283 @@
+/*
+ * 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.widgets;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.pages.TODOs;
+import org.apache.syncope.client.console.rest.UserWorkflowRestClient;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.Application;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.protocol.ws.api.WebSocketBehavior;
+import org.apache.wicket.protocol.ws.api.WebSocketPushBroadcaster;
+import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload;
+import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
+import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage;
+import org.apache.wicket.protocol.ws.api.registry.IKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TODOsWidget extends Panel {
+
+    private static final long serialVersionUID = 7667120094526529934L;
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(TODOsWidget.class);
+
+    private static final int UPDATE_PERIOD = 30;
+
+    private final Label linkTODOsNumber;
+
+    private final Label headerTODOsNumber;
+
+    private final WebMarkupContainer lastTODOsList;
+
+    private final ListView<WorkflowFormTO> lastFive;
+
+    private List<WorkflowFormTO> lastTODOs;
+
+    public TODOsWidget(final String id, final PageReference pageRef) {
+        super(id);
+        setOutputMarkupId(true);
+
+        LoadableDetachableModel<List<WorkflowFormTO>> model = new 
LoadableDetachableModel<List<WorkflowFormTO>>() {
+
+            private static final long serialVersionUID = 7474274077691068779L;
+
+            @Override
+            protected List<WorkflowFormTO> load() {
+                return TODOsWidget.this.lastTODOs.subList(
+                        0, TODOsWidget.this.lastTODOs.size() < 6 ? 
TODOsWidget.this.lastTODOs.size() : 5);
+            }
+        };
+
+        lastTODOs = getLastTODOs();
+        Collections.sort(lastTODOs, new WorkflowFormComparator());
+
+        linkTODOsNumber = new Label("todos", lastTODOs.size()) {
+
+            private static final long serialVersionUID = 4755868673082976208L;
+
+            @Override
+            protected void onComponentTag(final ComponentTag tag) {
+                super.onComponentTag(tag);
+                if (Integer.valueOf(getDefaultModelObject().toString()) > 0) {
+                    tag.put("class", "label label-danger");
+                } else {
+                    tag.put("class", "label label-info");
+                }
+            }
+
+        };
+        add(linkTODOsNumber.setOutputMarkupId(true));
+
+        headerTODOsNumber = new Label("number", lastTODOs.size());
+        headerTODOsNumber.setOutputMarkupId(true);
+        add(headerTODOsNumber);
+
+        lastTODOsList = new WebMarkupContainer("lastTODOsList");
+        lastTODOsList.setOutputMarkupId(true);
+        add(lastTODOsList);
+
+        lastFive = new ListView<WorkflowFormTO>("lastTODOs", model) {
+
+            private static final long serialVersionUID = 4949588177564901031L;
+
+            @Override
+            protected void populateItem(final ListItem<WorkflowFormTO> item) {
+                final WorkflowFormTO modelObject = item.getModelObject();
+
+                final AjaxLink<String> todo = new AjaxLink<String>("todo") {
+
+                    private static final long serialVersionUID = 
7021195294339489084L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        // do nothing
+                    }
+
+                    @Override
+                    protected void onComponentTag(final ComponentTag tag) {
+                        super.onComponentTag(tag);
+                        if 
(StringUtils.isNotBlank(modelObject.getDescription())) {
+                            tag.put("title", 
modelObject.getDescription().trim());
+                        }
+                    }
+                };
+
+                item.add(todo);
+
+                todo.add(new Label("key", new 
ResourceModel(modelObject.getKey(), modelObject.getKey())).
+                        setRenderBodyOnly(true));
+
+                todo.add(new Label("owner", modelObject.getOwner()));
+
+                todo.add(new Label("createTime",
+                        
SyncopeConsoleSession.get().getDateFormat().format(modelObject.getCreateTime())).
+                        setRenderBodyOnly(true));
+
+                WebMarkupContainer dueDateContainer = new 
WebMarkupContainer("dueDateContainer");
+                dueDateContainer.setOutputMarkupId(true);
+                todo.add(dueDateContainer);
+
+                if (modelObject.getDueDate() == null) {
+                    dueDateContainer.add(new Label("dueDate"));
+                    dueDateContainer.setVisible(false);
+                } else {
+                    dueDateContainer.add(new Label("dueDate",
+                            
SyncopeConsoleSession.get().getDateFormat().format(modelObject.getDueDate())).
+                            setRenderBodyOnly(true));
+                }
+
+            }
+        };
+        
lastTODOsList.add(lastFive.setReuseItems(false).setOutputMarkupId(true));
+
+        final BookmarkablePageLink<Object> todos = 
BookmarkablePageLinkBuilder.build("todosLink", TODOs.class);
+        add(todos);
+
+        MetaDataRoleAuthorizationStrategy.authorize(todos, WebPage.ENABLE, 
StandardEntitlement.WORKFLOW_FORM_LIST);
+
+        add(new WebSocketBehavior() {
+
+            private static final long serialVersionUID = 7944352891541344021L;
+
+            @Override
+            protected void onConnect(final ConnectedMessage message) {
+                super.onConnect(message);
+                SyncopeConsoleSession.get().scheduleAtFixedRate(
+                        new TODOInfoUpdater(message), 0, UPDATE_PERIOD, 
TimeUnit.SECONDS);
+            }
+        });
+    }
+
+    private List<WorkflowFormTO> getLastTODOs() {
+        if 
(SyncopeConsoleSession.get().owns(StandardEntitlement.WORKFLOW_FORM_LIST)) {
+            return new UserWorkflowRestClient().getForms();
+        } else {
+            return Collections.<WorkflowFormTO>emptyList();
+        }
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof WebSocketPushPayload) {
+            WebSocketPushPayload wsEvent = (WebSocketPushPayload) 
event.getPayload();
+            if (wsEvent.getMessage() instanceof UpdateMessage) {
+
+                
TODOsWidget.this.linkTODOsNumber.setDefaultModelObject(TODOsWidget.this.lastTODOs.size());
+                wsEvent.getHandler().add(TODOsWidget.this.linkTODOsNumber);
+
+                
TODOsWidget.this.headerTODOsNumber.setDefaultModelObject(TODOsWidget.this.lastTODOs.size());
+                wsEvent.getHandler().add(TODOsWidget.this.headerTODOsNumber);
+
+                TODOsWidget.this.lastFive.removeAll();
+                wsEvent.getHandler().add(TODOsWidget.this.lastTODOsList);
+            }
+        } else {
+            super.onEvent(event);
+        }
+    }
+
+    protected final class TODOInfoUpdater implements Runnable {
+
+        private final Application application;
+
+        private final SyncopeConsoleSession session;
+
+        private final IKey key;
+
+        public TODOInfoUpdater(final ConnectedMessage message) {
+            this.application = message.getApplication();
+            this.session = SyncopeConsoleSession.get();
+            this.key = message.getKey();
+        }
+
+        @Override
+        public void run() {
+            try {
+                ThreadContext.setApplication(application);
+                ThreadContext.setSession(session);
+
+                final List<WorkflowFormTO> actual = getLastTODOs();
+                Collections.sort(actual, new WorkflowFormComparator());
+
+                if (!actual.equals(lastTODOs)) {
+                    LOG.debug("Update TODOs");
+
+                    lastTODOs.clear();
+                    lastTODOs = actual;
+
+                    WebSocketSettings settings = 
WebSocketSettings.Holder.get(application);
+                    WebSocketPushBroadcaster broadcaster
+                            = new 
WebSocketPushBroadcaster(settings.getConnectionRegistry());
+                    broadcaster.broadcast(new ConnectedMessage(application, 
session.getId(), key), new UpdateMessage());
+                }
+            } catch (Throwable t) {
+                LOG.error("Unexpected error while checking for updated Job 
info", t);
+            } finally {
+                ThreadContext.detach();
+            }
+        }
+    }
+
+    private static class UpdateMessage implements IWebSocketPushMessage, 
Serializable {
+
+        private static final long serialVersionUID = -824793424112532838L;
+
+    }
+
+    private class WorkflowFormComparator implements Comparator<WorkflowFormTO> 
{
+
+        @Override
+        public int compare(final WorkflowFormTO o1, final WorkflowFormTO o2) {
+            if (o1 == null) {
+                return o2 == null ? 0 : 1;
+            } else if (o2 == null) {
+                return -1;
+            } else {
+                // inverse
+                return o2.getCreateTime().compareTo(o1.getCreateTime());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractModalPanelBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractModalPanelBuilder.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractModalPanelBuilder.java
index 8acea1d..b4d7a69 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractModalPanelBuilder.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractModalPanelBuilder.java
@@ -48,7 +48,7 @@ public abstract class AbstractModalPanelBuilder<T extends 
Serializable> implemen
         this.pageRef = pageRef;
     }
 
-    public abstract ModalPanel<T> build(final int index, final boolean edit);
+    public abstract ModalPanel<T> build(final int index, final AjaxWizard.Mode 
mode);
 
     protected void onCancelInternal(final T modelObject) {
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java
index 59bb335..a03ccf5 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.wizards;
 
 import java.io.Serializable;
+import java.util.Iterator;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.ModalPanel;
@@ -26,8 +27,10 @@ import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.wizard.IWizardModel;
+import org.apache.wicket.extensions.wizard.IWizardStep;
 import org.apache.wicket.extensions.wizard.Wizard;
 import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.request.cycle.RequestCycle;
@@ -38,11 +41,18 @@ public abstract class AjaxWizard<T extends Serializable> 
extends Wizard implemen
 
     private static final long serialVersionUID = -1272120742876833520L;
 
+    public enum Mode {
+        CREATE,
+        EDIT,
+        READONLY;
+
+    }
+
     protected static final Logger LOG = 
LoggerFactory.getLogger(AjaxWizard.class);
 
     private T item;
 
-    private final boolean edit;
+    private final Mode mode;
 
     /**
      * Construct.
@@ -50,12 +60,17 @@ public abstract class AjaxWizard<T extends Serializable> 
extends Wizard implemen
      * @param id The component id.
      * @param item model object.
      * @param model wizard model
-     * @param edit <tt>true</tt> if edit mode.
+     * @param mode <tt>true</tt> if edit mode.
      */
-    public AjaxWizard(final String id, final T item, final WizardModel model, 
final boolean edit) {
+    public AjaxWizard(final String id, final T item, final WizardModel model, 
final Mode mode) {
         super(id);
         this.item = item;
-        this.edit = edit;
+        this.mode = mode;
+
+        if (mode == Mode.READONLY) {
+            model.setCancelVisible(false);
+        }
+
         setOutputMarkupId(true);
         setDefaultModel(new CompoundPropertyModel<>(this));
         init(model);
@@ -65,11 +80,18 @@ public abstract class AjaxWizard<T extends Serializable> 
extends Wizard implemen
     protected void init(final IWizardModel wizardModel) {
         super.init(wizardModel);
         getForm().remove(FEEDBACK_ID);
+
+        if (mode == Mode.READONLY) {
+            final Iterator<IWizardStep> iter = wizardModel.stepIterator();
+            while (iter.hasNext()) {
+                WizardStep.class.cast(iter.next()).setEnabled(false);
+            }
+        }
     }
 
     @Override
     protected Component newButtonBar(final String id) {
-        return new AjaxWizardMgtButtonBar(id, this, edit);
+        return new AjaxWizardMgtButtonBar<>(id, this, mode);
     }
 
     protected abstract void onCancelInternal();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java
index c183910..3e79047 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java
@@ -38,19 +38,19 @@ public abstract class AjaxWizardBuilder<T extends 
Serializable> extends Abstract
     }
 
     @Override
-    public AjaxWizard<T> build(final int index, final boolean edit) {
-        final AjaxWizard<T> wizard = build(edit);
+    public AjaxWizard<T> build(final int index, final AjaxWizard.Mode mode) {
+        final AjaxWizard<T> wizard = build(mode);
         for (int i = 1; i < index; i++) {
             wizard.getWizardModel().next();
         }
         return wizard;
     }
 
-    public AjaxWizard<T> build(final boolean edit) {
+    public AjaxWizard<T> build(final AjaxWizard.Mode mode) {
         // ge the specified item if available
         final T modelObject = newModelObject();
 
-        return new AjaxWizard<T>(id, modelObject, buildModelSteps(modelObject, 
new WizardModel()), edit) {
+        return new AjaxWizard<T>(id, modelObject, buildModelSteps(modelObject, 
new WizardModel()), mode) {
 
             private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.java
index e183721..6a58e46 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards;
 
+import java.io.Serializable;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
@@ -32,19 +33,17 @@ import org.apache.wicket.extensions.wizard.WizardButton;
 import org.apache.wicket.extensions.wizard.WizardButtonBar;
 import org.apache.wicket.markup.ComponentTag;
 
-public class AjaxWizardMgtButtonBar extends WizardButtonBar {
+public class AjaxWizardMgtButtonBar<T extends Serializable> extends 
WizardButtonBar {
 
     private static final long serialVersionUID = 7453943437344127136L;
 
-    private final boolean edit;
+    private final AjaxWizard.Mode mode;
 
-    private final AjaxWizard wizard;
-
-    public AjaxWizardMgtButtonBar(final String id, final AjaxWizard wizard, 
final boolean edit) {
+    public AjaxWizardMgtButtonBar(final String id, final AjaxWizard<T> wizard, 
final AjaxWizard.Mode mode) {
         super(id, wizard);
-        this.edit = edit;
-        this.wizard = wizard;
+        this.mode = mode;
         wizard.setOutputMarkupId(true);
+        wizard.getWizardModel().isCancelVisible();
     }
 
     @Override
@@ -103,6 +102,7 @@ public class AjaxWizardMgtButtonBar extends WizardButtonBar 
{
     protected void updateAjaxAttributes(final AjaxRequestAttributes 
attributes) {
     }
 
+    @Override
     protected FinishButton newFinishButton(final String id, final IWizard 
wizard) {
         return new FinishButton(id, wizard) {
 
@@ -110,11 +110,24 @@ public class AjaxWizardMgtButtonBar extends 
WizardButtonBar {
 
             @Override
             public final boolean isEnabled() {
-                if (edit) {
-                    return true;
-                } else {
-                    final IWizardStep activeStep = 
getWizardModel().getActiveStep();
-                    return (activeStep != null) && 
getWizardModel().isLastStep(activeStep) && super.isEnabled();
+                switch (mode) {
+                    case EDIT:
+                        return true;
+                    case READONLY:
+                        return false;
+                    default:
+                        final IWizardStep activeStep = 
getWizardModel().getActiveStep();
+                        return (activeStep != null) && 
getWizardModel().isLastStep(activeStep) && super.isEnabled();
+                }
+            }
+
+            @Override
+            public boolean isVisible() {
+                switch (mode) {
+                    case READONLY:
+                        return false;
+                    default:
+                        return true;
                 }
             }
         };

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
index 34dc4a3..dbb99bc 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
@@ -83,7 +83,7 @@ public abstract class WizardMgtPanel<T extends Serializable> 
extends Panel imple
      * Modal window.
      */
     protected final BaseModal<T> altDefaultModal = new 
BaseModal<>("alternativeDefaultModal");
-    
+
     protected final BaseModal<T> displayAttributeModal = new 
BaseModal<>("displayAttributeModal");
 
     protected WizardMgtPanel(final String id) {
@@ -134,7 +134,8 @@ public abstract class WizardMgtPanel<T extends 
Serializable> extends Panel imple
                 newItemPanelBuilder.setItem(item);
 
                 final ModalPanel<T> modalPanel = newItemPanelBuilder.build(
-                        ((AjaxWizard.NewItemActionEvent<T>) 
newItemEvent).getIndex(), item != null);
+                        ((AjaxWizard.NewItemActionEvent<T>) 
newItemEvent).getIndex(),
+                        item != null ? AjaxWizard.Mode.EDIT : 
AjaxWizard.Mode.CREATE);
 
                 if (wizardInModal) {
                     final IModel<T> model = new CompoundPropertyModel<>(item);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
index 1a2f6d0..673691d 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
@@ -215,7 +215,7 @@ public class PlainAttrs extends AbstractAttrs {
                 if (required) {
                     panel.addRequiredLabel();
                 }
-                
+
                 break;
             case Enum:
                 panel = new AjaxDropDownChoicePanel<>("panel", 
schemaTO.getKey(), new Model<String>(), false);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css 
b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
index 9972ec9..b2d692d 100644
--- 
a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
+++ 
b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
@@ -642,4 +642,8 @@ div#parametersForm{
 }
 /**
 END - Parameters Details
-*/
\ No newline at end of file
+*/
+
+li.todoitem a {
+  cursor: default;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
index 8de6319..daf1a2b 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
@@ -33,6 +33,7 @@ under the License.
     <link href="css/syncopeConsole.css" rel="stylesheet" type="text/css"/>
 
     <script type="text/javascript" 
src="webjars/bootbox/${bootbox.version}/bootbox.js"></script>
+    <script type="text/javascript" 
src="webjars/jQuery-slimScroll/${jquery-slimscroll.version}/jquery.slimscroll.min.js"></script>
   </head>
   <body class="skin-green-light hold-transition sidebar-mini" wicket:id="body">
 
@@ -52,16 +53,8 @@ under the License.
           <div class="navbar-custom-menu">
             <ul class="nav navbar-nav">
 
-              <li class="dropdown tasks-menu" wicket:id="todosContainer">
-                <a href="#" class="dropdown-toggle" data-toggle="dropdown" 
aria-expanded="false">
-                  <i class="fa fa-flag-o"></i>
-                  <span class="label label-danger" wicket:id="todos"></span>
-                </a>
-                <ul class="dropdown-menu">
-                  <li class="footer">
-                    <a href="#">View all TODOs</a>
-                  </li>
-                </ul>
+              <li class="dropdown tasks-menu">
+                <span wicket:id="todosWidget" />
               </li>
 
               <li class="dropdown user user-menu">

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.properties
index 47f583c..9a12bae 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.properties
@@ -17,3 +17,4 @@
 home=Home
 version=VERSION
 domain=Domain
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_it.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_it.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_it.properties
index ca4a19e..04f4225 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_it.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_it.properties
@@ -17,3 +17,4 @@
 home=Home
 version=VERSIONE
 domain=Dom\u00ednio
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_pt_BR.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_pt_BR.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_pt_BR.properties
index 675cff5..b5bdaf3 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_pt_BR.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage_pt_BR.properties
@@ -17,3 +17,4 @@
 home=In\u00edcio
 version=VERS\u00c3O
 domain=Domain
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/Realms.html
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Realms.html
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Realms.html
index e2c5948..3588eb5 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Realms.html
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Realms.html
@@ -17,13 +17,6 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml"; 
xmlns:wicket="http://wicket.apache.org";>
-  <wicket:head>
-    <script type="text/javascript">
-      $(document).ready(function () {
-        $("#pageTitleInBradcrumb").append($("#pageTitle").text());
-      });
-    </script>
-  </wicket:head>
   <wicket:extend>
     <script lang="text/javascript">
 
@@ -31,10 +24,9 @@ under the License.
     <section class="content-header">
       <h1>&nbsp;</h1>
       <ol class="breadcrumb">
-        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> 
<wicket:message key="dashboard"/></a></li>
-        <li class="active" id="pageTitleInBradcrumb"/>
+        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> 
<wicket:message key="dashboard"></wicket:message></a></li>
+        <li class="active" id="pageTitleInBradcrumb"><wicket:message 
key="realms"></wicket:message></li>
       </ol>
-      <div id="pageTitle" style="visibility: hidden;"><wicket:message 
key='realms'/></div>
     </section>
 
     <section class="content" wicket:id="content">

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.html
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.html
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.html
new file mode 100644
index 0000000..34f9578
--- /dev/null
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.html
@@ -0,0 +1,35 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"; 
xmlns:wicket="http://wicket.apache.org";>
+  <wicket:extend>
+    <section class="content-header">
+      <h1>&nbsp;</h1>
+      <ol class="breadcrumb">
+        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> 
<wicket:message key="dashboard">[DASHBOARD]</wicket:message></a></li>
+        <li class="active">TODO</li>
+      </ol>
+    </section>
+
+    <section class="content" wicket:id="content">
+      <div class="box">
+        <div class="box-body" wicket:id="wfPanel"/>
+      </div>
+    </section>
+  </wicket:extend>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/9014cf28/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.properties
new file mode 100644
index 0000000..d6b8c87
--- /dev/null
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/pages/TODOs.properties
@@ -0,0 +1,32 @@
+# 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.
+taskId=Task
+key=Chiave
+description=Descrizione
+createTime=Data di creazione
+dueDate=Scadenza
+owner=Esecutore
+claim=Richiedi
+manage=Gestisci
+approvals=Approvazioni
+delete=Rimuovi
+type=Tipo
+username=Utente
+new_user=Nuovo utente
+creationDate = Data creazione
+claimDate = Data rivendicazione
+approval.edit=Approval

Reply via email to