Create and Edit Site Dialog Customization with Aikau

cancel
Showing results for 
Search instead for 
Did you mean: 

Create and Edit Site Dialog Customization with Aikau

Intermediate II
5 3 4,096

Introduction

If you've tried out the Early Access Community Release (201611) of Alfresco you might have noticed that in version 5.2 the Create and Edit site dialogs are now being rendered by Aikau. As well as providing some user experience improvements the main benefit of switching to Aikau is to make it much easier to customize both dialogs. In this post I'm going to provide some examples of the options that are now available to you.

PLEASE NOTE: The early access release doesn't have all of the customization options described here - to try them all out you'll need version 1.0.98 of Aikau.

Don't Panic

If you have already made significant customizations to the the YUI2 based versions of the dialog then don't panic. We've provided a very simple way in which to use the old dialogs so that your existing customizations can continue to work just as they've always done. The SiteService that controls which dialogs are used has a legacyMode configuration attribute that when set to true will use the YUI2 dialogs. In Share 5.2 we are re-configuring this to be false so if you want to continue using the YUI2 dialogs you just need to create an extension that configures it back to true again!

Download Extension

The first job is to actually build an extension module to customize the SiteService on all pages within Share.... however, you may not want to do that so I've provided an extension module that does exactly this in this GitHub repository. You can download a pre-built extension from here (to re-enable the YUI dialogs) or use it as a starting point for implementing the other customizations described in this post (but don't forget to switch legacyMode to false!!!)

Custom Presets

Alfresco only comes with a single site preset (the "Collaboration Site"). In order to make more site presets show up in the old dialog it was necessary to create an extension module to customize the create-site.get.js WebScript JavaScript controller. All customization is now done via the SiteService and you now have options to:

  • Explicitly define the presets (via the sitePresets attribute)
  • Provide additional presets (via the additionalSitePresets attribute)
  • Remove existing presets (via the sitePresetsToRemove attribute)

Let's add some additional presets. In the share-header.get.js customization file create the following:

var siteService = widgetUtils.findObject(model.jsonModel, "id", "SITE_SERVICE");
if (siteService && siteService.config)
{
  siteService.config.additionalSitePresets = [{ label: "Custom Preset", value: "CUSTOM" } ];
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This will add the additional preset into the create site dialog, like so:

Customized create site dialog with additional preset

Dialog Model Overrides

The widgets model for the create site dialog is defined in the widgetsForCreateSiteDialog attribute. You can completely replace the model if you wish - but a more efficient way to make changes would be to make use of the widgetsForCreateSiteDialogOverrides attribute. This is an additional model that lets you...

  • add widgets (at the start and end or before/after a specific widget in the default model)
  • remove widgets
  • replace widgets
  • merge additional configuration into existing widgets

Removing Fields

Let's start by removing the "Description" field. Update the share-header.get.js file so that it looks like this:

var siteService = widgetUtils.findObject(model.jsonModel, "id", "SITE_SERVICE");
if (siteService && siteService.config)
{
  siteService.config.additionalSitePresets = [{ label: "Custom Preset", value: "CUSTOM" } ];
  siteService.config.widgetsForCreateSiteDialogOverrides = [
    {
      id: "CREATE_SITE_FIELD_DESCRIPTION",
      remove: true
    }
  ];
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This instructs the SiteService to remove any widget with the id attribute "CREATE_SITE_FIELD_DESCRIPTION" and has the effect of removing the "Description" field as shown here:

Create site dialog with the description field removed

Updating Fields

There are two ways in which you can update an existing field. The first method is using the replace attribute. As the name suggests this will completely replace any widget with a matching id. Add the following entry into the widgetsForCreateSiteDialogOverrides array:

{
  id: "CREATE_SITE_FIELD_VISIBILITY",
  replace: true,
  name: "alfresco/forms/controls/Select",
  config: {
    fieldId: "VISIBILITY",
    label: "How am I seen?",
    name: "visibility",
    optionsConfig: {
      fixed: [
        {
          label: "By everyone",
          value: "PUBLIC"
        },
        {
          label: "By Some",
          value: "MODERATED"
        }
      ]
    }
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

...and the result is that the original RadioButtons widget is replaced by a Select widget like this:

Create site dialog with a replaced field

If you just want to merge some existing configuration into an existing field then you can just omit the replace attribute and just provide the new or changed attributes. Change the replace entry to be this:

{
  id: "CREATE_SITE_FIELD_VISIBILITY",
  config: {
    label: "How am I seen?",
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This has the effect of simply updating the label displayed:

Create site dialog with an updated field

Adding New Fields

If you just want to add a brand new field into the dialog then you can do so using the targetPosition attribute. This accepts the following 4 different values:

  • "START"
  • "END"
  • "BEFORE"
  • "AFTER"

When using "BEFORE" or "AFTER" it is also necessary to specific a targetId attribute to indicate which existing field the new fields should be added in relation to.

For example, let's say that you want to add a new field at the start of the dialog. Add the following entry into the widgetsForCreateSiteDialogOverrides array:

{
  id: "FIRST",
  name: "alfresco/forms/controls/TextBox",
  targetPosition: "START",
  config: {
    fieldId: "FIRST",
    label: "First!",
    name: "first",
    description: "This field has been added as the first entry"
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This will result in the following dialog:

Create site dialog with a new field at the start of the dialog

If you wanted to insert a field between the "Site ID" and "Name" fields then use a combination of targetPostition and targetId like this:

{
  id: "INSERTED",
  name: "alfresco/forms/controls/TextBox",
  targetPosition: "BEFORE",
  targetId: "CREATE_SITE_FIELD_SHORTNAME",
  config: {
    fieldId: "INSERTED",
    label: "Inserted",
    name: "inserted",
    description: "This field has been inserted before another field"
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This would then result in the following dialog:

Create site dialog with a new field inserted in the middle of the form

How the Form Works

The examples shown are very simplistic and are provided to demonstrate the principals of customizing the dialog forms. You can make full use of any and all of the capabilities provided by the many Aikau form controls that are available. You can find a full list of the form controls available in the JSDoc (look under the alfresco/forms/controls package) and can find examples of the basic form concepts in a Sandpit page.  Lots of information about form control configuration can also be found in videos embedded in this blog post.

Any form control added to the dialog will automatically have it's value included in the XHR request to the /modules/create-site and /modules/edit-site WebScripts respectively. It will therefore be necessary to also customize or override these WebScripts to make use of the extra data that your customized dialogs provide (for example you may wish to apply custom Aspects to the site and set additional metadata on them). However, these changes are outside the scope of this article which is focused solely on the client-side user interface changes.

Reusable Mix-in Module

The overriding capabilities are provided through the new module WidgetsOverrideMixin introduced in Aikau 1.0.97. This module can be mixed into other widgets and services to provide the same model manipulation. If there are any existing areas of Aikau code that you feel could benefit from this capability then please let me know!

Missing Use Cases?

It's quite possible that these capabilities still do not meet your specific customization requirements for the create and edit site dialogs. I did create a poll a few weeks ago to try and gather as much information as possible but didn't get many concrete use cases to address. If you feel that these updates don't support your specific requirements then please let me know in order that we can address them. 

3 Comments
Master

The customisation of these dialogs works really great - for anyone interested in a more elaborate example you may check one of my customisations.

At the moment there are some restrictions that people need to be aware of and that Alfresco will hopefully address in the 5.2 code line (before 5.2 Enterprise ships / in an additional 5.2 GA release).

  • Customisations should only add simple widgets - adding a picker may cause interference with Share-bundled TinyMCE (ALF-21855)
  • Handling custom data currently needs additional Xhr / pub-sub handling - ideally the Repository web scripts site.get / sites.post / site.put should support extensions (ALF-21812)
Member II

We've recently had to address a maintenance issue regarding share-header customisations when used with Records Management (RM). In the example given, an individual wanted to provide some site service customisations at the same time as they were using RM, which uses a site service customisation itself to provide the Records Management entry in the create site type drop-down. The example provided by this blog post suggests code such as this for adding additional site presets via a customisation:

var siteService = widgetUtils.findObject(model.jsonModel, "id", "SITE_SERVICE");
if (siteService && siteService.config)
{
  siteService.config.additionalSitePresets = [
    {label: "Custom Preset", value: "CUSTOM"}
  ];
}‍‍‍‍‍

This code will work, but only in isolation as it very fixedly sets the siteService.config.additionalSitePresets to an array with a single item. The same configuration was found to be in use within the RM code. The result of either of these entries is simply that the last module processed, whether that be RM or another customisation, will be the version that persists.

A more suitable way in which to work with these siteService configuration settings is to try to extract any existing config from siteService.config, add anything new to the extracted value, and then set it back on the siteService.config. A modification has been made to the RM code so that it will not override any customisations, but a similar change is also required to any customisations in order that they do not override RM. The additionalSitePresets extracted from the siteService.config is an array and any usual array manipulation techniques may be used - in this case push but unshift is acceptable too and has been used in the RM code for example.

var siteService = widgetUtils.findObject(model.jsonModel, "id", "SITE_SERVICE");
if (siteService && siteService.config)
{
  var additionalSitePresets = (siteService.config.additionalSitePresets) ?
    siteService.config.additionalSitePresets : [];
 
  additionalSitePresets.push({
    label: "Custom Preset",
    value: "CUSTOM"
});

siteService.config.additionalSitePresets = additionalSitePresets;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Master

Indeed when using Aikau and post-processing of JSON model, one should always assume there is already existing data. I prefer the following pattern over the ternary operator:

siteService.config.additionalSitePresets = siteService.config.additionalSitePresets || [];
siteService.config.additionalSitePresets.push({...});