You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2019/03/07 14:22:53 UTC

[syncope] branch master updated: [SYNCOPE-1421] first working release of enduser 3.0, added ui-commons module

This is an automated email from the ASF dual-hosted git repository.

andreapatricelli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new c8e5eb5  [SYNCOPE-1421] first working release of enduser 3.0, added ui-commons module
c8e5eb5 is described below

commit c8e5eb5b16dd3319fc10436c47407499e4d3a775
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Thu Jan 3 09:07:36 2019 +0100

    [SYNCOPE-1421] first working release of enduser 3.0, added ui-commons module
---
 ...DirectoryPanelAditionalActionLinksProvider.java |    2 +-
 .../IdMAnyWizardBuilderAdditionalSteps.java        |    6 +-
 .../client/console/commons/IdMStatusProvider.java  |    2 +-
 .../commons/status/AbstractStatusBeanProvider.java |    1 +
 .../ConnInstanceHistoryConfDirectoryPanel.java     |    1 +
 .../syncope/client/console/panels/ConnObjects.java |    3 +-
 .../client/console/panels/HistoryConfDetails.java  |    2 +-
 .../client/console/panels/HistoryConfList.java     |    1 +
 .../console/panels/ProvisionAuxClassesPanel.java   |    4 +-
 .../console/panels/RemediationDirectoryPanel.java  |    4 +-
 .../panels/ResourceHistoryConfDirectoryPanel.java  |    1 +
 .../client/console/panels/VirSchemaDetails.java    |    8 +-
 .../client/console/rest/ConnectorRestClient.java   |   17 +-
 .../console/status/AnyStatusDirectoryPanel.java    |    8 +-
 .../client/console/status/AnyStatusModal.java      |    2 +-
 .../client/console/status/ReconTaskPanel.java      |    6 +-
 .../status/ResourceStatusDirectoryPanel.java       |    6 +-
 .../client/console/status/ResourceStatusModal.java |    4 +-
 .../syncope/client/console/status/StatusModal.java |    4 +-
 .../console/topology/TopologyTogglePanel.java      |    2 +-
 .../markup/html/list/ConnConfPropertyListView.java |   14 +-
 .../wizards/resources/AbstractMappingPanel.java    |    6 +-
 .../resources/AbstractResourceWizardBuilder.java   |    5 +-
 .../wizards/resources/CapabilitiesPanel.java       |    2 +-
 .../wizards/resources/ConnectorDetailsPanel.java   |    8 +-
 .../wizards/resources/ConnectorWizardBuilder.java  |    2 +-
 .../resources/ItemTransformersTogglePanel.java     |    2 +-
 .../resources/JEXLTransformersTogglePanel.java     |    2 +-
 .../wizards/resources/ObjectTypeTogglePanel.java   |    2 +-
 .../wizards/resources/ProvisionWizardBuilder.java  |   10 +-
 .../resources/ResourceConnCapabilitiesPanel.java   |    4 +-
 .../wizards/resources/ResourceDetailsPanel.java    |   10 +-
 .../wizards/resources/ResourceMappingPanel.java    |    2 +-
 .../wizards/resources/ResourceProvisionPanel.java  |    2 +-
 .../wizards/resources/ResourceSecurityPanel.java   |    2 +-
 .../wizards/resources/ResourceWizardBuilder.java   |    2 +-
 client/idrepo/console/pom.xml                      |    6 +
 .../client/console/SyncopeWebApplication.java      |   25 +-
 .../syncope/client/console/batch/BatchContent.java |    4 +-
 .../syncope/client/console/batch/BatchModal.java   |    2 +-
 ...DirectoryPanelAditionalActionLinksProvider.java |    2 +-
 .../commons/AnyWizardBuilderAdditionalSteps.java   |    6 +-
 ...DirectoryPanelAditionalActionLinksProvider.java |    2 +-
 .../EmptyAnyWizardBuilderAdditionalSteps.java      |    6 +-
 .../console/commons/EmptyStatusProvider.java       |    2 +-
 .../client/console/commons/PreviewUtils.java       |    4 +-
 .../client/console/commons/StatusProvider.java     |    2 +-
 .../client/console/events/EventCategoryPanel.java  |    4 +-
 .../client/console/events/EventSelectionPanel.java |    2 +-
 .../init/ClassPathScanImplementationLookup.java    |    4 +-
 .../client/console/init/MIMETypesLoader.java       |   53 +-
 .../client/console/layout/AnyObjectForm.java       |    1 +
 .../console/layout/AnyObjectFormLayoutInfo.java    |    1 +
 .../client/console/layout/FormLayoutInfoUtils.java |    2 +
 .../syncope/client/console/layout/GroupForm.java   |    1 +
 .../client/console/layout/GroupFormLayoutInfo.java |    1 +
 .../client/console/layout/UserFormLayoutInfo.java  |    2 +
 .../notifications/MailTemplateDirectoryPanel.java  |    6 +-
 .../notifications/NotificationDirectoryPanel.java  |    2 +-
 .../console/notifications/NotificationTasks.java   |    2 +-
 .../notifications/NotificationWizardBuilder.java   |   16 +-
 .../console/notifications/TemplateModal.java       |    2 +-
 .../syncope/client/console/pages/BasePage.java     |   24 +-
 .../syncope/client/console/pages/LogViewer.java    |    2 +-
 .../apache/syncope/client/console/pages/Login.java |  173 +--
 .../client/console/pages/MustChangePassword.java   |    4 +-
 .../syncope/client/console/pages/Realms.java       |   11 +-
 .../client/console/panels/AbstractLogsPanel.java   |    4 +-
 .../client/console/panels/AbstractModalPanel.java  |    2 +
 .../console/panels/AbstractSchemaDetailsPanel.java |    2 +-
 .../console/panels/ActionDataTablePanel.java       |    2 +-
 .../client/console/panels/AjaxDataTablePanel.java  |    4 +-
 .../client/console/panels/AnyDirectoryPanel.java   |    4 +-
 .../console/panels/AnyObjectDirectoryPanel.java    |    4 +-
 .../syncope/client/console/panels/AnyPanel.java    |    4 +-
 .../console/panels/AnyTypeClassDetailsPanel.java   |    4 +-
 .../client/console/panels/AnyTypeClassesPanel.java |    5 +-
 .../client/console/panels/AnyTypeDetailsPanel.java |    6 +-
 .../client/console/panels/AnyTypesPanel.java       |    5 +-
 .../console/panels/ApplicationModalPanel.java      |    2 +-
 .../syncope/client/console/panels/BeanPanel.java   |   12 +-
 .../client/console/panels/DirectoryPanel.java      |    4 +-
 .../panels/DisplayAttributesModalPanel.java        |    2 +-
 .../client/console/panels/DynRealmModalPanel.java  |    4 +-
 .../client/console/panels/ExecMessageModal.java    |    1 +
 .../client/console/panels/FailureMessageModal.java |    1 +
 .../client/console/panels/GroupDirectoryPanel.java |    5 +-
 .../panels/ImplementationEngineTogglePanel.java    |    2 +-
 .../console/panels/ImplementationModalPanel.java   |    4 +-
 .../client/console/panels/ListViewPanel.java       |    4 +-
 .../client/console/panels/MembersTogglePanel.java  |    4 +-
 .../console/panels/ParametersCreateModalPanel.java |    2 +-
 .../panels/ParametersCreateWizardAttrStep.java     |   12 +-
 .../panels/ParametersCreateWizardPanel.java        |    4 +-
 .../panels/ParametersCreateWizardSchemaStep.java   |    8 +-
 .../console/panels/ParametersDetailsPanel.java     |   12 +-
 .../console/panels/ParametersDirectoryPanel.java   |    5 +-
 .../client/console/panels/PlainSchemaDetails.java  |    8 +-
 .../console/panels/PrivilegeDirectoryPanel.java    |    3 +-
 .../console/panels/PrivilegeWizardBuilder.java     |    6 +-
 .../syncope/client/console/panels/Realm.java       |    2 +-
 .../client/console/panels/RealmDetails.java        |    8 +-
 .../client/console/panels/RealmWizardBuilder.java  |    4 +-
 .../panels/RelationshipTypeDetailsPanel.java       |    2 +-
 .../console/panels/RelationshipTypesPanel.java     |    5 +-
 .../client/console/panels/RoleDirectoryPanel.java  |    3 +-
 .../client/console/panels/SchemaTypePanel.java     |    2 +-
 .../console/panels/SchemaTypeWizardBuilder.java    |    8 +-
 .../client/console/panels/SchemasPanel.java        |    4 +-
 .../panels/SecurityQuestionDetailsPanel.java       |    2 +-
 .../console/panels/SecurityQuestionsPanel.java     |    5 +-
 .../client/console/panels/StartAtTogglePanel.java  |    4 +-
 .../syncope/client/console/panels/TogglePanel.java |    6 +-
 .../panels/TypeExtensionDirectoryPanel.java        |    3 +-
 .../client/console/panels/TypesDirectoryPanel.java |    2 +-
 .../client/console/panels/UserDirectoryPanel.java  |    6 +-
 .../search/AnyObjectSelectionDirectoryPanel.java   |    2 +-
 .../search/GroupSelectionDirectoryPanel.java       |    2 +-
 .../console/panels/search/SearchClausePanel.java   |    8 +-
 .../panels/search/UserSelectionDirectoryPanel.java |    2 +-
 .../console/policies/PolicyDirectoryPanel.java     |    2 +-
 .../console/policies/PolicyModalPanelBuilder.java  |   18 +-
 .../console/policies/PolicyRuleDirectoryPanel.java |    4 +-
 .../console/policies/PolicyRuleWizardBuilder.java  |    6 +-
 .../policies/ProvisioningPolicyModalPanel.java     |   13 +-
 .../console/reports/ReportDirectoryPanel.java      |    2 +-
 .../console/reports/ReportExecutionDetails.java    |    2 +-
 .../reports/ReportTemplateDirectoryPanel.java      |    6 +-
 .../console/reports/ReportWizardBuilder.java       |   10 +-
 .../console/reports/ReportletDirectoryPanel.java   |    4 +-
 .../console/reports/ReportletWizardBuilder.java    |    6 +-
 .../client/console/rest/AbstractAnyRestClient.java |    4 +-
 .../client/console/rest/BaseRestClient.java        |    1 +
 .../client/console/rest/ExecutionRestClient.java   |    1 +
 .../client/console/rest/TemplateRestClient.java    |    1 +
 .../client/console/rest/UserRestClient.java        |    6 +-
 .../client/console/status/ChangePasswordModal.java |    8 +-
 .../client/console/tasks/AbstractTasks.java        |    2 +-
 .../syncope/client/console/tasks/CrontabPanel.java |   10 +-
 .../tasks/NotificationTaskDirectoryPanel.java      |    2 +-
 .../tasks/PropagationTaskDirectoryPanel.java       |    2 +-
 .../client/console/tasks/PushTaskFilters.java      |    2 +-
 .../console/tasks/SchedTaskDirectoryPanel.java     |    4 +-
 .../console/tasks/SchedTaskWizardBuilder.java      |   14 +-
 .../client/console/tasks/TaskDirectoryPanel.java   |    2 +-
 .../client/console/tasks/TemplatesTogglePanel.java |    8 +-
 .../markup/html/bootstrap/dialog/BaseModal.java    |    6 +-
 .../markup/html/form/ActionLinksTogglePanel.java   |    6 +-
 .../markup/html/form/AjaxDateFieldPanel.java       |   10 +
 .../markup/html/form/AjaxDateTimeFieldPanel.java   |   10 +
 .../wicket/markup/html/form/AjaxDownload.java      |    2 +-
 .../wicket/markup/html/form/BinaryFieldPanel.java  |   19 +-
 .../wicket/markup/html/form/MultiFieldPanel.java   |   12 +-
 .../wicket/markup/html/form/MultiPanel.java        |    1 +
 .../html/form/preview/BinaryCertPreviewer.java     |    3 +-
 .../html/form/preview/BinaryImagePreviewer.java    |    3 +-
 .../html/form/preview/BinaryPDFPreviewer.java      |    3 +-
 .../html/form/preview/BinaryTextPreviewer.java     |    3 +-
 .../syncope/client/console/widgets/JobWidget.java  |    2 +-
 .../console/wizards/BaseAjaxWizardBuilder.java     |   59 +
 .../client/console/wizards/WizardMgtPanel.java     |   10 +-
 .../client/console/wizards/any/AbstractAttrs.java  |    1 +
 .../console/wizards/any/AnyObjectDetails.java      |    3 +-
 .../any/AnyObjectTemplateWizardBuilder.java        |    3 +-
 .../wizards/any/AnyObjectWizardBuilder.java        |    3 +-
 .../console/wizards/any/AnyObjectWrapper.java      |    1 +
 .../console/wizards/any/AnyWizardBuilder.java      |   39 +-
 .../console/wizards/any/ConnObjectPanel.java       |    4 +-
 .../{AnyWrapper.java => ConsoleAuxClasses.java}    |   21 +-
 .../client/console/wizards/any/DerAttrs.java       |    5 +-
 .../client/console/wizards/any/Details.java        |    7 +-
 .../console/wizards/any/DynamicMemberships.java    |    2 +-
 .../client/console/wizards/any/GroupDetails.java   |    2 +-
 .../wizards/any/GroupTemplateWizardBuilder.java    |    3 +-
 .../console/wizards/any/GroupWizardBuilder.java    |    5 +-
 .../client/console/wizards/any/GroupWrapper.java   |    1 +
 .../syncope/client/console/wizards/any/Groups.java |  101 +-
 .../client/console/wizards/any/Ownership.java      |    4 +-
 .../client/console/wizards/any/PlainAttrs.java     |   24 +-
 .../client/console/wizards/any/Relationships.java  |   10 +-
 .../client/console/wizards/any/Resources.java      |   51 +-
 .../client/console/wizards/any/ResultPage.java     |    2 +-
 .../syncope/client/console/wizards/any/Roles.java  |    6 +-
 .../client/console/wizards/any/StatusPanel.java    |    8 +-
 .../console/wizards/any/TemplateWizardBuilder.java |    3 +-
 .../wizards/any/TypeExtensionWizardBuilder.java    |   10 +-
 .../client/console/wizards/any/UserDetails.java    |    8 +-
 .../wizards/any/UserTemplateWizardBuilder.java     |    4 +-
 .../console/wizards/any/UserWizardBuilder.java     |    8 +-
 .../client/console/wizards/any/VirAttrs.java       |   12 +-
 .../console/wizards/role/RoleWizardBuilder.java    |   11 +-
 .../{AuxClasses.html => ConsoleAuxClasses.html}    |    0
 ...ses.properties => ConsoleAuxClasses.properties} |    0
 ....properties => ConsoleAuxClasses_it.properties} |    0
 ....properties => ConsoleAuxClasses_ja.properties} |    0
 ...operties => ConsoleAuxClasses_pt_BR.properties} |    0
 ....properties => ConsoleAuxClasses_ru.properties} |    0
 .../markup/html/form/AbstractFieldPanel.html       |    0
 .../markup/html/form/AjaxCheckBoxPanel.html        |    0
 .../markup/html/form/AjaxDropDownChoicePanel.html  |    0
 .../markup/html/form/AjaxPalettePanel.html         |    0
 .../markup/html/form/AjaxPasswordFieldPanel.html   |    0
 .../markup/html/form/AjaxSpinnerFieldPanel.html    |    0
 .../markup/html/form/AjaxTextFieldPanel.html       |    0
 .../markup/html/form/EncryptedFieldPanel.html      |    0
 .../html/form/EncryptedFieldPanel.properties       |    0
 .../html/form/EncryptedFieldPanel_it.properties    |    0
 .../html/form/EncryptedFieldPanel_ja.properties    |    0
 .../html/form/EncryptedFieldPanel_pt_BR.properties |    0
 .../html/form/EncryptedFieldPanel_ru.properties    |    0
 .../commons}/markup/html/form/NonI18nPalette.html  |    0
 .../html/form/preview/AbstractBinaryPreviewer.html |    0
 .../markup/html/form/preview/DefaultPreviewer.html |    0
 .../{console => ui/commons}/panels/LabelPanel.html |    0
 .../commons}/panels/NotificationPanel.html         |    0
 .../markup/html/bootstrap/tabs/Accordion.html      |    0
 .../commons}/wizards/AjaxWizard.html               |    0
 .../commons}/wizards/AjaxWizard.properties         |    0
 .../commons}/wizards/AjaxWizardMgtButtonBar.html   |    0
 .../commons}/wizards/AjaxWizard_it.properties      |    0
 .../commons}/wizards/AjaxWizard_ja.properties      |    0
 .../commons}/wizards/AjaxWizard_pt_BR.properties   |    0
 .../commons}/wizards/AjaxWizard_ru.properties      |    0
 .../commons}/wizards/any/PasswordPanel.html        |    0
 client/idrepo/{console => enduser}/pom.xml         |   16 +-
 .../client/enduser/SyncopeEnduserApplication.java  |   62 +
 .../client/enduser/SyncopeEnduserConstants.java}   |   20 +-
 .../client/enduser/SyncopeEnduserSession.java      |  230 ++++
 .../client/enduser/SyncopeWebApplication.java      |  407 ++++++
 .../client/enduser/annotations/Resource.java}      |   14 +-
 .../client/enduser}/commons/PreviewUtils.java      |   20 +-
 .../init/ClassPathScanImplementationLookup.java    |  113 ++
 .../client/enduser/init/MIMETypesLoader.java}      |   17 +-
 .../enduser}/layout/FormLayoutInfoUtils.java       |   74 +-
 .../client/enduser}/layout/UserFormLayoutInfo.java |   27 +-
 .../markup/html/form/AjaxDateFieldPanel.java       |   16 +-
 .../markup/html/form/AjaxDateTimeFieldPanel.java   |   16 +-
 .../enduser}/markup/html/form/AjaxDownload.java    |    6 +-
 .../markup/html/form/BinaryFieldPanel.java         |   46 +-
 .../enduser}/markup/html/form/MultiFieldPanel.java |   14 +-
 .../client/enduser/model/CustomAttribute.java      |   62 +
 .../enduser/model/CustomAttributesInfo.java}       |   28 +-
 .../client/enduser/pages/BaseEnduserWebPage.java}  |   21 +-
 .../syncope/client/enduser/pages/LandingPage.java} |   14 +-
 .../apache/syncope/client/enduser/pages/Login.java |   95 ++
 .../client/enduser/pages/MustChangePassword.java}  |   16 +-
 .../apache/syncope/client/enduser/pages/Self.java  |   87 ++
 .../client/enduser/pages/SelfPasswordReset.java}   |   14 +-
 .../syncope/client/enduser/pages/SelfUpdate.java}  |   14 +-
 .../client/enduser/resources/CaptchaResource.java  |   56 +
 .../enduser/rest/AbstractAnyRestClient.java}       |   19 +-
 .../client/enduser/rest/AnyTypeRestClient.java     |  130 ++
 .../client/enduser}/rest/BaseRestClient.java       |   20 +-
 .../client/enduser/rest/GroupRestClient.java       |   78 ++
 .../client/enduser/rest/RealmRestClient.java}      |   22 +-
 .../client/enduser/rest/RoleRestClient.java        |   83 ++
 .../client/enduser/rest/SchemaRestClient.java      |  146 +++
 .../enduser/rest/SecurityQuestionRestClient.java}  |   19 +-
 .../client/enduser/rest/SyncopeRestClient.java}    |   25 +-
 .../client/enduser/rest/UserSelfRestClient.java    |   61 +
 .../client/enduser/themes/EnduserTheme.java}       |   29 +-
 .../themes/EnduserThemeCssResourceReference.java   |   48 +
 .../client/enduser}/wizards/any/AbstractAttrs.java |   26 +-
 .../enduser/wizards/any/AnyWizardBuilder.java      |  153 +++
 .../client/enduser}/wizards/any/DerAttrs.java      |   11 +-
 .../enduser/wizards/any/EnduserAuxClasses.java     |   45 +
 .../syncope/client/enduser/wizards/any/Groups.java |  192 +++
 .../client/enduser}/wizards/any/PlainAttrs.java    |  203 +--
 .../client/enduser/wizards/any/Resources.java}     |   27 +-
 .../client/enduser}/wizards/any/UserDetails.java   |  106 +-
 .../enduser}/wizards/any/UserWizardBuilder.java    |   30 +-
 .../client/enduser}/wizards/any/VirAttrs.java      |   22 +-
 .../resources/META-INF/cxf/org.apache.cxf.Logger   |    1 +
 .../META-INF/resources/css/accessibility.css}      |   26 +-
 .../css/accessibility/accessibilityFont.css        |  101 ++
 .../css/accessibility/accessibilityHC.css          |  296 +++++
 .../resources/META-INF/resources/css/fonts.css     |   89 ++
 ...-latin-ext_cyrillic_latin_cyrillic-ext-300.woff |  Bin 0 -> 113012 bytes
 ...latin-ext_cyrillic_latin_cyrillic-ext-300.woff2 |  Bin 0 -> 86284 bytes
 ...-ext_cyrillic_latin_cyrillic-ext-300italic.woff |  Bin 0 -> 46356 bytes
 ...ext_cyrillic_latin_cyrillic-ext-300italic.woff2 |  Bin 0 -> 35780 bytes
 ...-latin-ext_cyrillic_latin_cyrillic-ext-600.woff |  Bin 0 -> 113196 bytes
 ...latin-ext_cyrillic_latin_cyrillic-ext-600.woff2 |  Bin 0 -> 86120 bytes
 ...-ext_cyrillic_latin_cyrillic-ext-600italic.woff |  Bin 0 -> 46280 bytes
 ...ext_cyrillic_latin_cyrillic-ext-600italic.woff2 |  Bin 0 -> 35928 bytes
 ...-latin-ext_cyrillic_latin_cyrillic-ext-700.woff |  Bin 0 -> 112628 bytes
 ...latin-ext_cyrillic_latin_cyrillic-ext-700.woff2 |  Bin 0 -> 85436 bytes
 ...tin-ext_cyrillic_latin_cyrillic-ext-italic.woff |  Bin 0 -> 46364 bytes
 ...in-ext_cyrillic_latin_cyrillic-ext-italic.woff2 |  Bin 0 -> 35924 bytes
 ...in-ext_cyrillic_latin_cyrillic-ext-regular.woff |  Bin 0 -> 113924 bytes
 ...n-ext_cyrillic_latin_cyrillic-ext-regular.woff2 |  Bin 0 -> 86732 bytes
 .../resources/META-INF/resources/css/login.css     |  142 +++
 .../META-INF/resources/css/syncopeEnduser.css      | 1164 ++++++++++++++++++
 .../META-INF/resources/img/logo-green.png          |  Bin 0 -> 12178 bytes
 .../main/resources/META-INF/resources/img/logo.png |  Bin 0 -> 8913 bytes
 .../enduser/src/main/resources/MIMETypes.json      | 1289 ++++++++++++++++++++
 .../src/main/resources/application.properties}     |   10 +-
 .../src/main/resources/customFormAttributes.json   |    1 +
 .../src/main/resources/enduser.properties}         |   18 +-
 .../enduser/SyncopeWebApplication.properties       |   77 ++
 .../enduser/SyncopeWebApplication_it.properties    |   76 ++
 .../enduser/SyncopeWebApplication_ja.properties    |   74 ++
 .../enduser/SyncopeWebApplication_pt_BR.properties |   76 ++
 .../enduser/SyncopeWebApplication_ru.properties    |   75 ++
 .../markup/html/form/AjaxDateFieldPanel.html}      |    8 +-
 .../markup/html/form/AjaxDateTimeFieldPanel.html}  |   15 +-
 .../markup/html/form/BinaryFieldPanel.html}        |   20 +-
 .../markup/html/form/BinaryFieldPanel.properties}  |    2 +-
 .../html/form/BinaryFieldPanel_ja.properties}      |    2 +-
 .../enduser/markup/html/form/MultiFieldPanel.html  |   67 +
 .../markup/html/form/MultiFieldPanel_ru.properties |   29 +
 .../client/enduser/pages/BaseEnduserWebPage.html   |   64 +
 .../syncope/client/enduser/pages/LandingPage.html} |   10 +-
 .../apache/syncope/client/enduser/pages/Login.html |   90 ++
 .../syncope/client/enduser/pages/Login.properties} |    7 +-
 .../client/enduser/pages/Login_it.properties}      |    7 +-
 .../client/enduser/pages/Login_ja.properties}      |    7 +-
 .../client/enduser/pages/Login_pt_BR.properties}   |    7 +-
 .../client/enduser/pages/Login_ru.properties       |   27 +
 .../client/enduser/pages/MustChangePassword.html   |   58 +
 .../apache/syncope/client/enduser/pages/Self.html} |   10 +-
 .../client/enduser/pages/SelfPasswordReset.html}   |    9 +-
 .../syncope/client/enduser/pages/SelfUpdate.html}  |   10 +-
 .../client/enduser/pages/WizardMgtPanel.html       |   60 +
 .../client/enduser/themes/css/accessibility.css}   |   37 +-
 .../syncope/client/enduser/themes/css/app.css      |  110 ++
 .../client/enduser/themes/css/customSpinner.css}   |   51 +-
 .../syncope/client/enduser/themes/css/editUser.css |  822 +++++++++++++
 .../syncope/client/enduser/themes/css/init.css}    |   13 +-
 .../syncope/client/enduser/themes/css/login.css    |   83 ++
 .../client/enduser/themes/css/notification.css}    |   19 +-
 .../client/enduser/themes/css/passwordReset.css}   |   35 +-
 .../wizards/any/AbstractAttrs$Schemas.html}        |   10 +-
 .../client/enduser/wizards/any/AbstractAttrs.html} |    7 +-
 .../enduser/wizards/any/AbstractAttrs.properties}  |    3 +-
 .../wizards/any/AbstractAttrs_it.properties}       |    3 +-
 .../wizards/any/AbstractAttrs_ja.properties}       |    3 +-
 .../wizards/any/AbstractAttrs_pt_BR.properties}    |    3 +-
 .../wizards/any/AbstractAttrs_ru.properties}       |    3 +-
 .../client/enduser/wizards/any/DerAttrs.html}      |   11 +-
 .../enduser/wizards/any/DerAttrs.properties}       |    4 +-
 .../enduser/wizards/any/DerAttrs_it.properties}    |    4 +-
 .../enduser/wizards/any/DerAttrs_ja.properties}    |    4 +-
 .../enduser/wizards/any/DerAttrs_pt_BR.properties} |    4 +-
 .../enduser/wizards/any/DerAttrs_ru.properties}    |    5 +-
 .../enduser/wizards/any/EnduserAuxClasses.html}    |    0
 .../wizards/any/EnduserAuxClasses.properties}      |    0
 .../wizards/any/EnduserAuxClasses_it.properties}   |    0
 .../wizards/any/EnduserAuxClasses_ja.properties}   |    0
 .../any/EnduserAuxClasses_pt_BR.properties}        |    0
 .../wizards/any/EnduserAuxClasses_ru.properties}   |    0
 .../client/enduser/wizards/any/Groups.html}        |    6 +-
 .../client/enduser/wizards/any/Groups.properties}  |    3 +-
 .../enduser/wizards/any/Groups_it.properties}      |    3 +-
 .../enduser/wizards/any/Groups_ja.properties}      |    3 +-
 .../enduser/wizards/any/Groups_pt_BR.properties}   |    3 +-
 .../enduser/wizards/any/Groups_ru.properties}      |    4 +-
 .../client/enduser/wizards/any/PlainAttrs.html}    |   11 +-
 .../enduser/wizards/any/PlainAttrs.properties}     |    3 +-
 .../enduser/wizards/any/PlainAttrs_it.properties}  |    3 +-
 .../enduser/wizards/any/PlainAttrs_ja.properties}  |    3 +-
 .../wizards/any/PlainAttrs_pt_BR.properties}       |    3 +-
 .../enduser/wizards/any/PlainAttrs_ru.properties}  |    3 +-
 .../client/enduser/wizards/any/Resources.html}     |    4 +-
 .../enduser/wizards/any/Resources.properties}      |    2 +-
 .../enduser/wizards/any/Resources_it.properties}   |    2 +-
 .../enduser/wizards/any/Resources_ja.properties}   |    2 +-
 .../wizards/any/Resources_pt_BR.properties}        |    2 +-
 .../enduser/wizards/any/Resources_ru.properties}   |    4 +-
 .../any/UserDetails$EditUserPasswordPanel.html}    |    7 +-
 .../client/enduser/wizards/any/UserDetails.html}   |   14 +-
 .../enduser/wizards/any/UserDetails.properties}    |    8 +-
 .../enduser/wizards/any/UserDetails_it.properties} |    8 +-
 .../enduser/wizards/any/UserDetails_ja.properties} |    8 +-
 .../wizards/any/UserDetails_pt_BR.properties}      |    8 +-
 .../enduser/wizards/any/UserDetails_ru.properties} |    8 +-
 .../client/enduser/wizards/any/VirAttrs.html}      |   11 +-
 .../enduser/wizards/any/VirAttrs.properties}       |    3 +-
 .../enduser/wizards/any/VirAttrs_it.properties}    |    3 +-
 .../enduser/wizards/any/VirAttrs_ja.properties}    |    3 +-
 .../enduser/wizards/any/VirAttrs_pt_BR.properties} |    3 +-
 .../enduser/wizards/any/VirAttrs_ru.properties}    |    4 +-
 .../markup/html/form/AbstractFieldPanel.html       |    0
 .../markup/html/form/AjaxCheckBoxPanel.html        |    0
 .../markup/html/form/AjaxDropDownChoicePanel.html  |    0
 .../markup/html/form/AjaxPalettePanel.html         |    0
 .../markup/html/form/AjaxPasswordFieldPanel.html   |    0
 .../markup/html/form/AjaxSpinnerFieldPanel.html    |    0
 .../markup/html/form/AjaxTextFieldPanel.html       |    0
 .../markup/html/form/EncryptedFieldPanel.html      |    0
 .../html/form/EncryptedFieldPanel.properties       |    0
 .../html/form/EncryptedFieldPanel_it.properties    |    0
 .../html/form/EncryptedFieldPanel_ja.properties    |    0
 .../html/form/EncryptedFieldPanel_pt_BR.properties |    0
 .../html/form/EncryptedFieldPanel_ru.properties    |    0
 .../commons}/markup/html/form/NonI18nPalette.html  |    0
 .../html/form/preview/AbstractBinaryPreviewer.html |    0
 .../markup/html/form/preview/DefaultPreviewer.html |    0
 .../client/ui/commons}/panels/LabelPanel.html      |    0
 .../ui/commons}/panels/NotificationPanel.html      |    0
 .../markup/html/bootstrap/tabs/Accordion.html      |    0
 .../client/ui/commons}/wizards/AjaxWizard.html     |    0
 .../ui/commons}/wizards/AjaxWizard.properties      |    0
 .../commons}/wizards/AjaxWizardMgtButtonBar.html   |    0
 .../ui/commons}/wizards/AjaxWizard_it.properties   |    0
 .../ui/commons}/wizards/AjaxWizard_ja.properties   |    0
 .../commons}/wizards/AjaxWizard_pt_BR.properties   |    0
 .../ui/commons}/wizards/AjaxWizard_ru.properties   |    0
 .../ui/commons}/wizards/any/PasswordPanel.html     |    0
 client/idrepo/pom.xml                              |    2 +
 client/idrepo/ui/pom.xml                           |   93 ++
 .../ui/commons/AbstractMIMETypesLoader.java}       |   18 +-
 .../syncope/client/ui/commons/BaseLogin.java}      |  127 +-
 .../client/ui/commons/ConnIdSpecialName.java}      |   31 +-
 .../syncope/client/ui/commons/Constants.java       |  236 ++++
 .../client/ui}/commons/HttpResourceStream.java     |    2 +-
 .../syncope/client/ui}/commons/SchemaUtils.java    |    2 +-
 .../ui/commons/StyledNotificationBehavior.java     |   51 +
 .../ui/commons/SyncopeUIRequestCycleListener.java} |   32 +-
 ...torAjaxFormChoiceComponentUpdatingBehavior.java |    2 +-
 ...IndicatorAjaxFormComponentUpdatingBehavior.java |    2 +-
 .../ajax/form/IndicatorAutoCompleteBehavior.java   |    2 +-
 .../ajax/markup/html/IndicatorAjaxSubmitLink.java  |    2 +-
 .../ui/commons}/ajax/markup/html/LabelInfo.java    |    2 +-
 .../ui/commons}/annotations/BinaryPreview.java     |    2 +-
 .../ui/commons}/layout/AbstractAnyFormLayout.java  |    3 +-
 .../client/ui/commons}/layout/UserForm.java        |    3 +-
 .../markup/html/form/AbstractFieldPanel.java       |    2 +-
 .../markup/html/form/AbstractMultiPanel.java       |   15 +-
 .../markup/html/form/AjaxCheckBoxPanel.java        |    6 +-
 .../markup/html/form/AjaxDropDownChoicePanel.java  |    6 +-
 .../commons}/markup/html/form/AjaxPaletteConf.java |    2 +-
 .../markup/html/form/AjaxPalettePanel.java         |    2 +-
 .../markup/html/form/AjaxPasswordFieldPanel.java   |    6 +-
 .../markup/html/form/AjaxSpinnerFieldPanel.java    |    6 +-
 .../markup/html/form/AjaxTextFieldPanel.java       |    8 +-
 .../markup/html/form/BaseBinaryFieldPanel.java}    |   21 +-
 .../commons}/markup/html/form/DateFieldPanel.java  |   13 +-
 .../markup/html/form/EncryptedFieldPanel.java      |    6 +-
 .../ui/commons}/markup/html/form/FieldPanel.java   |    2 +-
 .../commons}/markup/html/form/NonI18nPalette.java  |    2 +-
 .../markup/html/form/SelectChoiceRenderer.java     |    2 +-
 .../ui/commons}/markup/html/form/SelectOption.java |    2 +-
 .../html/form/preview/AbstractBinaryPreviewer.java |    2 +-
 .../markup/html/form/preview/DefaultPreviewer.java |    4 +-
 .../client/ui/commons/pages/BaseWebPage.java       |   63 +
 .../client/ui/commons}/panels/LabelPanel.java      |    2 +-
 .../client/ui/commons}/panels/ModalPanel.java      |    2 +-
 .../ui/commons}/panels/NotificationPanel.java      |    6 +-
 .../ui/commons/panels/SSOLoginFormPanel.java}      |   10 +-
 .../ui/commons}/panels/SubmitableModalPanel.java   |    2 +-
 .../ui/commons}/panels/WizardModalPanel.java       |    2 +-
 .../client/ui/commons}/rest/RestClient.java        |    2 +-
 .../ui}/commons/status/ConnObjectWrapper.java      |    2 +-
 .../syncope/client/ui}/commons/status/Status.java  |    2 +-
 .../client/ui}/commons/status/StatusBean.java      |    2 +-
 .../client/ui}/commons/status/StatusUtils.java     |    8 +-
 .../markup/html/bootstrap/tabs/Accordion.java      |    2 +-
 .../wizards/AbstractModalPanelBuilder.java         |    2 +-
 .../commons/wizards/AbstractWizardMgtPanel.java}   |   14 +-
 .../client/ui/commons}/wizards/AjaxWizard.java     |   43 +-
 .../ui/commons}/wizards/AjaxWizardBuilder.java     |   36 +-
 .../commons}/wizards/AjaxWizardMgtButtonBar.java   |    6 +-
 .../ui/commons}/wizards/ModalPanelBuilder.java     |    4 +-
 .../wizards/any/AbstractAnyWizardBuilder.java      |   67 +
 .../commons/wizards/any/AbstractAuxClasses.java}   |   17 +-
 .../ui/commons/wizards/any/AbstractGroups.java}    |   57 +-
 .../commons/wizards/any/AbstractGroupsModel.java   |   68 ++
 .../ui/commons/wizards/any/AbstractResources.java} |   36 +-
 .../client/ui/commons/wizards/any}/AnyForm.java    |    5 +-
 .../client/ui/commons}/wizards/any/AnyWrapper.java |    2 +-
 .../ui/commons}/wizards/any/PasswordPanel.java     |   10 +-
 .../ui/commons}/wizards/any/UserWrapper.java       |    2 +-
 .../console/panels/BpmnProcessDirectoryPanel.java  |   28 +-
 .../console/panels/UserRequestFormDetails.java     |    2 +-
 .../panels/UserRequestFormDirectoryPanel.java      |    4 +-
 .../console/panels/UserRequestFormModal.java       |    2 +
 .../console/panels/UserRequestFormPanel.java       |    8 +-
 .../panels/OIDCProvidersDirectoryPanel.java        |    5 +-
 .../console/panels/OIDCSSOLoginFormPanel.java      |    2 +-
 .../console/wizards/OIDCProviderWizardBuilder.java |   35 +-
 .../resources/OIDCProviderMappingPanel.java        |    2 +-
 .../console/panels/SAML2IdPsDirectoryPanel.java    |    5 +-
 .../client/console/panels/SAML2SPPanel.java        |    2 +-
 .../console/panels/SAMLSSOLoginFormPanel.java      |    2 +-
 .../console/wizards/SAML2IdPWizardBuilder.java     |   39 +-
 .../wizards/resources/SAML2IdPMappingPanel.java    |    2 +-
 .../console/panels/SCIMConfAccordionContainer.java |    2 +-
 .../panels/SCIMConfEnterpriseUserPanel.java        |    4 +-
 .../console/panels/SCIMConfGeneralPanel.java       |    2 +-
 .../client/console/panels/SCIMConfTabPanel.java    |    1 +
 .../client/console/panels/SCIMConfUserPanel.java   |    4 +-
 fit/core-reference/pom.xml                         |    6 +
 .../syncope/fit/console/AbstractConsoleITCase.java |   81 +-
 .../fit/console/AjaxPalettePanelITCase.java        |    2 +-
 .../syncope/fit/console/AjaxTextFieldITCase.java   |    2 +-
 .../apache/syncope/fit/console/BatchesITCase.java  |    4 +-
 .../apache/syncope/fit/console/TopologyITCase.java |    2 +-
 .../AbstractEnduserITCase.java}                    |   93 +-
 .../fit/enduser/SelfRegistrationITCase.java        |  105 ++
 .../AbstractUITCase.java}                          |   97 +-
 .../src/test/resources/enduser.properties          |   17 +-
 fit/enduser-reference/pom.xml                      |  227 +---
 .../src/main/resources/log4j2.xml                  |    2 +-
 .../src/main/webapp/WEB-INF/web.xml                |    6 +-
 .../src/test/resources/hotswap-agent.properties    |    2 +-
 .../src/test/resources/protractor-conf.js          |   38 -
 .../src/test/resources/tests/abstract.js           |   40 -
 .../src/test/resources/tests/create.js             |   73 --
 .../src/test/resources/tests/edit.js               |   97 --
 .../src/test/resources/tests/passwordreset.js      |   55 -
 511 files changed, 9669 insertions(+), 2449 deletions(-)

diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyDirectoryPanelAditionalActionLinksProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyDirectoryPanelAditionalActionLinksProvider.java
index 55414fd..9e84c74 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyDirectoryPanelAditionalActionLinksProvider.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyDirectoryPanelAditionalActionLinksProvider.java
@@ -24,7 +24,7 @@ import org.apache.syncope.client.console.status.AnyStatusModal;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.Action;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyWizardBuilderAdditionalSteps.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyWizardBuilderAdditionalSteps.java
index 5484b45..961c667 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyWizardBuilderAdditionalSteps.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMAnyWizardBuilderAdditionalSteps.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.client.console.commons;
 
-import org.apache.syncope.client.console.layout.AbstractAnyFormLayout;
-import org.apache.syncope.client.console.layout.AnyForm;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.Resources;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.wicket.extensions.wizard.WizardModel;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMStatusProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMStatusProvider.java
index 8c43cae..557d182 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMStatusProvider.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMStatusProvider.java
@@ -22,7 +22,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
 import org.apache.syncope.client.console.status.ReconStatusUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
index 7992362..dae1ba6 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.commons.status;
 
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import java.util.Iterator;
 import java.util.List;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnInstanceHistoryConfDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnInstanceHistoryConfDirectoryPanel.java
index 271d104..ca89403 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnInstanceHistoryConfDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnInstanceHistoryConfDirectoryPanel.java
@@ -37,6 +37,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ConnInstanceHistoryConfTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java
index 881ae74..f0ff98c 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java
@@ -23,7 +23,8 @@ import java.util.stream.Collectors;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfDetails.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfDetails.java
index d5a06f4..bc64d5d 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfDetails.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfDetails.java
@@ -31,7 +31,7 @@ import org.apache.syncope.client.console.commons.Constants;
 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.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonDiffPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
 import org.apache.syncope.common.lib.to.AbstractHistoryConf;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfList.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfList.java
index 5848b7a..b4f4125 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfList.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/HistoryConfList.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.panels;
 
 import java.io.Serializable;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.ConnInstanceHistoryConfTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ProvisionAuxClassesPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ProvisionAuxClassesPanel.java
index 02cc13d..891202f 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ProvisionAuxClassesPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ProvisionAuxClassesPanel.java
@@ -25,8 +25,8 @@ import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.EntityTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/RemediationDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/RemediationDirectoryPanel.java
index 4342c71..b0d01fc 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/RemediationDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/RemediationDirectoryPanel.java
@@ -46,9 +46,9 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.AnyObjectWizardBuilder;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupWizardBuilder;
 import org.apache.syncope.client.console.wizards.any.UserWizardBuilder;
 import org.apache.syncope.common.lib.AnyOperations;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
index a9a0f06..59e2767 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
@@ -38,6 +38,7 @@ 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.ActionsPanel;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ResourceHistoryConfTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
index 8a74d7f..1e33945 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
@@ -29,10 +29,10 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.ConnIdObjectClassTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.EntityTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
index d8b3fdf..72e946f 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
@@ -65,14 +65,17 @@ public class ConnectorRestClient extends BaseRestClient {
 
     public List<String> getObjectClasses(final String connectorKey) {
         List<String> result = new ArrayList<>();
-
-        ConnectorService service = getService(ConnectorService.class);
-        ConnInstanceTO connInstance = service.read(connectorKey, SyncopeConsoleSession.get().getLocale().getLanguage());
-        if (connInstance != null) {
-            result.addAll(service.buildObjectClassInfo(connInstance, true).stream().
-                    map(input -> input.getType()).collect(Collectors.toList()));
+        try {
+            ConnectorService service = getService(ConnectorService.class);
+            ConnInstanceTO connInstance = service.read(connectorKey, SyncopeConsoleSession.get().getLocale().
+                    getLanguage());
+            if (connInstance != null) {
+                result.addAll(service.buildObjectClassInfo(connInstance, true).stream().
+                        map(input -> input.getType()).collect(Collectors.toList()));
+            }
+        } catch (Exception e) {
+            LOG.error("While reading object classes for connector {}", connectorKey, e);
         }
-
         return result;
     }
 
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
index afd03a2..e3389e6 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
@@ -28,12 +28,11 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
-import org.apache.syncope.client.console.commons.status.Status;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.Status;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
@@ -43,6 +42,7 @@ import org.apache.syncope.client.console.rest.UserRestClient;
 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.ActionsPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
index 8f67def..265bedd 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.status;
 
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
index ba08b8d..31cb9b8 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
@@ -28,9 +28,9 @@ import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.ReconciliationRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
index b0582f9..2747a38 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
@@ -26,11 +26,10 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
@@ -40,6 +39,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.to.AnyTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
index ff974e2..dbfdf00 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
@@ -22,13 +22,13 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
index 50b14cd..b617e16 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
@@ -19,12 +19,12 @@
 package org.apache.syncope.client.console.status;
 
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.markup.html.panel.Panel;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
index a309d0e..b1669e9 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
@@ -39,7 +39,7 @@ import org.apache.syncope.client.console.tasks.SchedTasks;
 import org.apache.syncope.client.console.tasks.PullTasks;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.IndicatingOnConfirmAjaxLink;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.resources.AbstractResourceWizardBuilder;
 import org.apache.syncope.client.console.wizards.resources.ResourceProvision;
 import org.apache.syncope.client.console.wizards.resources.ResourceProvisionPanel;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/list/ConnConfPropertyListView.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/list/ConnConfPropertyListView.java
index bc4ef01..97d4cc4 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/list/ConnConfPropertyListView.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/list/ConnConfPropertyListView.java
@@ -25,14 +25,14 @@ import java.util.List;
 import org.apache.commons.lang3.ClassUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AbstractFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.ComponentTag;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractMappingPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractMappingPanel.java
index 63be87f..864df83 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractMappingPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractMappingPanel.java
@@ -29,11 +29,11 @@ import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MappingPurposePanel;
 import org.apache.syncope.client.console.widgets.JEXLTransformerWidget;
 import org.apache.syncope.client.console.widgets.ItemTransformerWidget;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
index a5a7642..59f4d9f 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.console.wizards.resources;
 import java.io.Serializable;
 import org.apache.syncope.client.console.topology.TopologyNode;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal.ModalEvent;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 
@@ -30,7 +30,8 @@ import org.apache.wicket.ajax.AjaxRequestTarget;
  *
  * @param <T> model object type
  */
-public abstract class AbstractResourceWizardBuilder<T extends Serializable> extends AjaxWizardBuilder<Serializable> {
+public abstract class AbstractResourceWizardBuilder<T extends Serializable>
+        extends BaseAjaxWizardBuilder<Serializable> {
 
     private static final long serialVersionUID = 1734415311027284221L;
 
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
index 9dad020..760c38b 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.console.wizards.resources;
 
 import java.util.Arrays;
 import java.util.List;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.PropertyModel;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
index d69b7d3..5341c69 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
@@ -24,10 +24,10 @@ import java.util.stream.Collectors;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.RealmRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.ConnBundleTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.ConnPoolConfTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
index 7fcd82c..1e812e5 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
@@ -25,7 +25,7 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.topology.TopologyNode;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.ConnBundleTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
index ca5b038..8905016 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
@@ -25,7 +25,7 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.panels.TogglePanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/JEXLTransformersTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/JEXLTransformersTogglePanel.java
index f375a68..9b4a05f 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/JEXLTransformersTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/JEXLTransformersTogglePanel.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.console.wizards.resources;
 import java.io.Serializable;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.panels.TogglePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel.java
index 46b99b3..131f33f 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.List;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.TogglePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
index 40086f9..d06f266 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
@@ -26,10 +26,10 @@ import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.ProvisionAuxClassesPanel;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
@@ -45,7 +45,7 @@ import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 
-public class ProvisionWizardBuilder extends AjaxWizardBuilder<ResourceProvision> {
+public class ProvisionWizardBuilder extends BaseAjaxWizardBuilder<ResourceProvision> {
 
     private static final long serialVersionUID = 3739399543837732640L;
 
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
index 6268984..5d6d7cf 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
@@ -20,8 +20,8 @@ package org.apache.syncope.client.console.wizards.resources;
 
 import java.util.Set;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
index 52f3b0d..6d40209 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
@@ -22,11 +22,11 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 2456f9e..123eedb 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -25,7 +25,7 @@ import java.util.List;
 import java.util.Set;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
index b3c8b33..7982f49 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
@@ -35,7 +35,7 @@ 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.ActionLinksTogglePanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceSecurityPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceSecurityPanel.java
index 755c11e..d8793c3 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceSecurityPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceSecurityPanel.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
 import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java
index b08e29b..fff254a 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java
@@ -23,7 +23,7 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 import org.apache.syncope.client.console.topology.TopologyNode;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idrepo/console/pom.xml b/client/idrepo/console/pom.xml
index 25d4739..6a0b471 100644
--- a/client/idrepo/console/pom.xml
+++ b/client/idrepo/console/pom.xml
@@ -93,6 +93,12 @@ under the License.
     </dependency>
 
     <dependency>
+      <groupId>org.apache.syncope.client.idrepo</groupId>
+      <artifactId>syncope-client-idrepo-ui-commons</artifactId>      
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.cxf</groupId>
       <artifactId>cxf-rt-rs-security-jose</artifactId>
     </dependency>
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
index fad0aa9..a9356b9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
@@ -39,7 +39,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.annotations.Resource;
 import org.apache.syncope.client.console.commons.AnyDirectoryPanelAditionalActionLinksProvider;
 import org.apache.syncope.client.console.commons.AnyWizardBuilderAdditionalSteps;
-import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.pages.Dashboard;
@@ -72,7 +71,11 @@ import org.slf4j.LoggerFactory;
 import org.apache.syncope.client.console.commons.ExternalResourceProvider;
 import org.apache.syncope.client.console.commons.StatusProvider;
 import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
+import org.apache.syncope.client.ui.commons.SyncopeUIRequestCycleListener;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.wicket.request.component.IRequestablePage;
 import org.apache.wicket.request.cycle.IRequestCycleListener;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -231,7 +234,25 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
         if (BooleanUtils.toBoolean(csrf)) {
             getRequestCycleListeners().add(new WebSocketAwareCsrfPreventionRequestCycleListener());
         }
-        getRequestCycleListeners().add(new SyncopeConsoleRequestCycleListener());
+
+        getRequestCycleListeners().add(new SyncopeUIRequestCycleListener() {
+
+            @Override
+            protected boolean isSignedIn() {
+                return SyncopeConsoleSession.get().isSignedIn();
+            }
+
+            @Override
+            protected void invalidateSession() {
+                SyncopeConsoleSession.get().invalidate();
+            }
+
+            @Override
+            protected IRequestablePage getErrorPage(final PageParameters errorParameters) {
+                return new Login(errorParameters);
+            }
+        });
+
         getRequestCycleListeners().add(new IRequestCycleListener() {
 
             @Override
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
index e3edf04..59655e3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
@@ -30,13 +30,13 @@ import java.util.Set;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.rest.RestClient;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import org.apache.syncope.client.console.rest.UserRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BatchResponseColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchModal.java
index 1d15619..9e247a5 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchModal.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
-import org.apache.syncope.client.console.rest.RestClient;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 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.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDirectoryPanelAditionalActionLinksProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDirectoryPanelAditionalActionLinksProvider.java
index b56fecc..9e5e120 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDirectoryPanelAditionalActionLinksProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDirectoryPanelAditionalActionLinksProvider.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.List;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.Action;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyWizardBuilderAdditionalSteps.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyWizardBuilderAdditionalSteps.java
index 99c7186..35fbfaa 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyWizardBuilderAdditionalSteps.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyWizardBuilderAdditionalSteps.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.client.console.commons;
 
 import java.io.Serializable;
-import org.apache.syncope.client.console.layout.AbstractAnyFormLayout;
-import org.apache.syncope.client.console.layout.AnyForm;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.wicket.extensions.wizard.WizardModel;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyDirectoryPanelAditionalActionLinksProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyDirectoryPanelAditionalActionLinksProvider.java
index 60878a8..33d5dff 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyDirectoryPanelAditionalActionLinksProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyDirectoryPanelAditionalActionLinksProvider.java
@@ -22,7 +22,7 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.Action;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyWizardBuilderAdditionalSteps.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyWizardBuilderAdditionalSteps.java
index eaf7d44..a616dfd 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyWizardBuilderAdditionalSteps.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyAnyWizardBuilderAdditionalSteps.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.client.console.commons;
 
-import org.apache.syncope.client.console.layout.AbstractAnyFormLayout;
-import org.apache.syncope.client.console.layout.AnyForm;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.wicket.extensions.wizard.WizardModel;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
index 0dd9f44..9efe358 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
@@ -22,7 +22,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java
index fc85cb5..791a34e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java
@@ -20,8 +20,8 @@ package org.apache.syncope.client.console.commons;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.DefaultPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.DefaultPreviewer;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.util.ClassUtils;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/StatusProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/StatusProvider.java
index a098cf8..3aa01dc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/StatusProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/StatusProvider.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
index bf49fc2..18602b7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
@@ -33,8 +33,8 @@ import org.apache.syncope.client.console.events.SelectedEventsPanel.EventSelecti
 import org.apache.syncope.client.console.events.SelectedEventsPanel.InspectSelectedEvent;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.log.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
index 6e3d5ca..ffc4b99 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
@@ -23,7 +23,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
 import org.apache.syncope.common.lib.log.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
index 56f8eda..08b79e3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
@@ -31,7 +31,7 @@ import java.util.Set;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.syncope.client.console.pages.BaseExtPage;
-import org.apache.syncope.client.console.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.syncope.client.console.annotations.ExtPage;
 import org.apache.syncope.client.console.annotations.ExtWidget;
 import org.apache.syncope.client.console.annotations.IdMPage;
@@ -45,7 +45,7 @@ import org.apache.syncope.client.console.commons.EmptyStatusProvider;
 import org.apache.syncope.client.console.commons.EmptyVirSchemaDetailsPanelProvider;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.SSOLoginFormPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
 import org.apache.syncope.client.console.widgets.BaseExtWidget;
 import org.apache.syncope.client.console.widgets.ExtAlertWidget;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/MIMETypesLoader.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/MIMETypesLoader.java
index d2f4845..c1da9ce 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/MIMETypesLoader.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/MIMETypesLoader.java
@@ -18,55 +18,14 @@
  */
 package org.apache.syncope.client.console.init;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.io.IOException;
+import org.apache.syncope.client.ui.commons.AbstractMIMETypesLoader;
 import org.apache.wicket.util.io.IOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-public class MIMETypesLoader {
+public class MIMETypesLoader extends AbstractMIMETypesLoader {
 
-    private static final Logger LOG = LoggerFactory.getLogger(MIMETypesLoader.class);
-
-    private static final ObjectMapper MAPPER = new ObjectMapper();
-
-    private Map<String, String> mimeTypesMap;
-
-    private List<String> mimeTypes;
-
-    public void load() {
-        mimeTypesMap = new HashMap<>();
-        try {
-            JsonNode jsonNode = MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("/MIMETypes.json")));
-            for (JsonNode node : jsonNode) {
-                JsonNode type = node.path("name");
-                JsonNode ext = node.path("extension");
-                if (!type.isMissingNode()) {
-                    mimeTypesMap.put(type.asText(), ext.isMissingNode() ? "" : ext.asText());
-                }
-            }
-
-            mimeTypesMap = Collections.unmodifiableMap(mimeTypesMap);
-            LOG.debug("MIME types loaded: {}", mimeTypesMap);
-
-            mimeTypes = new ArrayList<>(mimeTypesMap.keySet());
-            Collections.sort(mimeTypes);
-            mimeTypes = Collections.unmodifiableList(mimeTypes);
-        } catch (Exception e) {
-            LOG.error("Error reading file MIMETypes from resources", e);
-        }
-    }
-
-    public List<String> getMimeTypes() {
-        return mimeTypes;
-    }
-
-    public String getFileExt(final String mimeType) {
-        return mimeTypesMap.get(mimeType);
+    @Override
+    protected String getMimeTypesFile() throws IOException {
+        return IOUtils.toString(getClass().getResourceAsStream("/MIMETypes.json"));
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectForm.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectForm.java
index c8b7c0c..fecfb1d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectForm.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectForm.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.layout;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 
 public interface AnyObjectForm extends AnyForm<AnyObjectTO> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectFormLayoutInfo.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectFormLayoutInfo.java
index 211aa25..cb622a6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectFormLayoutInfo.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyObjectFormLayoutInfo.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.layout;
 
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
 import org.apache.syncope.client.console.wizards.any.AnyObjectWizardBuilder;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java
index 2a6a191..b3caa6c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.layout;
 
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupForm.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupForm.java
index 7b8e27f..eb9f1e1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupForm.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupForm.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.layout;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
 import org.apache.syncope.common.lib.to.GroupTO;
 
 public interface GroupForm extends AnyForm<GroupTO> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupFormLayoutInfo.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupFormLayoutInfo.java
index 354a8d0..5d7ef29 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupFormLayoutInfo.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/GroupFormLayoutInfo.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.layout;
 
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
 import org.apache.syncope.client.console.wizards.any.GroupWizardBuilder;
 import org.apache.syncope.common.lib.to.GroupTO;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
index c100143..53e7182 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
@@ -19,6 +19,8 @@
 package org.apache.syncope.client.console.layout;
 
 import org.apache.syncope.client.console.wizards.any.UserWizardBuilder;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
 import org.apache.syncope.common.lib.to.UserTO;
 
 public class UserFormLayoutInfo extends AbstractAnyFormLayout<UserTO, UserForm> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
index d5289cd..ac981fb 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
@@ -36,8 +36,8 @@ import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.rest.NotificationRestClient;
 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.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.MailTemplateTO;
 import org.apache.syncope.common.lib.types.MailTemplateFormat;
@@ -51,9 +51,9 @@ import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColu
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.model.PropertyModel;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
index a567e22..b24622d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
@@ -40,7 +40,7 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
index 9a01fe8..82e9369 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationTasks.java
@@ -19,12 +19,12 @@
 package org.apache.syncope.client.console.notifications;
 
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.tasks.NotificationMailBodyDetails;
 import org.apache.syncope.client.console.tasks.NotificationTaskDirectoryPanel;
 import org.apache.syncope.client.console.tasks.TaskExecutionDetails;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MailTemplateFormat;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index 733aaab..be4b0c2 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.events.EventCategoryPanel;
 import org.apache.syncope.client.console.panels.search.AbstractSearchPanel;
@@ -37,12 +38,12 @@ import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.LoggerRestClient;
 import org.apache.syncope.client.console.rest.NotificationRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.DerSchemaTO;
@@ -70,7 +71,7 @@ import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.validation.validator.EmailAddressValidator;
 
-public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWrapper> {
+public class NotificationWizardBuilder extends BaseAjaxWizardBuilder<NotificationWrapper> {
 
     private static final long serialVersionUID = -1975312550059578553L;
 
@@ -321,6 +322,11 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
                         }
                     });
                 }
+
+                @Override
+                protected void sendError(final String message) {
+                    SyncopeConsoleSession.get().error(getString(Constants.OPERATION_ERROR));
+                }
             }.hideLabel());
         }
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateModal.java
index b2e3bff..df58427 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateModal.java
@@ -25,7 +25,7 @@ import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
 import org.apache.syncope.client.console.rest.TemplateRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 36b9155..fe2a75d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -27,13 +27,13 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.annotations.ExtPage;
 import org.apache.syncope.client.console.annotations.IdMPage;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.HttpResourceStream;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.console.panels.NotificationPanel;
 import org.apache.syncope.client.console.rest.ConfRestClient;
 import org.apache.syncope.client.console.wicket.markup.head.MetaHeaderItem;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.widgets.ExtAlertWidget;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
 import org.apache.syncope.common.lib.info.PlatformInfo;
 import org.apache.syncope.common.lib.info.SystemInfo;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -42,7 +42,6 @@ import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.IAjaxIndicatorAware;
 import org.apache.wicket.ajax.attributes.AjaxCallListener;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
@@ -69,7 +68,7 @@ import org.apache.wicket.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BasePage extends WebPage implements IAjaxIndicatorAware {
+public class BasePage extends BaseWebPage {
 
     private static final long serialVersionUID = 1571997737305598502L;
 
@@ -80,10 +79,6 @@ public class BasePage extends WebPage implements IAjaxIndicatorAware {
     @SpringBean
     protected ClassPathScanImplementationLookup lookup;
 
-    protected final WebMarkupContainer body;
-
-    protected NotificationPanel notificationPanel;
-
     public BasePage() {
         this(null);
     }
@@ -91,16 +86,12 @@ public class BasePage extends WebPage implements IAjaxIndicatorAware {
     public BasePage(final PageParameters parameters) {
         super(parameters);
 
-        body = new WebMarkupContainer("body");
         Serializable leftMenuCollapse = SyncopeConsoleSession.get().getAttribute(Constants.MENU_COLLAPSE);
         if ((leftMenuCollapse instanceof Boolean) && ((Boolean) leftMenuCollapse)) {
             body.add(new AttributeAppender("class", " sidebar-collapse"));
         }
         add(body);
 
-        notificationPanel = new NotificationPanel(Constants.FEEDBACK);
-        body.addOrReplace(notificationPanel.setOutputMarkupId(true));
-
         // header, footer
         body.add(new Label("username", SyncopeConsoleSession.get().getSelfTO().getUsername()));
 
@@ -455,15 +446,6 @@ public class BasePage extends WebPage implements IAjaxIndicatorAware {
         return linkId + "UL";
     }
 
-    @Override
-    public String getAjaxIndicatorMarkupId() {
-        return Constants.VEIL_INDICATOR_MARKUP_ID;
-    }
-
-    public NotificationPanel getNotificationPanel() {
-        return notificationPanel;
-    }
-
     /**
      * Set a WindowClosedCallback for a Modal instance.
      *
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java
index da27cf0..71a7f33 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java
@@ -24,7 +24,7 @@ import org.apache.commons.collections4.list.SetUniqueList;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.LogStatementPanel;
 import org.apache.syncope.client.console.rest.LoggerRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.log.LogStatement;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
index a1e0ebe..39f07c1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
@@ -27,30 +27,20 @@ import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.console.panels.NotificationPanel;
+import org.apache.syncope.client.ui.commons.BaseLogin;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.authentication.IAuthenticationStrategy;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.ChoiceRenderer;
-import org.apache.wicket.markup.html.form.PasswordTextField;
-import org.apache.wicket.markup.html.form.StatelessForm;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class Login extends WebPage {
+public class Login extends BaseLogin {
 
     private static final Logger LOG = LoggerFactory.getLogger(Login.class);
 
@@ -59,59 +49,8 @@ public class Login extends WebPage {
     @SpringBean
     private ClassPathScanImplementationLookup lookup;
 
-    private final NotificationPanel notificationPanel;
-
-    private final StatelessForm<Void> form;
-
-    private final TextField<String> usernameField;
-
-    private final TextField<String> passwordField;
-
     public Login(final PageParameters parameters) {
         super(parameters);
-        setStatelessHint(true);
-
-        notificationPanel = new NotificationPanel(Constants.FEEDBACK);
-        add(notificationPanel);
-
-        Label exceptionMessage = new Label("exceptionMessage");
-        exceptionMessage.setOutputMarkupPlaceholderTag(true);
-        exceptionMessage.setVisible(false);
-        if (!parameters.get("errorMessage").isNull()) {
-            exceptionMessage.setVisible(true);
-            exceptionMessage.setDefaultModel(Model.of(parameters.get("errorMessage")));
-        }
-        add(exceptionMessage);
-
-        form = new StatelessForm<>("login");
-
-        usernameField = new TextField<>("username", new Model<>());
-        usernameField.setMarkupId("username");
-        form.add(usernameField);
-
-        passwordField = new PasswordTextField("password", new Model<>());
-        passwordField.setMarkupId("password");
-        form.add(passwordField);
-
-        LocaleDropDown languageSelect = new LocaleDropDown("language");
-        languageSelect.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
-
-            private static final long serialVersionUID = -1107858522700306810L;
-
-            @Override
-            protected void onUpdate(final AjaxRequestTarget target) {
-                // nothing to do
-            }
-        }).add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-            private static final long serialVersionUID = -1107858522700306810L;
-
-            @Override
-            protected void onUpdate(final AjaxRequestTarget target) {
-                // nothing to do
-            }
-        });
-        form.add(languageSelect);
 
         DomainDropDown domainSelect = new DomainDropDown("domain");
         if (SyncopeWebApplication.get().getDomains().size() == 1) {
@@ -135,35 +74,10 @@ public class Login extends WebPage {
             }
         });
         form.add(domainSelect);
+    }
 
-        AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
-
-            private static final long serialVersionUID = 429178684321093953L;
-
-            @Override
-            protected void onSubmit(final AjaxRequestTarget target) {
-                if (SyncopeWebApplication.get().getAnonymousUser().equals(usernameField.getRawInput())) {
-                    throw new AccessControlException("Illegal username");
-                }
-
-                IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
-
-                if (AuthenticatedWebSession.get().signIn(usernameField.getRawInput(), passwordField.getRawInput())) {
-                    // If login has been called because the user was not yet logged in, than continue to the
-                    // original destination, otherwise to the Home page
-                    continueToOriginalDestination();
-                    setResponsePage(getApplication().getHomePage());
-                } else {
-                    SyncopeConsoleSession.get().error(getString("login-error"));
-                    notificationPanel.refresh(target);
-                }
-                strategy.remove();
-            }
-        };
-        submitButton.setDefaultFormProcessing(false);
-        form.add(submitButton);
-        form.setDefaultButton(submitButton);
-
+    @Override
+    protected List<Panel> getSSOLoginFormPanels() {
         List<Panel> ssoLoginFormPanels = new ArrayList<>();
         lookup.getSSOLoginFormPanels().forEach(ssoLoginFormPanel -> {
             try {
@@ -172,64 +86,43 @@ public class Login extends WebPage {
                 LOG.error("Could not initialize the provided SSO login form panel", e);
             }
         });
-        ListView<Panel> ssoLogins = new ListView<Panel>("ssoLogins", ssoLoginFormPanels) {
-
-            private static final long serialVersionUID = -9180479401817023838L;
-
-            @Override
-            protected void populateItem(final ListItem<Panel> item) {
-                item.add(item.getModelObject());
-            }
-        };
-        form.add(ssoLogins);
-
-        add(form);
+        return ssoLoginFormPanels;
     }
 
-    /**
-     * Inner class which implements (custom) Locale DropDownChoice component.
-     */
-    private class LocaleDropDown extends BootstrapSelect<Locale> {
-
-        private static final long serialVersionUID = 2349382679992357202L;
+    @Override
+    protected void sendError(final String error) {
+        SyncopeConsoleSession.get().error(error);
+    }
 
-        private class LocaleRenderer extends ChoiceRenderer<Locale> {
+    @Override
+    protected String getAnonymousUser() {
+        return SyncopeWebApplication.get().getAnonymousUser();
+    }
 
-            private static final long serialVersionUID = -3657529581555164741L;
+    @Override
+    protected List<Locale> getSupportedLocales() {
+        return SyncopeWebApplication.SUPPORTED_LOCALES;
+    }
 
-            @Override
-            public String getDisplayValue(final Locale locale) {
-                return locale.getDisplayName(getLocale());
-            }
+    @Override
+    protected void authenticate(final String username, final String password, final AjaxRequestTarget target) throws
+            AccessControlException {
+        if (SyncopeWebApplication.get().getAnonymousUser().equals(username)) {
+            throw new AccessControlException("Illegal username");
         }
 
-        LocaleDropDown(final String id) {
-            super(id, SyncopeWebApplication.SUPPORTED_LOCALES);
-
-            setChoiceRenderer(new LocaleRenderer());
-            setModel(new IModel<Locale>() {
-
-                private static final long serialVersionUID = -6985170095629312963L;
-
-                @Override
-                public Locale getObject() {
-                    return getSession().getLocale();
-                }
-
-                @Override
-                public void setObject(final Locale object) {
-                    getSession().setLocale(object);
-                }
-
-                @Override
-                public void detach() {
-                    // Empty.
-                }
-            });
+        IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
 
-            // set default value to English
-            getModel().setObject(Locale.ENGLISH);
+        if (AuthenticatedWebSession.get().signIn(username, password)) {
+            // If login has been called because the user was not yet logged in, than continue to the
+            // original destination, otherwise to the Home page
+            continueToOriginalDestination();
+            setResponsePage(getApplication().getHomePage());
+        } else {
+            SyncopeConsoleSession.get().error(getString("login-error"));
+            notificationPanel.refresh(target);
         }
+        strategy.remove();
     }
 
     /**
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/MustChangePassword.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/MustChangePassword.java
index 4fcca5b..f83ca8f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/MustChangePassword.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/MustChangePassword.java
@@ -21,9 +21,9 @@ package org.apache.syncope.client.console.pages;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.panels.NotificationPanel;
 import org.apache.syncope.client.console.rest.UserSelfRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.markup.html.WebPage;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index b113144..be8be41 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -20,18 +20,19 @@ package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
-import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.Realm;
 import org.apache.syncope.client.console.panels.RealmChoicePanel;
 import org.apache.syncope.client.console.panels.RealmChoicePanel.ChosenRealm;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.tasks.TemplatesTogglePanel;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.ResultPage;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RealmTO;
@@ -164,7 +165,7 @@ public class Realms extends BasePage {
                 templateModal.close(newItemEvent.getTarget());
             } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
                 SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
-                ((BasePage) getPage()).getNotificationPanel().refresh(newItemEvent.getTarget());
+                ((BaseWebPage) getPage()).getNotificationPanel().refresh(newItemEvent.getTarget());
                 templateModal.close(newItemEvent.getTarget());
             }
         }
@@ -245,7 +246,7 @@ public class Realms extends BasePage {
                     // Escape line breaks
                     SyncopeConsoleSession.get().error(e.getMessage().replace("\n", " "));
                 }
-                ((BasePage) Realms.this.getPage()).getNotificationPanel().refresh(target);
+                ((BaseWebPage) Realms.this.getPage()).getNotificationPanel().refresh(target);
             }
         });
         return content;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java
index 58e1a4e..d5c224e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java
@@ -25,8 +25,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.log.LoggerTO;
 import org.apache.syncope.common.lib.types.LoggerLevel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractModalPanel.java
index 9179854..586cc54 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractModalPanel.java
@@ -18,10 +18,12 @@
  */
 package org.apache.syncope.client.console.panels;
 
+import org.apache.syncope.client.ui.commons.panels.SubmitableModalPanel;
 import java.io.Serializable;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.wicket.markup.head.MetaHeaderItem;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.head.HeaderItem;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSchemaDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSchemaDetailsPanel.java
index c3a4bb7..ab092a3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSchemaDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSchemaDetailsPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.PropertyModel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
index 17717c5..1c8558a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 import org.apache.syncope.client.console.commons.ActionTableCheckGroup;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AjaxFallbackDataTable;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
index 0069c52..565712a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
@@ -26,12 +26,12 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.syncope.client.console.rest.BaseRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
 import org.apache.syncope.client.console.batch.BatchModal;
 import org.apache.syncope.client.console.batch.BatchContent;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel.EventDataWrapper;
-import org.apache.syncope.client.console.rest.RestClient;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AjaxFallbackDataTable;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
index 05f7062..1833582 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
@@ -31,7 +31,7 @@ import org.apache.commons.lang3.tuple.Triple;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.AnyDataProvider;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
@@ -41,7 +41,7 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.TokenColumn;
 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.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.ResultPage;
 import org.apache.syncope.client.console.wizards.any.StatusPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
index ad064ed..97b86c6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
@@ -32,9 +32,9 @@ import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
index cd62839..b37284f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
+import org.apache.syncope.client.ui.commons.panels.LabelPanel;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -36,8 +37,9 @@ import org.apache.syncope.client.console.panels.search.SearchClausePanel;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassDetailsPanel.java
index c54ebea..df22131 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassDetailsPanel.java
@@ -24,8 +24,8 @@ import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.ConfRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.wicket.markup.html.WebMarkupContainer;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
index b9068b5..393d25e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeClassesPanel.java
@@ -36,8 +36,9 @@ import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeDetailsPanel.java
index 0e31a67..e022165 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypeDetailsPanel.java
@@ -22,9 +22,9 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
index 7f75281..0f2a097 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyTypesPanel.java
@@ -36,8 +36,9 @@ import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ApplicationModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ApplicationModalPanel.java
index 72aec89..1321fc3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ApplicationModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ApplicationModalPanel.java
@@ -24,7 +24,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.rest.ApplicationRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.ApplicationTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
index 6fb90bf..b372650 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
@@ -35,14 +35,14 @@ import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.Schema;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
index c2ef5e5..a4248dc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
@@ -26,8 +26,8 @@ import org.apache.syncope.client.console.PreferenceManager;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.rest.RestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 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.ActionLinksTogglePanel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DisplayAttributesModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DisplayAttributesModalPanel.java
index 49dd601..4f756b8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DisplayAttributesModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DisplayAttributesModalPanel.java
@@ -28,7 +28,7 @@ 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.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.search.SearchableFields;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
index 7f260e0..ccb9387 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
@@ -31,8 +31,8 @@ import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.DynRealmRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wizards.DynRealmWrapper;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ExecMessageModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ExecMessageModal.java
index 91e0b98..0b77669 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ExecMessageModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ExecMessageModal.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.panels;
 
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Panel;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/FailureMessageModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/FailureMessageModal.java
index f548bfe..601e796 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/FailureMessageModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/FailureMessageModal.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.panels;
 
 import java.io.Serializable;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Panel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
index 2c7e192..f43ebea 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
@@ -38,11 +38,12 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupWrapper;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java
index 7e588d8..744453c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.Arrays;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
index 3b7ddd2..29176b9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
@@ -33,8 +33,8 @@ import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
index 21d9022..96da748 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
@@ -28,11 +28,11 @@ import java.util.List;
 import java.util.Optional;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 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.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
index 9fc398e..1cd90e4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
@@ -25,8 +25,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
index 6a3e8b3..34cfa57 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateModalPanel.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.panels;
 
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.wicket.PageReference;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardAttrStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardAttrStep.java
index f36c5da..3b6e795 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardAttrStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardAttrStep.java
@@ -20,16 +20,16 @@ package org.apache.syncope.client.console.panels;
 
 import java.util.Arrays;
 import java.util.List;
-import org.apache.syncope.client.console.commons.SchemaUtils;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.SchemaUtils;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.EncryptedFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardPanel.java
index 8ff948e..9a9de85 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardPanel.java
@@ -21,14 +21,14 @@ package org.apache.syncope.client.console.panels;
 import java.io.Serializable;
 import org.apache.syncope.client.console.rest.ConfRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.wizard.WizardModel;
 
-public class ParametersCreateWizardPanel extends AjaxWizardBuilder<ParametersCreateWizardPanel.ParametersForm> {
+public class ParametersCreateWizardPanel extends BaseAjaxWizardBuilder<ParametersCreateWizardPanel.ParametersForm> {
 
     private static final long serialVersionUID = -2868592590785581481L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
index e81fd1e..9bd7b5a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
@@ -26,11 +26,11 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.PropertyList;
 import org.apache.syncope.client.console.init.MIMETypesLoader;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDetailsPanel.java
index b9ed131..d4bbd11 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDetailsPanel.java
@@ -21,17 +21,17 @@ package org.apache.syncope.client.console.panels;
 import java.util.Arrays;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.SchemaUtils;
+import org.apache.syncope.client.ui.commons.SchemaUtils;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.EncryptedFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
index 2418e89..72395f5 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
@@ -35,9 +35,10 @@ import org.apache.syncope.client.console.rest.SchemaRestClient;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
index af555dc..fc5baa5 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
@@ -30,11 +30,11 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.PropertyList;
 import org.apache.syncope.client.console.init.MIMETypesLoader;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeDirectoryPanel.java
index 47c972d..8ed357b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeDirectoryPanel.java
@@ -34,7 +34,8 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ApplicationTO;
 import org.apache.syncope.common.lib.to.PrivilegeTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeWizardBuilder.java
index e1c4f5d..72b3f80 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PrivilegeWizardBuilder.java
@@ -20,9 +20,9 @@ package org.apache.syncope.client.console.panels;
 
 import java.io.Serializable;
 import org.apache.syncope.client.console.rest.ApplicationRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.ApplicationTO;
 import org.apache.syncope.common.lib.to.PrivilegeTO;
 import org.apache.wicket.PageReference;
@@ -32,7 +32,7 @@ import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.StringResourceModel;
 
-public class PrivilegeWizardBuilder extends AjaxWizardBuilder<PrivilegeTO> {
+public class PrivilegeWizardBuilder extends BaseAjaxWizardBuilder<PrivilegeTO> {
 
     private static final long serialVersionUID = -1817419622749405208L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 73d18ca..c1736e7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
@@ -32,7 +32,7 @@ import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.ITabComponent;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
 import org.apache.syncope.client.console.layout.FormLayoutInfoUtils;
 import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index 5371af3..bb07693 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -26,10 +26,10 @@ import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.EntityTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
index 9edcded..f1234a3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.console.panels;
 
 import java.io.Serializable;
 import org.apache.syncope.client.console.rest.RealmRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.wicket.PageReference;
@@ -28,7 +28,7 @@ import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 
-public class RealmWizardBuilder extends AjaxWizardBuilder<RealmTO> {
+public class RealmWizardBuilder extends BaseAjaxWizardBuilder<RealmTO> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypeDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypeDetailsPanel.java
index 068ce5b..c75ba2c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypeDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypeDetailsPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.RelationshipTypeTO;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.Form;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
index a55bc2e..2613a5d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipTypesPanel.java
@@ -37,8 +37,9 @@ import org.apache.syncope.client.console.rest.RelationshipTypeRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.to.RelationshipTypeTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index c58c095..7125d88 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -42,10 +42,11 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.console.wizards.role.RoleWrapper;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
index d0ccb5e..4421950 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
@@ -42,7 +42,7 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.types.SchemaType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
index ad75eb4..da0d2b3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
@@ -31,9 +31,9 @@ import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.DerSchemaTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.SchemaTO;
@@ -55,7 +55,7 @@ import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.apache.wicket.validation.ValidationError;
 
-public class SchemaTypeWizardBuilder extends AjaxWizardBuilder<SchemaTO> {
+public class SchemaTypeWizardBuilder extends BaseAjaxWizardBuilder<SchemaTO> {
 
     private static final long serialVersionUID = -3893521796674873644L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
index e45a58a..9dfc39a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
@@ -21,8 +21,8 @@ package org.apache.syncope.client.console.panels;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionDetailsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionDetailsPanel.java
index d75c483..4bfbc42 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionDetailsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionDetailsPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.SecurityQuestionTO;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.Form;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
index 2f05b43..3186a40 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
@@ -35,9 +35,10 @@ import org.apache.syncope.client.console.rest.SecurityQuestionRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.to.SecurityQuestionTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/StartAtTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/StartAtTogglePanel.java
index 1faf3e1..0fd44b6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/StartAtTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/StartAtTogglePanel.java
@@ -25,8 +25,8 @@ 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.rest.ExecutionRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
index f49befa..d6de626 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TogglePanel.java
@@ -21,13 +21,13 @@ package org.apache.syncope.client.console.panels;
 import java.io.Serializable;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.policies.PolicyRuleWrapper;
 import org.apache.syncope.client.console.reports.ReportletWrapper;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupWrapper;
-import org.apache.syncope.client.console.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.EntityTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypeExtensionDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypeExtensionDirectoryPanel.java
index 16bbcdc..79e84d1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypeExtensionDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypeExtensionDirectoryPanel.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
+import org.apache.syncope.client.ui.commons.panels.SubmitableModalPanel;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -35,7 +36,7 @@ import org.apache.syncope.client.console.rest.GroupRestClient;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.TypeExtensionWizardBuilder;
 import org.apache.syncope.common.lib.request.GroupUR;
 import org.apache.syncope.common.lib.to.GroupTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypesDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypesDirectoryPanel.java
index 8e4a0f4..744fc71 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypesDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/TypesDirectoryPanel.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.console.panels;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.rest.RestClient;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.wicket.PageReference;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
index 1305213..4e59fee 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
@@ -35,10 +35,10 @@ import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
-import org.apache.syncope.client.console.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
index 6654091..3e9957c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
@@ -23,7 +23,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.AnyObjectDisplayAttributesModalPanel;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
index a31fb41..20de17e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
@@ -23,7 +23,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.GroupDisplayAttributesModalPanel;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
index 69e6e1c..01abfe0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
@@ -36,10 +36,10 @@ import org.apache.syncope.client.console.panels.search.SearchClause.Type;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.rest.RelationshipTypeRestClient;
 import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxEventBehavior;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.GroupTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
index 542536c..175dc2d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
@@ -23,7 +23,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.UserDisplayAttributesModalPanel;
 import org.apache.syncope.client.console.rest.UserRestClient;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
index 5f09529..bb80dcb 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
@@ -39,7 +39,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.PolicyTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
index 2fe8133..7fc039c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
@@ -28,17 +28,17 @@ 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.AbstractModalPanel;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
-import org.apache.syncope.client.console.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
index 3a14f41..cf4db2b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
@@ -33,14 +33,14 @@ import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.ComposablePolicy;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
index 855837e..d649d93 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
@@ -27,8 +27,8 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.BeanPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.policy.ComposablePolicy;
 import org.apache.syncope.common.lib.policy.RuleConf;
@@ -45,7 +45,7 @@ import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.PropertyModel;
 
-public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper> {
+public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWrapper> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
index 96176b6..629c0be 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
@@ -35,11 +35,11 @@ import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiPanel;
 import org.apache.syncope.common.lib.policy.AbstractCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultPullCorrelationRuleConf;
@@ -142,6 +142,11 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             protected CorrelationRulePanel getItemPanel(final ListItem<CorrelationRule> item) {
                 return new CorrelationRulePanel("panel", Model.of(item.getModelObject()));
             }
+
+            @Override
+            protected void sendError(final String message) {
+                SyncopeConsoleSession.get().error(getString(Constants.OPERATION_ERROR));
+            }
         });
     }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportDirectoryPanel.java
index 537f5fd..a20afb8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportDirectoryPanel.java
@@ -42,7 +42,7 @@ 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.ActionsPanel;
 import org.apache.syncope.client.console.widgets.JobActionPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.JobTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
index 4311a1b..d5d920b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportExecutionDetails.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.reports;
 
-import org.apache.syncope.client.console.commons.HttpResourceStream;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.ExecutionRestClient;
 import org.apache.syncope.client.console.rest.ReportRestClient;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
index 4cd32b7..ff32336 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
@@ -35,8 +35,8 @@ import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 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.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ReportTemplateTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -49,11 +49,11 @@ import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColu
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.reports.ReportTemplateDirectoryPanel.ReportTemplateProvider;
 import org.apache.syncope.client.console.rest.ReportRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 import org.apache.syncope.common.lib.types.ReportTemplateFormat;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.model.PropertyModel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
index ffb24e2..3ceb127 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java
@@ -22,10 +22,10 @@ import java.io.Serializable;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.ReportRestClient;
 import org.apache.syncope.client.console.tasks.CrontabPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.wicket.PageReference;
@@ -33,7 +33,7 @@ import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.model.PropertyModel;
 
-public class ReportWizardBuilder extends AjaxWizardBuilder<ReportTO> {
+public class ReportWizardBuilder extends BaseAjaxWizardBuilder<ReportTO> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
index 7b7edd1..9bd791e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
@@ -33,14 +33,14 @@ import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.ReportRestClient;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.report.ReportletConf;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
index 17785b0..43c3a6b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
@@ -25,8 +25,8 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.BeanPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.ReportRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
@@ -41,7 +41,7 @@ import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.LoadableDetachableModel;
 
-public class ReportletWizardBuilder extends AjaxWizardBuilder<ReportletWrapper> {
+public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapper> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AbstractAnyRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AbstractAnyRestClient.java
index 3956e7d..d4a580a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AbstractAnyRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AbstractAnyRestClient.java
@@ -30,8 +30,8 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.Client;
 import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.client.lib.batch.BatchRequest;
 import org.apache.syncope.common.lib.request.ResourceAR;
 import org.apache.syncope.common.lib.request.ResourceDR;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
index ecea2ae..ea83255 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
@@ -24,6 +24,7 @@ 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.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
 import org.apache.syncope.common.lib.types.ExecStatus;
 import org.apache.syncope.common.rest.api.RESTHeaders;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
index d8c9ff9..dbff175 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.rest;
 
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
index d3d5c35..10dd1f4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.rest;
 
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import java.util.List;
 
 public interface TemplateRestClient<T, F> extends RestClient {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index 4ff2bca..f6df82e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@ -24,9 +24,9 @@ import java.util.Map;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.Status;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.Status;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.common.lib.request.BooleanReplacePatchItem;
 import org.apache.syncope.common.lib.request.StatusR;
 import org.apache.syncope.common.lib.request.UserCR;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
index 254fb89..8881397 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
@@ -23,15 +23,15 @@ import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
 import org.apache.syncope.client.console.panels.ListViewPanel;
 import org.apache.syncope.client.console.rest.UserRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
-import org.apache.syncope.client.console.wizards.any.PasswordPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
 import org.apache.syncope.client.console.wizards.any.StatusPanel;
-import org.apache.syncope.client.console.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.request.PasswordPatch;
 import org.apache.syncope.common.lib.request.UserUR;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
index dc947f2..ba364bc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/AbstractTasks.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.tasks;
 
-import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.wicket.markup.html.panel.Panel;
 
 public abstract class AbstractTasks extends Panel implements ModalPanel {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
index f5f84b9..7cc10f1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
@@ -21,11 +21,11 @@ package org.apache.syncope.client.console.tasks;
 import java.util.Arrays;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.SelectChoiceRenderer;
-import org.apache.syncope.client.console.wicket.markup.html.form.SelectOption;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.SelectChoiceRenderer;
+import org.apache.syncope.client.ui.commons.markup.html.form.SelectOption;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.form.FormComponent;
 import org.apache.wicket.markup.html.panel.Panel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
index 3a584ca..fbf9e09 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/NotificationTaskDirectoryPanel.java
@@ -27,7 +27,6 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.TaskDataProvider;
 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.wicket.extensions.markup.html.repeater.data.table.CollectionPropertyColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
@@ -35,6 +34,7 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.
 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.ActionsPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.SyncopeClientException;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
index 67be4c8..ab7fcf0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
@@ -27,7 +27,6 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.TaskDataProvider;
 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.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
@@ -35,6 +34,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.types.TaskType;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
index 5feba57..dcf08b1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
@@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
 import org.apache.syncope.client.console.panels.search.MapOfListModel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
index c333f34..558552b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
@@ -30,7 +30,6 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.TaskDataProvider;
 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.BooleanPropertyColumn;
@@ -40,7 +39,8 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.SyncopeClientException;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
index a23f39b..67c126e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
@@ -27,12 +27,12 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.rest.TaskRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
 import org.apache.syncope.common.lib.to.SchedTaskTO;
@@ -54,7 +54,7 @@ import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBuilder<T> {
+public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends BaseAjaxWizardBuilder<T> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
index 35aabff..022b21a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskDirectoryPanel.java
@@ -22,10 +22,10 @@ import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import org.apache.syncope.client.console.commons.TaskDataProvider;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-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.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
 import org.apache.syncope.common.lib.to.TaskTO;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
index 802b34c..963e8a8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
@@ -29,12 +29,12 @@ import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.TogglePanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.AnyObjectTemplateWizardBuilder;
 import org.apache.syncope.client.console.wizards.any.AnyWizardBuilder;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupTemplateWizardBuilder;
 import org.apache.syncope.client.console.wizards.any.TemplateWizardBuilder;
 import org.apache.syncope.client.console.wizards.any.UserTemplateWizardBuilder;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
index 69ede94..55ee40e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
@@ -25,8 +25,6 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
-import org.apache.syncope.client.console.panels.NotificationPanel;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.buttons.DefaultModalCloseButton;
 import org.apache.wicket.Component;
 import org.apache.wicket.WicketRuntimeException;
@@ -43,8 +41,10 @@ import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.syncope.client.console.panels.SubmitableModalPanel;
+import org.apache.syncope.client.ui.commons.panels.SubmitableModalPanel;
 import org.apache.syncope.client.console.wicket.ajax.form.IndicatorModalCloseBehavior;
+import org.apache.syncope.client.ui.commons.panels.ModalPanel;
+import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.markup.head.IHeaderResponse;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksTogglePanel.java
index 9e55b10..6ca8595 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksTogglePanel.java
@@ -22,13 +22,13 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.util.UUID;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
 import org.apache.syncope.client.console.panels.TogglePanel;
 import org.apache.syncope.client.console.policies.PolicyRuleWrapper;
 import org.apache.syncope.client.console.reports.ReportletWrapper;
-import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupWrapper;
-import org.apache.syncope.client.console.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.GroupTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java
index 69e572c..7d9bb08 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java
@@ -20,7 +20,10 @@ package org.apache.syncope.client.console.wicket.markup.html.form;
 
 import com.googlecode.wicket.kendo.ui.form.datetime.AjaxDatePicker;
 import java.util.Date;
+import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.ui.commons.markup.html.form.DateFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 
@@ -48,4 +51,11 @@ public class AjaxDateFieldPanel extends DateFieldPanel {
 
         return panel;
     }
+
+    @Override
+    protected FastDateFormat getDateFormat(final String datePattern) {
+        return datePattern == null
+                ? SyncopeConsoleSession.get().getDateFormat()
+                : FastDateFormat.getInstance(datePattern);
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java
index 8d5fe2e..46fad5f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java
@@ -18,8 +18,11 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.DateFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import com.googlecode.wicket.kendo.ui.form.datetime.AjaxDateTimePicker;
 import java.util.Date;
+import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
@@ -52,4 +55,11 @@ public class AjaxDateTimeFieldPanel extends DateFieldPanel {
 
         return panel;
     }
+
+    @Override
+    protected FastDateFormat getDateFormat(final String datePattern) {
+        return datePattern == null
+                ? SyncopeConsoleSession.get().getDateFormat()
+                : FastDateFormat.getInstance(datePattern);
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java
index cac77e3..7752afc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.client.console.wicket.markup.html.form;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.HttpResourceStream;
 import org.apache.syncope.client.console.init.MIMETypesLoader;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.AbstractAjaxBehavior;
 import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
index e380ceb..f57091e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+
 import static de.agilecoders.wicket.jquery.JQuery.$;
 
 import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.fileinput.BootstrapFileInputField;
@@ -34,10 +36,11 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.HttpResourceStream;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
 import org.apache.syncope.client.console.commons.PreviewUtils;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.BaseBinaryFieldPanel;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
@@ -58,7 +61,7 @@ import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.apache.wicket.util.lang.Bytes;
 
-public class BinaryFieldPanel extends FieldPanel<String> {
+public class BinaryFieldPanel extends BaseBinaryFieldPanel {
 
     private static final long serialVersionUID = 6264462604183088931L;
 
@@ -291,4 +294,14 @@ public class BinaryFieldPanel extends FieldPanel<String> {
         setVisibleFileButtons(StringUtils.isNotBlank(modelObj));
         return this;
     }
+
+    @Override
+    protected void sendError(final String message) {
+        SyncopeConsoleSession.get().error(message);
+    }
+
+    @Override
+    protected Integer getMaxUploadFileSizeMB() {
+        return SyncopeWebApplication.get().getMaxUploadFileSizeMB();
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java
index 367591e..525fcb9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java
@@ -18,10 +18,13 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 import java.io.Serializable;
 import java.util.List;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractMultiPanel;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.panel.Panel;
@@ -107,6 +110,11 @@ public abstract class MultiFieldPanel<E extends Serializable> extends AbstractMu
                 protected void clearInput(final Panel panel) {
                     FieldPanel.class.cast(panel).getField().clearInput();
                 }
+
+                @Override
+                protected void sendError(final String message) {
+                    SyncopeConsoleSession.get().error(getString(Constants.OPERATION_ERROR));
+                }
             };
         }
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiPanel.java
index 893c9e8..ee29475 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiPanel.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.wicket.markup.html.form;
 
 import java.io.Serializable;
 import java.util.List;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractMultiPanel;
 import org.apache.wicket.model.IModel;
 
 public abstract class MultiPanel<INNER extends Serializable> extends AbstractMultiPanel<INNER> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryCertPreviewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryCertPreviewer.java
index 90e49ae..3da5608 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryCertPreviewer.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryCertPreviewer.java
@@ -18,13 +18,14 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form.preview;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
 import java.io.ByteArrayInputStream;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.basic.Label;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryImagePreviewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryImagePreviewer.java
index 2468cc1..7397462 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryImagePreviewer.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryImagePreviewer.java
@@ -18,7 +18,8 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form.preview;
 
-import org.apache.syncope.client.console.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.wicket.Component;
 import org.apache.wicket.extensions.markup.html.image.resource.ThumbnailImageResource;
 import org.apache.wicket.markup.html.image.NonCachingImage;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryPDFPreviewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryPDFPreviewer.java
index 23aa4ef..6efdec6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryPDFPreviewer.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryPDFPreviewer.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form.preview;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.awt.image.BufferedImage;
@@ -32,7 +33,7 @@ import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.graphics.PDXObject;
 import org.apache.pdfbox.rendering.ImageType;
 import org.apache.pdfbox.rendering.PDFRenderer;
-import org.apache.syncope.client.console.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.image.NonCachingImage;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryTextPreviewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryTextPreviewer.java
index 33558d1..fe893d7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryTextPreviewer.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/preview/BinaryTextPreviewer.java
@@ -18,11 +18,12 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form.preview;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
-import org.apache.syncope.client.console.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.OnLoadHeaderItem;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
index 5760b37..dae2d58 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
@@ -49,7 +49,7 @@ 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.ActionLinksTogglePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ExecTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/BaseAjaxWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/BaseAjaxWizardBuilder.java
new file mode 100644
index 0000000..ff5d427
--- /dev/null
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/BaseAjaxWizardBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.wizards;
+
+import java.io.Serializable;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.SyncopeWebApplication;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
+import org.apache.wicket.PageReference;
+
+public abstract class BaseAjaxWizardBuilder<T extends Serializable> extends AjaxWizardBuilder<T> {
+
+    private static final long serialVersionUID = -5729026353086171480L;
+
+    public BaseAjaxWizardBuilder(final T defaultItem, final PageReference pageRef) {
+        super(defaultItem, pageRef);
+    }
+
+    @Override
+    protected long getMaxWaitTimeInSeconds() {
+        return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
+    }
+
+    @Override
+    protected void sendError(final String message) {
+        SyncopeConsoleSession.get().error(message);
+    }
+
+    @Override
+    protected void sendWarning(final String message) {
+        SyncopeConsoleSession.get().warn(message);
+    }
+
+    @Override
+    protected Future<Pair<Serializable, Serializable>> execute(
+            final Callable<Pair<Serializable, Serializable>> future) {
+        return SyncopeConsoleSession.get().execute(future);
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
index 9cca5ae..722d007 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards;
 
+import org.apache.syncope.client.ui.commons.wizards.ModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -26,7 +28,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.NotificationPanel;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wizards.any.ResultPage;
 import org.apache.wicket.Component;
@@ -36,7 +37,6 @@ import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
-import org.apache.wicket.event.IEventSource;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -46,11 +46,13 @@ import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.StringResourceModel;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
+import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
+import org.apache.syncope.client.ui.commons.wizards.AbstractWizardMgtPanel;
 import org.apache.wicket.markup.html.basic.Label;
 
-public abstract class WizardMgtPanel<T extends Serializable> extends Panel implements IEventSource {
+public abstract class WizardMgtPanel<T extends Serializable> extends AbstractWizardMgtPanel<T> {
 
     private static final long serialVersionUID = -4152438633429194882L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java
index bd783b8..683e70b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java
@@ -31,6 +31,7 @@ import org.apache.cxf.common.util.StringUtils;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
index 5dff819..d4c1923 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
@@ -18,7 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.model.PropertyModel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectTemplateWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectTemplateWizardBuilder.java
index 141aa9d..27b49fd 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectTemplateWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectTemplateWizardBuilder.java
@@ -18,9 +18,10 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.List;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.TemplatableTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
index 1d63ea9..156d594 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
@@ -23,7 +23,8 @@ import java.util.List;
 import org.apache.syncope.client.console.layout.AnyObjectForm;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.request.AnyObjectCR;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWrapper.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWrapper.java
index 3855bd8..cb84a99 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWrapper.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWrapper.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 
 public class AnyObjectWrapper extends AnyWrapper<AnyObjectTO> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
index b4ca67b..d722918 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
@@ -18,15 +18,21 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import java.io.Serializable;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.SyncopeWebApplication;
-import org.apache.syncope.client.console.layout.AbstractAnyFormLayout;
-import org.apache.syncope.client.console.layout.AnyForm;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
 import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
 import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractAnyWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.GroupTO;
@@ -35,7 +41,7 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.wizard.WizardModel;
 
-public abstract class AnyWizardBuilder<A extends AnyTO> extends AjaxWizardBuilder<AnyWrapper<A>> {
+public abstract class AnyWizardBuilder<A extends AnyTO> extends AbstractAnyWizardBuilder<A> {
 
     private static final long serialVersionUID = -2480279868319546243L;
 
@@ -103,7 +109,7 @@ public abstract class AnyWizardBuilder<A extends AnyTO> extends AjaxWizardBuilde
         }
 
         if (formLayoutInfo.isAuxClasses()) {
-            wizardModel.add(new AuxClasses(modelObject, anyTypeClasses));
+            wizardModel.add(new ConsoleAuxClasses(modelObject, anyTypeClasses));
         }
 
         if (formLayoutInfo.isGroups()) {
@@ -173,6 +179,7 @@ public abstract class AnyWizardBuilder<A extends AnyTO> extends AjaxWizardBuilde
         }
     }
 
+    @Override
     protected void fixPlainAndVirAttrs(final AnyTO updated, final AnyTO original) {
         // re-add to the updated object any missing plain or virtual attribute (compared to original): this to cope with
         // form layout, which might have not included some plain or virtual attributes
@@ -212,4 +219,24 @@ public abstract class AnyWizardBuilder<A extends AnyTO> extends AjaxWizardBuilde
         }
     }
 
+    @Override
+    protected long getMaxWaitTimeInSeconds() {
+        return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
+    }
+
+    @Override
+    protected void sendError(final String message) {
+        SyncopeConsoleSession.get().error(message);
+    }
+
+    @Override
+    protected void sendWarning(final String message) {
+        SyncopeConsoleSession.get().warn(message);
+    }
+
+    @Override
+    protected Future<Pair<Serializable, Serializable>> execute(
+            final Callable<Pair<Serializable, Serializable>> future) {
+        return SyncopeConsoleSession.get().execute(future);
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
index 881e440..ca7f8ed 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
@@ -27,10 +27,10 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.commons.ConnIdSpecialName;
+import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.wicket.Component;
 import org.apache.wicket.behavior.Behavior;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
similarity index 56%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
copy to client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
index 095cef5..3efd013 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
@@ -18,20 +18,23 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import java.io.Serializable;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractAuxClasses;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import java.util.List;
+import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 
-public class AnyWrapper<T extends AnyTO> implements Serializable {
+public class ConsoleAuxClasses extends AbstractAuxClasses {
 
-    private static final long serialVersionUID = 8058288034211558375L;
+    private static final long serialVersionUID = 552437609667518888L;
 
-    protected final T anyTO;
-
-    public AnyWrapper(final T anyTO) {
-        this.anyTO = anyTO;
+    public <T extends AnyTO> ConsoleAuxClasses(final AnyWrapper<T> modelObject, final List<String> anyTypeClasses) {
+        super(modelObject, anyTypeClasses);
     }
 
-    public T getInnerObject() {
-        return anyTO;
+    @Override
+    protected final List<AnyTypeClassTO> listAnyTypecClasses() {
+        return new AnyTypeClassRestClient().list();
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
index fef043c..52f251f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,8 +27,8 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
index 5016e7d..2eeb914 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
@@ -23,9 +23,10 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.pages.Realms;
 import org.apache.syncope.client.console.rest.RealmRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
index bf59b5f..6de2fa8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
@@ -26,7 +26,7 @@ import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
 import org.apache.syncope.client.console.panels.search.MapOfListModel;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
index 249f4cf..641fc64 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.model.PropertyModel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupTemplateWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupTemplateWizardBuilder.java
index d9199fe..bab9f09 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupTemplateWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupTemplateWizardBuilder.java
@@ -18,9 +18,10 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.List;
 import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.TemplatableTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
index 575f6bc..d06c0bd 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.io.Serializable;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
@@ -25,8 +26,8 @@ import org.apache.cxf.common.util.CollectionUtils;
 import org.apache.syncope.client.console.layout.GroupForm;
 import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
 import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.request.GroupCR;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWrapper.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWrapper.java
index 8e82041..bce9de9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWrapper.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWrapper.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index 6594b13..f6b8604 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -18,22 +18,22 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
 import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.rest.DynRealmRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroups;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroupsModel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.to.AnyTO;
@@ -42,7 +42,6 @@ import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
-import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.util.ListModel;
@@ -50,38 +49,30 @@ import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
-import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.PropertyModel;
 
-public class Groups extends WizardStep implements ICondition {
+public class Groups extends AbstractGroups {
 
     private static final long serialVersionUID = 552437609667518888L;
 
-    private static final int MAX_GROUP_LIST_CARDINALITY = 30;
-
     private final GroupRestClient groupRestClient = new GroupRestClient();
 
-    private final List<DynRealmTO> allDynRealms = new DynRealmRestClient().list();
-
-    private GroupsModel groupsModel;
-
-    private final AnyTO anyTO;
-
     private boolean templateMode;
 
     protected WebMarkupContainer dyngroupsContainer;
 
     protected WebMarkupContainer dynrealmsContainer;
 
-    public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject, final boolean templateMode) {
-        super();
-        this.templateMode = templateMode;
+    private final ConsoleGroupsModel groupsModel;
 
-        this.anyTO = modelObject.getInnerObject();
+    private final List<DynRealmTO> allDynRealms = new ArrayList<>();
 
-        groupsModel = new GroupsModel();
+    public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject, final boolean templateMode) {
+        super(modelObject);
+        this.templateMode = templateMode;
+        this.groupsModel = new ConsoleGroupsModel();
 
         // -----------------------------------------------------------------
         // Pre-Authorizations
@@ -91,18 +82,26 @@ public class Groups extends WizardStep implements ICondition {
         permissions.authorizeAll(RENDER);
         // -----------------------------------------------------------------
 
-        setOutputMarkupId(true);
+        addDynamicGroupsContainer();
 
-        WebMarkupContainer groupsContainer = new WebMarkupContainer("groupsContainer");
-        groupsContainer.setOutputMarkupId(true);
-        groupsContainer.setOutputMarkupPlaceholderTag(true);
-        add(groupsContainer);
+        addGroupsPanel();
 
-        dyngroupsContainer = new WebMarkupContainer("dyngroupsContainer");
-        dyngroupsContainer.setOutputMarkupId(true);
-        dyngroupsContainer.setOutputMarkupPlaceholderTag(true);
-        add(dyngroupsContainer);
+        addDynamicRealmsContainer();
+    }
+
+    private void addDynamicRealmsContainer() {
+        dynrealmsContainer = new WebMarkupContainer("dynrealmsContainer");
+        dynrealmsContainer.setOutputMarkupId(true);
+        dynrealmsContainer.setOutputMarkupPlaceholderTag(true);
+        dynrealmsContainer.add(new AjaxPalettePanel.Builder<>().build("dynrealms",
+                new PropertyModel<>(anyTO, "dynRealms"),
+                new ListModel<>(allDynRealms.stream().map(EntityTO::getKey).collect(Collectors.toList()))).
+                hideLabel().setEnabled(false).setOutputMarkupId(true));
+        add(dynrealmsContainer);
+    }
 
+    @Override
+    protected void addGroupsPanel() {
         if (anyTO instanceof GroupTO) {
             groupsContainer.add(new Label("groups").setVisible(false));
             groupsContainer.setVisible(false);
@@ -179,29 +178,13 @@ public class Groups extends WizardStep implements ICondition {
 
             // ---------------------------------
         }
+    }
 
-        dynrealmsContainer = new WebMarkupContainer("dynrealmsContainer");
-        dynrealmsContainer.setOutputMarkupId(true);
-        dynrealmsContainer.setOutputMarkupPlaceholderTag(true);
-        dynrealmsContainer.add(new AjaxPalettePanel.Builder<>().build("dynrealms",
-                new PropertyModel<>(anyTO, "dynRealms"),
-                new ListModel<>(allDynRealms.stream().map(EntityTO::getKey).collect(Collectors.toList()))).
-                hideLabel().setEnabled(false).setOutputMarkupId(true));
-        add(dynrealmsContainer);
-
-        // ------------------
-        // insert changed label if needed
-        // ------------------
-        if (modelObject instanceof UserWrapper
-                && UserWrapper.class.cast(modelObject).getPreviousUserTO() != null
-                && !ListUtils.isEqualList(
-                        UserWrapper.class.cast(modelObject).getInnerObject().getMemberships(),
-                        UserWrapper.class.cast(modelObject).getPreviousUserTO().getMemberships())) {
-            groupsContainer.add(new LabelInfo("changed", StringUtils.EMPTY));
-        } else {
-            groupsContainer.add(new Label("changed", StringUtils.EMPTY));
-        }
-        // ------------------
+    private void addDynamicGroupsContainer() {
+        dyngroupsContainer = new WebMarkupContainer("dyngroupsContainer");
+        dyngroupsContainer.setOutputMarkupId(true);
+        dyngroupsContainer.setOutputMarkupPlaceholderTag(true);
+        add(dyngroupsContainer);
     }
 
     @Override
@@ -213,7 +196,7 @@ public class Groups extends WizardStep implements ICondition {
                         isActionAuthorized(this, RENDER);
     }
 
-    private class GroupsModel extends ListModel<GroupTO> {
+    public class ConsoleGroupsModel extends AbstractGroupsModel {
 
         private static final long serialVersionUID = -4541954630939063927L;
 
@@ -234,7 +217,8 @@ public class Groups extends WizardStep implements ICondition {
         /**
          * Retrieve the first MAX_GROUP_LIST_CARDINALITY assignable.
          */
-        private void reloadObject() {
+        @Override
+        protected void reloadObject() {
             groups = groupRestClient.search(
                     realm,
                     SyncopeClient.getGroupSearchConditionBuilder().isAssignable().query(),
@@ -244,6 +228,7 @@ public class Groups extends WizardStep implements ICondition {
                     null);
         }
 
+        @Override
         public List<MembershipTO> getMemberships() {
             reload();
             return memberships;
@@ -252,7 +237,8 @@ public class Groups extends WizardStep implements ICondition {
         /**
          * Retrieve group memberships.
          */
-        private void reloadMemberships() {
+        @Override
+        protected void reloadMemberships() {
             // this is to be sure to have group names (required to see membership details in approval page)
             GroupFiqlSearchConditionBuilder searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
 
@@ -286,6 +272,7 @@ public class Groups extends WizardStep implements ICondition {
             memberships = GroupableRelatableTO.class.cast(anyTO).getMemberships();
         }
 
+        @Override
         public List<String> getDynMemberships() {
             reload();
             return dynMemberships;
@@ -294,7 +281,8 @@ public class Groups extends WizardStep implements ICondition {
         /**
          * Retrieve dyn group memberships.
          */
-        private void reloadDynMemberships() {
+        @Override
+        protected void reloadDynMemberships() {
             GroupFiqlSearchConditionBuilder searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
 
             List<CompleteCondition> conditions = GroupableRelatableTO.class.cast(anyTO).getDynMemberships().
@@ -317,7 +305,8 @@ public class Groups extends WizardStep implements ICondition {
         /**
          * Reload data if the realm changes (see SYNCOPE-1135).
          */
-        private void reload() {
+        @Override
+        protected void reload() {
             boolean reload;
 
             if (Groups.this.templateMode) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Ownership.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Ownership.java
index 859c71d..627fee7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Ownership.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Ownership.java
@@ -37,8 +37,8 @@ import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
index 67dd335..7a9de30 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
@@ -19,6 +19,8 @@
 package org.apache.syncope.client.console.wizards.any;
 
 import java.io.Serializable;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -29,21 +31,21 @@ import java.util.stream.Collectors;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.SchemaUtils;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AbstractFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.SchemaUtils;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.EncryptedFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
index bfbdc1d..c25d458 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -39,13 +41,13 @@ import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.RelationshipTypeRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 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.ActionsPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
index 5c13dbe..b44fadc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
@@ -18,41 +18,20 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.SyncopeWebApplication;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractResources;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
-import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.util.ListModel;
 
-public class Resources extends WizardStep implements ICondition {
+public class Resources extends AbstractResources {
 
-    private static final long serialVersionUID = 552437609667518888L;
-
-    private final ListModel<String> available;
+    private static final long serialVersionUID = 702900610508752856L;
 
     public <T extends AnyTO> Resources(final AnyWrapper<T> modelObject) {
-        final T entityTO = modelObject.getInnerObject();
-
-        if (modelObject instanceof UserWrapper
-                && UserWrapper.class.cast(modelObject).getPreviousUserTO() != null
-                && !modelObject.getInnerObject().getResources().equals(
-                        UserWrapper.class.cast(modelObject).getPreviousUserTO().getResources())) {
-
-            add(new LabelInfo("changed", StringUtils.EMPTY));
-        } else {
-            add(new Label("changed", StringUtils.EMPTY));
-        }
+        super(modelObject);
 
         // -----------------------------------------------------------------
         // Pre-Authorizations
@@ -62,26 +41,6 @@ public class Resources extends WizardStep implements ICondition {
         permissions.authorize(RENDER,
                 new org.apache.wicket.authroles.authorization.strategies.role.Roles(StandardEntitlement.RESOURCE_LIST));
         // -----------------------------------------------------------------
-
-        this.setOutputMarkupId(true);
-        this.available = new ListModel<>(Collections.<String>emptyList());
-
-        add(new AjaxPalettePanel.Builder<String>().build("resources",
-                new PropertyModel<List<String>>(entityTO, "resources") {
-
-            private static final long serialVersionUID = 3799387950428254072L;
-
-            @Override
-            public List<String> getObject() {
-                return new ArrayList<>(entityTO.getResources());
-            }
-
-            @Override
-            public void setObject(final List<String> object) {
-                entityTO.getResources().clear();
-                entityTO.getResources().addAll(object);
-            }
-        }, available).hideLabel().setOutputMarkupId(true));
     }
 
     @Override
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ResultPage.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ResultPage.java
index a195b8a..85a45ce 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ResultPage.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ResultPage.java
@@ -24,8 +24,8 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.syncope.client.console.panels.WizardModalPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 
 public abstract class ResultPage<T extends Serializable> extends Panel implements WizardModalPanel<T> {
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Roles.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Roles.java
index 913e867..1e9c38f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Roles.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Roles.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -26,8 +28,8 @@ import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.rest.RoleRestClient;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
index 3857969..39f0408 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
@@ -28,10 +28,10 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.lang3.tuple.Triple;
 import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
-import org.apache.syncope.client.console.commons.status.Status;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.ui.commons.status.Status;
+import org.apache.syncope.client.ui.commons.status.StatusBean;
+import org.apache.syncope.client.ui.commons.status.StatusUtils;
 import org.apache.syncope.client.console.panels.ListViewPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.panels.PropagationErrorPanel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TemplateWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TemplateWizardBuilder.java
index 4e994c1..89b92a4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TemplateWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TemplateWizardBuilder.java
@@ -18,7 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.AnyTO;
 
 public interface TemplateWizardBuilder<T extends AnyTO> {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TypeExtensionWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TypeExtensionWizardBuilder.java
index 2e5f725..7cb6251 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TypeExtensionWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/TypeExtensionWizardBuilder.java
@@ -23,10 +23,10 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.TypeExtensionTO;
@@ -38,7 +38,7 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class TypeExtensionWizardBuilder extends AjaxWizardBuilder<TypeExtensionTO> {
+public class TypeExtensionWizardBuilder extends BaseAjaxWizardBuilder<TypeExtensionTO> {
 
     private static final long serialVersionUID = -7185214439144835423L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
index 6fbd21a..bca9994 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
@@ -18,11 +18,13 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
 import java.util.Collections;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.Component;
 import org.apache.wicket.PageReference;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserTemplateWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserTemplateWizardBuilder.java
index 3c8111c..43bbaeb 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserTemplateWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserTemplateWizardBuilder.java
@@ -18,9 +18,11 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.List;
 import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.TemplatableTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java
index 8201ec1..8f12031 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java
@@ -21,10 +21,12 @@ package org.apache.syncope.client.console.wizards.any;
 import java.io.Serializable;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.layout.UserForm;
-import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
 import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
+import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.request.PasswordPatch;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
index 4b7c2df..6272669 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,12 +28,12 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AbstractFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
index 1f3ecd3..8fbc178 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
@@ -29,10 +29,11 @@ import org.apache.syncope.client.console.rest.ApplicationRestClient;
 import org.apache.syncope.client.console.rest.DynRealmRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.rest.RoleRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.RoleTO;
@@ -47,7 +48,7 @@ import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class RoleWizardBuilder extends AjaxWizardBuilder<RoleWrapper> {
+public class RoleWizardBuilder extends BaseAjaxWizardBuilder<RoleWrapper> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_it.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_it.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_it.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_ja.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_ja.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_ja.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_pt_BR.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_pt_BR.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_pt_BR.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_ru.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AuxClasses_ru.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses_ru.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AbstractFieldPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AbstractFieldPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDropDownChoicePanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDropDownChoicePanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSpinnerFieldPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxSpinnerFieldPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSpinnerFieldPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxSpinnerFieldPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTextFieldPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTextFieldPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_it.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_it.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_it.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_ja.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_ja.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_ja.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_pt_BR.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_pt_BR.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_pt_BR.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_ru.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/EncryptedFieldPanel_ru.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/EncryptedFieldPanel_ru.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/NonI18nPalette.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/NonI18nPalette.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/NonI18nPalette.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/NonI18nPalette.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/preview/AbstractBinaryPreviewer.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/preview/AbstractBinaryPreviewer.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/preview/AbstractBinaryPreviewer.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/preview/AbstractBinaryPreviewer.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/preview/DefaultPreviewer.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/preview/DefaultPreviewer.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/preview/DefaultPreviewer.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/preview/DefaultPreviewer.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LabelPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/panels/LabelPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LabelPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/panels/LabelPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/panels/NotificationPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/panels/NotificationPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/bootstrap/tabs/Accordion.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wicket/markup/html/bootstrap/tabs/Accordion.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/bootstrap/tabs/Accordion.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wicket/markup/html/bootstrap/tabs/Accordion.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizardMgtButtonBar.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizardMgtButtonBar.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizardMgtButtonBar.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_it.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_it.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_it.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ja.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_ja.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ja.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_pt_BR.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_pt_BR.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_pt_BR.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ru.properties
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/AjaxWizard_ru.properties
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ru.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/PasswordPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.html
similarity index 100%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/PasswordPanel.html
copy to client/idrepo/console/src/main/resources/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.html
diff --git a/client/idrepo/console/pom.xml b/client/idrepo/enduser/pom.xml
similarity index 95%
copy from client/idrepo/console/pom.xml
copy to client/idrepo/enduser/pom.xml
index 25d4739..f2cb5c1 100644
--- a/client/idrepo/console/pom.xml
+++ b/client/idrepo/enduser/pom.xml
@@ -27,10 +27,10 @@ under the License.
     <version>3.0.0-SNAPSHOT</version>
   </parent>
 
-  <name>Apache Syncope Client IdRepo Console</name>
-  <description>Apache Syncope Client IdRepo Console</description>
+  <name>Apache Syncope Client IdRepo Enduser</name>
+  <description>Apache Syncope Client IdRepo Enduser</description>
   <groupId>org.apache.syncope.client.idrepo</groupId>
-  <artifactId>syncope-client-idrepo-console</artifactId>
+  <artifactId>syncope-client-idrepo-enduser</artifactId>
   <packaging>jar</packaging>
   
   <properties>
@@ -91,6 +91,12 @@ under the License.
       <artifactId>syncope-client-idrepo-lib</artifactId>
       <version>${project.version}</version>
     </dependency>
+    
+    <dependency>
+      <groupId>org.apache.syncope.client.idrepo</groupId>
+      <artifactId>syncope-client-idrepo-ui-commons</artifactId>      
+      <version>${project.version}</version>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.cxf</groupId>
@@ -142,7 +148,7 @@ under the License.
       <groupId>org.webjars</groupId>
       <artifactId>jQuery-slimScroll</artifactId>
     </dependency>
-
+    
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
@@ -250,4 +256,4 @@ under the License.
       </build>
     </profile>
   </profiles>
-</project>
+</project>
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
new file mode 100644
index 0000000..df3837b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
@@ -0,0 +1,62 @@
+/*
+ * 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.enduser;
+
+import com.giffing.wicket.spring.boot.starter.web.config.WicketWebInitializerAutoConfig.WebSocketWicketWebInitializerAutoConfiguration;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.enduser.init.MIMETypesLoader;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = {
+    ErrorMvcAutoConfiguration.class,
+    HttpMessageConvertersAutoConfiguration.class })
+public class SyncopeEnduserApplication extends SpringBootServletInitializer {
+
+    public static void main(final String[] args) {
+        SpringApplication.run(SyncopeEnduserApplication.class, args);
+    }
+
+    @Override
+    protected SpringApplicationBuilder configure(final SpringApplicationBuilder builder) {
+        builder.properties(WebSocketWicketWebInitializerAutoConfiguration.REGISTER_SERVER_ENDPOINT_ENABLED + "=false");
+        return super.configure(builder);
+    }
+
+    @Bean
+    public ClassPathScanImplementationLookup classPathScanImplementationLookup() {
+        ClassPathScanImplementationLookup lookup = new ClassPathScanImplementationLookup();
+        lookup.load();
+        return lookup;
+    }
+
+    @Bean
+    public MIMETypesLoader mimeTypesLoader() {
+        MIMETypesLoader mimeTypesLoader = new MIMETypesLoader();
+        mimeTypesLoader.load();
+        return mimeTypesLoader;
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
similarity index 65%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
index 095cef5..0a683a9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
@@ -16,22 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser;
 
-import java.io.Serializable;
-import org.apache.syncope.common.lib.to.AnyTO;
+public final class SyncopeEnduserConstants {
 
-public class AnyWrapper<T extends AnyTO> implements Serializable {
+    public static final String CAPTCHA_SESSION_KEY = "captcha";
 
-    private static final long serialVersionUID = 8058288034211558375L;
+    public static final String XSRF_COOKIE = "XSRF-TOKEN";
 
-    protected final T anyTO;
+    public static final String XSRF_HEADER_NAME = "X-XSRF-TOKEN";
 
-    public AnyWrapper(final T anyTO) {
-        this.anyTO = anyTO;
-    }
+    public static final String MEMBERSHIP_ATTR_SEPARATOR = "#";
 
-    public T getInnerObject() {
-        return anyTO;
+    private SyncopeEnduserConstants() {
+        // private constructor for utility class
     }
+
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
new file mode 100644
index 0000000..ece546a
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
@@ -0,0 +1,230 @@
+/*
+ * 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.enduser;
+
+import java.text.DateFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.info.PlatformInfo;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.request.Request;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.task.TaskRejectedException;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+/**
+ * Custom Syncope Enduser Session class.
+ */
+public class SyncopeEnduserSession extends WebSession {
+
+    private static final long serialVersionUID = 1284946129513378647L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(SyncopeEnduserSession.class);
+
+    private final SyncopeClient anonymousClient;
+
+    private SyncopeClient client;
+
+    private final PlatformInfo platformInfo;
+
+    private UserTO selfTO;
+
+    private final Map<Class<?>, Object> services = Collections.synchronizedMap(new HashMap<>());
+    
+    private final ThreadPoolTaskExecutor executor;
+
+    public static SyncopeEnduserSession get() {
+        return (SyncopeEnduserSession) Session.get();
+    }
+
+    public SyncopeEnduserSession(final Request request) {
+        super(request);
+        anonymousClient = SyncopeWebApplication.get().getClientFactory().
+                create(new AnonymousAuthenticationHandler(
+                        SyncopeWebApplication.get().getAnonymousUser(),
+                        SyncopeWebApplication.get().getAnonymousKey()));
+        platformInfo = anonymousClient.getService(SyncopeService.class).platform();
+        
+        executor = new ThreadPoolTaskExecutor();
+        executor.setWaitForTasksToCompleteOnShutdown(false);
+        executor.setCorePoolSize(SyncopeWebApplication.get().getCorePoolSize());
+        executor.setMaxPoolSize(SyncopeWebApplication.get().getMaxPoolSize());
+        executor.setQueueCapacity(SyncopeWebApplication.get().getQueueCapacity());
+        executor.initialize();
+    }
+
+    public void cleanup() {
+        client = null;
+        selfTO = null;
+        services.clear();
+    }
+
+    public MediaType getMediaType() {
+        return SyncopeWebApplication.get().getClientFactory().getContentType().getMediaType();
+    }
+
+    public String getJWT() {
+        return client == null ? null : client.getJWT();
+    }
+
+    private void afterAuthentication(final String username) {
+        try {
+            selfTO = client.self().getRight();
+        } catch (ForbiddenException e) {
+            LOG.warn("Could not read self(), probably in a {} scenario", StandardEntitlement.MUST_CHANGE_PASSWORD, e);
+
+            selfTO = new UserTO();
+            selfTO.setUsername(username);
+            selfTO.setMustChangePassword(true);
+        }
+
+        // bind explicitly this session to have a stateful behavior during http requests, unless session will
+        // expire at each request
+        this.bind();
+    }
+
+    public boolean authenticate(final String username, final String password) {
+        boolean authenticated = false;
+
+        try {
+            client = SyncopeWebApplication.get().getClientFactory().
+                    setDomain(SyncopeWebApplication.get().getDomain()).
+                    create(username, password);
+
+            afterAuthentication(username);
+
+            authenticated = true;
+        } catch (Exception e) {
+            LOG.error("Authentication failed", e);
+        }
+
+        return authenticated;
+    }
+
+    public boolean authenticate(final String jwt) {
+        boolean authenticated = false;
+
+        try {
+            client = SyncopeWebApplication.get().getClientFactory().
+                    setDomain(SyncopeWebApplication.get().getDomain()).create(jwt);
+
+            afterAuthentication(null);
+
+            authenticated = true;
+        } catch (Exception e) {
+            LOG.error("Authentication failed", e);
+        }
+
+        return authenticated;
+    }
+
+    @Override
+    public void invalidate() {
+        if (isAuthenticated()) {
+            try {
+                client.logout();
+            } catch (Exception e) {
+                LOG.debug("Unexpected exception while logging out", e);
+            } finally {
+                client = null;
+                selfTO = null;
+            }
+        }
+        super.invalidate();
+    }
+
+    public <T> T getService(final Class<T> serviceClass) {
+        return (client == null || !isAuthenticated())
+                ? anonymousClient.getService(serviceClass)
+                : client.getService(serviceClass);
+    }
+
+    public <T> T getService(final String etag, final Class<T> serviceClass) {
+        T serviceInstance = getService(serviceClass);
+        WebClient.client(serviceInstance).match(new EntityTag(etag), false).
+                type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
+
+        return serviceInstance;
+    }
+
+    public PlatformInfo getPlatformInfo() {
+        return platformInfo;
+    }
+
+    public UserTO getSelfTO() {
+        if (selfTO == null) {
+            throw new IllegalArgumentException("User not authenticated");
+        }
+        return selfTO;
+    }
+
+    public <T> Future<T> execute(final Callable<T> command) {
+        try {
+            return executor.submit(command);
+        } catch (TaskRejectedException e) {
+            LOG.error("Could not execute {}", command, e);
+
+            return new CompletableFuture<>();
+        }
+    }
+
+    public boolean isAuthenticated() {
+        return client != null && client.getJWT() != null;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T getCachedService(final Class<T> serviceClass) {
+        T service;
+        if (services.containsKey(serviceClass)) {
+            service = (T) services.get(serviceClass);
+        } else {
+            service = client.getService(serviceClass);
+            services.put(serviceClass, service);
+        }
+
+        WebClient.client(service).type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
+
+        return service;
+    }
+
+    public <T> void resetClient(final Class<T> service) {
+        T serviceInstance = getCachedService(service);
+        WebClient.client(serviceInstance).reset();
+    }
+
+    public FastDateFormat getDateFormat() {
+        return FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale());
+    }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
new file mode 100644
index 0000000..c5bf95b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
@@ -0,0 +1,407 @@
+/*
+ * 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.enduser;
+
+import org.apache.syncope.client.enduser.themes.EnduserTheme;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.giffing.wicket.spring.boot.starter.app.WicketBootStandardWebApplication;
+import de.agilecoders.wicket.core.Bootstrap;
+import de.agilecoders.wicket.core.settings.BootstrapSettings;
+import de.agilecoders.wicket.core.settings.IBootstrapSettings;
+import de.agilecoders.wicket.core.settings.SingleThemeProvider;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.monitor.FileAlterationListener;
+import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
+import org.apache.commons.io.monitor.FileAlterationMonitor;
+import org.apache.commons.io.monitor.FileAlterationObserver;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.client.enduser.pages.MustChangePassword;
+import org.apache.syncope.client.enduser.pages.Self;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.client.ui.commons.SyncopeUIRequestCycleListener;
+import org.apache.syncope.common.lib.PropertyUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.wicket.Page;
+import org.apache.wicket.Session;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.CsrfPreventionRequestCycleListener;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.component.IRequestablePage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.resource.JQueryResourceReference;
+import org.apache.wicket.util.lang.Args;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SyncopeWebApplication extends WicketBootStandardWebApplication {
+
+    private static final long serialVersionUID = -6445919351044845120L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(SyncopeWebApplication.class);
+
+    private static final String ENDUSER_PROPERTIES = "enduser.properties";
+
+    private static final String CUSTOM_FORM_ATTRIBUTES_FILE = "customFormAttributes.json";
+
+    public static final List<Locale> SUPPORTED_LOCALES = Collections.unmodifiableList(Arrays.asList(
+            new Locale[] {
+                Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR"), new Locale("ru"), Locale.JAPANESE
+            }));
+
+    public static SyncopeWebApplication get() {
+        return (SyncopeWebApplication) WebApplication.get();
+    }
+
+    @Autowired
+    private ClassPathScanImplementationLookup lookup;
+
+    private String domain;
+
+    private String adminUser;
+
+    private String anonymousUser;
+
+    private String anonymousKey;
+
+    private boolean captchaEnabled;
+
+    private boolean xsrfEnabled;
+
+    private Integer maxWaitTime;
+
+    private Integer corePoolSize;
+
+    private Integer maxPoolSize;
+
+    private Integer queueCapacity;
+
+    private Integer maxUploadFileSizeMB;
+
+    private SyncopeClientFactoryBean clientFactory;
+
+    private Map<String, CustomAttributesInfo> customFormAttributes;
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    @Override
+    protected void init() {
+        super.init();
+
+        // read enduser.properties
+        Properties props = PropertyUtils.read(getClass(), ENDUSER_PROPERTIES, "enduser.directory");
+
+        domain = props.getProperty("domain", SyncopeConstants.MASTER_DOMAIN);
+        adminUser = props.getProperty("adminUser");
+        Args.notNull(adminUser, "<adminUser>");
+        anonymousUser = props.getProperty("anonymousUser");
+        Args.notNull(anonymousUser, "<anonymousUser>");
+        anonymousKey = props.getProperty("anonymousKey");
+        Args.notNull(anonymousKey, "<anonymousKey>");
+
+        captchaEnabled = Boolean.parseBoolean(props.getProperty("captcha"));
+        Args.notNull(captchaEnabled, "<captcha>");
+
+        xsrfEnabled = Boolean.parseBoolean(props.getProperty("xsrf"));
+        Args.notNull(xsrfEnabled, "<xsrf>");
+
+        String scheme = props.getProperty("scheme");
+        Args.notNull(scheme, "<scheme>");
+        String host = props.getProperty("host");
+        Args.notNull(host, "<host>");
+        String port = props.getProperty("port");
+        Args.notNull(port, "<port>");
+        String rootPath = props.getProperty("rootPath");
+        Args.notNull(rootPath, "<rootPath>");
+        String useGZIPCompression = props.getProperty("useGZIPCompression");
+        Args.notNull(useGZIPCompression, "<useGZIPCompression>");
+        maxUploadFileSizeMB = props.getProperty("maxUploadFileSizeMB") == null
+                ? null
+                : Integer.valueOf(props.getProperty("maxUploadFileSizeMB"));
+
+        maxWaitTime = Integer.valueOf(props.getProperty("maxWaitTimeOnApplyChanges", "30"));
+
+        // Resource connections check thread pool size
+        corePoolSize = Integer.valueOf(props.getProperty("executor.corePoolSize", "5"));
+        maxPoolSize = Integer.valueOf(props.getProperty("executor.maxPoolSize", "10"));
+        queueCapacity = Integer.valueOf(props.getProperty("executor.queueCapacity", "50"));
+
+        clientFactory = new SyncopeClientFactoryBean().
+                setAddress(scheme + "://" + host + ":" + port + StringUtils.prependIfMissing(rootPath, "/")).
+                setContentType(SyncopeClientFactoryBean.ContentType.JSON).
+                setUseCompression(BooleanUtils.toBoolean(useGZIPCompression));
+
+        // read customFormAttributes.json
+        File enduserDir;
+        try (InputStream is = getClass().getResourceAsStream("/" + CUSTOM_FORM_ATTRIBUTES_FILE)) {
+            customFormAttributes = MAPPER.readValue(is,
+                    new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+            });
+            enduserDir = new File(props.getProperty("enduser.directory"));
+            boolean existsEnduserDir = enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory();
+            if (existsEnduserDir) {
+                File customFormAttributesFile = FileUtils.getFile(enduserDir, CUSTOM_FORM_ATTRIBUTES_FILE);
+                if (customFormAttributesFile.exists()
+                        && customFormAttributesFile.canRead()
+                        && customFormAttributesFile.isFile()) {
+                    customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(customFormAttributesFile),
+                            new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+                    });
+                }
+            }
+            FileAlterationObserver observer = existsEnduserDir
+                    ? new FileAlterationObserver(enduserDir,
+                            pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_ATTRIBUTES_FILE))
+                    : new FileAlterationObserver(getClass().getResource("/" + CUSTOM_FORM_ATTRIBUTES_FILE).getFile(),
+                            pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_ATTRIBUTES_FILE));
+
+            FileAlterationMonitor monitor = new FileAlterationMonitor(5000);
+
+            FileAlterationListener listener = new FileAlterationListenerAdaptor() {
+
+                @Override
+                public void onFileChange(final File file) {
+                    try {
+                        LOG.trace("{} has changed. Reloading form attributes customization configuration.",
+                                CUSTOM_FORM_ATTRIBUTES_FILE);
+                        customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(file),
+                                new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+                        });
+                    } catch (IOException e) {
+                        e.printStackTrace(System.err);
+                    }
+                }
+
+                @Override
+                public void onFileCreate(final File file) {
+                    try {
+                        LOG.trace("{} has been created. Loading form attributes customization configuration.",
+                                CUSTOM_FORM_ATTRIBUTES_FILE);
+                        customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(file),
+                                new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+                        });
+                    } catch (IOException e) {
+                        e.printStackTrace(System.err);
+                    }
+                }
+
+                @Override
+                public void onFileDelete(final File file) {
+                    LOG.trace("{} has been deleted. Resetting form attributes customization configuration.",
+                            CUSTOM_FORM_ATTRIBUTES_FILE);
+                    customFormAttributes = null;
+                }
+            };
+
+            observer.addListener(listener);
+            monitor.addObserver(observer);
+            monitor.start();
+        } catch (Exception e) {
+            throw new WicketRuntimeException("Could not read " + CUSTOM_FORM_ATTRIBUTES_FILE, e);
+        }
+
+        // Application settings
+        IBootstrapSettings settings = new BootstrapSettings();
+
+        // set theme provider
+        settings.setThemeProvider(new SingleThemeProvider(new EnduserTheme()));
+
+        // install application settings
+        Bootstrap.install(this, settings);
+
+        getResourceSettings().setUseMinifiedResources(true);
+
+        getResourceSettings().setThrowExceptionOnMissingResource(true);
+
+        getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV2());
+
+        getResourceSettings().setThrowExceptionOnMissingResource(true);
+
+        getMarkupSettings().setStripWicketTags(true);
+        getMarkupSettings().setCompressWhitespace(true);
+
+        getMarkupSettings().setStripWicketTags(true);
+        getMarkupSettings().setCompressWhitespace(true);
+
+        String csrf = props.getProperty("csrf");
+
+        if (BooleanUtils.toBoolean(csrf)) {
+            getRequestCycleListeners().add(new CsrfPreventionRequestCycleListener());
+        }
+
+        getRequestCycleListeners().add(new SyncopeUIRequestCycleListener() {
+
+            @Override
+            protected boolean isSignedIn() {
+                return SyncopeEnduserSession.get().isAuthenticated();
+            }
+
+            @Override
+            protected void invalidateSession() {
+                SyncopeEnduserSession.get().invalidate();
+            }
+
+            @Override
+            protected IRequestablePage getErrorPage(final PageParameters errorParameters) {
+                return new Login(errorParameters);
+            }
+
+        });
+
+        for (Class<? extends AbstractResource> resource : lookup.getResources()) {
+            Resource annotation = resource.getAnnotation(Resource.class);
+            try {
+                AbstractResource instance = resource.getDeclaredConstructor().newInstance();
+
+                mountResource(annotation.path(), new ResourceReference(annotation.key()) {
+
+                    private static final long serialVersionUID = -128426276529456602L;
+
+                    @Override
+                    public IResource getResource() {
+                        return instance;
+                    }
+                });
+            } catch (Exception e) {
+                LOG.error("Could not instantiate {}", resource.getName(), e);
+            }
+        }
+        
+        // enable component path
+        if (getDebugSettings().isAjaxDebugModeEnabled()) {
+            getDebugSettings().setComponentPathAttributeName("syncope-path");
+        }
+    }
+
+    @Override
+    public Class<? extends Page> getHomePage() {
+        return SyncopeEnduserSession.get().isAuthenticated() && SyncopeEnduserSession.get().getSelfTO().
+                isMustChangePassword()
+                        ? MustChangePassword.class
+                        : SyncopeEnduserSession.get().isAuthenticated()
+                        ? Self.class
+                        : Login.class;
+    }
+
+    @Override
+    public Session newSession(final Request request, final Response response) {
+        return new SyncopeEnduserSession(request);
+    }
+
+    protected Class<? extends WebPage> getSignInPageClass() {
+        return Login.class;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public String getAdminUser() {
+        return adminUser;
+    }
+
+    public String getAnonymousUser() {
+        return anonymousUser;
+    }
+
+    public String getAnonymousKey() {
+        return anonymousKey;
+    }
+
+    public SyncopeClientFactoryBean getClientFactory() {
+        return clientFactory;
+    }
+
+    public boolean isCaptchaEnabled() {
+        return captchaEnabled;
+    }
+
+    public boolean isXsrfEnabled() {
+        return xsrfEnabled;
+    }
+
+    public Integer getMaxUploadFileSizeMB() {
+        return maxUploadFileSizeMB;
+    }
+
+    public Integer getCorePoolSize() {
+        return corePoolSize;
+    }
+
+    public void setCorePoolSize(final Integer corePoolSize) {
+        this.corePoolSize = corePoolSize;
+    }
+
+    public Integer getMaxPoolSize() {
+        return maxPoolSize;
+    }
+
+    public void setMaxPoolSize(final Integer maxPoolSize) {
+        this.maxPoolSize = maxPoolSize;
+    }
+
+    public Integer getQueueCapacity() {
+        return queueCapacity;
+    }
+
+    public void setQueueCapacity(final Integer queueCapacity) {
+        this.queueCapacity = queueCapacity;
+    }
+
+    public Integer getMaxWaitTimeInSeconds() {
+        return maxWaitTime;
+    }
+
+    public void setMaxWaitTime(final Integer maxWaitTime) {
+        this.maxWaitTime = maxWaitTime;
+    }
+
+    public Map<String, CustomAttributesInfo> getCustomFormAttributes() {
+        return customFormAttributes;
+    }
+
+    public void setCustomFormAttributes(final Map<String, CustomAttributesInfo> customFormAttributes) {
+        this.customFormAttributes.clear();
+        this.customFormAttributes.putAll(customFormAttributes);
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/annotations/BinaryPreview.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/annotations/Resource.java
similarity index 75%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/annotations/BinaryPreview.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/annotations/Resource.java
index d629969..b54e142 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/annotations/BinaryPreview.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/annotations/Resource.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.annotations;
+package org.apache.syncope.client.enduser.annotations;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.ElementType;
@@ -27,8 +27,16 @@ import java.lang.annotation.Target;
 @Target({ ElementType.TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
-public @interface BinaryPreview {
+public @interface Resource {
 
-    String[] mimeTypes() default {};
+    /**
+     * @return string for {@link org.apache.wicket.request.resource.ResourceReference#ResourceReference}
+     */
+    String key();
+
+    /**
+     * @return path for{@link org.apache.wicket.protocol.http.WebApplication#mountResource}
+     */
+    String path();
 
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/PreviewUtils.java
similarity index 75%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/PreviewUtils.java
index fc85cb5..f6bbab4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtils.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/PreviewUtils.java
@@ -16,21 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.commons;
+package org.apache.syncope.client.enduser.commons;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.DefaultPreviewer;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.DefaultPreviewer;
+import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.springframework.stereotype.Component;
 import org.springframework.util.ClassUtils;
 
 @Component
-public class PreviewUtils {
+public final class PreviewUtils {
 
-    @Autowired
-    private ClassPathScanImplementationLookup lookup;
+    public static PreviewUtils getInstance() {
+        return new PreviewUtils();
+    }
+
+    @SpringBean
+    protected ClassPathScanImplementationLookup lookup;
 
     public AbstractBinaryPreviewer getDefaultPreviewer(final String mimeType) {
         return new DefaultPreviewer("previewer", mimeType);
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java
new file mode 100644
index 0000000..9cdd056
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java
@@ -0,0 +1,113 @@
+/*
+ * 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.enduser.init;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.panels.SSOLoginFormPanel;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+import org.springframework.util.ClassUtils;
+
+public class ClassPathScanImplementationLookup {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class);
+
+    private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.client.enduser";
+
+    private List<Class<? extends SSOLoginFormPanel>> ssoLoginFormPanels = new ArrayList<>();
+
+    private List<Class<? extends AbstractResource>> resources = new ArrayList<>();
+
+    private List<Class<? extends AbstractBinaryPreviewer>> previewers = new ArrayList<>();
+
+    /**
+     * This method can be overridden by subclasses to customize classpath scan.
+     *
+     * @return basePackage for classpath scanning
+     */
+    protected String getBasePackage() {
+        return DEFAULT_BASE_PACKAGE;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void load() {
+        resources = new ArrayList<>();
+        previewers = new ArrayList<>();
+
+        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
+        scanner.addIncludeFilter(new AssignableTypeFilter(AbstractResource.class));
+
+        for (BeanDefinition bd : scanner.findCandidateComponents(getBasePackage())) {
+            try {
+                Class<?> clazz = ClassUtils.resolveClassName(bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
+                boolean isAbsractClazz = Modifier.isAbstract(clazz.getModifiers());
+
+                if (!isAbsractClazz) {
+                    if (AbstractResource.class.isAssignableFrom(clazz)) {
+                        if (clazz.isAnnotationPresent(Resource.class)) {
+                            resources.add((Class<? extends AbstractResource>) clazz);
+                        } else if (AbstractBinaryPreviewer.class.isAssignableFrom(clazz)) {
+                            previewers.add((Class<? extends AbstractBinaryPreviewer>) clazz);
+                        } else {
+                            LOG.error("Could not find annotation {} in {}, ignoring",
+                                    Resource.class.getName(), clazz.getName());
+                        }
+                    }
+                }
+            } catch (Throwable t) {
+                LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
+            }
+        }
+        resources = Collections.unmodifiableList(resources);
+    }
+
+    public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) {
+        LOG.debug("Searching for previewer class for MIME type: {}", mimeType);
+        Class<? extends AbstractBinaryPreviewer> previewer = null;
+        for (Class<? extends AbstractBinaryPreviewer> candidate : previewers) {
+            LOG.debug("Evaluating previewer class {} for MIME type {}", candidate.getName(), mimeType);
+            if (candidate.isAnnotationPresent(BinaryPreview.class)
+                    && ArrayUtils.contains(candidate.getAnnotation(BinaryPreview.class).mimeTypes(), mimeType)) {
+                LOG.debug("Found existing previewer for MIME type {}: {}", mimeType, candidate.getName());
+                previewer = candidate;
+            }
+        }
+        return previewer;
+    }
+
+    public List<Class<? extends AbstractResource>> getResources() {
+        return resources;
+    }
+
+    public List<Class<? extends SSOLoginFormPanel>> getSSOLoginFormPanels() {
+        return this.ssoLoginFormPanels;
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/MIMETypesLoader.java
similarity index 66%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/MIMETypesLoader.java
index ff10b8d..596f17f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/MIMETypesLoader.java
@@ -16,17 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
+package org.apache.syncope.client.enduser.init;
 
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
+import java.io.IOException;
+import org.apache.syncope.client.ui.commons.AbstractMIMETypesLoader;
+import org.apache.wicket.util.io.IOUtils;
 
-public class LabelPanel extends Panel {
+public class MIMETypesLoader extends AbstractMIMETypesLoader {
 
-    private static final long serialVersionUID = 5564818820574092960L;
-
-    public LabelPanel(final String id, final Label label) {
-        super(id);
-        add(label);
+    @Override
+    protected String getMimeTypesFile() throws IOException {
+        return IOUtils.toString(getClass().getResourceAsStream("/MIMETypes.json"));
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/FormLayoutInfoUtils.java
similarity index 57%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/FormLayoutInfoUtils.java
index 2a6a191..c921e9e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/FormLayoutInfoUtils.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/FormLayoutInfoUtils.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.layout;
+package org.apache.syncope.client.enduser.layout;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -24,14 +24,12 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.rest.RoleRestClient;
-import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.rest.RoleRestClient;
+import org.apache.syncope.client.ui.commons.wizards.ModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.PageReference;
@@ -45,10 +43,10 @@ public final class FormLayoutInfoUtils {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
-    public static Triple<UserFormLayoutInfo, GroupFormLayoutInfo, Map<String, AnyObjectFormLayoutInfo>> fetch(
+    public static UserFormLayoutInfo fetch(
             final Collection<String> anyTypes) {
 
-        List<String> ownedRoles = SyncopeConsoleSession.get().getSelfTO().getRoles();
+        List<String> ownedRoles = SyncopeEnduserSession.get().getSelfTO().getRoles();
         try {
             JsonNode tree = null;
             for (int i = 0; i < ownedRoles.size() && tree == null; i++) {
@@ -65,26 +63,10 @@ public final class FormLayoutInfoUtils {
                     ? MAPPER.treeToValue(tree.get(AnyTypeKind.USER.name()), UserFormLayoutInfo.class)
                     : new UserFormLayoutInfo();
 
-            GroupFormLayoutInfo groupFormLayoutInfo = tree.has(AnyTypeKind.USER.name())
-                    ? MAPPER.treeToValue(tree.get(AnyTypeKind.GROUP.name()), GroupFormLayoutInfo.class)
-                    : new GroupFormLayoutInfo();
-
-            Map<String, AnyObjectFormLayoutInfo> anyObjectFormLayoutInfos = new HashMap<>();
-            for (String anyType : anyTypes) {
-                if (!anyType.equals(AnyTypeKind.USER.name()) && !anyType.equals(AnyTypeKind.GROUP.name())) {
-
-                    anyObjectFormLayoutInfos.put(
-                            anyType,
-                            tree.has(anyType)
-                            ? MAPPER.treeToValue(tree.get(anyType), AnyObjectFormLayoutInfo.class)
-                            : new AnyObjectFormLayoutInfo());
-                }
-            }
-
-            return Triple.of(userFormLayoutInfo, groupFormLayoutInfo, anyObjectFormLayoutInfos);
+            return userFormLayoutInfo;
         } catch (IOException e) {
             throw new IllegalArgumentException("While parsing console layout info for "
-                    + SyncopeConsoleSession.get().getSelfTO().getUsername(), e);
+                    + SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
         }
     }
 
@@ -96,17 +78,11 @@ public final class FormLayoutInfoUtils {
                 ObjectNode tree = MAPPER.createObjectNode();
 
                 tree.set(AnyTypeKind.USER.name(), MAPPER.valueToTree(new UserFormLayoutInfo()));
-                tree.set(AnyTypeKind.GROUP.name(), MAPPER.valueToTree(new GroupFormLayoutInfo()));
-                for (String anyType : anyTypes) {
-                    if (!anyType.equals(AnyTypeKind.USER.name()) && !anyType.equals(AnyTypeKind.GROUP.name())) {
-                        tree.set(anyType, MAPPER.valueToTree(new AnyObjectFormLayoutInfo()));
-                    }
-                }
 
                 result = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
             } catch (IOException e) {
                 throw new IllegalArgumentException("While generating default console layout info for "
-                        + SyncopeConsoleSession.get().getSelfTO().getUsername(), e);
+                        + SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
             }
         } else {
             try {
@@ -119,29 +95,21 @@ public final class FormLayoutInfoUtils {
         return result;
     }
 
-    public static <A extends AnyTO, F extends AnyForm<A>, FL extends AbstractAnyFormLayout<A, F>> F instantiate(
-            final A anyTO,
+    public static ModalPanelBuilder<AnyWrapper<UserTO>> instantiate(
+            final UserTO userTO,
             final List<String> anyTypeClasses,
-            final FL anyFormLayout,
+            final UserFormLayoutInfo anyFormLayout,
             final PageReference pageRef) {
 
         try {
-            if (anyTO instanceof UserTO) {
-                return anyFormLayout.getFormClass().getConstructor(
-                        anyTO.getClass(), // previous
-                        anyTO.getClass(), // actual
-                        List.class,
-                        anyFormLayout.getClass(),
-                        pageRef.getClass()).
-                        newInstance(null, anyTO, anyTypeClasses, anyFormLayout, pageRef);
-            } else {
-                return anyFormLayout.getFormClass().getConstructor(
-                        anyTO.getClass(), // actual
-                        List.class,
-                        anyFormLayout.getClass(),
-                        pageRef.getClass()).
-                        newInstance(anyTO, anyTypeClasses, anyFormLayout, pageRef);
-            }
+            return anyFormLayout.getFormClass().getConstructor(
+                    userTO.getClass(), // previous
+                    userTO.getClass(), // actual
+                    List.class,
+                    anyFormLayout.getClass(),
+                    pageRef.getClass()).
+                    newInstance(null, userTO, anyTypeClasses, anyFormLayout, pageRef);
+
         } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
                 | IllegalArgumentException | InvocationTargetException e) {
             throw new IllegalArgumentException("Could not instantiate " + anyFormLayout.getFormClass().getName(), e);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
similarity index 72%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
index c100143..865b931 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.layout;
+package org.apache.syncope.client.enduser.layout;
 
-import org.apache.syncope.client.console.wizards.any.UserWizardBuilder;
+import org.apache.syncope.client.enduser.wizards.any.UserWizardBuilder;
+import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
 import org.apache.syncope.common.lib.to.UserTO;
 
 public class UserFormLayoutInfo extends AbstractAnyFormLayout<UserTO, UserForm> {
@@ -27,10 +29,6 @@ public class UserFormLayoutInfo extends AbstractAnyFormLayout<UserTO, UserForm>
 
     private boolean passwordManagement = true;
 
-    private boolean roles = true;
-
-    private boolean relationships = true;
-
     @Override
     protected Class<? extends UserForm> getDefaultFormClass() {
         return UserWizardBuilder.class;
@@ -43,21 +41,4 @@ public class UserFormLayoutInfo extends AbstractAnyFormLayout<UserTO, UserForm>
     public void setPasswordManagement(final boolean passwordManagement) {
         this.passwordManagement = passwordManagement;
     }
-
-    public boolean isRoles() {
-        return roles;
-    }
-
-    public void setRoles(final boolean roles) {
-        this.roles = roles;
-    }
-
-    public boolean isRelationships() {
-        return relationships;
-    }
-
-    public void setRelationships(final boolean relationships) {
-        this.relationships = relationships;
-    }
-
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateFieldPanel.java
similarity index 71%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateFieldPanel.java
index 69e572c..4ba9685 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateFieldPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateFieldPanel.java
@@ -16,11 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.enduser.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import com.googlecode.wicket.kendo.ui.form.datetime.AjaxDatePicker;
 import java.util.Date;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.markup.html.form.DateFieldPanel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 
@@ -31,7 +34,7 @@ public class AjaxDateFieldPanel extends DateFieldPanel {
     public AjaxDateFieldPanel(final String id, final String name, final IModel<Date> model, final String datePattern) {
         super(id, name, model, datePattern);
 
-        field = new AjaxDatePicker("field", model, SyncopeConsoleSession.get().getLocale(), datePattern);
+        field = new AjaxDatePicker("field", model, AjaxDateFieldPanel.this.getLocale(), datePattern);
         add(field.setLabel(new Model<>(name)).setOutputMarkupId(true));
     }
 
@@ -48,4 +51,11 @@ public class AjaxDateFieldPanel extends DateFieldPanel {
 
         return panel;
     }
+
+    @Override
+    protected FastDateFormat getDateFormat(final String datePattern) {
+        return datePattern == null
+                ? SyncopeEnduserSession.get().getDateFormat()
+                : FastDateFormat.getInstance(datePattern);
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateTimeFieldPanel.java
similarity index 75%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateTimeFieldPanel.java
index 8d5fe2e..7073ae2 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDateTimeFieldPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDateTimeFieldPanel.java
@@ -16,11 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.enduser.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.DateFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import com.googlecode.wicket.kendo.ui.form.datetime.AjaxDateTimePicker;
 import java.util.Date;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 
@@ -35,7 +38,7 @@ public class AjaxDateTimeFieldPanel extends DateFieldPanel {
 
         // dateTimePattern should be spit into separate date and time pattern strings in order to be passed to the
         // AjaxDateTimePicker constructor, but there is no safe way to do that - ignoring
-        field = new AjaxDateTimePicker("field", model, SyncopeConsoleSession.get().getLocale());
+        field = new AjaxDateTimePicker("field", model, getLocale());
         add(field.setLabel(new Model<>(name)).setOutputMarkupId(true));
     }
 
@@ -52,4 +55,11 @@ public class AjaxDateTimeFieldPanel extends DateFieldPanel {
 
         return panel;
     }
+
+    @Override
+    protected FastDateFormat getDateFormat(final String datePattern) {
+        return datePattern == null
+                ? SyncopeEnduserSession.get().getDateFormat()
+                : FastDateFormat.getInstance(datePattern);
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java
similarity index 94%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java
index cac77e3..26eee3b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDownload.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.enduser.markup.html.form;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.HttpResourceStream;
-import org.apache.syncope.client.console.init.MIMETypesLoader;
+import org.apache.syncope.client.enduser.init.MIMETypesLoader;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.AbstractAjaxBehavior;
 import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
similarity index 87%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
index e380ceb..3352bd1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
@@ -16,7 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.enduser.markup.html.form;
+
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 
 import static de.agilecoders.wicket.jquery.JQuery.$;
 
@@ -31,13 +33,14 @@ import java.util.Base64;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeWebApplication;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.HttpResourceStream;
-import org.apache.syncope.client.console.commons.PreviewUtils;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.commons.PreviewUtils;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.BaseBinaryFieldPanel;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
@@ -55,15 +58,13 @@ import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.util.ListModel;
-import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.apache.wicket.util.lang.Bytes;
 
-public class BinaryFieldPanel extends FieldPanel<String> {
+public class BinaryFieldPanel extends BaseBinaryFieldPanel {
 
     private static final long serialVersionUID = 6264462604183088931L;
 
-    @SpringBean
-    private PreviewUtils previewUtils;
+    private static final PreviewUtils PREVIEW_UTILS = PreviewUtils.getInstance();
 
     private final String mimeType;
 
@@ -95,13 +96,12 @@ public class BinaryFieldPanel extends FieldPanel<String> {
             final IModel<String> model,
             final String mimeType,
             final String fileKey) {
-
         super(id, name, model);
         this.model = model;
         this.fileKey = fileKey;
         this.mimeType = mimeType;
 
-        previewer = previewUtils.getPreviewer(mimeType);
+        previewer = PREVIEW_UTILS.getPreviewer(mimeType);
 
         maxUploadSize = SyncopeWebApplication.get().getMaxUploadFileSizeMB() == null
                 ? null
@@ -168,7 +168,7 @@ public class BinaryFieldPanel extends FieldPanel<String> {
                 try {
                     fileDownload.initiate(target);
                 } catch (Exception e) {
-                    SyncopeConsoleSession.get().error(
+                    SyncopeEnduserSession.get().error(
                             StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage());
                 }
             }
@@ -194,10 +194,10 @@ public class BinaryFieldPanel extends FieldPanel<String> {
                 if (uploadedFile != null) {
                     if (maxUploadSize != null && uploadedFile.getSize() > maxUploadSize.bytes()) {
                         // SYNCOPE-1213 manage directly max upload file size (if set in properties file)
-                        SyncopeConsoleSession.get().error(getString("tooLargeFile")
+                        SyncopeEnduserSession.get().error(getString("tooLargeFile")
                                 .replace("${maxUploadSizeB}", String.valueOf(maxUploadSize.bytes()))
                                 .replace("${maxUploadSizeMB}", String.valueOf(maxUploadSize.bytes() / 1000000L)));
-                        ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+                        ((BaseWebPage) getPageReference().getPage()).getNotificationPanel().refresh(target);
                     } else {
                         final byte[] uploadedBytes = uploadedFile.getBytes();
                         final String uploaded = Base64.getEncoder().encodeToString(uploadedBytes);
@@ -277,7 +277,7 @@ public class BinaryFieldPanel extends FieldPanel<String> {
         if (StringUtils.isNotBlank(modelObj)) {
             final Component panelPreview;
             if (previewer == null) {
-                panelPreview = previewUtils.getDefaultPreviewer(mimeType);
+                panelPreview = PREVIEW_UTILS.getDefaultPreviewer(mimeType);
             } else {
                 panelPreview = previewer.preview(modelObj);
             }
@@ -291,4 +291,14 @@ public class BinaryFieldPanel extends FieldPanel<String> {
         setVisibleFileButtons(StringUtils.isNotBlank(modelObj));
         return this;
     }
+
+    @Override
+    protected void sendError(final String message) {
+        SyncopeEnduserSession.get().error(message);
+    }
+
+    @Override
+    protected Integer getMaxUploadFileSizeMB() {
+        return SyncopeWebApplication.get().getMaxUploadFileSizeMB();
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.java
similarity index 86%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.java
index 367591e..81717bd 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MultiFieldPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.java
@@ -16,12 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.enduser.markup.html.form;
 
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 import java.io.Serializable;
 import java.util.List;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractMultiPanel;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.panel.Panel;
@@ -107,6 +110,11 @@ public abstract class MultiFieldPanel<E extends Serializable> extends AbstractMu
                 protected void clearInput(final Panel panel) {
                     FieldPanel.class.cast(panel).getField().clearInput();
                 }
+
+                @Override
+                protected void sendError(final String message) {
+                    SyncopeEnduserSession.get().error(getString(Constants.OPERATION_ERROR));
+                }
             };
         }
     }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttribute.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttribute.java
new file mode 100644
index 0000000..7d713f0
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * 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.enduser.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CustomAttribute implements Serializable {
+
+    private static final long serialVersionUID = 4910266842123376686L;
+
+    private boolean readonly;
+
+    private List<String> defaultValues = new ArrayList<>();
+
+    public CustomAttribute() {
+    }
+
+    public boolean isReadonly() {
+        return readonly;
+    }
+
+    public void setReadonly(final boolean readonly) {
+        this.readonly = readonly;
+    }
+
+    public List<String> getDefaultValues() {
+        return defaultValues;
+    }
+
+    public void setDefaultValues(final List<String> defaultValues) {
+        this.defaultValues = defaultValues;
+    }
+
+    public CustomAttribute readonly(final Boolean value) {
+        this.readonly = value;
+        return this;
+    }
+
+    public CustomAttribute defaultValues(final List<String> value) {
+        this.defaultValues = value;
+        return this;
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttributesInfo.java
similarity index 54%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttributesInfo.java
index 095cef5..c49253c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/model/CustomAttributesInfo.java
@@ -16,22 +16,32 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.model;
 
 import java.io.Serializable;
-import org.apache.syncope.common.lib.to.AnyTO;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
-public class AnyWrapper<T extends AnyTO> implements Serializable {
+public class CustomAttributesInfo implements Serializable {
 
-    private static final long serialVersionUID = 8058288034211558375L;
+    private static final long serialVersionUID = 878444785696091916L;
 
-    protected final T anyTO;
+    private Map<String, CustomAttribute> attributes = new LinkedHashMap<>();
 
-    public AnyWrapper(final T anyTO) {
-        this.anyTO = anyTO;
+    public CustomAttributesInfo() {
     }
 
-    public T getInnerObject() {
-        return anyTO;
+    public Map<String, CustomAttribute> getAttributes() {
+        return attributes;
     }
+
+    public void setAttributes(final Map<String, CustomAttribute> attributes) {
+        this.attributes = attributes;
+    }
+
+    public CustomAttributesInfo attributes(final Map<String, CustomAttribute> value) {
+        this.attributes = value;
+        return this;
+    }
+
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java
similarity index 64%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java
index 095cef5..09f42b4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java
@@ -16,22 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.pages;
 
-import java.io.Serializable;
-import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
 
-public class AnyWrapper<T extends AnyTO> implements Serializable {
+public class BaseEnduserWebPage extends BaseWebPage {
 
-    private static final long serialVersionUID = 8058288034211558375L;
+    private static final long serialVersionUID = 5760583420031293480L;
 
-    protected final T anyTO;
-
-    public AnyWrapper(final T anyTO) {
-        this.anyTO = anyTO;
+    public BaseEnduserWebPage() {
+        this(null);
     }
 
-    public T getInnerObject() {
-        return anyTO;
+    public BaseEnduserWebPage(final PageParameters parameters) {
+        super(parameters);
     }
+
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/LandingPage.java
similarity index 71%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/LandingPage.java
index eb6df35..60e8cc9 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/LandingPage.java
@@ -16,10 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
+package org.apache.syncope.client.enduser.pages;
 
-import java.io.Serializable;
-import org.apache.wicket.request.component.IRequestableComponent;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class LandingPage extends BaseEnduserWebPage {
+
+    private static final long serialVersionUID = 164651008547631054L;
+
+    public LandingPage(final PageParameters parameters) {
+        super(parameters);
+    }
 
-public interface ModalPanel extends IRequestableComponent, Serializable {
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java
new file mode 100644
index 0000000..5045e6c
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java
@@ -0,0 +1,95 @@
+/*
+ * 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.enduser.pages;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.ui.commons.BaseLogin;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class Login extends BaseLogin {
+
+    private static final long serialVersionUID = -3422492668689122688L;
+
+    @SpringBean
+    private ClassPathScanImplementationLookup lookup;
+
+    public Login(final PageParameters parameters) {
+        super(parameters);
+
+        add(new BookmarkablePageLink<>("self-registration", Self.class).setOutputMarkupId(true));
+        add(new BookmarkablePageLink<>("self-pwd-reset", SelfPasswordReset.class).setOutputMarkupId(true));
+    }
+
+    @Override
+    protected List<Panel> getSSOLoginFormPanels() {
+        List<Panel> ssoLoginFormPanels = new ArrayList<>();
+        lookup.getSSOLoginFormPanels().forEach(ssoLoginFormPanel -> {
+            try {
+                ssoLoginFormPanels.add(ssoLoginFormPanel.getConstructor(String.class).newInstance("ssoLogin"));
+            } catch (Exception e) {
+                LOG.error("Could not initialize the provided SSO login form panel", e);
+            }
+        });
+        return ssoLoginFormPanels;
+    }
+
+    @Override
+    protected void sendError(final String error) {
+        SyncopeEnduserSession.get().error(error);
+    }
+
+    @Override
+    protected String getAnonymousUser() {
+        return SyncopeWebApplication.get().getAnonymousUser();
+    }
+
+    @Override
+    protected List<Locale> getSupportedLocales() {
+        return SyncopeWebApplication.SUPPORTED_LOCALES;
+    }
+
+    @Override
+    protected void authenticate(
+            final String username,
+            final String password,
+            final AjaxRequestTarget target) throws AccessControlException {
+        if (!SyncopeWebApplication.get().getAdminUser().equalsIgnoreCase(username)
+                && SyncopeEnduserSession.get().authenticate(username, password)) {
+            // user has been authenticated successfully
+            continueToOriginalDestination();
+            setResponsePage(getApplication().getHomePage());
+        } else {
+            // not authenticated
+            sendError(getString("login-error"));
+            notificationPanel.refresh(target);
+
+        }
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
similarity index 68%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
index ff10b8d..8a9901e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LabelPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
@@ -16,17 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
+package org.apache.syncope.client.enduser.pages;
 
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
 
-public class LabelPanel extends Panel {
+public class MustChangePassword extends WebPage {
 
-    private static final long serialVersionUID = 5564818820574092960L;
+    private static final long serialVersionUID = 164651008547631054L;
 
-    public LabelPanel(final String id, final Label label) {
-        super(id);
-        add(label);
+    public MustChangePassword(final PageParameters parameters) {
+        super(parameters);
     }
+
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java
new file mode 100644
index 0000000..eef84d5
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java
@@ -0,0 +1,87 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.wizards.any.UserWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.event.IEventSource;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class Self extends BaseEnduserWebPage implements IEventSource {
+
+    private static final long serialVersionUID = 164651008547631054L;
+
+    private UserWizardBuilder userWizardBuilder;
+
+    protected static final String WIZARD_ID = "wizard";
+
+    public Self(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(buildWizard(SyncopeEnduserSession.get().isAuthenticated()
+                ? SyncopeEnduserSession.get().getSelfTO()
+                : buildNewUserTO()));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
+            final AjaxWizard.NewItemEvent<AnyWrapper<UserTO>> newItemEvent = AjaxWizard.NewItemEvent.class.cast(event.
+                    getPayload());
+            final AjaxRequestTarget target = newItemEvent.getTarget();
+            final AnyWrapper<UserTO> item = newItemEvent.getItem();
+            if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
+                SyncopeEnduserSession.get().invalidate();
+                setResponsePage(Login.class);
+            } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
+                SyncopeEnduserSession.get().invalidate();
+                setResponsePage(LandingPage.class);
+            }
+        }
+        super.onEvent(event);
+    }
+
+    protected final AjaxWizard<AnyWrapper<UserTO>> buildWizard(final UserTO userTO) {
+        userWizardBuilder = new UserWizardBuilder(
+                null,
+                userTO,
+                SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getUserClasses(),
+                new UserFormLayoutInfo(),
+                this.getPageReference());
+        userWizardBuilder.setItem(new UserWrapper(userTO));
+        return userWizardBuilder.build(WIZARD_ID, userTO == null ? AjaxWizard.Mode.CREATE : AjaxWizard.Mode.EDIT);
+    }
+
+    private UserTO buildNewUserTO() {
+        final UserTO userTO = new UserTO();
+        userTO.setRealm(SyncopeConstants.ROOT_REALM);
+        return userTO;
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
similarity index 70%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
index eb6df35..b509ddf 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
@@ -16,10 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
+package org.apache.syncope.client.enduser.pages;
 
-import java.io.Serializable;
-import org.apache.wicket.request.component.IRequestableComponent;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class SelfPasswordReset extends BaseEnduserWebPage {
+
+    private static final long serialVersionUID = 164651008547631054L;
+
+    public SelfPasswordReset(final PageParameters parameters) {
+        super(parameters);
+    }
 
-public interface ModalPanel extends IRequestableComponent, Serializable {
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
similarity index 71%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
index eb6df35..7c86c2d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ModalPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
@@ -16,10 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
+package org.apache.syncope.client.enduser.pages;
 
-import java.io.Serializable;
-import org.apache.wicket.request.component.IRequestableComponent;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class SelfUpdate extends BaseEnduserWebPage {
+
+    private static final long serialVersionUID = 164651008547631054L;
+
+    public SelfUpdate(final PageParameters parameters) {
+        super(parameters);
+    }
 
-public interface ModalPanel extends IRequestableComponent, Serializable {
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
new file mode 100644
index 0000000..7cbb5f5
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
@@ -0,0 +1,56 @@
+/*
+ * 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.enduser.resources;
+
+import java.security.SecureRandom;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.text.RandomStringGenerator;
+import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
+import org.apache.wicket.extensions.markup.html.captcha.CaptchaImageResource;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CaptchaResource extends CaptchaImageResource {
+
+    private static final long serialVersionUID = 8293404296348102926L;
+
+    private static final SecureRandom RANDOM = new SecureRandom();
+
+    private static final Logger LOG = LoggerFactory.getLogger(CaptchaResource.class);
+
+    private static final RandomStringGenerator RANDOM_LETTERS = new RandomStringGenerator.Builder().
+            usingRandom(RANDOM::nextInt).
+            withinRange('a', 'z').
+            build();
+
+    @Override
+    protected byte[] render() {
+        LOG.debug("Generate captcha");
+
+        String captcha = RANDOM_LETTERS.generate(6);
+        HttpServletRequest request = ((HttpServletRequest) RequestCycle.get().getRequest().getContainerRequest());
+        // store the captcha in the current session
+        request.getSession().setAttribute(SyncopeEnduserConstants.CAPTCHA_SESSION_KEY, captcha);
+
+        getChallengeIdModel().setObject(captcha);
+        return super.render();
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AbstractAnyRestClient.java
similarity index 62%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AbstractAnyRestClient.java
index 095cef5..b03a9cb 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWrapper.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AbstractAnyRestClient.java
@@ -16,22 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.rest;
 
-import java.io.Serializable;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.rest.api.service.AnyService;
 
-public class AnyWrapper<T extends AnyTO> implements Serializable {
+public abstract class AbstractAnyRestClient<TO extends AnyTO> extends BaseRestClient {
 
-    private static final long serialVersionUID = 8058288034211558375L;
+    private static final long serialVersionUID = 1962529678091410544L;
 
-    protected final T anyTO;
+    protected abstract Class<? extends AnyService<TO>> getAnyServiceClass();
 
-    public AnyWrapper(final T anyTO) {
-        this.anyTO = anyTO;
-    }
+    public abstract int count(String realm, String fiql, String type);
 
-    public T getInnerObject() {
-        return anyTO;
+    public TO read(final String key) {
+        return getService(getAnyServiceClass()).read(key);
     }
+
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java
new file mode 100644
index 0000000..5c65775
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java
@@ -0,0 +1,130 @@
+/*
+ * 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.enduser.rest;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
+
+public class AnyTypeRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -2211371717449597247L;
+
+    public static final Comparator<String> KEY_COMPARATOR = new AnyTypeKeyComparator();
+
+    public AnyTypeTO read(final String key) {
+        AnyTypeTO type = null;
+
+        try {
+            type = getService(AnyTypeService.class).read(key);
+        } catch (SyncopeClientException e) {
+            LOG.error("While reading all any types", e);
+        }
+
+        return type;
+    }
+
+    public List<AnyTypeTO> listAnyTypes() {
+        List<AnyTypeTO> types = Collections.emptyList();
+
+        try {
+            types = getService(AnyTypeService.class).list();
+            Collections.sort(types, new AnyTypeComparator());
+        } catch (SyncopeClientException e) {
+            LOG.error("While reading all any types", e);
+        }
+
+        return types;
+    }
+
+    public List<String> list() {
+        List<String> types = getSyncopeService().platform().getAnyTypes();
+        Collections.sort(types, new AnyTypeKeyComparator());
+        return types;
+    }
+
+    public void create(final AnyTypeTO anyTypeTO) {
+        getService(AnyTypeService.class).create(anyTypeTO);
+    }
+
+    public void update(final AnyTypeTO anyTypeTO) {
+        getService(AnyTypeService.class).update(anyTypeTO);
+    }
+
+    public void delete(final String key) {
+        getService(AnyTypeService.class).delete(key);
+    }
+
+    private static class AnyTypeComparator implements Comparator<AnyTypeTO>, Serializable {
+
+        private static final long serialVersionUID = -8227715253094467138L;
+
+        @Override
+        public int compare(final AnyTypeTO o1, final AnyTypeTO o2) {
+            if (o1.getKind() == AnyTypeKind.USER) {
+                return -1;
+            }
+            if (o2.getKind() == AnyTypeKind.USER) {
+                return 1;
+            }
+            if (o1.getKind() == AnyTypeKind.GROUP) {
+                return -1;
+            }
+            if (o2.getKind() == AnyTypeKind.GROUP) {
+                return 1;
+            }
+            return ObjectUtils.compare(o1.getKey(), o2.getKey());
+        }
+    }
+
+    private static class AnyTypeKeyComparator implements Comparator<String>, Serializable {
+
+        private static final long serialVersionUID = -7778622183107320760L;
+
+        @Override
+        public int compare(final String o1, final String o2) {
+            if (SyncopeConstants.REALM_ANYTYPE.equals(o1)) {
+                return -1;
+            }
+            if (SyncopeConstants.REALM_ANYTYPE.equals(o2)) {
+                return 1;
+            }
+            if (AnyTypeKind.USER.name().equals(o1)) {
+                return -1;
+            }
+            if (AnyTypeKind.USER.name().equals(o2)) {
+                return 1;
+            }
+            if (AnyTypeKind.GROUP.name().equals(o1)) {
+                return -1;
+            }
+            if (AnyTypeKind.GROUP.name().equals(2)) {
+                return 1;
+            }
+            return ObjectUtils.compare(o1, o2);
+        }
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
similarity index 83%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
index ecea2ae..ea4959d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
@@ -16,17 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.rest;
+package org.apache.syncope.client.enduser.rest;
 
 import java.net.URI;
 import javax.ws.rs.core.HttpHeaders;
 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.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
 import org.apache.syncope.common.lib.types.ExecStatus;
-import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.JAXRSService;
 import org.apache.syncope.common.rest.api.service.SyncopeService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
@@ -44,15 +44,15 @@ public abstract class BaseRestClient implements RestClient {
     }
 
     protected static <T> T getService(final Class<T> serviceClass) {
-        return SyncopeConsoleSession.get().getService(serviceClass);
+        return SyncopeEnduserSession.get().getService(serviceClass);
     }
 
     protected static <T> T getService(final String etag, final Class<T> serviceClass) {
-        return SyncopeConsoleSession.get().getService(etag, serviceClass);
+        return SyncopeEnduserSession.get().getService(etag, serviceClass);
     }
 
     protected static <T> void resetClient(final Class<T> serviceClass) {
-        SyncopeConsoleSession.get().resetClient(serviceClass);
+        SyncopeEnduserSession.get().resetClient(serviceClass);
     }
 
     protected static String toOrderBy(final SortParam<String> sort) {
@@ -76,10 +76,9 @@ public abstract class BaseRestClient implements RestClient {
             final E service, final URI location, final Class<T> resultClass) {
 
         WebClient webClient = WebClient.fromClient(WebClient.client(service));
-        webClient.accept(SyncopeConsoleSession.get().getMediaType()).to(location.toASCIIString(), false);
+        webClient.accept(SyncopeEnduserSession.get().getMediaType()).to(location.toASCIIString(), false);
         return webClient.
-                header(RESTHeaders.DOMAIN, SyncopeConsoleSession.get().getDomain()).
-                header(HttpHeaders.AUTHORIZATION, "Bearer " + SyncopeConsoleSession.get().getJWT()).
+                header(HttpHeaders.AUTHORIZATION, "Bearer " + SyncopeEnduserSession.get().getJWT()).
                 get(resultClass);
     }
 
@@ -89,4 +88,5 @@ public abstract class BaseRestClient implements RestClient {
                 ? Constants.UNKNOWN
                 : execStatus.name();
     }
+
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java
new file mode 100644
index 0000000..0c14ad1
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java
@@ -0,0 +1,78 @@
+/*
+ * 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.enduser.rest;
+
+import java.util.List;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.request.GroupCR;
+import org.apache.syncope.common.lib.request.GroupUR;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.rest.api.beans.AnyQuery;
+import org.apache.syncope.common.rest.api.service.AnyService;
+import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+
+/**
+ * Console client for invoking Rest Group's services.
+ */
+public class GroupRestClient extends AbstractAnyRestClient<GroupTO> {
+
+    private static final long serialVersionUID = -8549081557283519638L;
+
+    @Override
+    protected Class<? extends AnyService<GroupTO>> getAnyServiceClass() {
+        return GroupService.class;
+    }
+
+    public ProvisioningResult<GroupTO> create(final GroupCR groupCR) {
+        Response response = getService(GroupService.class).create(groupCR);
+        return response.readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
+        });
+    }
+
+    public ProvisioningResult<GroupTO> update(final String etag, final GroupUR updateReq) {
+        ProvisioningResult<GroupTO> result;
+        synchronized (this) {
+            result = getService(etag, GroupService.class).update(updateReq).
+                    readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
+                    });
+            resetClient(getAnyServiceClass());
+        }
+        return result;
+    }
+
+    public List<GroupTO> searchAssignableGroups(
+            final String realm,
+            final String term,
+            final int page,
+            final int size) {
+
+        return getService(SyncopeService.class).searchAssignableGroups(realm, term, page, size).getResult();
+    }
+
+    @Override
+    public int count(final String realm, final String fiql, final String type) {
+        return getService(GroupService.class).
+                search(new AnyQuery.Builder().realm(realm).fiql(fiql).page(1).size(1).build()).
+                getTotalCount();
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RealmRestClient.java
similarity index 65%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RealmRestClient.java
index d3d5c35..a95636a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RealmRestClient.java
@@ -16,21 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.rest;
+package org.apache.syncope.client.enduser.rest;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.rest.api.service.RealmService;
 
-public interface TemplateRestClient<T, F> extends RestClient {
-
-    List<T> listTemplates();
-
-    void createTemplate(final T templateTO);
-
-    void deleteTemplate(final String key);
+/**
+ * Console client for invoking REST Realm's services.
+ */
+public class RealmRestClient extends BaseRestClient {
 
-    T readTemplate(final String key);
+    private static final long serialVersionUID = -8549081557283519638L;
 
-    String readTemplateFormat(final String key, final F format);
+    public List<RealmTO> list() {
+        return getService(RealmService.class).list();
+    }
 
-    void updateTemplateFormat(final String key, final String content, final F format);
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java
new file mode 100644
index 0000000..d411ce4
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.enduser.rest;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.rest.api.service.RoleService;
+
+/**
+ * Console client for invoking Rest Role's services.
+ */
+public class RoleRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -3161863874876938094L;
+
+    public void delete(final String key) {
+        getService(RoleService.class).delete(key);
+    }
+
+    public RoleTO read(final String key) {
+        return getService(RoleService.class).read(key);
+    }
+
+    public void update(final RoleTO roleTO) {
+        getService(RoleService.class).update(roleTO);
+    }
+
+    public void create(final RoleTO roleTO) {
+        getService(RoleService.class).create(roleTO);
+    }
+
+    public List<RoleTO> list() {
+        return getService(RoleService.class).list();
+    }
+
+    public String readConsoleLayoutInfo(final String roleKey) {
+        try {
+            return IOUtils.toString(InputStream.class.cast(
+                    getService(RoleService.class).getConsoleLayoutInfo(roleKey).getEntity()),
+                    StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            LOG.error("Error retrieving console layout info for role {}", roleKey, e);
+            return StringUtils.EMPTY;
+        }
+    }
+
+    public void setConsoleLayoutInfo(final String roleKey, final String content) {
+        getService(RoleService.class).setConsoleLayoutInfo(
+                roleKey, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+    }
+
+    public void removeConsoleLayoutInfo(final String roleKey) {
+        getService(RoleService.class).removeConsoleLayoutInfo(roleKey);
+    }
+
+    public List<String> getAllAvailableEntitlements() {
+        List<String> entitlements = new ArrayList<>(getSyncopeService().platform().getEntitlements());
+        Collections.sort(entitlements);
+        return entitlements;
+    }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java
new file mode 100644
index 0000000..57c6859
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java
@@ -0,0 +1,146 @@
+/*
+ * 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.enduser.rest;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.SchemaTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.DerSchemaTO;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.beans.SchemaQuery;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+
+/**
+ * Console client for invoking rest schema services.
+ */
+public class SchemaRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -2479730152700312373L;
+
+    public <T extends SchemaTO> List<T> getSchemas(final SchemaType schemaType, final AnyTypeKind kind) {
+        final AnyTypeService client = getService(AnyTypeService.class);
+
+        final List<String> classes = new ArrayList<>();
+
+        switch (kind) {
+            case USER:
+            case GROUP:
+                final AnyTypeTO type = client.read(kind.name());
+                if (type != null) {
+                    classes.addAll(type.getClasses());
+                }
+                break;
+
+            default:
+                new AnyTypeRestClient().listAnyTypes().stream().filter(
+                        anyTypeTO -> (anyTypeTO.getKind() != AnyTypeKind.USER
+                        && anyTypeTO.getKind() != AnyTypeKind.GROUP)).
+                        forEach((anyTypeTO) -> {
+                            classes.addAll(anyTypeTO.getClasses());
+                        });
+        }
+        return getSchemas(schemaType, null, classes.toArray(new String[] {}));
+    }
+
+    public <T extends SchemaTO> List<T> getSchemas(
+            final SchemaType schemaType, final String keyword, final String... anyTypeClasses) {
+
+        SchemaQuery.Builder builder = new SchemaQuery.Builder().type(schemaType);
+        if (StringUtils.isNotBlank(keyword)) {
+            builder.keyword(keyword);
+        }
+        if (anyTypeClasses != null && anyTypeClasses.length > 0) {
+            builder.anyTypeClasses(anyTypeClasses);
+        }
+
+        List<T> schemas = new ArrayList<>();
+        try {
+            schemas.addAll(getService(SchemaService.class).<T>search(builder.build()));
+        } catch (SyncopeClientException e) {
+            LOG.error("While getting all {} schemas for {}", schemaType, anyTypeClasses, e);
+        }
+        return schemas;
+    }
+
+    public List<String> getSchemaNames(final SchemaType schemaType) {
+        List<String> schemaNames = Collections.emptyList();
+
+        try {
+            schemaNames = getSchemas(schemaType, null, new String[0]).stream().
+                    map(EntityTO::getKey).collect(Collectors.toList());
+        } catch (SyncopeClientException e) {
+            LOG.error("While getting all user schema names", e);
+        }
+
+        return schemaNames;
+    }
+
+    public List<String> getPlainSchemaNames() {
+        return getSchemaNames(SchemaType.PLAIN);
+    }
+
+    public List<String> getDerSchemaNames() {
+        return getSchemaNames(SchemaType.DERIVED);
+    }
+
+    public List<String> getVirSchemaNames() {
+        return getSchemaNames(SchemaType.VIRTUAL);
+    }
+
+    public PlainSchemaTO read(final SchemaType schemaType, final String key) {
+        return getService(SchemaService.class).read(schemaType, key);
+
+    }
+
+    public void create(final SchemaType schemaType, final SchemaTO modelObject) {
+        getService(SchemaService.class).create(schemaType, modelObject);
+    }
+
+    public void update(final SchemaType schemaType, final SchemaTO modelObject) {
+        getService(SchemaService.class).update(schemaType, modelObject);
+    }
+
+    public PlainSchemaTO deletePlainSchema(final String name) {
+        PlainSchemaTO response = getService(SchemaService.class).read(SchemaType.PLAIN, name);
+        getService(SchemaService.class).delete(SchemaType.PLAIN, name);
+        return response;
+    }
+
+    public DerSchemaTO deleteDerSchema(final String name) {
+        DerSchemaTO schemaTO = getService(SchemaService.class).read(SchemaType.DERIVED, name);
+        getService(SchemaService.class).delete(SchemaType.DERIVED, name);
+        return schemaTO;
+    }
+
+    public VirSchemaTO deleteVirSchema(final String name) {
+        VirSchemaTO schemaTO = getService(SchemaService.class).read(SchemaType.VIRTUAL, name);
+        getService(SchemaService.class).delete(SchemaType.VIRTUAL, name);
+        return schemaTO;
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SecurityQuestionRestClient.java
similarity index 65%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SecurityQuestionRestClient.java
index d3d5c35..aab131f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TemplateRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SecurityQuestionRestClient.java
@@ -16,21 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.rest;
+package org.apache.syncope.client.enduser.rest;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
 
-public interface TemplateRestClient<T, F> extends RestClient {
+public class SecurityQuestionRestClient extends BaseRestClient {
 
-    List<T> listTemplates();
+    private static final long serialVersionUID = -3167730221361895176L;
 
-    void createTemplate(final T templateTO);
+    public List<SecurityQuestionTO> list() {
+        return getService(SecurityQuestionService.class).list();
+    }
 
-    void deleteTemplate(final String key);
-
-    T readTemplate(final String key);
-
-    String readTemplateFormat(final String key, final F format);
-
-    void updateTemplateFormat(final String key, final String content, final F format);
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
similarity index 57%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
index 0dd9f44..1f88621 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
@@ -16,24 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.commons;
+package org.apache.syncope.client.enduser.rest;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
 
-public class EmptyStatusProvider implements StatusProvider {
+public class SyncopeRestClient extends BaseRestClient {
 
-    private static final long serialVersionUID = -7948190795547208134L;
+    private static final long serialVersionUID = -2211371717449597247L;
 
-    @Override
-    public List<Triple<ConnObjectTO, ConnObjectWrapper, String>> get(
-            final AnyTO any, final Collection<String> resources) {
+    public List<String> listAnyTypeClasses() {
+        List<String> types = Collections.emptyList();
 
-        return Collections.emptyList();
+        try {
+            types = getService(SyncopeService.class).platform().getAnyTypeClasses();
+        } catch (SyncopeClientException e) {
+            LOG.error("While reading all any type classes", e);
+        }
+        return types;
     }
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java
new file mode 100644
index 0000000..d6330ec
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java
@@ -0,0 +1,61 @@
+/*
+ * 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.enduser.rest;
+
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.request.BooleanReplacePatchItem;
+import org.apache.syncope.common.lib.request.UserCR;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
+
+/**
+ * Console client for invoking rest users services.
+ */
+public class UserSelfRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -1575748964398293968L;
+
+    public ProvisioningResult<UserTO> create(final UserCR createReq) {
+        Response response = getService(UserSelfService.class).create(createReq);
+        return response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+        });
+    }
+
+    public ProvisioningResult<UserTO> update(final String etag, final UserUR updateReq) {
+        ProvisioningResult<UserTO> result;
+        synchronized (this) {
+            result = getService(etag, UserSelfService.class).update(updateReq).
+                    readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+                    });
+            resetClient(UserSelfService.class);
+        }
+        return result;
+    }
+
+    public ProvisioningResult<UserTO> mustChangePassword(final String etag, final boolean value, final String key) {
+        UserUR userUR = new UserUR();
+        userUR.setKey(key);
+        userUR.setMustChangePassword(new BooleanReplacePatchItem.Builder().value(value).build());
+        return update(etag, userUR);
+    }
+
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserTheme.java
similarity index 52%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserTheme.java
index 0dd9f44..0320ba3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserTheme.java
@@ -16,24 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.commons;
+package org.apache.syncope.client.enduser.themes;
 
-import java.util.Collection;
-import java.util.Collections;
+import de.agilecoders.wicket.core.settings.Theme;
+import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.HeaderItem;
 
-public class EmptyStatusProvider implements StatusProvider {
+public class EnduserTheme extends Theme {
 
-    private static final long serialVersionUID = -7948190795547208134L;
+    public EnduserTheme() {
+        super("adminLTE");
+    }
 
     @Override
-    public List<Triple<ConnObjectTO, ConnObjectWrapper, String>> get(
-            final AnyTO any, final Collection<String> resources) {
-
-        return Collections.emptyList();
+    public List<HeaderItem> getDependencies() {
+        List<HeaderItem> references = new ArrayList<>();
+//        references.add(JavaScriptHeaderItem
+//.forReference(new JQueryPluginResourceReference(EnduserTheme.class, "js/AdminLTE-app.min.js"), "adminltejs"));
+        references.add(CssHeaderItem.forReference(EnduserThemeCssResourceReference.INSTANCE));
+        references.addAll(super.getDependencies());
+        return references;
     }
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserThemeCssResourceReference.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserThemeCssResourceReference.java
new file mode 100644
index 0000000..b306560
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/themes/EnduserThemeCssResourceReference.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.enduser.themes;
+
+import de.agilecoders.wicket.core.Bootstrap;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.HeaderItem;
+import org.apache.wicket.request.resource.CssResourceReference;
+
+public class EnduserThemeCssResourceReference extends CssResourceReference {
+
+    private static final long serialVersionUID = -7658929012906790600L;
+
+    /**
+     * Singleton instance of this reference.
+     */
+    public static final EnduserThemeCssResourceReference INSTANCE = new EnduserThemeCssResourceReference();
+
+    public EnduserThemeCssResourceReference() {
+        super(EnduserThemeCssResourceReference.class, "css/login.css");
+    }
+
+    @Override
+    public List<HeaderItem> getDependencies() {
+        final List<HeaderItem> dependencies = new ArrayList<>();
+        dependencies.add(CssHeaderItem.forReference(Bootstrap.getSettings().getCssResourceReference()));
+        dependencies.addAll(super.getDependencies());
+        return dependencies;
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java
similarity index 89%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java
index bd783b8..87812fb 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -26,15 +26,13 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.apache.commons.collections4.CollectionUtils;
 import org.apache.cxf.common.util.StringUtils;
-import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.rest.SchemaRestClient;
+import org.apache.syncope.client.enduser.rest.GroupRestClient;
+import org.apache.syncope.client.enduser.rest.SchemaRestClient;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
-import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -57,8 +55,6 @@ public abstract class AbstractAttrs<S extends SchemaTO> extends WizardStep imple
 
     private final SchemaRestClient schemaRestClient = new SchemaRestClient();
 
-    private final AnyTypeClassRestClient anyTypeClassRestClient = new AnyTypeClassRestClient();
-
     private final GroupRestClient groupRestClient = new GroupRestClient();
 
     protected final AnyTO anyTO;
@@ -92,14 +88,14 @@ public abstract class AbstractAttrs<S extends SchemaTO> extends WizardStep imple
 
     private List<Attr> loadAttrs() {
         List<String> classes = new ArrayList<>(anyTypeClasses);
-        classes.addAll(anyTypeClassRestClient.list(anyTO.getAuxClasses()).stream().
-                map(EntityTO::getKey).collect(Collectors.toList()));
+        // just add keys
+        classes.addAll(anyTO.getAuxClasses());
         setSchemas(classes);
         setAttrs();
         return AbstractAttrs.this.getAttrsFromTO();
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({ "unchecked" })
     private List<MembershipTO> loadMembershipAttrs() {
         List<MembershipTO> memberships = new ArrayList<>();
         try {
@@ -107,9 +103,7 @@ public abstract class AbstractAttrs<S extends SchemaTO> extends WizardStep imple
 
             for (MembershipTO membership : (List<MembershipTO>) PropertyResolver.getPropertyField(
                     "memberships", anyTO).get(anyTO)) {
-                setSchemas(membership.getGroupKey(),
-                        anyTypeClassRestClient.list(getMembershipAuxClasses(membership, anyTO.getType())).
-                                stream().map(EntityTO::getKey).collect(Collectors.toList()));
+                setSchemas(membership.getGroupKey(), getMembershipAuxClasses(membership, anyTO.getType()));
                 setAttrs(membership);
 
                 if (AbstractAttrs.this instanceof PlainAttrs && !membership.getPlainAttrs().isEmpty()) {
@@ -173,8 +167,8 @@ public abstract class AbstractAttrs<S extends SchemaTO> extends WizardStep imple
     @Override
     public void renderHead(final IHeaderResponse response) {
         super.renderHead(response);
-        if (CollectionUtils.isEmpty(attrs.getObject())
-                && CollectionUtils.isEmpty(membershipTOs.getObject())) {
+        if (org.apache.cxf.common.util.CollectionUtils.isEmpty(attrs.getObject())
+                && org.apache.cxf.common.util.CollectionUtils.isEmpty(membershipTOs.getObject())) {
             response.render(OnDomReadyHeaderItem.forScript(
                     String.format("$('#emptyPlaceholder').append(\"%s\"); $('#attributes').hide();",
                             getString("attribute.empty.list"))));
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
new file mode 100644
index 0000000..22e1b3b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
@@ -0,0 +1,153 @@
+/*
+ * 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.enduser.wizards.any;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractAnyWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.wizard.WizardModel;
+
+public abstract class AnyWizardBuilder extends AbstractAnyWizardBuilder<UserTO> {
+
+    private static final long serialVersionUID = -2480279868319546243L;
+
+    protected final List<String> anyTypeClasses;
+
+    protected UserFormLayoutInfo formLayoutInfo;
+
+    /**
+     * Construct.
+     *
+     * @param anyTO any
+     * @param anyTypeClasses any type classes
+     * @param formLayoutInfo form layout info
+     * @param pageRef caller page reference.
+     */
+    public AnyWizardBuilder(
+            final UserTO anyTO,
+            final List<String> anyTypeClasses,
+            final UserFormLayoutInfo formLayoutInfo,
+            final PageReference pageRef) {
+
+        super(new AnyWrapper<>(anyTO), pageRef);
+        this.anyTypeClasses = anyTypeClasses;
+        this.formLayoutInfo = formLayoutInfo;
+    }
+
+    /**
+     * Construct.
+     *
+     * @param wrapper any wrapper
+     * @param anyTypeClasses any type classes
+     * @param formLayoutInfo form layout info
+     * @param pageRef caller page reference.
+     */
+    public AnyWizardBuilder(
+            final UserWrapper wrapper,
+            final List<String> anyTypeClasses,
+            final UserFormLayoutInfo formLayoutInfo,
+            final PageReference pageRef) {
+
+        super(wrapper, pageRef);
+        this.anyTypeClasses = anyTypeClasses;
+        this.formLayoutInfo = formLayoutInfo;
+    }
+
+    @Override
+    protected WizardModel buildModelSteps(final AnyWrapper<UserTO> modelObject, final WizardModel wizardModel) {
+        wizardModel.add(new UserDetails(
+                UserWrapper.class.cast(modelObject),
+                mode == AjaxWizard.Mode.TEMPLATE,
+                modelObject.getInnerObject().getKey() != null,
+                UserFormLayoutInfo.class.cast(formLayoutInfo).isPasswordManagement(),
+                pageRef));
+
+        if (formLayoutInfo.isAuxClasses()) {
+            wizardModel.add(new EnduserAuxClasses(modelObject, anyTypeClasses));
+        }
+
+        if (formLayoutInfo.isGroups()) {
+            wizardModel.add(new Groups(modelObject, mode == AjaxWizard.Mode.TEMPLATE));
+        }
+
+        // attributes panel steps
+        if (formLayoutInfo.isPlainAttrs()) {
+            wizardModel.add(new PlainAttrs(
+                    modelObject,
+                    null,
+                    mode,
+                    anyTypeClasses,
+                    formLayoutInfo.getWhichPlainAttrs()) {
+
+                private static final long serialVersionUID = 8167894751609598306L;
+
+                @Override
+                public PageReference getPageReference() {
+                    return pageRef;
+                }
+
+            });
+        }
+        if (formLayoutInfo.isDerAttrs() && mode != AjaxWizard.Mode.TEMPLATE) {
+            wizardModel.add(new DerAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs()));
+        }
+        if (formLayoutInfo.isVirAttrs()) {
+            wizardModel.add(new VirAttrs(
+                    modelObject, mode, anyTypeClasses, formLayoutInfo.getWhichVirAttrs()));
+        }
+
+        if (formLayoutInfo.isResources()) {
+            wizardModel.add(new Resources(modelObject));
+        }
+
+        return wizardModel;
+    }
+
+    @Override
+    protected long getMaxWaitTimeInSeconds() {
+        return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
+    }
+
+    @Override
+    protected void sendError(final String message) {
+        SyncopeEnduserSession.get().error(message);
+    }
+
+    @Override
+    protected void sendWarning(final String message) {
+        SyncopeEnduserSession.get().warn(message);
+    }
+
+    @Override
+    protected Future<Pair<Serializable, Serializable>> execute(
+            final Callable<Pair<Serializable, Serializable>> future) {
+        return SyncopeEnduserSession.get().execute(future);
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
similarity index 95%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
index fef043c..e4f60ed 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
@@ -16,8 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -25,9 +26,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
@@ -193,7 +194,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
 
                     AjaxTextFieldPanel panel = new AjaxTextFieldPanel(
                             "panel",
-                            schemas.get(attrTO.getSchema()).getLabel(SyncopeConsoleSession.get().getLocale()),
+                            schemas.get(attrTO.getSchema()).getLabel(SyncopeEnduserSession.get().getLocale()),
                             model,
                             false);
                     panel.setEnabled(false);
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java
new file mode 100644
index 0000000..8ebc5e7
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java
@@ -0,0 +1,45 @@
+/*
+ * 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.enduser.wizards.any;
+
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractAuxClasses;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.enduser.rest.SyncopeRestClient;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+
+public class EnduserAuxClasses extends AbstractAuxClasses {
+
+    private static final long serialVersionUID = 552437609667518888L;
+
+    public <T extends AnyTO> EnduserAuxClasses(final AnyWrapper<T> modelObject, final List<String> anyTypeClasses) {
+        super(modelObject, anyTypeClasses);
+    }
+
+    @Override
+    protected final List<AnyTypeClassTO> listAnyTypecClasses() {
+        return new SyncopeRestClient().listAnyTypeClasses().stream().map(name -> {
+            AnyTypeClassTO anyTypeClassTO = new AnyTypeClassTO();
+            anyTypeClassTO.setKey(name);
+            return anyTypeClassTO;
+        }).collect(Collectors.toList());
+    }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java
new file mode 100644
index 0000000..7c55e87
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java
@@ -0,0 +1,192 @@
+/*
+ * 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.enduser.wizards.any;
+
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.rest.GroupRestClient;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroups;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroupsModel;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
+import org.apache.wicket.markup.html.basic.Label;
+
+public class Groups extends AbstractGroups {
+
+    private static final long serialVersionUID = 552437609667518888L;
+
+    private final GroupRestClient groupRestClient = new GroupRestClient();
+
+    private final AnyTO anyTO;
+
+    private final EnduserGroupsModel groupsModel;
+
+    public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject, final boolean templateMode) {
+        super(modelObject);
+        this.anyTO = modelObject.getInnerObject();
+        this.groupsModel = new EnduserGroupsModel();
+
+        setOutputMarkupId(true);
+
+        addGroupsPanel();
+    }
+
+    @Override
+    protected void addGroupsPanel() {
+        if (anyTO instanceof GroupTO) {
+            groupsContainer.add(new Label("groups").setVisible(false));
+            groupsContainer.setVisible(false);
+        } else {
+            AjaxPalettePanel.Builder<MembershipTO> builder = new AjaxPalettePanel.Builder<MembershipTO>().
+                    setRenderer(new IChoiceRenderer<MembershipTO>() {
+
+                        private static final long serialVersionUID = -3086661086073628855L;
+
+                        @Override
+                        public Object getDisplayValue(final MembershipTO object) {
+                            return object.getGroupName();
+                        }
+
+                        @Override
+                        public String getIdValue(final MembershipTO object, final int index) {
+                            return object.getGroupName();
+                        }
+
+                        @Override
+                        public MembershipTO getObject(
+                                final String id, final IModel<? extends List<? extends MembershipTO>> choices) {
+
+                            return choices.getObject().stream().
+                                    filter(object -> id.equalsIgnoreCase(object.getGroupName())).findAny().orElse(null);
+                        }
+                    });
+
+            groupsContainer.add(builder.setAllowOrder(true).withFilter().build("groups",
+                    new ListModel<MembershipTO>() {
+
+                private static final long serialVersionUID = -2583290457773357445L;
+
+                @Override
+                public List<MembershipTO> getObject() {
+                    return Groups.this.groupsModel.getMemberships();
+                }
+
+            }, new AjaxPalettePanel.Builder.Query<MembershipTO>() {
+
+                private static final long serialVersionUID = -7223078772249308813L;
+
+                @Override
+                public List<MembershipTO> execute(final String filter) {
+                    return (StringUtils.isEmpty(filter) || "*".equals(filter)
+                            ? groupsModel.getObject()
+                            : groupRestClient.searchAssignableGroups(
+                                    anyTO.getRealm(),
+                                    SyncopeClient.getGroupSearchConditionBuilder().
+                                            isAssignable().and().is("name").equalTo(filter).query(),
+                                    1, MAX_GROUP_LIST_CARDINALITY)).stream().map(input -> {
+
+                                return new MembershipTO.Builder(input.getKey()).groupName(input.getName()).build();
+                            }).collect(Collectors.toList());
+                }
+            }).hideLabel().setOutputMarkupId(true));
+            // ---------------------------------
+        }
+    }
+
+    protected class EnduserGroupsModel extends AbstractGroupsModel {
+
+        private static final long serialVersionUID = -4541954630939063927L;
+
+        private List<GroupTO> groups;
+
+        private List<MembershipTO> memberships;
+
+        private String realm;
+
+        @Override
+        public List<GroupTO> getObject() {
+            reload();
+            return groups;
+        }
+
+        /**
+         * Retrieve the first MAX_GROUP_LIST_CARDINALITY assignable.
+         */
+        @Override
+        protected void reloadObject() {
+            groups = groupRestClient.searchAssignableGroups(
+                    realm,
+                    null,
+                    1,
+                    MAX_GROUP_LIST_CARDINALITY);
+        }
+
+        @Override
+        public List<MembershipTO> getMemberships() {
+            reload();
+            return memberships;
+        }
+
+        /**
+         * Retrieve group memberships.
+         */
+        @Override
+        protected void reloadMemberships() {
+            memberships = GroupableRelatableTO.class.cast(anyTO).getMemberships();
+        }
+
+        @Override
+        public List<String> getDynMemberships() {
+            return Collections.emptyList();
+        }
+
+        /**
+         * Retrieve dyn group memberships.
+         */
+        @Override
+        protected void reloadDynMemberships() {
+            // DO NOTHING
+        }
+
+        /**
+         * Reload data if the realm changes (see SYNCOPE-1135).
+         */
+        @Override
+        protected void reload() {
+            boolean reload = Groups.this.anyTO.getRealm() != null
+                    && !Groups.this.anyTO.getRealm().equalsIgnoreCase(realm);
+            realm = Groups.this.anyTO.getRealm();
+
+            if (reload) {
+                reloadObject();
+                reloadMemberships();
+            }
+        }
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
similarity index 65%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
index 67dd335..9a4aed0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
@@ -16,9 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
-import java.io.Serializable;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -28,26 +29,26 @@ import java.util.Optional;
 import java.util.stream.Collectors;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.SchemaUtils;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AbstractFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDateTimeFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.EncryptedFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.enduser.markup.html.form.AjaxDateFieldPanel;
+import org.apache.syncope.client.enduser.markup.html.form.AjaxDateTimeFieldPanel;
+import org.apache.syncope.client.enduser.markup.html.form.BinaryFieldPanel;
+import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
+import org.apache.syncope.client.ui.commons.SchemaUtils;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
@@ -64,14 +65,11 @@ import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 import org.apache.wicket.model.util.ListModel;
-import org.apache.syncope.common.lib.Attr;
-import org.apache.syncope.common.lib.Attributable;
 
 public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
@@ -116,7 +114,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             @Override
             public WebMarkupContainer getPanel(final String panelId) {
-                return new PlainSchemasOwn(panelId, schemas, attrs);
+                return new PlainSchemas(panelId, schemas, attrs);
             }
         }), Model.of(0)).setOutputMarkupId(true));
 
@@ -137,19 +135,10 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
                     @Override
                     public WebMarkupContainer getPanel(final String panelId) {
-                        return new PlainSchemasMemberships(
+                        return new PlainSchemas(
                                 panelId,
                                 membershipSchemas.get(membershipTO.getGroupKey()),
-                                new LoadableDetachableModel<Attributable>() { // SYNCOPE-1439
-
-                            private static final long serialVersionUID = 526768546610546553L;
-
-                            @Override
-                            protected Attributable load() {
-                                return membershipTO;
-                            }
-
-                        });
+                                new ListModel<>(getAttrsFromTO(membershipTO)));
                     }
                 }), Model.of(-1)).setOutputMarkupId(true));
             }
@@ -250,7 +239,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Boolean:
                 panel = new AjaxCheckBoxPanel(
                         "panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                        schemaTO.getLabel(getLocale()),
                         new Model<>(),
                         true);
                 panel.setRequired(required);
@@ -264,13 +253,13 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                 if (datePattern.contains("H")) {
                     panel = new AjaxDateTimeFieldPanel(
                             "panel",
-                            schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                            schemaTO.getLabel(getLocale()),
                             new Model<>(),
                             datePattern);
                 } else {
                     panel = new AjaxDateFieldPanel(
                             "panel",
-                            schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                            schemaTO.getLabel(getLocale()),
                             new Model<>(),
                             datePattern);
                 }
@@ -283,7 +272,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             case Enum:
                 panel = new AjaxDropDownChoicePanel<>("panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()), new Model<>(), true);
+                        schemaTO.getLabel(getLocale()), new Model<>(), true);
                 ((AjaxDropDownChoicePanel<String>) panel).setChoices(SchemaUtils.getEnumeratedValues(schemaTO));
 
                 if (StringUtils.isNotBlank(schemaTO.getEnumerationKeys())) {
@@ -319,7 +308,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Long:
                 panel = new AjaxSpinnerFieldPanel.Builder<Long>().enableOnChange().build(
                         "panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                        schemaTO.getLabel(getLocale()),
                         Long.class,
                         new Model<>());
 
@@ -331,7 +320,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Double:
                 panel = new AjaxSpinnerFieldPanel.Builder<Double>().enableOnChange().step(0.1).build(
                         "panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                        schemaTO.getLabel(getLocale()),
                         Double.class,
                         new Model<>());
 
@@ -344,7 +333,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                 final PageReference pageRef = getPageReference();
                 panel = new BinaryFieldPanel(
                         "panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                        schemaTO.getLabel(getLocale()),
                         new Model<>(),
                         schemaTO.getMimeType(),
                         fileKey) {
@@ -364,7 +353,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             case Encrypted:
                 panel = new EncryptedFieldPanel("panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()), new Model<>(), true);
+                        schemaTO.getLabel(getLocale()), new Model<>(), true);
 
                 if (required) {
                     panel.addRequiredLabel();
@@ -373,7 +362,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             default:
                 panel = new AjaxTextFieldPanel("panel",
-                        schemaTO.getLabel(SyncopeConsoleSession.get().getLocale()), new Model<>(), true);
+                        schemaTO.getLabel(getLocale()), new Model<>(), true);
 
                 if (jexlHelp) {
                     AjaxTextFieldPanel.class.cast(panel).enableJexlHelp();
@@ -389,88 +378,15 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
         return panel;
     }
 
-    protected class PlainSchemasMemberships extends PlainSchemas<Attributable> {
-
-        private static final long serialVersionUID = 456754923340249215L;
-
-        public PlainSchemasMemberships(
-                final String id,
-                final Map<String, PlainSchemaTO> schemas,
-                final IModel<Attributable> attributableTO) {
-
-            super(id, schemas, attributableTO);
-
-            add(new ListView<Attr>("schemas",
-                    new ListModel<Attr>(new ArrayList<Attr>(
-                            attributableTO.getObject().getPlainAttrs().stream().sorted(attrComparator).
-                                    collect(Collectors.toList())))) {
-
-                private static final long serialVersionUID = 5306618783986001008L;
-
-                @Override
-                @SuppressWarnings({ "unchecked", "rawtypes" })
-                protected void populateItem(final ListItem<Attr> item) {
-                    Attr attrTO = item.getModelObject();
-
-                    AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
-                    if (mode == AjaxWizard.Mode.TEMPLATE
-                            || !schemas.get(attrTO.getSchema()).isMultivalue()) {
-
-                        FieldPanel.class.cast(panel).setNewModel(new Model() {
-
-                            private static final long serialVersionUID = -4214654722524358000L;
-
-                            @Override
-                            public Serializable getObject() {
-                                return (!attributableTO.getObject().getPlainAttr(attrTO.getSchema()).
-                                        get().getValues().isEmpty())
-                                                ? attributableTO.getObject().getPlainAttr(attrTO.getSchema()).
-                                                        get().getValues().get(0)
-                                                : null;
-                            }
-
-                            @Override
-                            public void setObject(final Serializable object) {
-                                attributableTO.getObject().getPlainAttr(attrTO.getSchema()).get().getValues().clear();
-                                if (object != null) {
-                                    attributableTO.getObject().getPlainAttr(attrTO.getSchema()).
-                                            get().getValues().add(object.toString());
-                                }
-                            }
-                        });
-                    } else {
-                        panel = new MultiFieldPanel.Builder<>(new ListModel<String>() {
-
-                            private static final long serialVersionUID = -1765231556272935141L;
-
-                            @Override
-                            public List<String> getObject() {
-                                return attributableTO.getObject().getPlainAttr(attrTO.getSchema()).get().getValues();
-                            }
-                        }).build("panel",
-                                attrTO.getSchema(),
-                                FieldPanel.class.cast(panel));
-                        // SYNCOPE-1215 the entire multifield panel must be readonly, not only its field
-                        ((MultiFieldPanel) panel).setReadOnly(schemas.get(attrTO.getSchema()).isReadonly());
-                    }
-                    item.add(panel);
-
-                    setExternalAction(attrTO, panel);
-                }
-            });
-        }
-    }
-
-    protected class PlainSchemasOwn extends PlainSchemas<List<Attr>> {
+    public class PlainSchemas extends Schemas {
 
         private static final long serialVersionUID = -4730563859116024676L;
 
-        public PlainSchemasOwn(
+        public PlainSchemas(
                 final String id,
                 final Map<String, PlainSchemaTO> schemas,
                 final IModel<List<Attr>> attrTOs) {
-
-            super(id, schemas, attrTOs);
+            super(id);
 
             add(new ListView<Attr>("schemas", attrTOs) {
 
@@ -484,7 +400,6 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                     AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
                     if (mode == AjaxWizard.Mode.TEMPLATE
                             || !schemas.get(attrTO.getSchema()).isMultivalue()) {
-
                         FieldPanel.class.cast(panel).setNewModel(attrTO.getValues());
                     } else {
                         panel = new MultiFieldPanel.Builder<>(
@@ -497,42 +412,24 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                     }
                     item.add(panel);
 
-                    setExternalAction(attrTO, panel);
+                    Optional<Attr> prevAttr = previousObject == null
+                            ? Optional.empty()
+                            : previousObject.getPlainAttr(attrTO.getSchema());
+                    if (previousObject != null
+                            && ((!prevAttr.isPresent() && attrTO.getValues().stream().anyMatch(StringUtils::isNotBlank))
+                            || (prevAttr.isPresent() && !ListUtils.isEqualList(
+                            prevAttr.get().getValues().stream().
+                                    filter(StringUtils::isNotBlank).collect(Collectors.toList()),
+                            attrTO.getValues().stream().
+                                    filter(StringUtils::isNotBlank).collect(Collectors.toList()))))) {
+
+                        List<String> oldValues = prevAttr.isPresent()
+                                ? prevAttr.get().getValues()
+                                : Collections.<String>emptyList();
+                        panel.showExternAction(new LabelInfo("externalAction", oldValues));
+                    }
                 }
             });
         }
     }
-
-    protected abstract class PlainSchemas<T> extends Schemas {
-
-        private static final long serialVersionUID = 8315035592714180404L;
-
-        public PlainSchemas(
-                final String id,
-                final Map<String, PlainSchemaTO> schemas,
-                final IModel<T> attrTOs) {
-
-            super(id);
-        }
-
-        protected void setExternalAction(final Attr attrTO, final AbstractFieldPanel<?> panel) {
-            Optional<Attr> prevAttr = previousObject == null
-                    ? Optional.empty()
-                    : previousObject.getPlainAttr(attrTO.getSchema());
-            if (previousObject != null
-                    && ((!prevAttr.isPresent() && attrTO.getValues().stream().anyMatch(StringUtils::isNotBlank))
-                    || (prevAttr.isPresent() && !ListUtils.isEqualList(
-                    prevAttr.get().getValues().stream().
-                            filter(StringUtils::isNotBlank).collect(Collectors.toList()),
-                    attrTO.getValues().stream().
-                            filter(StringUtils::isNotBlank).collect(Collectors.toList()))))) {
-
-                List<String> oldValues = prevAttr.isPresent()
-                        ? prevAttr.get().getValues()
-                        : Collections.<String>emptyList();
-                panel.showExternAction(new LabelInfo("externalAction", oldValues));
-            }
-        }
-    }
-
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java
similarity index 53%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java
index 0dd9f44..c4e7857 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/EmptyStatusProvider.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java
@@ -16,24 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.commons;
+package org.apache.syncope.client.enduser.wizards.any;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AbstractResources;
 import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
 
-public class EmptyStatusProvider implements StatusProvider {
+public class Resources extends AbstractResources {
 
-    private static final long serialVersionUID = -7948190795547208134L;
+    private static final long serialVersionUID = 702900610508752856L;
 
-    @Override
-    public List<Triple<ConnObjectTO, ConnObjectWrapper, String>> get(
-            final AnyTO any, final Collection<String> resources) {
+    public <T extends AnyTO> Resources(final AnyWrapper<T> modelObject) {
+        super(modelObject);
+    }
 
-        return Collections.emptyList();
+    @Override
+    public boolean evaluate() {
+        available.setObject(SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getResources());
+        return !available.getObject().isEmpty();
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
similarity index 55%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
index 6fbd21a..665f546 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
@@ -16,44 +16,66 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
 import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.enduser.rest.RealmRestClient;
+import org.apache.syncope.client.enduser.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.Component;
 import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 
-public class UserDetails extends Details<UserTO> {
+public class UserDetails extends WizardStep {
 
     private static final long serialVersionUID = 6592027822510220463L;
 
     private static final String PASSWORD_CONTENT_PATH = "body:content";
 
+    private final FieldPanel<String> realm;
+
     protected final AjaxTextFieldPanel username;
 
+    private final FieldPanel<String> securityQuestion;
+
+    private final FieldPanel<String> securityAnswer;
+
     protected final UserTO userTO;
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public UserDetails(
             final UserWrapper wrapper,
             final boolean templateMode,
             final boolean includeStatusPanel,
             final boolean showPasswordManagement,
             final PageReference pageRef) {
-        super(wrapper, templateMode, includeStatusPanel, pageRef);
+        super();
 
         userTO = wrapper.getInnerObject();
         // ------------------------
@@ -75,6 +97,16 @@ public class UserDetails extends Details<UserTO> {
         // ------------------------
 
         // ------------------------
+        // Realm
+        // ------------------------
+        realm = new AjaxDropDownChoicePanel<>(
+                "destinationRealm", "destinationRealm", new PropertyModel<>(userTO, "realm"), false);
+
+        ((AjaxDropDownChoicePanel<String>) realm).setChoices(
+                new RealmRestClient().list().stream().map(RealmTO::getFullPath).collect(Collectors.toList()));
+        add(realm);
+
+        // ------------------------
         // Password
         // ------------------------
         final Model<Integer> model = Model.of(-1);
@@ -120,12 +152,64 @@ public class UserDetails extends Details<UserTO> {
         accordion.setOutputMarkupId(true);
         accordion.setVisible(showPasswordManagement);
         add(accordion);
-        // ------------------------        
-    }
+        // ------------------------
+
+        // ------------------------
+        // Security Answer
+        // ------------------------
+        securityAnswer =
+                new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
+                        new PropertyModel<>(userTO, "securityAnswer"), false);
+        add(securityAnswer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).setEnabled(false));
+        // ------------------------
+
+        // ------------------------
+        // Security Question
+        // ------------------------
+        securityQuestion = new AjaxDropDownChoicePanel("securityQuestion", "securityQuestion", new PropertyModel<>(
+                userTO, "securityQuestion"));
+        ((AjaxDropDownChoicePanel) securityQuestion).setNullValid(true);
+
+        final List<SecurityQuestionTO> securityQuestions = new SecurityQuestionRestClient().list();
+        ((AjaxDropDownChoicePanel<String>) securityQuestion).setChoices(securityQuestions.stream().map(
+                SecurityQuestionTO::getKey).collect(Collectors.toList()));
+        ((AjaxDropDownChoicePanel<String>) securityQuestion).setChoiceRenderer(
+                new IChoiceRenderer<String>() {
 
-    @Override
-    protected AnnotatedBeanPanel getGeneralStatusInformation(final String id, final UserTO anyTO) {
-        return new UserInformationPanel(id, anyTO);
+            private static final long serialVersionUID = -4421146737845000747L;
+
+            @Override
+            public Object getDisplayValue(final String value) {
+                return securityQuestions.stream().filter(sq -> value.equals(sq.getKey()))
+                        .map(SecurityQuestionTO::getContent).findFirst().orElse(null);
+            }
+
+            @Override
+            public String getIdValue(final String value, final int index) {
+                return value;
+            }
+
+            @Override
+            public String getObject(
+                    final String id,
+                    final IModel<? extends List<? extends String>> choices) {
+                return id;
+            }
+        });
+
+        securityQuestion.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = 192359260308762078L;
+
+            @Override
+            protected void onEvent(final AjaxRequestTarget target) {
+                securityAnswer.setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject()));
+                target.add(securityAnswer);
+            }
+        });
+
+        add(securityQuestion);
+        // ------------------------
     }
 
     public static class EditUserPasswordPanel extends Panel {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java
similarity index 80%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java
index 8201ec1..9346bf4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserWizardBuilder.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java
@@ -16,15 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
 import java.io.Serializable;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.layout.UserForm;
-import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.request.PasswordPatch;
@@ -34,11 +35,11 @@ import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.PageReference;
 
-public class UserWizardBuilder extends AnyWizardBuilder<UserTO> implements UserForm {
+public class UserWizardBuilder extends AnyWizardBuilder implements UserForm {
 
     private static final long serialVersionUID = 6716803168859873877L;
 
-    protected final UserRestClient userRestClient = new UserRestClient();
+    protected final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
 
     /**
      * Constructor to be used for templating only.
@@ -86,7 +87,7 @@ public class UserWizardBuilder extends AnyWizardBuilder<UserTO> implements UserF
                     ? UserWrapper.class.cast(modelObject).isStorePasswordInSyncope()
                     : StringUtils.isNotBlank(inner.getPassword()));
 
-            result = userRestClient.create(req);
+            result = userSelfRestClient.create(req);
         } else {
             fixPlainAndVirAttrs(inner, getOriginalItem().getInnerObject());
             UserUR userUR = AnyOperations.diff(inner, getOriginalItem().getInnerObject(), false);
@@ -102,23 +103,13 @@ public class UserWizardBuilder extends AnyWizardBuilder<UserTO> implements UserF
                 result = new ProvisioningResult<>();
                 result.setEntity(inner);
             } else {
-                result = userRestClient.update(getOriginalItem().getInnerObject().getETagValue(), userUR);
+                result = userSelfRestClient.update(getOriginalItem().getInnerObject().getETagValue(), userUR);
             }
         }
 
         return result;
     }
 
-    @Override
-    protected Details<UserTO> addOptionalDetailsPanel(final AnyWrapper<UserTO> modelObject) {
-        return new UserDetails(
-                UserWrapper.class.cast(modelObject),
-                mode == AjaxWizard.Mode.TEMPLATE,
-                modelObject.getInnerObject().getKey() != null,
-                UserFormLayoutInfo.class.cast(formLayoutInfo).isPasswordManagement(),
-                pageRef);
-    }
-
     /**
      * Overrides default setItem() in order to clean statusModel as well.
      *
@@ -130,4 +121,5 @@ public class UserWizardBuilder extends AnyWizardBuilder<UserTO> implements UserF
         super.setItem(item == null ? null : new UserWrapper(item.getInnerObject()));
         return this;
     }
+
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
similarity index 90%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
copy to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
index 4b7c2df..9dec684 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
@@ -16,8 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.wizards.any;
+package org.apache.syncope.client.enduser.wizards.any;
 
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -25,13 +27,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.wicket.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.console.wicket.markup.html.form.AbstractFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
@@ -192,7 +194,7 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
                     AbstractFieldPanel<?> panel = new AjaxTextFieldPanel(
                             "panel",
-                            virSchemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                            virSchemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
                             new Model<>(),
                             false);
 
@@ -202,7 +204,7 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
                         panel = new MultiFieldPanel.Builder<>(
                                 new PropertyModel<List<String>>(attrTO, "values")).build(
                                 "panel",
-                                virSchemaTO.getLabel(SyncopeConsoleSession.get().getLocale()),
+                                virSchemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
                                 AjaxTextFieldPanel.class.cast(panel));
                         panel.setEnabled(!virSchemaTO.isReadonly());
                     }
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/cxf/org.apache.cxf.Logger b/client/idrepo/enduser/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
new file mode 100644
index 0000000..6e7bd36
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
@@ -0,0 +1 @@
+org.apache.cxf.common.logging.Slf4jLogger
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SubmitableModalPanel.java b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
similarity index 71%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SubmitableModalPanel.java
copy to client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
index b008980..21b9201 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SubmitableModalPanel.java
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
@@ -16,13 +16,29 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.panels;
 
-import org.apache.wicket.ajax.AjaxRequestTarget;
+.btn-accessibility {
+  position: absolute;
+  right: 0;
+  font-size: 12px;
+  padding: 15px 15px 0 0;
+}
+
+.btn-accessibility i {
+  font-size: 30px;
+}
 
-public interface SubmitableModalPanel extends ModalPanel {
+.btn-accessibility:hover {
+  cursor:pointer;
+}
 
-    void onSubmit(AjaxRequestTarget target);
+.control-sidebar-menu a:focus {
+  outline: 1px #949494 solid;
+}
 
-    void onError(AjaxRequestTarget target);
+#change_contrast {
+  top: 0;
+}
+#change_fontSize {
+  top: 40px;
 }
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css
new file mode 100644
index 0000000..da26456
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+body,
+p {
+  font-size: 200%;
+}
+
+.menu a,
+.treeview-menu a,
+.control-sidebar-subheading {
+  font-size: 80% !important;
+}
+
+.box-header > .fa, 
+.box-header > .glyphicon, 
+.box-header > .ion, .box-header .box-title,
+.dropdown-toggle .filter-option,
+.dropdown-menu a,
+.menu-info span,
+.user-header,
+.header,
+.modal-title,
+.small-box p,
+.alert-widget,
+.alert-widget > a > .label,
+.alert h4,
+#mappings .fa,
+.popover-content,
+.box .dropdown-toggle .glyphicon,
+.box-header button,
+.toggle .toggle-group .btn,
+.input-group .form-control label {
+  font-size: 120%;
+}
+
+input,
+select,
+.footer a,
+.modal-footer button,
+.dropdown-menu:not([role='menu']),
+.dropdown-menu > li.header,
+div#tablehandling ul.menu i,
+.content-header > .breadcrumb,
+.btn-primary:not(.btn-circle),
+.modal-content .box .dialog pre {
+  font-size: 100% !important;
+}
+
+#topology .window {
+  height: 90px;
+}
+
+.dataTables_length select {
+  font-size: 85% !important;
+}
+
+button.close {
+  font-size: 2em;
+}
+
+.details-footer .information {
+  font-size: 12px;
+}
+
+.btn-file i,
+.btn-file span,
+.input-group-btn button.btn-primary {
+  font-size: 20px !important;
+}
+
+.checkbox input[type=checkbox], 
+.checkbox-inline input[type=checkbox], 
+.radio input[type=radio], 
+.radio-inline input[type=radio],
+input[type=checkbox], 
+input[type=radio] {
+  width: 20px;
+  height: 20px;
+}
+
+.k-timepicker, 
+.k-datepicker {
+  width: 200px !important;
+}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css
new file mode 100644
index 0000000..aa4d5b9
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+/* General
+============================================================================= */
+.content-wrapper,
+.content-wrapper .box,
+.modal-content,
+.modal-header,
+.background-footer,
+input:not(:disabled):not([type="file"]),
+select,
+select option,
+button:not(.close),
+.table .sorting,
+.dataTables_paginate a,
+.modal-footer,
+.box-header,
+.dropdown-menu,
+.main-footer,
+.circular-actions a,
+.k-select,
+.file-caption.kv-fileinput-caption {
+  color: #f7f7f7 !important;
+  background-color: #0f1417 !important;
+}
+
+
+.dataTable thead th:after,
+.close {
+  color: #f7f7f7 !important;
+  opacity: 0.8 !important;
+}
+
+
+.input-group-addon a,
+.input-group-addon i,
+.dropdown-menu > li:not(.disabled) > a:hover,
+.dropdown-menu > li:not(.disabled) > a:hover span,
+.dropdown-menu > li:not(.disabled) > a:focus,
+.dropdown-menu > li:not(.disabled) > a:focus span,
+#startAtContainer .input-group-addon span,
+#startAtContainer .k-widget span,
+#startAtContainer .k-widget i,
+#startAtContainer .k-widget input,
+.modal-footer i,
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default,
+.content-wrapper .nav-tabs a,
+.wrapper .content-wrapper .nav.nav-tabs li.active a span,
+.wrapper .content-wrapper .nav.nav-tabs li.active a,
+.wrapper .content-wrapper .nav.nav-tabs li a:hover span,
+.wrapper .content-wrapper .nav.nav-tabs li a:hover,
+.wrapper .content-wrapper .nav.nav-tabs li a:active span,
+.wrapper .content-wrapper .nav.nav-tabs li a:active,
+.wrapper .content-wrapper .nav.nav-tabs li a:focus span,
+.wrapper .content-wrapper .nav.nav-tabs li a:focus,
+.wrapper .content-wrapper .tab-content .btn-primary .fa-download {
+  color: #000000 !important;
+}
+
+
+.content-wrapper a:not(.btn-primary),
+.content-wrapper span:not(.label-info):not([role="presentation"]):not([class^='cm-']),
+.content-wrapper p,
+.content-wrapper .box-title a,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:hover,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:hover span,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:focus,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:focus span,
+.box-header,
+.breadcrumb .active,
+table tbody tr:hover button span,
+.dropdown-menu > li > a,
+.modal-header button,
+.circular-actions a i,
+.wizard-form .input-group-addon i,
+#startAtContainer .input-group-addon i,
+.attribute .input-group-addon i {
+  color: #f7f7f7 !important;
+}
+
+
+.box.box-primary {
+  border-top-color: #f7f7f7;
+}
+
+
+img,
+.content-wrapper div.btn.btn-file span.hidden-xs {
+  background-color: #f7f7f7;
+  color: #000000 !important;
+}
+.btn-primary,
+.callout.callout-info,
+.alert-info,
+.label-info,
+.modal-info .modal-body {
+  background-color: #f7f7f7 !important;
+  color: #000000 !important;
+}
+
+
+.logo img,
+.modal-content .input-group .input-group-addon {
+  background-color: transparent;
+}
+
+
+.modal-dialog {
+  border: 2px solid white;
+}
+
+
+#veil:not(:required):after {
+  -webkit-box-shadow: #f7f7f7 1.5em 0 0 0, 
+    #f7f7f7 1.1em 1.1em 0 0, 
+    #f7f7f7 0 1.5em 0 0,
+    #f7f7f7 -1.1em 1.1em 0 0, 
+    rgba(0, 0, 0, 0.5) -1.5em 0 0 0, 
+    rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, 
+    #f7f7f7 0 -1.5em 0 0, 
+    #f7f7f7 1.1em -1.1em 0 0;
+  box-shadow: #f7f7f7 1.5em 0 0 0, 
+    #f7f7f7 1.1em 1.1em 0 0, 
+    #f7f7f7 0 1.5em 0 0, 
+    #f7f7f7 -1.1em 1.1em 0 0, 
+    #f7f7f7 -1.5em 0 0 0, 
+    #f7f7f7 -1.1em -1.1em 0 0, 
+    #f7f7f7 0 -1.5em 0 0, 
+    #f7f7f7 1.1em -1.1em 0 0; 
+}
+
+
+.input-group input:disabled,
+.input-group input[disabled],
+.control-sidebar-dark .control-sidebar-menu > li > a:hover,
+.table-hover > tbody > tr:hover,
+.skin-blue .main-header .navbar .sidebar-toggle:hover,
+.main-header .navbar .sidebar-toggle:hover,
+.skin-blue .main-header .logo:hover,
+.main-header .logo:hover,
+div.toggle-menu ul li:hover,
+.skin-blue .main-header .navbar .nav > li > a:hover, 
+.skin-blue .main-header .navbar .nav > li > a:active, 
+.skin-blue .main-header .navbar .nav > li > a:focus, 
+.skin-blue .main-header .navbar .nav .open > a:hover, 
+.skin-blue .main-header .navbar .nav .open > a:focus,
+.skin-blue .sidebar-menu > li:hover > a, 
+.skin-blue .sidebar-menu > li.active > a,
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus, 
+.dropdown-menu > li > a:hover,
+.k-block, 
+.k-draghandle, 
+.k-grid-header, 
+.k-grouping-header, 
+.k-header, 
+.k-pager-wrap, 
+.k-toolbar, 
+.k-treemap-tile,
+.k-picker-wrap,
+.k-state-disabled,
+.km-pane-wrapper .k-header {
+  background-color: rgba(108, 115, 117, 0.55);
+}
+
+
+.sidebar-mini .main-header .navbar {
+  background-color: #222d32; /* color from 'skin-blue' */
+  border-bottom: 1px white solid;
+  box-sizing: border-box;
+}
+.sidebar-mini .main-header .logo,
+div.toggle-menu,
+.skin-blue .main-header li.user-header {
+  background-color: #222d32;
+}
+
+
+div.toggle-menu {
+  border: 1px solid #f7f7f7;
+}
+
+
+a,
+.pagination > .active > a, 
+.pagination > .active > a:focus, 
+.pagination > .active > a:hover, 
+.pagination > .active > span, 
+.pagination > .active > span:focus, 
+.pagination > .active > span:hover {
+  border-color: #76abd9;
+}
+a {
+  color: #76abd9;
+}
+
+
+.logs button.btn-primary {
+  border-color: #f7f7f7;
+}
+.logs button.btn-primary:hover {
+  border-color: #adadad;
+}
+div.infolabel,
+.input-group input:disabled,
+.input-group input[disabled] {
+  color: #d2d2d2;
+}
+
+
+.bg-red,
+.callout.callout-danger,
+.alert-danger,
+.alert-error,
+.label-danger,
+.modal-danger .modal-body,
+.btn-danger.active, 
+.btn-danger:active, 
+.open>.dropdown-toggle.btn-danger {
+  background-color: #942819 !important;
+}
+.bg-yellow {
+  background-color: #6F4706 !important;
+}
+.bg-green,
+.copy-clipboard-feedback,
+.btn-success,
+.callout.callout-success, 
+.alert-success, 
+.label-success, 
+.modal-success .modal-body {
+  background-color: #005C32 !important;
+}
+.bg-aqua {
+  background-color: #004E61 !important;
+}
+.bg-yellow, 
+.callout.callout-warning, 
+.alert-warning, 
+.label-warning, 
+.modal-warning .modal-body {
+  background-color: #6F4706 !important;
+}
+.callout.callout-warning {
+  border-color: #6F4706;
+}
+
+
+.bootstrap-select .btn.btn-default {
+  background-color: rgba(101, 101, 101, 0.7) !important;
+}
+
+
+/* Login page
+============================================================================= */
+.login-body {
+  background-image: linear-gradient(rgb(31, 109, 142), #004626);
+}
+
+.login-logo {
+  background: transparent;
+}
+
+.btn-accessibility {
+  color: #f7f7f7 !important;
+}
+
+.form-signin .btn-primary, 
+.form-signin .btn-primary {
+  border: 2px solid white;
+}
+.form-signin .btn-primary.focus, 
+.form-signin .btn-primary:focus {
+  border-color: #8c8c8c;
+}
+
+.login-card {
+  background-color: #0f1417;
+}
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css
new file mode 100644
index 0000000..da7bdf8
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+/* source-sans-pro-300 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-300italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: italic;
+  font-weight: 300;
+  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-regular - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: italic;
+  font-weight: 400;
+  src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-600 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: normal;
+  font-weight: 600;
+  src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-600italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: italic;
+  font-weight: 600;
+  src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-700 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+  font-family: 'Source Sans Pro';
+  font-style: normal;
+  font-weight: 700;
+  src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+    url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff
new file mode 100644
index 0000000..2132b5e
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2
new file mode 100644
index 0000000..943f826
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff
new file mode 100644
index 0000000..aa25cd3
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2
new file mode 100644
index 0000000..441997f
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff
new file mode 100644
index 0000000..24d2824
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2
new file mode 100644
index 0000000..9ec7d25
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff
new file mode 100644
index 0000000..ce5a1cc
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2
new file mode 100644
index 0000000..7ed2f82
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff
new file mode 100644
index 0000000..9fbfe68
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2
new file mode 100644
index 0000000..096dcb1
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff
new file mode 100644
index 0000000..c1cf1ea
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2
new file mode 100644
index 0000000..ff006be
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff
new file mode 100644
index 0000000..e8a1ac7
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2
new file mode 100644
index 0000000..1b0bc46
Binary files /dev/null and b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2 differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css
new file mode 100644
index 0000000..575df66
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+body, html {
+  height: 100% !important;
+  background-repeat: no-repeat;
+  background-image: linear-gradient(rgb(104, 145, 162), #00a65a);
+}
+
+.card-container.card {
+  width: 350px;
+  padding: 40px 40px;
+}
+
+.btn {
+  font-weight: 700;
+  height: 36px;
+  -moz-user-select: none;
+  -webkit-user-select: none;
+  user-select: none;
+  cursor: default;
+}
+
+/*
+ * Card component
+ */
+.card {
+  background-color: #F7F7F7;
+  /* just in case there no content*/
+  padding: 20px 25px 30px;
+  margin: 0 auto 25px;
+  margin-top: 50px;
+  /* shadows and rounded borders */
+  -moz-border-radius: 2px;
+  -webkit-border-radius: 2px;
+  border-radius: 2px;
+  -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+  -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+  box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+}
+
+.login-logo {
+  width: 200px;
+  margin: 0 auto 10px;
+  display: block;
+}
+
+/*
+ * Form styles
+ */
+.profile-name-card {
+  font-size: 16px;
+  font-weight: bold;
+  text-align: center;
+  margin: 10px 0 0;
+  min-height: 1em;
+}
+
+.form-signin #inputPassword,
+.form-signin #inputPassword {
+  direction: ltr;
+  height: 44px;
+  font-size: 16px;
+}
+
+.form-signin input[type=password],
+.form-signin input[type=text],
+.form-signin button {
+  width: 100%;
+  display: block;
+  margin-bottom: 10px;
+  z-index: 1;
+  position: relative;
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+.form-signin .form-control:focus {
+  border-color: rgb(104, 145, 162);
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
+  box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
+}
+
+.btn.btn-signin {
+  background-color: rgb(104, 145, 162);
+  padding: 0px;
+  font-weight: 700;
+  font-size: 14px;
+  height: 36px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  border: none;
+  -o-transition: all 0.218s;
+  -moz-transition: all 0.218s;
+  -webkit-transition: all 0.218s;
+  transition: all 0.218s;
+}
+
+.btn.btn-signin:hover,
+.btn.btn-signin:active,
+.btn.btn-signin:focus {
+  background-color: #00a65a;
+}
+
+.btn.btn-sso {
+  padding: 0px;
+  font-weight: 700;
+  font-size: 14px;
+  height: 36px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  border: none;
+  -o-transition: all 0.218s;
+  -moz-transition: all 0.218s;
+  -webkit-transition: all 0.218s;
+  transition: all 0.218s;
+}
+
+.btn.btn-sso:hover,
+.btn.btn-sso:active,
+.btn.btn-sso:focus {
+  background-color: #00a65a;
+}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css
new file mode 100644
index 0000000..c2dcf2c
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css
@@ -0,0 +1,1164 @@
+/*
+ * 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.
+ */
+
+pre {
+  white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+  white-space: -pre-wrap; /* Opera */
+  white-space: -o-pre-wrap; /* Opera */
+  white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
+  word-wrap: break-word; /* IE 5.5+ */
+}
+
+/* Absolute Center Spinner */
+#veil {
+  display:none;
+  position: fixed;
+  z-index:99999;
+  height: 2em;
+  width: 2em;
+  overflow: show;
+  margin: auto;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+
+/* Transparent Overlay */
+#veil:before {
+  content: '';
+  display: block;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0,0,0,0.3);
+}
+
+/* :not(:required) hides these rules from IE9 and below */
+#veil:not(:required) {
+  /* hide "loading..." text */
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+#veil:not(:required):after {
+  content: '';
+  display: block;
+  font-size: 10px;
+  width: 1em;
+  height: 1em;
+  margin-top: -0.5em;
+  -webkit-animation: spinner 2000ms infinite linear;
+  -moz-animation: spinner 2000ms infinite linear;
+  -ms-animation: spinner 2000ms infinite linear;
+  -o-animation: spinner 2000ms infinite linear;
+  animation: spinner 2000ms infinite linear;
+  border-radius: 0.5em;
+  -webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
+  box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
+}
+
+/* Animation */
+
+@-webkit-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@-moz-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@-o-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+.block-sidebar {
+  max-height: 100% !important; 
+  overflow: auto !important; 
+  padding-top: 90px !important; 
+  padding-bottom: 50px !important; 
+  position: fixed !important;
+  width: 245px !important;
+}
+
+.inner-control-sidebar {
+  position: fixed; 
+  height: auto;
+}
+
+.content-margin-layout {
+  margin: 0px 230px 0px 0px !important;
+  padding: 20px !important;
+}
+
+.admin-content-page {
+  padding: 20px;
+  background: #ecf0f5
+}
+
+.realms {
+  min-height: 554px
+}
+
+.realm-header {
+  clear: both;
+  display:block;
+  display: inline-table;
+  margin: 0 0 10px;
+  line-height: 25px;
+}
+
+.realm-label {
+  float: left;
+  font-size: 16px;
+}
+
+.realm-label label {
+  font-weight: 600 !important;
+}
+
+.realm-choice {
+  right: 0px;
+  position: absolute;
+}
+
+.realm-header .dropdown-menu li a {
+  text-align: left !important;
+  white-space: pre !important;
+  line-height: 7px;
+}
+
+.block-header {
+  position: fixed !important;
+  width: 100% !important;
+  top: 0 !important;
+}
+
... 9731 lines suppressed ...