h1. UI Extension Framework



h1. Overview

Since DMS 2.5, it is possible to extend the *File Explorer* and the *ECM Administration* thanks to the *UI Extension Framework*. Indeed, you can add your own action buttons to the *File Explorer* and/or add your own managers to the *ECM Administration*.

In this tutorial, we will see how to add a new action button to the *File Explorer* but the logical is exactly the same for the managers in the *ECM Administration*.

{note}
For this tutorial, you will need java 5, maven 2 and eclipse
{note}

h1. How to add a new action button to the File Explorer?

h2. Create your UI Action

h3. Create the UI Action class

Create a *pom.xml* file from the following content

{code:xml}
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.exoplatform.ecm.dms.core</groupId>
  <artifactId>exo.ecm.dms.core.portlet.ecm.tutorial.main</artifactId>
  <packaging>jar</packaging>
  <name>UI Extension Framework Tutorial Classes</name>
  <version>trunk</version>
  <url>http://www.exoplatform.org</url>
  <description>UI Extension Framework Tutorial Classes</description>

  <dependencies>
    <dependency>
      <groupId>org.exoplatform.ecm.dms.core</groupId>
      <artifactId>exo.ecm.dms.core.webui.ext</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.exoplatform.ecm.dms.core</groupId>
      <artifactId>exo.ecm.dms.core.portlet.ecm.core.main</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>	
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
        	<source>1.5</source>
        	<target>1.5</target>
        	<optimize>true</optimize>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
{code}

Create the directories ~~src/main/java~~ and launch *mvn eclipse:eclipse*
You can then, launch your eclipse and import this new project

Create a new class called ~~org.exoplatform.ecm.tutorial.MyUIAction~~ that extends ~~org.exoplatform.webui.core.UIComponent~~

1.1.1 Create your ActionListener

The webui framework allows you to be notified when a given action has been triggered, you just need to call your action listener as follow ~~$\{ACTION_NAME}ActionListener~~

So, if you want to call our action ~~MyActionName~~, the listener will be then called ~~MyActionNameActionListener~~.

So first, add a static inner class called ~~MyActionNameActionListener~~ that extends ~~org.exoplatform.ecm.webui.component.explorer.control.listener.UIActionBarActionListener<MyUIAction>~~

See below the expected code

{code:java}
public static class MyActionNameActionListener extends UIActionBarActionListener<MyUIAction> {
	@Override
	protected void processEvent(Event<MyUIAction> event) throws Exception {
		System.out.println("MyActionName of the component MyUIAction has been triggered!!");
	}		
}
{code}

{info}
The UIActionBarActionListener is the super class of all the ActionListeners related to the action bar, this class sets internaly the context of an action button
{info}

Then, define the action listener at the class definition level with the webui annotations as below:

{code:java}
@ComponentConfig(
     events = {
       @EventConfig(listeners = MyUIAction.MyActionNameActionListener.class)
     }
 )
public class MyUIAction extends UIComponent {
{code}

1.1.1 Deploy your Action

Launch *mvn clean install* and copy the file ~~target/exo.ecm.dms.core.portlet.ecm.tutorial.main-trunk.jar~~ into ~~$\{TOMCAT_HOME}/webapps/ecm/WEB-INF/lib~~



1.1 Register your UI Action

To register your action, you need to create a dedicated project that will manage the configuration

1.1.1 Create the configuration file

Create a *pom.xml* file from the following content

{code:xml}
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.exoplatform.ecm.dms.core</groupId>
  <artifactId>exo.ecm.dms.core.portlet.ecm.tutorial.config</artifactId>
  <packaging>jar</packaging>
  <name>UI Extension Framework Tutorial Config</name>
  <version>trunk</version>
  <url>http://www.exoplatform.org</url>
  <description>UI Extension Framework Tutorial Config</description>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
    </resources>
  </build>
</project>
{code}

Create the directories _src/main/java_ and launch *mvn eclipse:eclipse*
You can then, launch your eclipse and import this new project

Create a new configuration file _conf/portal/configuration.xml_ to register your action with the service _org.exoplatform.webui.ext.UIExtensionManager_, as below:
{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>
<configuration>
  <external-component-plugins>
    <!- The full qualified name of the UIExtensionManager that manages all the UI Extensions ->
    <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
    <component-plugin>
      <name>add.action</name>
      <!- The method to call to register a new UI Extension ->
      <set-method>registerUIExtensionPlugin</set-method>
      <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
      <init-params>
        <object-param>
          <name>MyActionName</name>
          <object type="org.exoplatform.webui.ext.UIExtension">
            <!- The type of extension, here it is the type related to the Action Bar in the File Explorer ->
            <field name="type"><string>org.exoplatform.ecm.dms.UIActionBar</string></field>
            <!- The name of your action ->
            <field name="name"><string>MyActionName</string></field>
            <!- The full qualified name of your webui component ->
            <field name="component"><string>org.exoplatform.ecm.tutorial.MyUIAction</string></field>
          </object>
        </object-param>
      </init-params>
    </component-plugin>
  </external-component-plugins>
</configuration>
{code}

1.1.1 Deploy the configuration file

Launch *mvn clean install* and copy the file ~~target/exo.ecm.dms.core.portlet.ecm.tutorial.config-trunk.jar~~ into ~~$\{TOMCAT_HOME}/lib~~

1.1 Define a label and an icon for your action

1.1.1 Define a label in ECM Administration

Edit the file ~~$\{TOMCAT_HOME}/webapps/ecm/WEB-INF/classes/locale/portlet/ecm/ECMAdminPortlet_en.xml~~ (for english which is also the default language) and add the label as below:

{code:xml}
...
  <UIViewFormTabPane>
    ...
    <label>
      <myActionName>My Action Name</myActionName>
    ...
    </label>
    ...
  </UIViewFormTabPane>
...
{code}

h3. Define a label in the File Explorer

Edit the file _$\{TOMCAT_HOME}/webapps/ecm/WEB-INF/classes/locale/portlet/ecm/JCRExplorerPortlet_en.xml_ (for english which is also the default language) and add the label as below:

{code:xml}
...
  <UIActionBar>
    ...
    <tooltip>
      <MyActionName>My Action Name</MyActionName>
    ...
    </tooltip>
    ...
  </UIActionBar>
...
{code}

1.1.1 Define a logo

Edit the file ~~$\{TOMCAT_HOME}/webapps/ecm/skin/icons/24x24/DefaultStylesheet.css~~ (for the default Skin) and add the icon definition as below (in this case, we re-use the "Add Document" icon but you could add your own picture into the directory ~~$\{TOMCAT_HOME}/webapps/ecm/skin/icons/24x24/DefaultSkin~~):

{code:css}
...
.MyActionNameIcon {
  height: 24px;
  background: url('DefaultSkin/AddDocument.gif') no-repeat;
}
...
{code}
h2. Test your Action

* Launch tomcat
* Sign in as root
* Go to the *ECM Administration*
* Choose _Manage View_
* Edit the _admin-view_
* Select the tab _actions_
* Check the you action _My Action Name_ in the list
!EditView.png|height=450!
* Save the Tab change
* Save the View change
* Sign out/Sign in to force the reload of your *File Explorer*
* Go to the *File Explorer*
* Choose the drive _Collaboration Center_
* Select the tab _Actions_

You should see your action, you can then click on your button and see the message "MyActionName of the component MyUIAction has been triggered!!" in your log trace.

!ActionBar.png!



h1. How to filter an UI Extension?

h2. Filters Overview

In the UI Extension framework, you can use internal and external filters. The internal filters are part of the business logic of your component, for example if your component is only dedicated to articles, you will add an internal filter to your component that will check the type of the current document. The external filters are mainly used to add new filters that are not related to the business logic, to your component, a good example is the UserACLFilter which allows you to filter by access permissions.

For each filter, you must set its type. The types are defined in the interface _org.exoplatform.webui.ext.filter.UIExtensionFilterType_

{code:java}
public enum UIExtensionFilterType {

  /**
   * This type of filter will be used to know if the
   * action related to the extension can be launched
   * and to know if the component related to the
   * extension can be added to the webui tree
   * The filter is required to launch the action and
   * to add the component related to the extension
   * to the webui tree.
   * If it succeeds, we will check the other filters.
   * If it fails, we will stop.
   */
  MANDATORY,
  /**
   * This type of filter will be used to know if the
   * action related to the extension can be launched.
   * The filter is required to launch the action.
   * to the webui tree.
   * If it succeeds, we will check the other filters.
   * If it fails, we will stop.
   */
  REQUISITE,
  /**
   * This type of filter will only be used to know if the
   * action related to the extension can be launched.
   * The filter is required to launch the action.
   * If it succeeds or fails, we will check the other filters.
   * It can be used to add warnings
   */
  REQUIRED,
  /**
   * This type of filter will only be used to know if the
   * action related to the extension can be launched.
   * The filter is not required to launch the action.
   * If it succeeds or fails, we will check the other filters.
   * It can be used for auditing purpose
   */
  OPTIONAL
}
{code}



1.1 Add an internal Filter

Let's add a MANDATORY filter to our component that will check if the document is of type ~~exo:article~~.

First create a new class called ~~org.exoplatform.ecm.tutorial.MyUIFilter~~ that implements ~~org.exoplatform.webui.ext.filter.UIExtensionFilter~~

See below the code of our example

{code:java}
public class MyUIFilter implements UIExtensionFilter {

	/**
	 * This method checks if the current node is of the right type
	 */
	public boolean accept(Map<String, Object> context) throws Exception {
		// Retrieve the current node from the context
	    Node currentNode = (Node) context.get(Node.class.getName());
		return currentNode.isNodeType("exo:article");
	}

	/**
	 * This is the type of the filter
	 */
	public UIExtensionFilterType getType() {
		return UIExtensionFilterType.MANDATORY;
	}

	/**
	 * This is called when the filter has failed
	 */
	public void onDeny(Map<String, Object> context) throws Exception {
		System.out.println("This document has been rejected");
	}
}
{code}

{info}
In this example, the filter directly implements UIExtensionFilter but it can be very helpful to extend the class org.exoplatform.webui.ext.filter.UIExtensionAbstractFilter because it provides you the methods createUIPopupMessages that adds messages to the UIPopup Window
{info}

{info}
The context that you get in the accept method, has been set by the class UIActionBarActionListener, in this context you can find the UIActionBar, the UIJCRExplorer, the UIApplication, the WebuiRequestContext and the Node of the current context
{info}

Once done, you just need to assign this filter to our component by using the annotation _org.exoplatform.webui.ext.filter.UIExtensionFilters_ as below

{code:xml}
public class MyUIAction extends UIComponent {

    private static final List<UIExtensionFilter> FILTERS = Arrays.asList(new UIExtensionFilter[] {new MyUIFilter()});

	@UIExtensionFilters
	public List<UIExtensionFilter> getFilters() {
		return FILTERS;
	}
...
{code}

Launch *mvn clean install* and copy the file ~~target/exo.ecm.dms.core.portlet.ecm.tutorial.main-trunk.jar~~ into ~~$\{TOMCAT_HOME}/webapps/ecm/WEB-INF/lib~~

You can now check that your action only appears when you select an article.


1.1 Add an external Filter

If you want for example, that you action is only available for the managers of the group ~~platform/administrators~~, you just need to change the configuration file as below:

{code:xml}
...
<!-- The external filters -->
<field name="extendedFilters">
	<collection type="java.util.ArrayList">
		<value>									
			<object type="org.exoplatform.webui.ext.filter.impl.UserACLFilter">
				<field name="permissions">
					<collection type="java.util.ArrayList">
						<value>
							<string>manager:/platform/administrators</string>
						</value>
					</collection>
				</field>
			</object>
		</value>
	</collection>
</field>
...
{code}

Launch *mvn clean install* and copy the file _target/exo.ecm.dms.core.portlet.ecm.tutorial.config-trunk.jar_ into _$\{TOMCAT_HOME}/lib_

You can now check that your action only appears when the current user is a manager of the group _platform/administrators_.

!FinalResult.png!

{info}
The entire projects have been attached to this wiki article
{info}
