You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2016/01/14 17:53:10 UTC

syncope git commit: [SYNCOPE-743] providing toggle panel basic structure

Repository: syncope
Updated Branches:
  refs/heads/master c5b47d50c -> 9536ffa91


[SYNCOPE-743] providing toggle panel basic structure


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

Branch: refs/heads/master
Commit: 9536ffa91da22558067d186c90ecb2358fb9996d
Parents: c5b47d5
Author: fmartelli <fa...@gmail.com>
Authored: Thu Jan 14 17:52:45 2016 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Thu Jan 14 17:52:45 2016 +0100

----------------------------------------------------------------------
 .../client/console/panels/TogglePanel.java      |  96 ++++
 .../client/console/topology/Topology.java       |  36 +-
 .../console/topology/TopologyNodePanel.java     | 216 +--------
 .../console/topology/TopologyTogglePanel.java   | 275 ++++++++++++
 .../META-INF/resources/css/topology.css         | 186 ++++----
 .../resources/META-INF/resources/js/topology.js | 437 +++++++++----------
 .../client/console/panels/TogglePanel.html      | 119 +++++
 .../client/console/topology/Topology.html       |   2 +
 .../console/topology/TopologyNodePanel.html     |  38 --
 .../topology/TopologyNodePanel.properties       |  20 -
 .../topology/TopologyNodePanel_it.properties    |  20 -
 .../topology/TopologyNodePanel_pt_BR.properties |  20 -
 .../console/topology/TopologyTogglePanel.html   |  51 +++
 .../topology/TopologyTogglePanel.properties     |  28 ++
 .../topology/TopologyTogglePanel_it.properties  |  26 ++
 .../TopologyTogglePanel_pt_BR.properties        |  26 ++
 16 files changed, 976 insertions(+), 620 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
new file mode 100644
index 0000000..208a802
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
@@ -0,0 +1,96 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ * Toggle panel.
+ */
+public abstract class TogglePanel extends Panel {
+
+    private static final long serialVersionUID = -2025535531121434056L;
+
+    private enum Status {
+        INACTIVE,
+        ACTIVE
+
+    }
+
+    protected final BaseModal<Serializable> modal;
+
+    private Status status = Status.INACTIVE;
+
+    private final Label header;
+
+    public TogglePanel(final String id) {
+        super(id);
+        setRenderBodyOnly(true);
+        setOutputMarkupId(true);
+
+        this.modal = new BaseModal<Serializable>("resource-modal");
+        add(modal);
+
+        header = new Label("label", StringUtils.EMPTY);
+        header.setOutputMarkupId(true);
+        add(header);
+
+        add(new AjaxLink<Void>("close") {
+
+            private static final long serialVersionUID = 5538299138211283825L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                TogglePanel.this.toggle(target, false);
+            }
+
+        }.setMarkupId("close"));
+    }
+
+    protected void setHeader(final AjaxRequestTarget target, final String header) {
+        this.header.setDefaultModelObject(header.length() >= 40 ? (header.substring(0, 30) + " ... ") : header);
+        target.add(this.header);
+    }
+
+    /**
+     * Force toggle via java. To be used when the onclick has been intercepted before.
+     *
+     * @param target ajax request target.
+     * @param toggle toggle action.
+     */
+    public void toggle(final AjaxRequestTarget target, final boolean toggle) {
+        if (toggle) {
+            if (status == Status.INACTIVE) {
+                target.appendJavaScript("$(\"div.inactive-topology-menu\").toggle(\"slow\");"
+                        + "$(\"div.inactive-topology-menu\").attr(\"class\", \"topology-menu active-topology-menu\");");
+                status = Status.ACTIVE;
+            }
+        } else if (status == Status.ACTIVE) {
+            target.appendJavaScript("$(\"div.active-topology-menu\").toggle(\"slow\");"
+                    + "$(\"div.active-topology-menu\").attr(\"class\", \"topology-menu inactive-topology-menu\");");
+            status = Status.INACTIVE;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/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 1a904a1..6a20d08 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
@@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.AbstractResourceModal.CreateEvent;
 import org.apache.syncope.client.console.panels.NotificationPanel;
@@ -44,6 +45,7 @@ import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
+import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.IAjaxIndicatorAware;
 import org.apache.wicket.behavior.Behavior;
@@ -79,6 +81,8 @@ public class Topology extends BasePage {
 
     private final ListView<TopologyNode> newlyCreated;
 
+    private final TopologyTogglePanel togglePanel;
+
     private final LoadableDetachableModel<List<ResourceTO>> resModel = new LoadableDetachableModel<List<ResourceTO>>() {
 
         private static final long serialVersionUID = 5275935387613157431L;
@@ -168,6 +172,9 @@ public class Topology extends BasePage {
 
         add(new WebSocketBehavior());
 
+        togglePanel = new TopologyTogglePanel("toggle", getPage().getPageReference());
+        add(togglePanel);
+
         // -----------------------------------------
         // Add Zoom panel
         // -----------------------------------------
@@ -527,11 +534,13 @@ public class Topology extends BasePage {
 
     private TopologyNodePanel topologyNodePanel(final String id, final TopologyNode node) {
 
-        final TopologyNodePanel panel = new TopologyNodePanel(id, node, modal, getPageReference());
+        final TopologyNodePanel panel = new TopologyNodePanel(id, node);
         panel.setMarkupId(String.valueOf(node.getKey()));
         panel.setOutputMarkupId(true);
 
-        panel.add(new Behavior() {
+        final List<Behavior> behaviors = new ArrayList<>();
+
+        behaviors.add(new Behavior() {
 
             private static final long serialVersionUID = 1L;
 
@@ -542,6 +551,29 @@ public class Topology extends BasePage {
             }
         });
 
+        if (node.getKind() == TopologyNode.Kind.CONNECTOR_SERVER
+                || node.getKind() == TopologyNode.Kind.FS_PATH
+                || node.getKind() == TopologyNode.Kind.CONNECTOR
+                || node.getKind() == TopologyNode.Kind.RESOURCE) {
+
+            behaviors.add(new AjaxEventBehavior(Constants.ON_CLICK) {
+
+                private static final long serialVersionUID = -9027652037484739586L;
+
+                @Override
+                protected String findIndicatorId() {
+                    return StringUtils.EMPTY;
+                }
+
+                @Override
+                protected void onEvent(final AjaxRequestTarget target) {
+                    togglePanel.toggleWithContent(target, node);
+                }
+            });
+        }
+
+        panel.add(behaviors.toArray(new Behavior[] {}));
+
         return panel;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
index bcc7117..f692f02 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
@@ -18,58 +18,23 @@
  */
 package org.apache.syncope.client.console.topology;
 
-import java.io.Serializable;
-import java.text.MessageFormat;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.ConnectorModal;
-import org.apache.syncope.client.console.panels.ResourceModal;
-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.confirmation.ConfirmationModalBehavior;
-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.ConnInstanceTO;
-import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.IAjaxIndicatorAware;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.behavior.Behavior;
-import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.CompoundPropertyModel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class TopologyNodePanel extends Panel implements IAjaxIndicatorAware {
 
     private static final long serialVersionUID = -8775095410207013913L;
 
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyNodePanel.class);
-
-    private final ResourceRestClient resourceRestClient = new ResourceRestClient();
-
-    private final ConnectorRestClient connectorRestClient = new ConnectorRestClient();
-
-    private final BaseModal<Serializable> modal;
-
     public TopologyNodePanel(
             final String id,
-            final TopologyNode node,
-            final BaseModal<Serializable> modal,
-            final PageReference pageRef) {
+            final TopologyNode node) {
 
         super(id);
 
@@ -84,28 +49,23 @@ public class TopologyNodePanel extends Panel implements IAjaxIndicatorAware {
         switch (node.getKind()) {
             case SYNCOPE:
                 title = "";
-                add(getSyncopeFragment());
                 add(new AttributeAppender("class", "topology_root", " "));
                 break;
             case CONNECTOR_SERVER:
                 title = node.getDisplayName();
-                add(getLocationFragment(node, pageRef));
                 add(new AttributeAppender("class", "topology_cs", " "));
                 break;
             case FS_PATH:
                 title = node.getDisplayName();
-                add(getLocationFragment(node, pageRef));
                 add(new AttributeAppender("class", "topology_cs", " "));
                 break;
             case CONNECTOR:
                 title = (StringUtils.isBlank(node.getConnectionDisplayName())
                         ? "" : node.getConnectionDisplayName() + ":") + node.getDisplayName();
-                add(getConnectorFragment(node, pageRef));
                 add(new AttributeAppender("class", "topology_conn", " "));
                 break;
             default:
                 title = node.getDisplayName().length() > 20 ? node.getDisplayName() : "";
-                add(getResurceFragment(node, pageRef));
                 add(new AttributeAppender("class", "topology_res", " "));
         }
 
@@ -114,9 +74,6 @@ public class TopologyNodePanel extends Panel implements IAjaxIndicatorAware {
         }
 
         this.setMarkupId(node.getDisplayName());
-
-        this.modal = modal;
-        BasePage.class.cast(pageRef.getPage()).setWindowClosedCallback(modal, null);
     }
 
     @Override
@@ -134,177 +91,6 @@ public class TopologyNodePanel extends Panel implements IAjaxIndicatorAware {
         return super.setMarkupId(markupId);
     }
 
-    private Fragment getSyncopeFragment() {
-        return new Fragment("actions", "syncopeActions", this);
-    }
-
-    private Fragment getLocationFragment(final TopologyNode node, final PageReference pageRef) {
-        final Fragment fragment = new Fragment("actions", "locationActions", this);
-
-        final AjaxLink<String> create = new IndicatingAjaxLink<String>("create") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                final ConnInstanceTO modelObject = new ConnInstanceTO();
-                modelObject.setLocation(node.getKey().toString());
-
-                final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(modelObject);
-                modal.setFormModel(model);
-
-                target.add(modal.setContent(new ConnectorModal(modal, pageRef, model)));
-
-                modal.header(new Model<>(MessageFormat.format(getString("connector.new"), node.getKey())));
-
-                MetaDataRoleAuthorizationStrategy.
-                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.CONNECTOR_CREATE);
-
-                modal.show(true);
-            }
-        };
-        fragment.add(create);
-
-        MetaDataRoleAuthorizationStrategy.authorize(create, ENABLE, StandardEntitlement.CONNECTOR_CREATE);
-
-        return fragment;
-    }
-
-    private Fragment getConnectorFragment(final TopologyNode node, final PageReference pageRef) {
-        final Fragment fragment = new Fragment("actions", "connectorActions", this);
-
-        final AjaxLink<String> delete = new IndicatingAjaxLink<String>("delete") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                try {
-                    connectorRestClient.delete(Long.class.cast(node.getKey()));
-                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
-                    info(getString(Constants.OPERATION_SUCCEEDED));
-                } catch (SyncopeClientException e) {
-                    error(getString(Constants.ERROR) + ": " + e.getMessage());
-                    LOG.error("While deleting resource {}", node.getKey(), e);
-                }
-                ((BasePage) getPage()).getNotificationPanel().refresh(target);
-            }
-        };
-
-        fragment.add(delete);
-        delete.add(new ConfirmationModalBehavior());
-
-        MetaDataRoleAuthorizationStrategy.authorize(delete, ENABLE, StandardEntitlement.CONNECTOR_DELETE);
-
-        final AjaxLink<String> create = new IndicatingAjaxLink<String>("create") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                final ResourceTO modelObject = new ResourceTO();
-                modelObject.setConnector(Long.class.cast(node.getKey()));
-                modelObject.setConnectorDisplayName(node.getDisplayName());
-
-                final IModel<ResourceTO> model = new CompoundPropertyModel<>(modelObject);
-                modal.setFormModel(model);
-
-                target.add(modal.setContent(new ResourceModal<>(modal, pageRef, model, true)));
-
-                modal.header(new Model<>(MessageFormat.format(getString("resource.new"), node.getKey())));
-
-                MetaDataRoleAuthorizationStrategy.
-                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.RESOURCE_CREATE);
-
-                modal.show(true);
-            }
-        };
-        fragment.add(create);
-
-        MetaDataRoleAuthorizationStrategy.authorize(create, ENABLE, StandardEntitlement.RESOURCE_CREATE);
-
-        final AjaxLink<String> edit = new IndicatingAjaxLink<String>("edit") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                final ConnInstanceTO modelObject = connectorRestClient.read(Long.class.cast(node.getKey()));
-
-                final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(modelObject);
-                modal.setFormModel(model);
-
-                target.add(modal.setContent(new ConnectorModal(modal, pageRef, model)));
-
-                modal.header(new Model<>(MessageFormat.format(getString("connector.edit"), node.getKey())));
-
-                MetaDataRoleAuthorizationStrategy.
-                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.CONNECTOR_UPDATE);
-
-                modal.show(true);
-            }
-        };
-        fragment.add(edit);
-
-        MetaDataRoleAuthorizationStrategy.authorize(edit, ENABLE, StandardEntitlement.CONNECTOR_UPDATE);
-
-        return fragment;
-    }
-
-    private Fragment getResurceFragment(final TopologyNode node, final PageReference pageRef) {
-        final Fragment fragment = new Fragment("actions", "resourceActions", this);
-
-        final AjaxLink<String> delete = new IndicatingAjaxLink<String>("delete") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                try {
-                    resourceRestClient.delete(node.getKey().toString());
-                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
-                    info(getString(Constants.OPERATION_SUCCEEDED));
-                } catch (SyncopeClientException e) {
-                    error(getString(Constants.ERROR) + ": " + e.getMessage());
-                    LOG.error("While deleting resource {}", node.getKey(), e);
-                }
-                ((BasePage) getPage()).getNotificationPanel().refresh(target);
-            }
-        };
-        fragment.add(delete);
-
-        delete.add(new ConfirmationModalBehavior());
-
-        MetaDataRoleAuthorizationStrategy.authorize(delete, ENABLE, StandardEntitlement.RESOURCE_DELETE);
-
-        final AjaxLink<String> edit = new IndicatingAjaxLink<String>("edit") {
-
-            private static final long serialVersionUID = 3776750333491622263L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                final ResourceTO modelObject = resourceRestClient.read(node.getKey().toString());
-
-                final IModel<ResourceTO> model = new CompoundPropertyModel<>(modelObject);
-                modal.setFormModel(model);
-
-                target.add(modal.setContent(new ResourceModal<>(modal, pageRef, model, false)));
-
-                modal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
-
-                MetaDataRoleAuthorizationStrategy.
-                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.RESOURCE_UPDATE);
-
-                modal.show(true);
-            }
-        };
-        fragment.add(edit);
-
-        MetaDataRoleAuthorizationStrategy.authorize(edit, ENABLE, StandardEntitlement.RESOURCE_UPDATE);
-
-        return fragment;
-    }
-
     @Override
     public String getAjaxIndicatorMarkupId() {
         return "veil";

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/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
new file mode 100644
index 0000000..dc3a6d4
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
@@ -0,0 +1,275 @@
+/*
+ * 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.topology;
+
+import static org.apache.wicket.Component.ENABLE;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.text.MessageFormat;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.ConnectorModal;
+import org.apache.syncope.client.console.panels.ResourceModal;
+import org.apache.syncope.client.console.panels.TogglePanel;
+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.confirmation.ConfirmationModalBehavior;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+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.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Toggle panel.
+ */
+public class TopologyTogglePanel extends TogglePanel {
+
+    private static final long serialVersionUID = -2025535531121434056L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(TopologyTogglePanel.class);
+
+    private final ResourceRestClient resourceRestClient = new ResourceRestClient();
+
+    private final ConnectorRestClient connectorRestClient = new ConnectorRestClient();
+
+    private final WebMarkupContainer container;
+
+    private final PageReference pageRef;
+
+    public TopologyTogglePanel(final String id, final PageReference pageRef) {
+        super(id);
+        this.pageRef = pageRef;
+
+        modal.size(Modal.Size.Large);
+
+        container = new WebMarkupContainer("container");
+        container.setOutputMarkupPlaceholderTag(true);
+        add(container);
+
+        container.add(getEmptyFragment());
+    }
+
+    public void toggleWithContent(final AjaxRequestTarget target, final TopologyNode node) {
+        setHeader(target, node.getDisplayName());
+
+        switch (node.getKind()) {
+            case CONNECTOR_SERVER:
+                container.addOrReplace(getLocationFragment(node, pageRef));
+                break;
+            case FS_PATH:
+                container.addOrReplace(getLocationFragment(node, pageRef));
+                break;
+            case CONNECTOR:
+                container.addOrReplace(getConnectorFragment(node, pageRef));
+                break;
+            case RESOURCE:
+                container.addOrReplace(getResurceFragment(node, pageRef));
+                break;
+            default:
+                container.addOrReplace(getEmptyFragment());
+        }
+
+        target.add(container);
+
+        this.toggle(target, true);
+    }
+
+    private Fragment getEmptyFragment() {
+        return new Fragment("actions", "emptyFragment", this);
+    }
+
+    private Fragment getLocationFragment(final TopologyNode node, final PageReference pageRef) {
+        final Fragment fragment = new Fragment("actions", "locationActions", this);
+
+        final AjaxLink<String> create = new IndicatingAjaxLink<String>("create") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                final ConnInstanceTO modelObject = new ConnInstanceTO();
+                modelObject.setLocation(node.getKey().toString());
+
+                final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(modelObject);
+                modal.setFormModel(model);
+
+                target.add(modal.setContent(new ConnectorModal(modal, pageRef, model)));
+
+                modal.header(new Model<>(MessageFormat.format(getString("connector.new"), node.getKey())));
+
+                MetaDataRoleAuthorizationStrategy.
+                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.CONNECTOR_CREATE);
+
+                modal.show(true);
+            }
+        };
+        fragment.add(create);
+
+        MetaDataRoleAuthorizationStrategy.authorize(create, ENABLE, StandardEntitlement.CONNECTOR_CREATE);
+
+        return fragment;
+    }
+
+    private Fragment getConnectorFragment(final TopologyNode node, final PageReference pageRef) {
+        final Fragment fragment = new Fragment("actions", "connectorActions", this);
+
+        final AjaxLink<String> delete = new IndicatingAjaxLink<String>("delete") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                try {
+                    connectorRestClient.delete(Long.class.cast(node.getKey()));
+                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                } catch (SyncopeClientException e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    LOG.error("While deleting resource {}", node.getKey(), e);
+                }
+                ((BasePage) getPage()).getNotificationPanel().refresh(target);
+            }
+        };
+
+        fragment.add(delete);
+        delete.add(new ConfirmationModalBehavior());
+
+        MetaDataRoleAuthorizationStrategy.authorize(delete, ENABLE, StandardEntitlement.CONNECTOR_DELETE);
+
+        final AjaxLink<String> create = new IndicatingAjaxLink<String>("create") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                final ResourceTO modelObject = new ResourceTO();
+                modelObject.setConnector(Long.class.cast(node.getKey()));
+                modelObject.setConnectorDisplayName(node.getDisplayName());
+
+                final IModel<ResourceTO> model = new CompoundPropertyModel<>(modelObject);
+                modal.setFormModel(model);
+
+                target.add(modal.setContent(new ResourceModal<>(modal, pageRef, model, true)));
+
+                modal.header(new Model<>(MessageFormat.format(getString("resource.new"), node.getKey())));
+
+                MetaDataRoleAuthorizationStrategy.
+                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.RESOURCE_CREATE);
+
+                modal.show(true);
+            }
+        };
+        fragment.add(create);
+
+        MetaDataRoleAuthorizationStrategy.authorize(create, ENABLE, StandardEntitlement.RESOURCE_CREATE);
+
+        final AjaxLink<String> edit = new IndicatingAjaxLink<String>("edit") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                final ConnInstanceTO modelObject = connectorRestClient.read(Long.class.cast(node.getKey()));
+
+                final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(modelObject);
+                modal.setFormModel(model);
+
+                target.add(modal.setContent(new ConnectorModal(modal, pageRef, model)));
+
+                modal.header(new Model<>(MessageFormat.format(getString("connector.edit"), node.getKey())));
+
+                MetaDataRoleAuthorizationStrategy.
+                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.CONNECTOR_UPDATE);
+
+                modal.show(true);
+            }
+        };
+        fragment.add(edit);
+
+        MetaDataRoleAuthorizationStrategy.authorize(edit, ENABLE, StandardEntitlement.CONNECTOR_UPDATE);
+
+        return fragment;
+    }
+
+    private Fragment getResurceFragment(final TopologyNode node, final PageReference pageRef) {
+        final Fragment fragment = new Fragment("actions", "resourceActions", this);
+
+        final AjaxLink<String> delete = new IndicatingAjaxLink<String>("delete") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                try {
+                    resourceRestClient.delete(node.getKey().toString());
+                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                } catch (SyncopeClientException e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    LOG.error("While deleting resource {}", node.getKey(), e);
+                }
+                ((BasePage) getPage()).getNotificationPanel().refresh(target);
+            }
+        };
+        fragment.add(delete);
+
+        delete.add(new ConfirmationModalBehavior());
+
+        MetaDataRoleAuthorizationStrategy.authorize(delete, ENABLE, StandardEntitlement.RESOURCE_DELETE);
+
+        final AjaxLink<String> edit = new IndicatingAjaxLink<String>("edit") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                final ResourceTO modelObject = resourceRestClient.read(node.getKey().toString());
+
+                final IModel<ResourceTO> model = new CompoundPropertyModel<>(modelObject);
+                modal.setFormModel(model);
+
+                target.add(modal.setContent(new ResourceModal<>(modal, pageRef, model, false)));
+
+                modal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
+
+                MetaDataRoleAuthorizationStrategy.
+                        authorize(modal.addSumbitButton(), ENABLE, StandardEntitlement.RESOURCE_UPDATE);
+
+                modal.show(true);
+            }
+        };
+        fragment.add(edit);
+
+        MetaDataRoleAuthorizationStrategy.authorize(edit, ENABLE, StandardEntitlement.RESOURCE_UPDATE);
+
+        return fragment;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/META-INF/resources/css/topology.css
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/resources/css/topology.css b/client/console/src/main/resources/META-INF/resources/css/topology.css
index be3f04d..23093ca 100644
--- a/client/console/src/main/resources/META-INF/resources/css/topology.css
+++ b/client/console/src/main/resources/META-INF/resources/css/topology.css
@@ -17,139 +17,153 @@
  * under the License.
  */
 .window {
-    border:1px solid #346789;
-    box-shadow: 2px 2px 19px #aaa;
-    -o-box-shadow: 2px 2px 19px #aaa;
-    -webkit-box-shadow: 2px 2px 19px #aaa;
-    -moz-box-shadow: 2px 2px 19px #aaa;
-    -moz-border-radius:0.5em;
-    border-radius:0.5em;
-    opacity:0.8;
-    filter:alpha(opacity=80);
-    width:140px; height:55px;
-    line-height:5em;
-    text-align:center;
-    z-index:20; position:absolute;
-    background-color:#eeeeef;
-    color:black;
-    font-family:helvetica;padding:0.0em;
-    font-size:0.9em;}
+  border:1px solid #346789;
+  box-shadow: 2px 2px 19px #aaa;
+  -o-box-shadow: 2px 2px 19px #aaa;
+  -webkit-box-shadow: 2px 2px 19px #aaa;
+  -moz-box-shadow: 2px 2px 19px #aaa;
+  -moz-border-radius:0.5em;
+  border-radius:0.5em;
+  opacity:0.8;
+  filter:alpha(opacity=80);
+  width:140px; height:55px;
+  line-height:5em;
+  text-align:center;
+  z-index:20; position:absolute;
+  background-color:#eeeeef;
+  color:black;
+  font-family:helvetica;padding:0.0em;
+  font-size:0.9em;
+  vertical-align: middle;
+}
+
+.window p {
+  margin: 0px !important;
+  line-height: 1.5em;
+  display: inline-table;
+}
 
 .topology_root {
-    background-color:rgba(0,170,0,0.4);
+  background-color:rgba(0,170,0,0.4);
 }
 
 .topology_cs {
-    background-color:rgba(0,100,0,0.10);
+  background-color:rgba(0,100,0,0.10);
 }
 
 .topology_conn {
-    background-color:rgba(100,200,200,0.08);
+  background-color:rgba(100,200,200,0.08);
+}
+
+.topology_res {
+  background-color:rgba(250,230,0,0.09);
 }
 
+.topology_cs,
+.topology_conn,
 .topology_res {
-    background-color:rgba(250,230,0,0.09);
+  cursor: pointer;
 }
 
 .window:hover {
-    box-shadow: 2px 2px 19px #444;
-    -o-box-shadow: 2px 2px 19px #444;
-    -webkit-box-shadow: 2px 2px 19px #444;
-    -moz-box-shadow: 2px 2px 19px #444;
-    opacity:0.6;
-    filter:alpha(opacity=60);
+  box-shadow: 2px 2px 19px #444;
+  -o-box-shadow: 2px 2px 19px #444;
+  -webkit-box-shadow: 2px 2px 19px #444;
+  -moz-box-shadow: 2px 2px 19px #444;
+  opacity:0.6;
+  filter:alpha(opacity=60);
 }
 
 ._jsPlumb_dragging { 
-    z-index:4000;
+  z-index:4000;
 }
 
 #drawing ._jsPlumb_overlay.component.label{
-    background-color: white;
-    border: 1px solid #346789;
-    border-radius: 0.5em 0.5em 0.5em 0.5em;
-    color: black;
-    font-size: 0.8em;
-    opacity: 0.8;
-    padding: 0.5em;
+  background-color: white;
+  border: 1px solid #346789;
+  border-radius: 0.5em 0.5em 0.5em 0.5em;
+  color: black;
+  font-size: 0.8em;
+  opacity: 0.8;
+  padding: 0.5em;
 }
 
 .aLabel {
-    background-color:white; 
-    padding:0.4em; 
-    font:12px sans-serif; 
-    color:#444;
-    z-index:21;
-    border:1px dotted gray;
-    opacity:0.8;
-    filter:alpha(opacity=80);
-    cursor: pointer;
+  background-color:white; 
+  padding:0.4em; 
+  font:12px sans-serif; 
+  color:#444;
+  z-index:21;
+  border:1px dotted gray;
+  opacity:0.8;
+  filter:alpha(opacity=80);
+  cursor: pointer;
 }
 .aLabel._jsPlumb_hover {
-    background-color:#5C96BC;
-    color:white;	
-    border:1px solid white;
+  background-color:#5C96BC;
+  color:white;	
+  border:1px solid white;
 }
 
 div#topology {
-    position: relative; 
-    border: 0px; 
-    height: 800px; 
-    overflow: hidden;
+  position: relative; 
+  border: 0px; 
+  height: 800px; 
+  overflow: hidden;
 }
 
 div#drawing {
-    height: 5000px;
-    width: 5000px;
-    display: block;
-    position: relative;
-    top: -2490px;
-    left: -2270px;
+  height: 5000px;
+  width: 5000px;
+  display: block;
+  position: relative;
+  top: -2490px;
+  left: -2270px;
 }
 
 div#zoom {
-    padding : 10px;
-    text-align: right;
-    width: 100%;
+  padding : 10px;
+  text-align: right;
+  width: 100%;
 }
 
 div#zoom .fa{
-    font-size: 2em;
-    padding-right: 5px;
+  font-size: 2em;
+  padding-right: 5px;
 }
 
 div.node-action-link {
-    clear: both;
-    display: block;
-    height: 0px;
-    padding: 3px 8px 0px 0px;
-    position: absolute;
-    right: 0;
-    top: 0;
+  clear: both;
+  display: block;
+  height: 0px;
+  padding: 3px 8px 0px 0px;
+  position: absolute;
+  right: 0;
+  top: 0;
 }
 
 div.node-action-link .fa{
-    font-size: 14px;
-    display: block !important;
+  font-size: 14px;
+  display: block !important;
 }
 
 div.node-action-link .dropdown-menu{
-    border-radius: 12px;
-    min-width: 50px;
-    width: 50px;
+  border-radius: 12px;
+  min-width: 50px;
+  width: 50px;
 }
 
 .window[data-original-title]:hover::after{
-    border: 1px solid #BBB;
-    padding: 5px 10px;
-    background: #EEE;
-    content: attr(data-original-title);
-    position: relative;
-    right: -5px;
-    top:-70px;
-    white-space: nowrap;
-    text-align: center;
-    height: 20px;
-    margin: 0px;
-    border-radius: 0.5em;
+  border: 1px solid #BBB;
+  padding: 5px 10px;
+  background: #EEE;
+  content: attr(data-original-title);
+  position: relative;
+  right: -5px;
+  top:-70px;
+  white-space: nowrap;
+  text-align: center;
+  height: 20px;
+  margin: 0px;
+  border-radius: 0.5em;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/META-INF/resources/js/topology.js
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/resources/js/topology.js b/client/console/src/main/resources/META-INF/resources/js/topology.js
index 53494d0..f8ca683 100644
--- a/client/console/src/main/resources/META-INF/resources/js/topology.js
+++ b/client/console/src/main/resources/META-INF/resources/js/topology.js
@@ -17,296 +17,295 @@
  * under the License.
  */
 var def = {
-    paintStyle: {
-	lineWidth: 2,
-        strokeStyle: "rgba(204,204,204, 0.3)",
-        outlineColor: "#666",
-        outlineWidth: 1
-    },
-    connectorPaintStyle:{
-	lineWidth:2
+  paintStyle: {
+    lineWidth: 2,
+    strokeStyle: "rgba(204,204,204, 0.3)",
+    outlineColor: "#666",
+    outlineWidth: 1
+  },
+  connectorPaintStyle: {
+    lineWidth: 2
+  },
+  anchor: "AutoDefault",
+  detachable: false,
+  endpointStyle: {
+    gradient: {
+      stops: [
+        [0, "rgba(204,204,204, 1)"], [1, "rgba(180, 180, 200, 1)"]
+      ],
+      offset: 5.5,
+      innerRadius: 3.5
     },
-    anchor: "AutoDefault",
-    detachable: false,
-    endpointStyle: {
-	gradient: {
-	    stops: [
-            	[0, "rgba(204,204,204, 1)" ], [1, "rgba(180, 180, 200, 1)" ]
-	    ],
-	    offset: 5.5,
-	    innerRadius: 3.5
-	},
-	radius: 3.5
-    }
+    radius: 3.5
+  }
 };
 
 var failedConnectorStyle = {
-    lineWidth: 2,
-    strokeStyle: "rgba(220, 220, 220, 1)",
-    outlineColor: "#666",
-    outlineWidth: 1
+  lineWidth: 2,
+  strokeStyle: "rgba(220, 220, 220, 1)",
+  outlineColor: "#666",
+  outlineWidth: 1
 };
 
 var failedConnectorHoverStyle = {
-    strokeStyle: "#FFFFFF" 
+  strokeStyle: "#FFFFFF"
 };
 
 var failedEndpointStyle = {
-    gradient: {
-	stops: [
-	    [0, "rgba(220, 220, 220, 1)" ], [1, "rgba(180, 180, 200, 1)" ]
-	],
-	offset: 5.5,
-	innerRadius: 3.5
-    },
-    radius: 3.5
+  gradient: {
+    stops: [
+      [0, "rgba(220, 220, 220, 1)"], [1, "rgba(180, 180, 200, 1)"]
+    ],
+    offset: 5.5,
+    innerRadius: 0
+  },
+  radius: 0
 };
 
 var disabledConnectorStyle = {
-    lineWidth: 2,
-    strokeStyle: "rgba(255, 69, 0, 1)",
-    outlineColor: "#666",
-    outlineWidth: 1
+  lineWidth: 2,
+  strokeStyle: "rgba(255, 69, 0, 1)",
+  outlineColor: "#666",
+  outlineWidth: 1
 };
 
 var disabledConnectorHoverStyle = {
-    strokeStyle: "#FF8C00" 
+  strokeStyle: "#FF8C00"
 };
 
 var disabledEndpointStyle = {
-    gradient: {
-	stops: [
-	    [0, "rgba(255, 69, 0, 1)" ], [1, "rgba(180, 180, 200, 1)" ]
-	],
-	offset: 5.5,
-	innerRadius: 3.5
-    },
-    radius: 3.5
+  gradient: {
+    stops: [
+      [0, "rgba(255, 69, 0, 1)"], [1, "rgba(180, 180, 200, 1)"]
+    ],
+    offset: 5.5,
+    innerRadius: 1
+  },
+  radius: 1
 };
 
 var enabledConnectorStyle = {
-    lineWidth: 2,
-    strokeStyle: "rgba(65, 155, 30, 0.3)",
-    outlineColor: "#666",
-    outlineWidth: 1
+  lineWidth: 2,
+  strokeStyle: "rgba(65, 155, 30, 0.3)",
+  outlineColor: "#666",
+  outlineWidth: 1
 };
 
 var enabledConnectorHoverStyle = {
-    strokeStyle: "#00FF00" 
+  strokeStyle: "#00FF00"
 };
 
 var enabledEndpointStyle = {
-    gradient: {
-        stops: [
-            [0, "rgba(65, 155, 30, 0.1)" ], [1, "rgba(180, 180, 200, 0.1)" ]
-        ],
-        offset: 5.5,
-        innerRadius: 3.5
-    },
-    radius: 3.5
+  gradient: {
+    stops: [
+      [0, "rgba(65, 155, 30, 0.1)"], [1, "rgba(180, 180, 200, 0.1)"]
+    ],
+    offset: 5.5,
+    innerRadius: 2
+  },
+  radius: 2
 };
 
-window.disable = function(targetName){
-    jsPlumb.ready(function(){
-	jsPlumb.select({target:targetName}).setPaintStyle(disabledConnectorStyle).setHoverPaintStyle(disabledConnectorHoverStyle);
-	jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(disabledEndpointStyle);
-    });
+window.disable = function (targetName) {
+  jsPlumb.ready(function () {
+    jsPlumb.select({target: targetName}).setPaintStyle(disabledConnectorStyle).setHoverPaintStyle(disabledConnectorHoverStyle);
+    jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(disabledEndpointStyle);
+  });
 }
 
-window.enable = function(targetName){
-    jsPlumb.ready(function(){
-	jsPlumb.select({target:targetName}).setPaintStyle(enabledConnectorStyle).setHoverPaintStyle(enabledConnectorHoverStyle);
-	jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(enabledEndpointStyle);
-    });
+window.enable = function (targetName) {
+  jsPlumb.ready(function () {
+    jsPlumb.select({target: targetName}).setPaintStyle(enabledConnectorStyle).setHoverPaintStyle(enabledConnectorHoverStyle);
+    jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(enabledEndpointStyle);
+  });
 }
 
-window.failure = function(targetName){
-    jsPlumb.ready(function(){
-	jsPlumb.select({target:targetName}).setPaintStyle(failedConnectorStyle).setHoverPaintStyle(failedConnectorHoverStyle);
-	jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(failedEndpointStyle);
-    });
+window.failure = function (targetName) {
+  jsPlumb.ready(function () {
+    jsPlumb.select({target: targetName}).setPaintStyle(failedConnectorStyle).setHoverPaintStyle(failedConnectorHoverStyle);
+    jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(failedEndpointStyle);
+  });
 }
 
-window.unknown = function(targetName){
+window.unknown = function (targetName) {
 }
 
-function getTopology(){
-    var topology = $.cookie("topology");
+function getTopology() {
+  var topology = $.cookie("topology");
 
-    if(topology == null){
-	var val = {};
-    }else{
-	var val = JSON.parse(decodeURIComponent(topology));
-    }
+  if (topology == null) {
+    var val = {};
+  } else {
+    var val = JSON.parse(decodeURIComponent(topology));
+  }
 
-    return val;
+  return val;
 }
 
-window.refreshPosition = function(element) {
-    var val = getTopology();
-    
-    var id = $(element).attr('id');
-    var left = $(element).css('left');
-    var top = $(element).css('top');
-
-    if(val[id] == null){
-	val[id] = {'top':top,'left':left};
-    }else{
-	val[id].top=top;
-	val[id].left=left;
-    }
-    
-    $.cookie("topology", JSON.stringify(val), { expires: 9999 });
+window.refreshPosition = function (element) {
+  var val = getTopology();
+
+  var id = $(element).attr('id');
+  var left = $(element).css('left');
+  var top = $(element).css('top');
+
+  if (val[id] == null) {
+    val[id] = {'top': top, 'left': left};
+  } else {
+    val[id].top = top;
+    val[id].left = left;
+  }
+
+  $.cookie("topology", JSON.stringify(val), {expires: 9999});
 }
 
-window.setPosition = function(id, x, y) {
-    var val = getTopology();
+window.setPosition = function (id, x, y) {
+  var val = getTopology();
 
-    try{
-	// We cannot use jQuery selector for id since the syntax of connector server id
-	var element = $(document.getElementById(id));
-	
-	if(val[id] == null){ 
-	    element.css("left", x + "px");
-	    element.css("top", y + "px");
-	}else{
-	    element.css("left", val[id].left);
-	    element.css("top", val[id].top);
-	}
-    }catch(err){
-	console.log("Failure setting position for ", id);
+  try {
+    // We cannot use jQuery selector for id since the syntax of connector server id
+    var element = $(document.getElementById(id));
+
+    if (val[id] == null) {
+      element.css("left", x + "px");
+      element.css("top", y + "px");
+    } else {
+      element.css("left", val[id].left);
+      element.css("top", val[id].top);
     }
+  } catch (err) {
+    console.log("Failure setting position for ", id);
+  }
 }
 
-window.setZoom = function(el, zoom, instance, transformOrigin) {
-    transformOrigin = transformOrigin || [ 0.5, 0.5 ];
-    instance = instance || jsPlumb;
-    el = el || instance.getContainer();
-    
-    var p = [ "webkit", "moz", "ms", "o" ],
-	s = "scale(" + zoom + ")",
-	oString = (transformOrigin[0] * 100) + "% " + (transformOrigin[1] * 100) + "%";
-
-    for (var i = 0; i < p.length; i++) {
-	el.style[p[i] + "Transform"] = s;
-	el.style[p[i] + "TransformOrigin"] = oString;
-    }
+window.setZoom = function (el, zoom, instance, transformOrigin) {
+  transformOrigin = transformOrigin || [0.5, 0.5];
+  instance = instance || jsPlumb;
+  el = el || instance.getContainer();
 
-    el.style["transform"] = s;
-    el.style["transformOrigin"] = oString;
+  var p = ["webkit", "moz", "ms", "o"],
+          s = "scale(" + zoom + ")",
+          oString = (transformOrigin[0] * 100) + "% " + (transformOrigin[1] * 100) + "%";
 
-    instance.setZoom(zoom);
+  for (var i = 0; i < p.length; i++) {
+    el.style[p[i] + "Transform"] = s;
+    el.style[p[i] + "TransformOrigin"] = oString;
+  }
+
+  el.style["transform"] = s;
+  el.style["transformOrigin"] = oString;
+
+  instance.setZoom(zoom);
 };
 
-window.zoomIn = function(el, instance, transformOrigin) {
-    var val = getTopology();
-    if(val.__zoom__ == null){
-	var zoom = 0.69;
-    }else{
-	var zoom = val.__zoom__ + 0.01;
-    }
+window.zoomIn = function (el, instance, transformOrigin) {
+  var val = getTopology();
+  if (val.__zoom__ == null) {
+    var zoom = 0.69;
+  } else {
+    var zoom = val.__zoom__ + 0.01;
+  }
 
-    setZoom(el, zoom, instance, transformOrigin);
-    
-    val['__zoom__']=zoom;
-    $.cookie("topology", JSON.stringify(val), { expires: 9999 });
+  setZoom(el, zoom, instance, transformOrigin);
+
+  val['__zoom__'] = zoom;
+  $.cookie("topology", JSON.stringify(val), {expires: 9999});
 };
 
-window.zoomOut = function(el, instance, transformOrigin) {
-    var val = getTopology();
-    if(val.__zoom__ == null){
-	var zoom = 0.67;
-    }else{
-	var zoom = val.__zoom__ - 0.01;
-    }
+window.zoomOut = function (el, instance, transformOrigin) {
+  var val = getTopology();
+  if (val.__zoom__ == null) {
+    var zoom = 0.67;
+  } else {
+    var zoom = val.__zoom__ - 0.01;
+  }
 
-    setZoom(el, zoom, instance, transformOrigin);
-    
-    val['__zoom__']=zoom;
-    $.cookie("topology", JSON.stringify(val), { expires: 9999 });
+  setZoom(el, zoom, instance, transformOrigin);
+
+  val['__zoom__'] = zoom;
+  $.cookie("topology", JSON.stringify(val), {expires: 9999});
 };
 
-window.connect = function(source, target, scope){
-    jsPlumb.ready(function(){
-	if(jsPlumb.select({source:source, target:target, scope: scope}) != null){
-	    jsPlumb.connect({source:source, target:target, scope: scope}, def);
-	}
-    });
+window.connect = function (source, target, scope) {
+  jsPlumb.ready(function () {
+    if (jsPlumb.select({source: source, target: target, scope: scope}) != null) {
+      jsPlumb.connect({source: source, target: target, scope: scope}, def);
+    }
+  });
 }
 
-window.activate = function(zoom){
-    jsPlumb.ready(function(){
-	jsPlumb.draggable(jsPlumb.getSelector(".window"));
-	jsPlumb.setContainer("drawing");
-	
-	jsPlumb.Defaults.MaxConnections = 1000;
-	
-	$("#drawing").draggable({
-	    containment: 'topology',
-	    cursor: 'move'
-	});
-	
-	var val = getTopology();
-	if(val.__zoom__ == null){
-	    setZoom($("#drawing")[0], zoom);
-	} else {
-	    setZoom($("#drawing")[0], val.__zoom__);
-	}
+window.activate = function (zoom) {
+  jsPlumb.ready(function () {
+    jsPlumb.draggable(jsPlumb.getSelector(".window"));
+    jsPlumb.setContainer("drawing");
+
+    jsPlumb.Defaults.MaxConnections = 1000;
+
+    $("#drawing").draggable({
+      containment: 'topology',
+      cursor: 'move'
     });
+
+    var val = getTopology();
+    if (val.__zoom__ == null) {
+      setZoom($("#drawing")[0], zoom);
+    } else {
+      setZoom($("#drawing")[0], val.__zoom__);
+    }
+  });
 }
 
-window.checkConnection = function() {
-    jsPlumb.ready(function(){
-	jsPlumb.select({scope:"CONNECTOR"}).each(function(connection) {
-            Wicket.WebSocket.send("{ \"kind\":\"CHECK_CONNECTOR\", \"target\":\"" + connection.target.id + "\" }");
-	});
-	jsPlumb.select({scope:"RESOURCE"}).each(function(connection) {
-            Wicket.WebSocket.send("{ \"kind\":\"CHECK_RESOURCE\", \"target\":\"" + connection.target.id + "\" }");
-	});
+window.checkConnection = function () {
+  jsPlumb.ready(function () {
+    jsPlumb.select({scope: "CONNECTOR"}).each(function (connection) {
+      Wicket.WebSocket.send("{ \"kind\":\"CHECK_CONNECTOR\", \"target\":\"" + connection.target.id + "\" }");
+    });
+    jsPlumb.select({scope: "RESOURCE"}).each(function (connection) {
+      Wicket.WebSocket.send("{ \"kind\":\"CHECK_RESOURCE\", \"target\":\"" + connection.target.id + "\" }");
     });
+  });
 }
 
-window.addEndpoint = function(source, target, scope) {
-    var sourceElement = $(document.getElementById(source));
+window.addEndpoint = function (source, target, scope) {
+  var sourceElement = $(document.getElementById(source));
 
-    var top = parseFloat(sourceElement.css("top")) + 10;
-    var left = parseFloat(sourceElement.css("left")) - 150;
+  var top = parseFloat(sourceElement.css("top")) + 10;
+  var left = parseFloat(sourceElement.css("left")) - 150;
 
-    setPosition(target, left, top);
-    jsPlumb.ready(function(){
-	jsPlumb.draggable(jsPlumb.getSelector(document.getElementById(target)));
-	jsPlumb.connect({ source:source, target:target, scope:scope }, def);
-    });
+  setPosition(target, left, top);
+  jsPlumb.ready(function () {
+    jsPlumb.draggable(jsPlumb.getSelector(document.getElementById(target)));
+    jsPlumb.connect({source: source, target: target, scope: scope}, def);
+  });
 }
 
 jsPlumb.importDefaults({
-    Connector : [ "Straight" ],
-    DragOptions: {
-	cursor: "pointer",
-	zIndex: 2000
-    },
-    HoverClass: "connector-hover"
+  Connector: ["Straight"],
+  DragOptions: {
+    cursor: "pointer",
+    zIndex: 2000
+  },
+  HoverClass: "connector-hover"
 });
 
-jQuery(function($) {
-    Wicket.Event.subscribe("/websocket/message", function(jqEvent, message) {
-	var val = JSON.parse(decodeURIComponent(message));
-	switch (val.status) {
-	case 'UNKNOWN':
-	    unknown(val.target);
-	    break;
-        case 'REACHABLE':
-	    enable(val.target);
-	    break;
-	case 'UNREACHABLE':
-	    disable(val.target);
-	    break;
-        case 'FAILURE':
-	    failure(val.target);
-	    break;
-	default:
-	    break;
-	}
-    });
+jQuery(function ($) {
+  Wicket.Event.subscribe("/websocket/message", function (jqEvent, message) {
+    var val = JSON.parse(decodeURIComponent(message));
+    switch (val.status) {
+      case 'UNKNOWN':
+        unknown(val.target);
+        break;
+      case 'REACHABLE':
+        enable(val.target);
+        break;
+      case 'UNREACHABLE':
+        disable(val.target);
+        break;
+      case 'FAILURE':
+        failure(val.target);
+        break;
+      default:
+        break;
+    }
+  });
 });
-

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html
new file mode 100644
index 0000000..f42367b
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html
@@ -0,0 +1,119 @@
+<!--
+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://xmlns.jcp.org/jsf/composite">
+  <head><title>toggle menu</title></head>
+  <body>
+    <wicket:head>
+      <script type="text/javascript">
+        $(document).ready(function () {
+          $("div.defaultTogglePanel").click(function () {
+            $("div.inactive-topology-menu").toggle("slow");
+            $("div.inactive-topology-menu").attr("class", "topology-menu active-topology-menu");
+
+            $("div.active-topology-menu div a#close").click(function () {
+              $("div.active-topology-menu").toggle("slow");
+              $("div.active-topology-menu").attr("class", "topology-menu inactive-topology-menu");
+            });
+          });
+        });
+      </script>
+
+      <style type="text/css">
+        div.topology-menu {
+          display: none;
+          border-radius: 5px;
+          background-color: rgba(0, 0, 0, 0.45);
+          color: #fff;
+          position: absolute;
+          right: 5px;
+          top: 130px;
+          width: auto;
+          min-width: 250px;
+          z-index: 6000;
+        }
+
+        div.topology-menu ul.menu {
+          list-style: outside none none;
+          margin: 0;
+          padding: 0;
+          list-style: outside none none;
+        }
+
+        div.topology-menu ul.menu li {
+          display: block;
+          line-height: 2em;
+          vertical-align: middle;
+          padding: 5px 10px;
+        }
+
+        div.topology-menu ul.menu li a {
+          position: relative;
+          padding: 12px 5px 12px 15px;
+        }
+
+        div.topology-menu div.header a:active,
+        div.topology-menu div.header a:link,
+        div.topology-menu div.header a:visited,
+        div.topology-menu ul a:active,
+        div.topology-menu ul a:link,
+        div.topology-menu ul a:visited{
+          color: #fff;
+        }
+
+        div.topology-menu ul li:hover {
+          color: #fff;
+          background-color: rgba(0, 0, 0, 0.2);
+          z-index: 1000;
+          font-weight: bold;
+        }
+
+        div.topology-menu div.header {
+          background-color: rgba(0, 0, 0, 0);
+          position: relative;
+          font-size: 1.5em;
+          padding-bottom: 5px;
+          border-bottom: 1px solid #aaa;
+        }
+
+        div.topology-menu div.header a {
+          display: inline-table;
+          padding: 6px 2px 0px 0px;
+        }
+
+        div.topology-menu div.header .close {
+          text-align: right;
+        }
+      </style>
+    </wicket:head>
+    <wicket:panel>
+      <div class="topology-menu inactive-topology-menu">
+        <div class="header">
+          <div class="label">
+            <label wicket:id="label"/>
+          </div>
+          <div class="close">
+            <a wicket:id="close" id="close" href="#"><i class="glyphicon glyphicon-remove"></i></a>
+          </div>
+        </div>
+        <wicket:child/>
+      </div>
+      <div wicket:id="resource-modal">[modal]</div>
+    </wicket:panel>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/Topology.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/Topology.html b/client/console/src/main/resources/org/apache/syncope/client/console/topology/Topology.html
index c9bd4f3..14370cf 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/Topology.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/Topology.html
@@ -39,6 +39,8 @@ under the License.
     </style>
   </wicket:head>
   <wicket:extend>
+    <span wicket:id="toggle"/>
+
     <div id="zoom" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
       <span wicket:id="zoom">[Actions]</span>
     </div>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.html
index 6faea50..d1214be 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.html
@@ -19,44 +19,6 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:panel>
-    <wicket:container wicket:id="actions" />
     <p class="text-center text-primary" wicket:id="label"/>
-
-    <wicket:fragment wicket:id="connectorActions">
-      <div class="node-action-link btn-group">
-        <a href="javascript:void(0);" data-toggle="dropdown">
-          <i class="fa fa-sliders"></i>
-        </a>
-        <ul role="menu" class="dropdown-menu">
-          <li><a href="#" wicket:id="create"><i class="fa fa-plus"></i></a></li>
-          <li><a href="#" wicket:id="delete"><i class="fa fa-minus"></i></a></li>
-          <li><a href="#" wicket:id="edit"><i class="fa fa-pencil"></i></a></li>
-        </ul>
-      </div>
-    </wicket:fragment>
-
-    <wicket:fragment wicket:id="resourceActions">
-      <div class="node-action-link btn-group">
-        <a href="javascript:void(0);" data-toggle="dropdown">
-          <i class="fa fa-sliders"></i>
-        </a>
-        <ul role="menu" class="dropdown-menu">
-          <li><a href="#" wicket:id="delete"><i class="fa fa-minus"></i></a></li>
-          <li><a href="#" wicket:id="edit"><i class="fa fa-pencil"></i></a></li>
-        </ul>
-      </div>
-    </wicket:fragment>
-
-    <wicket:fragment wicket:id="locationActions">
-      <div class="node-action-link btn-group">
-        <a href="javascript:void(0);" data-toggle="dropdown">
-          <i class="fa fa-sliders"></i>
-        </a>
-        <ul role="menu" class="dropdown-menu">
-          <li><a href="#" wicket:id="create"><i class="fa fa-plus"></i></a></li>
-        </ul>
-      </div>
-    </wicket:fragment>
-    <wicket:fragment wicket:id="syncopeActions" />
   </wicket:panel>
 </html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.properties
deleted file mode 100644
index e0c2918..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel.properties
+++ /dev/null
@@ -1,20 +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.
-connector.new=New connector
-resource.new=New resource
-connector.edit=Edit connector {0}
-resource.edit=Edit resource {0}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_it.properties
deleted file mode 100644
index be33d41..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_it.properties
+++ /dev/null
@@ -1,20 +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.
-connector.new=Nuovo connettore
-resource.new=Nuova risorsa
-connector.edit=Modifica connettore {0}
-resource.edit=Modifica risorsa {0}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_pt_BR.properties
deleted file mode 100644
index 48ce11e..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyNodePanel_pt_BR.properties
+++ /dev/null
@@ -1,20 +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.
-connector.new=Novo conector
-resource.new=Novo recurso
-connector.edit=Alterar conector {0}
-resource.edit=Alterar recurso {0}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
new file mode 100644
index 0000000..99f3a3a
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
@@ -0,0 +1,51 @@
+<!--
+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://xmlns.jcp.org/jsf/composite">
+  <head><title>toggle menu</title></head>
+  <body>
+    <wicket:extend>
+      <div wicket:id="container" >
+        <wicket:container wicket:id="actions" />
+      </div>
+
+      <wicket:fragment wicket:id="connectorActions">
+        <ul class="menu">
+          <li><i class="fa fa-plus"></i><a href="#" wicket:id="create"><wicket:message key="resource.menu.add"/></a></li>
+          <li><i class="fa fa-minus"></i><a href="#" wicket:id="delete"><wicket:message key="connector.menu.remove"/></a></li>
+          <li><i class="fa fa-pencil"></i><a href="#" wicket:id="edit"><wicket:message key="connector.menu.edit"/></a></li>
+        </ul>
+      </wicket:fragment>
+
+      <wicket:fragment wicket:id="resourceActions">
+        <ul class="menu">
+          <li><i class="fa fa-minus"></i><a href="#" wicket:id="delete"><wicket:message key="resource.menu.remove"/></a></li>
+          <li><i class="fa fa-pencil"></i><a href="#" wicket:id="edit"><wicket:message key="resource.menu.edit"/></a></li>
+        </ul>
+      </wicket:fragment>
+
+      <wicket:fragment wicket:id="locationActions">
+        <ul class="menu">
+          <li><i class="fa fa-plus"></i><a href="#" wicket:id="create"><wicket:message key="connector.menu.add"/></a></li>
+        </ul>
+      </wicket:fragment>
+
+      <wicket:fragment wicket:id="emptyFragment"></wicket:fragment>
+    </wicket:extend>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
new file mode 100644
index 0000000..8bbd6e7
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
@@ -0,0 +1,28 @@
+# 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.
+connector.new=New connector
+connector.menu.add=Add new connector
+connector.menu.remove=Remove connector
+connector.menu.edit=Edit connector
+
+resource.new=New resource
+resource.menu.add=Add new resource
+resource.menu.remove=Remove resource
+resource.menu.edit=Edit resource
+
+connector.edit=Edit connector {0}
+resource.edit=Edit resource {0}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
new file mode 100644
index 0000000..7204af1
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
@@ -0,0 +1,26 @@
+# 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.
+connector.new=Nuovo connettore
+resource.new=Nuova risorsa
+connector.edit=Modifica connettore {0}
+resource.edit=Modifica risorsa {0}
+connector.menu.add=Aggiungi nuovo connettore
+connector.menu.remove=Rimuovi connettore
+connector.menu.edit=Modifica connettore
+resource.menu.add=Aggiungi nuova risorsa
+resource.menu.remove=Rimuovi risorsa
+resource.menu.edit=Modifica risorsa

http://git-wip-us.apache.org/repos/asf/syncope/blob/9536ffa9/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
new file mode 100644
index 0000000..0ee9526
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
@@ -0,0 +1,26 @@
+# 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.
+connector.new=Novo conector
+resource.new=Novo recurso
+connector.edit=Alterar conector {0}
+resource.edit=Alterar recurso {0}
+connector.menu.add=Adicionar novo conector
+connector.menu.remove=Retire conector
+connector.menu.edit=Alterar conector
+resource.menu.add=Adicionar novo recurso
+resource.menu.remove=Retire recurso
+resource.menu.edit=Alterar recurso