Now that Alfresco Community 4.2d has been released I thought it would be useful to begin providing some examples of how to customize the new header bar. The new header bar is the first feature in Share to use the updated widget processing framework provided by Surf. In this post I will demonstrate how to update the default menu to convert the 'Admin Tools' link into a drop-down menu with links to all of the individual Admin Console pages. In later posts I'll show how to remove menu items and how to add custom widgets into the header.
Let's first compare the old and new header menus...
As well as the obvious stylistic differences there are some major implementation differences. The original header was rendered by a combination of the 'header', 'title' and 'navigation' regions whereas these have been replaced by a single region called 'share-header'.
This new region is bound to the 'share-header.get' WebScript which uses the previously described approach to define the JSON model of widgets that comprise the header.
The structure of the old header was defined in the 'share-config.xml' configuration file whereas the new header is entirely defined by the 'share-header.get' WebScript's JavaScript controller. It is possible to render the header using the configuration from the 'share-config.xml' file by changing the 'legacy-mode-enabled' element value from 'false' to 'true'.
To customize the header you should follow the approach described in this blog post to extend the JavaScript controller of the 'share-header.get' WebScript. To briefly recap, follow these steps:
<extension>
<modules>
<module>
<id>Update Admin Menu</id>
<version>1.0</version>
<customizations>
<customization>
<targetPackageRoot>org.alfresco.share.header</targetPackageRoot>
<sourcePackageRoot>blogs.admin-menu</sourcePackageRoot>
</customization>
</customizations>
</module>
</modules>
</extension>
The 'targetPackageRoot' element identifies the location of the 'share-header.get' WebScript and the 'sourcePackageRoot' element identifies the location of your extension file. You now have the basic elements required to customize the header - everything else will be done in the '/alfresco/site-webscripts/blogs/admin-menu/share-header.get.js' file.
The purpose of a JavaScript controller is to construct a model object that the FreeMarker template uses when generating a fragment of DOM for the page. The model object created by the default JavaScript controller is made available to each extension controller before it is passed to the FreeMarker template and this provides them the opportunity to change the model before it is processed.
The model object is assigned an attribute called 'jsonModel' with a value that is a JSON object containing all the widgets to render in the header. Each widgets is given a unique 'id' attribute so that they can easily be found by extensions using the 'widgetUtils.findObject' helper function.
In this example we're going modify the 'alfresco/menus/AlfMenuBarItem' widget that creates the 'Admin Tools' menu item. The original definition of this can be found in the 'share-header.lib.js' library file (that is imported by 'share-header.get.js') and is:
{
id: 'HEADER_ADMIN_CONSOLE',
name: 'alfresco/menus/AlfMenuBarItem',
config: {
label: 'header.menu.admin.label',
targetUrl: 'console/admin-console/application'
}
}
We can work with this widget by adding the following to our 'share-header.get.js' extension file:
var adminMenu = widgetUtils.findObject(model.jsonModel, 'id', 'HEADER_ADMIN_CONSOLE');
if (adminMenu != null)
{
adminMenu.name = 'alfresco/header/AlfMenuBarPopup';
delete adminMenu.config.targetUrl;
}
This will find the widget (which will only be present in the model if the currently logged in user is the Admin) and then change the widget definition's 'name' attribute to be 'alfresco/header/AlfMenuBarPopup' which will convert it into a drop-down menu. We then delete the 'targetUrl' attribute because it is not required.
The final step is to add in the contents of the drop-down menu (I'm only going to show the first sub-group defined but you can find a JAR file containing all the source here😞
var adminMenu = widgetUtils.findObject(model.jsonModel, 'id', 'HEADER_ADMIN_CONSOLE');
if (adminMenu != null)
{
adminMenu.name = 'alfresco/header/AlfMenuBarPopup';
delete adminMenu.config.targetUrl;
adminMenu.config.widgets = [
{
name: 'alfresco/menus/AlfMenuGroup',
config: {
label: 'Tools',
widgets: [
{
name: 'alfresco/header/AlfMenuItem',
config:
{
label: 'Application',
targetUrl: 'console/admin-console/application'
}
},
{
name: 'alfresco/header/AlfMenuItem',
config:
{
label: 'Category Manager',
targetUrl: 'console/admin-console/category-manager'
}
}
]
}
}
];
}
Here we're adding a group with the label 'Tools' which contains two menu items labelled 'Application' and 'Category Manager' which each have a page relative (that is relative to '/share/page') URL for the page that they represent.
Copy the JAR to the '<tomcat-home>/webapps/share/WEB-INF/lib', restart your server and go to the 'share/page/modules/deploy' page and deploy your new module.
Login to Share as 'Admin' and you'll see that the 'Admin Tools' menu has now been converted into a drop-down menu (the screenshot shows the extension provided in my sample JAR):
Although I haven't yet explained exactly what all the widget definitions mean, which widgets are available or how you can configure each of them... this example should at least show you how you can easily update the new header to suit your needs.
You may wonder how exactly this is more beneficial than updating the menu via configuration? The main advantages are as follows:
Hopefully this information is useful as a starting point. In my next post I'll demonstrate how you can extend an existing widget and use it in the menu.