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 2017/05/05 22:23:47 UTC

[06/11] syncope git commit: [SYNCOPE-1047] Replaces ActionLinksPanel with TogglePanel

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/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 8b10e8d..f09c0dc 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
@@ -34,14 +34,13 @@ import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.TaskRestClient;
-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.BooleanPropertyColumn;
 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.ActionLink.ActionType;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.types.TaskType;
@@ -61,7 +60,6 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
-import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 
 /**
@@ -74,8 +72,8 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
 
     private static final long serialVersionUID = 4984337552918213290L;
 
-    private static final String GROUP_MEMBER_PROVISION_TASKJOB =
-            "org.apache.syncope.core.provisioning.java.job.GroupMemberProvisionTaskJobDelegate";
+    private static final String GROUP_MEMBER_PROVISION_TASKJOB
+            = "org.apache.syncope.core.provisioning.java.job.GroupMemberProvisionTaskJobDelegate";
 
     protected final Class<T> reference;
 
@@ -131,7 +129,7 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
         final List<IColumn<T, String>> columns = new ArrayList<>();
 
         columns.add(new KeyPropertyColumn<T>(
-                new StringResourceModel("key", this), "key", "key"));
+                new StringResourceModel("key", this), "key"));
 
         columns.add(new PropertyColumn<T, String>(
                 new StringResourceModel("name", this), "name", "name"));
@@ -179,113 +177,110 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
         final List<IColumn<T, String>> columns = new ArrayList<>();
 
         columns.addAll(getFieldColumns());
+        return columns;
+    }
+
+    @Override
+    public ActionsPanel<T> getActions(final IModel<T> model) {
+        final ActionsPanel<T> panel = super.getActions(model);
+        final T taskTO = model.getObject();
 
-        columns.add(new ActionColumn<T, String>(new ResourceModel("actions")) {
+        panel.add(new ActionLink<T>() {
 
-            private static final long serialVersionUID = 2054811145491901166L;
+            private static final long serialVersionUID = -3722207913631435501L;
 
             @Override
-            public ActionLinksPanel<T> getActions(final String componentId, final IModel<T> model) {
-                final T taskTO = model.getObject();
+            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                SchedTaskDirectoryPanel.this.getTogglePanel().close(target);
+                viewTask(taskTO, target);
+            }
+        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ);
 
-                ActionLinksPanel.Builder<T> panel = ActionLinksPanel.<T>builder().add(new ActionLink<T>() {
+        panel.add(new ActionLink<T>() {
 
-                    private static final long serialVersionUID = -3722207913631435501L;
+            private static final long serialVersionUID = -3722207913631435501L;
 
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final T ignore) {
-                        viewTask(taskTO, target);
-                    }
-                }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).add(new ActionLink<T>() {
-
-                    private static final long serialVersionUID = -3722207913631435501L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final T ignore) {
-                        send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
-                                new AjaxWizard.EditItemActionEvent<>(
-                                        restClient.readSchedTask(reference, model.getObject().getKey()),
-                                        target).setResourceModel(
-                                        new StringResourceModel("inner.task.edit",
-                                                SchedTaskDirectoryPanel.this,
-                                                Model.of(Pair.of(
-                                                        ActionLink.ActionType.EDIT, model.getObject())))));
-                    }
-                }, ActionLink.ActionType.EDIT, StandardEntitlement.TASK_UPDATE,
-                        !GROUP_MEMBER_PROVISION_TASKJOB.equals(taskTO.getJobDelegateClassName())).
-                        add(new ActionLink<T>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final T ignore) {
-                                final T clone = SerializationUtils.clone(model.getObject());
-                                clone.setKey(null);
-                                send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
-                                        new AjaxWizard.EditItemActionEvent<>(clone, target).setResourceModel(
-                                                new StringResourceModel("inner.task.clone",
-                                                        SchedTaskDirectoryPanel.this,
-                                                        Model.of(Pair.of(
-                                                                ActionLink.ActionType.CLONE, model.getObject())))));
-                            }
-                        }, ActionLink.ActionType.CLONE, StandardEntitlement.TASK_CREATE).add(new ActionLink<T>() {
-
-                    private static final long serialVersionUID = -3722207913631435501L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final T ignore) {
-                        startAt.setExecutionDetail(
-                                model.getObject().getKey(), model.getObject().getName(), target);
-                        startAt.toggle(target, true);
-                    }
-                }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE,
-                        !GROUP_MEMBER_PROVISION_TASKJOB.equals(taskTO.getJobDelegateClassName())).
-                        add(new ActionLink<T>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final T ignore) {
-                                try {
-                                    restClient.delete(taskTO.getKey(), reference);
-                                    SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
-                                    target.add(container);
-                                } catch (SyncopeClientException e) {
-                                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
-                                            ? e.getClass().getName() : e.getMessage());
-                                    LOG.error("While deleting propagation task {}", taskTO.getKey(), e);
-                                }
-                                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-                            }
-                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE);
-
-                addFurtherActions(panel, model);
-
-                return panel.build(componentId, model.getObject());
+            @Override
+            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                SchedTaskDirectoryPanel.this.getTogglePanel().close(target);
+                send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
+                        new AjaxWizard.EditItemActionEvent<>(
+                                restClient.readSchedTask(reference, model.getObject().getKey()),
+                                target).setResourceModel(
+                                new StringResourceModel("inner.task.edit",
+                                        SchedTaskDirectoryPanel.this,
+                                        Model.of(Pair.of(
+                                                ActionLink.ActionType.EDIT, model.getObject())))));
             }
 
             @Override
-            public ActionLinksPanel<T> getHeader(final String componentId) {
-                final ActionLinksPanel.Builder<T> panel = ActionLinksPanel.builder();
+            protected boolean statusCondition(final T modelObject) {
+                return !GROUP_MEMBER_PROVISION_TASKJOB.equals(taskTO.getJobDelegateClassName());
+            }
+        }, ActionLink.ActionType.EDIT, StandardEntitlement.TASK_UPDATE);
 
-                return panel.add(new ActionLink<T>() {
+        panel.add(new ActionLink<T>() {
 
-                    private static final long serialVersionUID = -7978723352517770644L;
+            private static final long serialVersionUID = -3722207913631435501L;
 
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final T ignore) {
-                        if (target != null) {
-                            target.add(container);
-                        }
-                    }
-                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
+            @Override
+            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                SchedTaskDirectoryPanel.this.getTogglePanel().close(target);
+                final T clone = SerializationUtils.clone(model.getObject());
+                clone.setKey(null);
+                send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
+                        new AjaxWizard.EditItemActionEvent<>(clone, target).setResourceModel(
+                                new StringResourceModel("inner.task.clone",
+                                        SchedTaskDirectoryPanel.this,
+                                        Model.of(Pair.of(
+                                                ActionLink.ActionType.CLONE, model.getObject())))));
             }
-        });
+        }, ActionLink.ActionType.CLONE, StandardEntitlement.TASK_CREATE);
 
-        return columns;
+        panel.add(new ActionLink<T>() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                SchedTaskDirectoryPanel.this.getTogglePanel().close(target);
+                startAt.setExecutionDetail(
+                        model.getObject().getKey(), model.getObject().getName(), target);
+                startAt.toggle(target, true);
+            }
+
+            @Override
+            protected boolean statusCondition(final T modelObject) {
+                return !GROUP_MEMBER_PROVISION_TASKJOB.equals(taskTO.getJobDelegateClassName());
+            }
+        }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE);
+
+        addFurtherActions(panel, model);
+
+        panel.add(new ActionLink<T>() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                try {
+                    restClient.delete(taskTO.getKey(), reference);
+                    SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                    target.add(container);
+                    SchedTaskDirectoryPanel.this.getTogglePanel().close(target);
+                } catch (SyncopeClientException e) {
+                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            ? e.getClass().getName() : e.getMessage());
+                    LOG.error("While deleting propagation task {}", taskTO.getKey(), e);
+                }
+                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+            }
+        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE, true);
+
+        return panel;
     }
 
-    protected void addFurtherActions(final ActionLinksPanel.Builder<T> panel, final IModel<T> model) {
+    protected void addFurtherActions(final ActionsPanel<T> panel, final IModel<T> model) {
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
index b70214b..d2ba682 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
@@ -38,7 +38,7 @@ import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 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.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -92,8 +92,8 @@ public class Topology extends BasePage {
         }
     };
 
-    private final LoadableDetachableModel<Map<String, List<ConnInstanceTO>>> connModel =
-            new LoadableDetachableModel<Map<String, List<ConnInstanceTO>>>() {
+    private final LoadableDetachableModel<Map<String, List<ConnInstanceTO>>> connModel
+            = new LoadableDetachableModel<Map<String, List<ConnInstanceTO>>>() {
 
         private static final long serialVersionUID = 5275935387613157432L;
 
@@ -116,8 +116,8 @@ public class Topology extends BasePage {
         }
     };
 
-    private final LoadableDetachableModel<Pair<List<URI>, List<URI>>> csModel =
-            new LoadableDetachableModel<Pair<List<URI>, List<URI>>>() {
+    private final LoadableDetachableModel<Pair<List<URI>, List<URI>>> csModel
+            = new LoadableDetachableModel<Pair<List<URI>, List<URI>>>() {
 
         private static final long serialVersionUID = 5275935387613157433L;
 
@@ -167,8 +167,7 @@ public class Topology extends BasePage {
         // -----------------------------------------
         // Add Zoom panel
         // -----------------------------------------
-        final ActionLinksPanel.Builder<Serializable> zoomActionPanel = ActionLinksPanel.builder();
-        zoomActionPanel.setDisableIndicator(true);
+        final ActionsPanel<Serializable> zoomActionPanel = new ActionsPanel<>("zoom", null);
 
         zoomActionPanel.add(new ActionLink<Serializable>() {
 
@@ -178,7 +177,8 @@ public class Topology extends BasePage {
             public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
                 target.appendJavaScript("zoomIn($('#drawing')[0]);");
             }
-        }, ActionLink.ActionType.ZOOM_IN, StandardEntitlement.RESOURCE_LIST).add(new ActionLink<Serializable>() {
+        }, ActionLink.ActionType.ZOOM_IN, StandardEntitlement.RESOURCE_LIST).disableIndicator().hideLabel();
+        zoomActionPanel.add(new ActionLink<Serializable>() {
 
             private static final long serialVersionUID = -3722207913631435501L;
 
@@ -186,9 +186,9 @@ public class Topology extends BasePage {
             public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
                 target.appendJavaScript("zoomOut($('#drawing')[0]);");
             }
-        }, ActionLink.ActionType.ZOOM_OUT, StandardEntitlement.RESOURCE_LIST);
+        }, ActionLink.ActionType.ZOOM_OUT, StandardEntitlement.RESOURCE_LIST).disableIndicator().hideLabel();
 
-        body.add(zoomActionPanel.build("zoom"));
+        body.add(zoomActionPanel);
         // -----------------------------------------
 
         // -----------------------------------------

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
index 4bb1aa2..dff34e6 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
@@ -76,7 +76,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
     protected final BaseModal<Serializable> provisionModal;
 
     public TopologyTogglePanel(final String id, final PageReference pageRef) {
-        super(id, pageRef);
+        super(id, "topologyTogglePanel", pageRef);
 
         modal.size(Modal.Size.Large);
         setFooterVisibility(false);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ActionColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ActionColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ActionColumn.java
deleted file mode 100644
index e1ec878..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ActionColumn.java
+++ /dev/null
@@ -1,50 +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.wicket.extensions.markup.html.repeater.data.table;
-
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
-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.markup.repeater.Item;
-import org.apache.wicket.model.IModel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class ActionColumn<T, S> extends AbstractColumn<T, S> {
-
-    private static final long serialVersionUID = 7955560320949560725L;
-
-    protected static final Logger LOG = LoggerFactory.getLogger(ActionColumn.class);
-
-    public ActionColumn(final IModel<String> displayModel) {
-        super(displayModel);
-    }
-
-    @Override
-    public String getCssClass() {
-        return "action";
-    }
-
-    @Override
-    public void populateItem(final Item<ICellPopulator<T>> item, final String componentId, final IModel<T> rowModel) {
-        item.add(getActions(componentId, rowModel));
-    }
-
-    public abstract ActionLinksPanel<?> getActions(final String componentId, final IModel<T> rowModel);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AjaxFallbackDataTable.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AjaxFallbackDataTable.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AjaxFallbackDataTable.java
index 9b8cccb..4afa9ea 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AjaxFallbackDataTable.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AjaxFallbackDataTable.java
@@ -18,8 +18,15 @@
  */
 package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table;
 
+import java.io.Serializable;
 import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.wicket.ajax.markup.html.navigation.paging.AjaxDataNavigationToolbar;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.sort.AjaxFallbackOrderByBorder;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackHeadersToolbar;
@@ -33,16 +40,20 @@ import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.markup.repeater.OddEvenItem;
 import org.apache.wicket.model.IModel;
 
-public class AjaxFallbackDataTable<T, S> extends DataTable<T, S> {
+public class AjaxFallbackDataTable<T extends Serializable, S> extends DataTable<T, S> {
 
     private static final long serialVersionUID = 6861105496141602937L;
 
+    private ActionLinksTogglePanel<T> togglePanel;
+
     public AjaxFallbackDataTable(final String id, final List<? extends IColumn<T, S>> columns,
             final ISortableDataProvider<T, S> dataProvider, final int rowsPerPage, final WebMarkupContainer container) {
         super(id, columns, dataProvider, rowsPerPage);
         setOutputMarkupId(true);
         setVersioned(false);
 
+        togglePanel = getTogglePanel();
+
         addTopToolbar(new AjaxFallbackHeadersToolbar<S>(this, dataProvider) {
 
             private static final long serialVersionUID = 7406306172424359609L;
@@ -90,8 +101,44 @@ public class AjaxFallbackDataTable<T, S> extends DataTable<T, S> {
         addBottomToolbar(new NoRecordsToolbar(this));
     }
 
+    protected ActionsPanel<T> getActions(final IModel<T> model) {
+        return null;
+    }
+
+    protected ActionLinksTogglePanel<T> getTogglePanel() {
+        return null;
+    }
+
     @Override
     protected Item<T> newRowItem(final String id, final int index, final IModel<T> model) {
-        return new OddEvenItem<>(id, index, model);
+        final OddEvenItem<T> item = new OddEvenItem<>(id, index, model);
+
+        if (togglePanel != null) {
+            final ActionsPanel<T> actions = getActions(model);
+
+            if (actions != null && !actions.isEmpty()) {
+                item.add(new AttributeModifier("style", "cursor: pointer;"));
+                item.add(new AjaxEventBehavior(Constants.ON_CLICK) {
+
+                    private static final long serialVersionUID = 1L;
+
+                    @Override
+                    protected String findIndicatorId() {
+                        return StringUtils.EMPTY;
+                    }
+
+                    @Override
+                    protected void onEvent(final AjaxRequestTarget target) {
+                        if (target.getLastFocusedElementId() == null
+                                || (!target.getLastFocusedElementId().startsWith("check")
+                                && !target.getLastFocusedElementId().startsWith("groupselector"))) {
+                            togglePanel.toggleWithContent(target, getActions(model), model.getObject());
+                        }
+                    }
+                });
+            }
+        }
+
+        return item;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/CollectionPropertyColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/CollectionPropertyColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/CollectionPropertyColumn.java
index a5fd774..eaac4dd 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/CollectionPropertyColumn.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/CollectionPropertyColumn.java
@@ -33,9 +33,8 @@ public class CollectionPropertyColumn<T> extends PropertyColumn<T, String> {
 
     public CollectionPropertyColumn(
             final IModel<String> displayModel,
-            final String sortProperty,
             final String propertyExpression) {
-        super(displayModel, sortProperty, propertyExpression);
+        super(displayModel, propertyExpression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/KeyPropertyColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/KeyPropertyColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/KeyPropertyColumn.java
index 281189a..3773712 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/KeyPropertyColumn.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/KeyPropertyColumn.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 import org.apache.wicket.markup.html.basic.Label;
@@ -35,8 +36,12 @@ public class KeyPropertyColumn<T> extends PropertyColumn<T, String> {
 
     private static final long serialVersionUID = 3527840552172947705L;
 
-    public KeyPropertyColumn(final IModel<String> displayModel, final String sortProperty,
-            final String propertyExpression) {
+    public KeyPropertyColumn(final IModel<String> displayModel, final String propertyExpression) {
+        super(displayModel, propertyExpression);
+    }
+
+    public KeyPropertyColumn(
+            final IModel<String> displayModel, final String sortProperty, final String propertyExpression) {
 
         super(displayModel, sortProperty, propertyExpression);
     }
@@ -57,4 +62,9 @@ public class KeyPropertyColumn<T> extends PropertyColumn<T, String> {
         return "keyColumn";
     }
 
+    @Override
+    public Component getHeader(final String componentId) {
+        return super.getHeader(componentId).setEnabled(false).setVisible(false);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
new file mode 100644
index 0000000..ab12413
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
@@ -0,0 +1,176 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.wicket.model.Model;
+
+/**
+ * Action link basic details.
+ *
+ * @param <T> model object type.
+ */
+public final class Action<T extends Serializable> implements Serializable {
+
+    private static final long serialVersionUID = -7989237020377623993L;
+
+    private final ActionLink<T> link;
+
+    private final ActionLink.ActionType type;
+
+    private String entitlements;
+
+    private boolean onConfirm;
+
+    private boolean visibleLabel;
+
+    private Model<String> label;
+
+    private Model<String> title;
+
+    private Model<String> alt;
+
+    private Model<String> icon;
+
+    private boolean indicator;
+
+    public Action(final ActionLink<T> link, final ActionLink.ActionType type) {
+        this.link = link;
+        this.type = type;
+        this.entitlements = StringUtils.EMPTY;
+        this.onConfirm = false;
+        this.visibleLabel = true;
+        this.label = null;
+        this.title = null;
+        this.alt = null;
+        this.icon = null;
+        this.indicator = true;
+    }
+
+    public ActionLink<T> getLink() {
+        return link;
+    }
+
+    public ActionLink.ActionType getType() {
+        return type;
+    }
+
+    public String getEntitlements() {
+        return entitlements;
+    }
+
+    public boolean isOnConfirm() {
+        return onConfirm;
+    }
+
+    public Action<T> setEntitlements(final String entitlements) {
+        this.entitlements = entitlements;
+        return this;
+    }
+
+    public Action<T> setOnConfirm(final boolean onConfirm) {
+        this.onConfirm = onConfirm;
+        return this;
+    }
+
+    public Action<T> hideLabel() {
+        this.visibleLabel = false;
+        return this;
+    }
+
+    public boolean isVisibleLabel() {
+        return visibleLabel;
+    }
+
+    /**
+     * Override default action label.
+     *
+     * @param label new action label;
+     * @return updated action.
+     */
+    public Action<T> setLabel(final Model<String> label) {
+        this.label = label;
+        return this;
+    }
+
+    public Model<String> getLabel() {
+        return label;
+    }
+
+    /**
+     * Override default action title.
+     *
+     * @param title new action title;
+     * @return updated action.
+     */
+    public Action<T> setTitleI(final Model<String> title) {
+        this.title = title;
+        return this;
+    }
+
+    public Model<String> getTitle() {
+        return title;
+    }
+
+    /**
+     * Override default action icon text name.
+     *
+     * @param alt action icon text name;
+     * @return updated action.
+     */
+    public Action<T> setAlt(final Model<String> alt) {
+        this.alt = alt;
+        return this;
+    }
+
+    public Model<String> getAlt() {
+        return alt;
+    }
+
+    /**
+     * Override default action css class.
+     *
+     * @param icon new action class;
+     * @return updated action.
+     */
+    public Action<T> setIcon(final Model<String> icon) {
+        this.icon = icon;
+        return this;
+    }
+
+    public Model<String> getIcon() {
+        return icon;
+    }
+
+    /**
+     * Override disable AJAX indicator.
+     *
+     * @return updated action.
+     */
+    public Action<T> disableIndicator() {
+        this.indicator = false;
+        return this;
+    }
+
+    public boolean hasIndicator() {
+        return indicator;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f8b61e78/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 c4c5bf7..c90ef37 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
@@ -58,7 +58,7 @@ public abstract class ActionLink<T extends Serializable> implements Serializable
         LAYOUT_EDIT("read"),
         RESET("update"),
         ENABLE("update"),
-        NOT_FOND("read"),
+        NOT_FOUND("read"),
         VIEW("view"),
         MEMBERS("members"),
         SEARCH("search"),