Skip navigation
All Places > Alfresco Content Services (ECM) > Blog > 2011 > August > 12
Having released v0.2 of the Node Browser Component for Share this week and having put a bit of work into refactoring the underlying code, it seemed like a good time to write a quick guide to creating Administration Console Components for Share.

Like dashlets, Admin Console components are easily defined using a single web script, along with some supporting resources, and are therefore are automatically picked up by the framework once added to Share, with no additional configuration needed.

Alfresco's Engineering team have added a number of new console components to the upcoming Swift release, and in addition to the Node Browser Share Extras provides two other additional components that you can add to your existing 3.3 or 3.4 installations.

  • Complenting the Node Browser, Florian Maul's JavaScript Console allows custom JavaScript code to be executed against the repository to display information or make changes. Loading and saving of scripts to and from the Data Dictionary is supported, as well as syntax highlighting and custom space contexts.

  • Secondly the Create Bulk Users component allows administrators to create multiple users in the repository, based on CSV/TSV or JSON data, and is capable of auto-generating usernames and passwords, sending email notifications and logging of all user created.

Each of the three add-on pages has information on checking out a copy of the source code, which you can use as a basis for creating your own components. You should also grab a copy of the Sample Project bundle, which can be used as a template for your projects.

But before you dive into the code, it's useful to have an understanding of the different parts that make up a component. So let's step through each of them in turn, using the Create Bulk Users component as an example.

1. Web-tier web script

Technically, this is the only required part of the component. The component is bound into the application via this web script, which must be declared as a member of the admin-console family within its .desc.xml file. It should also define a single, unique URL, have a unique path and provide a HTML template to render the component's UI.

The following XML is from the descriptor file (create-users.get.desc.xml) for the Create Bulk Users component, which should illustrate this.


   <shortname>Admin Console Create Users</shortname>

   <description>Administration Console - Create Users Console</description>




Although it's obviously possible to provide a JavaScript controller for the web script, it's normally not necessary if you're using a client-side module to encapsulate your business logic, as we'll explore in the next section.

A HTML template (create-users.get.html.ftl in this example) is responsible for laying out out the basic skeleton mark-up of the component, including instantiation of any client-side modules being used.

Although technically optional you will normally also need a corresponding .head.ftl template (create-users.get.head.ftl in this example) to include your own basic, custom CSS file as well as any client-side JavaScript files the component requires.

You can see these templates and all other files that make up this web script in the Create Bulk Users source code under config/alfresco/site-webscripts.

2. Client-side component

It's recommended that you use a client-side component for all but the most basic console components, since it will allow you to handle interactions with the user using standard script-based controls and widgets, and in a manner consistent with other admin console components.

Like dashlets that utilise client-side code, your client-side component will normally be defined in a dedicated .js file, which should be part of the static files (in addition to your CSS) supplied with your component.

The component should be defined using the standard Share pattern

  1. Components are JavaScript classes, defined within a specific namespace, which can be instantiated in page components when needed

  2. Components declare a constructor, then extend a base class using YAHOO.extend() and add their own class methods

  3. Component definitions are contained within a function closure

But whereas dashlet classes would typically extend Alfresco.component.Base, admin console components extend Alfresco.ConsoleTool, which adds some additional fields and methods to support multiple panels and the YUI History Manager.

The component constructor is also slightly more complex than for a dashlet component, since to support the panel approach it is necessary to define within the constructor at least one inner panel class, plus an instantiation of each class.

Panels provide different views of a console component, and whereas simple components such as the Create Bulk Users Console have only one panel, it allows more complex components such as the Node Browser to define more than one (in this case one for the search panel and another for the node view panel).

Like the main component, the pattern used to define the panel class is the constuctor + YUI.extend() method, with panels extending the base class Alfresco.ConsolePanelHandler.

Although this might seem complex, once understood, it provides a consistent pattern which can be applied again and again to define as many admin console components as you need.

So wrapping all of this up, the general pattern for admin console client-side components is something like the following, as illustrated for the Create Bulk Users component.

// Ensure Extras namespace exists

if (typeof Extras == 'undefined' || !Extras)


   var Extras = {};


(function() // Function closure



   Extras.ConsoleCreateUsers = function(htmlId) // Component constructor



      FormPanelHandler = function FormPanelHandler_constructor() // Form panel constructor

, 'form');


      YAHOO.extend(FormPanelHandler, Alfresco.ConsolePanelHandler, // Extend Alfresco.ConsolePanelHandler


         onLoad: function onLoad() // Fired on initial panel load






      new FormPanelHandler(); // Instantiate panel instance

      return this;



   YAHOO.extend(Extras.ConsoleCreateUsers, Alfresco.ConsoleTool,


      options: // Console component configurable options




      onReady: function ConsoleCreateUsers_onReady() // Fired when component ready






})(); // End function closure

Much of the code is stripped out here to convey the overall structure. In reality you would have other statements mixed in with the functions above, and all public classes, constructors and methods should be documented with appropriate JSDoc.

To explorer this some more, it's recommended that you take a look at the client-side JavaScript files inside the JavaScript Console and Create Bulk User Console add-ons. You will find these files in the checked-out source code under the directory source/web.

3. Web-tier Spring configuration and message bundle

Most of the strings that appear in the admin console component UI should be externalised in your web script .properties file, and will be accessible from the Freemarker template of the web script via the root-scoped msg() function.

However, the name of your component also appears in the component list on the left hand side of the Admin Console, and since the page component responsible for rendering this does not have access the messages defined in your web script, it is necessary to provide a globally-scoped message bundle to provide some text for a label and a description of our component.

You can define your message bundle in any valid .properties file, but for the sake of convention I normally give mine a unique name and place them in the package alfresco/messages in my configuration. This is the file used for the Create Bulk Users component, which you can find in the source code under config/alfresco/messages/

tool.create-users.label=Create Bulk Users

tool.create-users.description=Create repository users from CSV or JSON data

The message names should comply with this standard structure, with the part between the periods (.) being the same as the name of the console component's web script, minus the method part. Since the name of the web script was create-users.get, the message names required are tool.create-users.label are and tool.create-users.description.

Lastly, a small piece of Spring configuration is needed to bind the message bundle into the application. This file must have a unique name with the suffix -context.xml, and be placed within the package org/springframework/extensions/surf. See the file config/org/springframework/extensions/create-bulk-users-context.xml in the Create Bulk Users source code for an example.

4. Repository components

Lastly, it's likely that your admin console component will require some custom repository logic to perform your administration tasks. Normally this would take the form of one or more repository-tier web scripts, but other components such as a custom data model could also be required.

Fortunately the source directory structure used by the Sample Project in Share Extras (and by the three admin console add-ons) allows these to be placed in the same project, and you will find the repository web script used by the Create Bulk Users component in the source code under config/alfresco/templates/webscripts.


You should now have an idea of the basic parts involved in an admin console components such as the three examples provided by Share Extras, and how they interact with each other.

You can study these examples to help you gain further understanding of how each of the four parts are implemented in practice, by checking out the source code for them. The JavaScript Console and Create Bulk Users examples are the simplest, so start there and look at the Node Browser if you need a multi-panel example.

The Sample Project provides a good skeleton project for you to define your own add-ons. Although the example code provided in it implements a web script, you can easily delete these and add your own files to define an admin console component, based on one of the three examples.

As well as giving you a basic directory structure, the project also gives you an Ant build script that you can use to build, test and distribute your add-on.

If you have any feedback, please leave a comment below.


In the previous two blog posts I've introduced extension module customizations for i18n properties files and JavaScript controllers. In this post I'm going to describe how Spring Surf has been updated to allow FreeMarker templates to be customized through the use of new extensibility directives. These features are currently available in the latest Alfresco Community source and will be available in Alfresco Enterprise 4.0.



Customizing the i18n properties file was relatively trivial to implement because ultimately it becomes a map and is easy to update. Giving additional JavaScript controllers the opportunity to update the template model was also reasonably straightforward. However.... providing the opportunity for extension files to update a FreeMarker template was a much more significant challenge. Essentially the objective was to provide a way of dynamically editing HTML through configuration.


The approach we have taken to solve this problem may not solve all your customization problems immediately, but what we have implemented should pave the way for future extensibility enhancements in later releases. We've also provided an extensibility platform to provide your own solutions to the problem.


Essentially we have changed Spring Surf so that instead of writing templates directly to the output stream we write to an in-memory model and then allow extensions to manipulate that model before it gets flushed to the output stream. The mechanism for updating the model is through the use of new and updated FreeMarker template directives.


Wherever an extensibility directive is used in a bass template it can be manipulated by a corresponding extension file. There are a initial set of actions:


  • remove (completely remove the directive contents from the model)
  • replace (replace the directive contents in the model with something new)
  • before (place a new directive immediately before the target directive contents)
  • after (place new directive contents immediate after the target directive contents)
  • In the current code we provide 2 directives that support extensibility: <@region> and <@markup>.


The <@region> directive was used extensively in previous versions of Alfresco Share to define the Regions into which Component are bound - we have simply updated its implementation to work with the extensibility model. The <@markup> directive model is entirely new and is simply used to demarcate sections of HTML in a template.


In the first 2 blog posts I described how you can add and remove content from Alfresco Share by modifying the Components (and their Sub-Components). This approach relies on their being a Component available that will be bound to a Region in the template.


Using this alternative mechanism makes it possible to add new regions and also completely remove regions to prevent Components from being bound. This is significantly different because it is a much more volatile approach but could be useful in certain circumstances. If you want to remove some content and prevent another module from either restoring or adding to it, you can remove it entirely from the model so that it cannot be changed.



In an earlier blog I demonstrated how to add a new content to an Alfresco Share page by providing an additional Sub-Component as an extension. This could have also been done using a <@region> directive extension.


Enable Surf Bug and click on the Title bar.  Note the 'Template Type' property which in this case is 'org/alfresco/dashboard'. This means that the file we need to extend is 'dashboard.ftl' in the 'org.alfresco' package.


Screen shot showing Surf Bug data for Title on User Dashboard


Update the 'blog-demo.xml' file to add the following module definition:


    <id>Blog Module (Add Region)</id>


Create a file called 'dashboard.ftl' and place it in the package ''. The file should contain the following:


<@region id='additional-content' target='title' action='before' scope='global' />


Note that the package we've added the file to is prefixed by 'alfresco.templates'. This is the source package at which Spring Surf Class Loader starts looking for template files. It is vitally important to include this prefix to your package or your extension won't be found.


We need to create a new Component to bind to our new Region. We're going to be lazy and use the legacy configuration style (although we could use the new style, this way is shorter and suitable for our purposes).


Create a file called 'global.additional-content.xml' and place it in the '' package. The file should contain the following:




Note that we're re-using the same Web Script created in the first extensibility blog. If you haven't completed the tutorial in that blog then the Component won't find the Web Script specified by the <uri> element.


Re-build and re-deploy the JAR and restart the Alfresco Share web server and you should see the additional content.


Screen shot showing customized user dashboard


If you want to test out the other customization operations then you can update the 'dashboard.ftl' as follows:


To place the new content AFTER the title bar:


<@region id='additional-content' target='title' action='after' scope='global' />


To REPLACE the content of the title bar with the new content:


<@region id='additional-content' target='title' action='replace' scope='global' />


To REMOVE the title bar region completely:


<@region id='additional-content' target='title' action='remove' />


<@markup> Directives

At the time of writing there are currently no uses of the <@markup> directive anywhere in Alfresco Share. It's hoped that the Alfresco Community will make suggestions/contributions as to where they would best be added. They can wrap any section of FreeMarker source in either a WebScript or TemplateInstance to identify sections of the template that can be customized. If you have any suggestions then please post to the Community forums.

Filter Blog

By date: By tag: