Actions, Views, Navigation URLs and JSF tags

Table of Contents

7.1. Introduction
7.2. Actions
7.2.1. Concepts
7.2.2. Manage actions
7.3. Views
7.3.1. UI Views
7.3.2. Manage views
7.4. Navigation URLs
7.4.1. Document view codec service
7.4.2. URL policy service
7.4.3. Additional configuration
7.4.4. URL JSF tags
7.5. Nuxeo Document Lists Manager
7.6. Nuxeo File Manager
7.7. Nuxeo JSF tags

7.1. Introduction

The User Interface framework uses different kinds of concepts to make the interface configurable in the same way that the application itself is.

Links and pages that appear on the site can be the result of a "static" template written in the XHTML language, but can also be the result of a configuration change, taken into account thanks to more "generic" XHTML pages.

The following chapters will explain how configuration and templating combine to achieve the UI of the site.

7.2. Actions

7.2.1. Concepts

In this chapter, an action will stand for any kind of command that can be triggered via user interface interaction. In other words, it will describe a link and other information that may be used to manage its display (the link label, an icon, security information for instance).

7.2.2. Manage actions

Custom actions can be contributed to the actions service, using its extension point. Their description is then available through this service to control where and how they will be displayed.

7.2.2.1. Register a new action

An action can be registered using the following example extension:

<extension target="org.nuxeo.ecm.platform.actions.ActionService"
    point="actions">

  <action id="logout" link="#{loginLogoutAction.logout}"
    label="command.logout">
    <category>USER_SERVICES</category>
  </action>

</extension>

Example 7.1. Example of an action registration


The above action will be used to display a "logout" link on the site. Here are its properties:

  • id: string identifying the action. In the example, the action id is "logout".

  • label: the action name that will be used when displaying the link. In the example, the label is "command.logout". This label is a message that will be translated at display.

  • link: string representing the command the action will trigger. This string may represent a different action given the template that will display the action. In the example, a JSF command link will be used, so it represents an action method expression. The seam component called "loginLogoutAction" holds a method named "logout" that will perform the logout and return a string for navigation.

  • category: a string useful to group actions that will be rendered in the same area of a page. An action can define several categories. Here, the only category defined is "USER_SERVICES". It is designed to group all the actions that will be displayed on the right top corner of any page of the site.

Other properties can be used to define an action. They are listed here but you can have a look at the main actions contributions file for more examples: nuxeo-platform-webapp-core/srs/main/resources/OSGI-INF/actions-contrib.xml.

  • filter-ids: id of a filter that will be used to control the action visibility. An action can have several filters: it is visible if all its filters grant the access.

  • filter: a filter definition can be done directly within the action definition. It is a filter like others and can be referred by other actions.

  • icon: the optional icon path for this action.

  • confirm: an optional Javascript confirmation string that can be triggered when executing the command.

  • order: an optional integer used to sort actions within the same category. This attribute may be deprecated in the future.

  • enabled: boolean indicating whether the action is currently active. This can be used to hide existing actions when customizing the site behavior.

Actions extension point provides merging features: you can change an existing action definition in your custom extension point provided you use the same identifier. Properties holding single values (label, link for instance) will be replaced using the new value. Properties holding multiple values (categories, filters) will be merged with existing values.

7.2.2.2. Manage category to display an action at the right place

Actions in the same category are supposed to be displayed in the same area of a page. Here are listed the main default categories if you want to add an action there:

  • USER_SERVICES: used to display actions in the top right corner of every page. The link attribute should look like a JSF action command link. See the example above.

  • VIEW_ACTION_LIST: used for tabs displayed on every document. As each tab is not displayed in a different page, but just includes a specific template content in the middle of the page, the link attribute has to be a template path. For instance:

    <action id="TAB_VIEW" link="/incl/tabs/document_view.xhtml" enabled="true"
        order="0" label="action.view.summary">
      <category>VIEW_ACTION_LIST</category>
      <filter-id>view</filter-id>
    </action>
    
    <action id="TAB_CONTENT" link="/incl/tabs/document_content.xhtml" order="10"
        enabled="true" label="action.view.content">
      <category>VIEW_ACTION_LIST</category>
      <filter-id>view_content</filter-id>
    </action>
  • SUBVIEW_UPPER_LIST: used to display actions just below a document tabs listing. As USER_SERVICES, these actions will be displayed using a command link, so the link attribute has to be an action method expression. For instance:

    <action id="newSection" link="#{documentActions.createDocument('Section')}"
        enabled="true" label="command.create.section"
        icon="/icons/action_add.gif">
      <category>SUBVIEW_UPPER_LIST</category>
      <filter id="newSection">
        <rule grant="true">
          <permission>AddChildren</permission>
          <type>SectionRoot</type>
        </rule>
      </filter>
    </action>
    
    <action id="newDocument" link="select_document_type" enabled="true"
        label="action.new.document" icon="/icons/action_add.gif">
      <category>SUBVIEW_UPPER_LIST</category>
      <filter-id>create</filter-id>
    </action>

7.2.2.3. Manage filters to control an action visibility

An action visibility can be controlled using filters. An action filter is a set of rules that will apply - or not - given an action and a context.

Filters can be registered using their own extension point, or registered implicitly when defining them inside of an action definition:

<filter id="view_content">
  <rule grant="true">
    <permission>ReadChildren</permission>
    <facet>Folderish</facet>
  </rule>
  <rule grant="false">
    <type>Root</type>
  </rule>
</filter>

Example 7.2. Example of a filter registration


<action id="newSection" link="#{documentActions.createDocument('Section')}"
    enabled="true" label="command.create.section"
    icon="/icons/action_add.gif">
  <category>SUBVIEW_UPPER_LIST</category>
  <filter id="newSection">
    <rule grant="true">
      <permission>AddChildren</permission>
      <type>SectionRoot</type>
    </rule>
  </filter>
</action>

Example 7.3. Example of a filter registration inside an action registration


A filter can accept any number of rules. It will grant access to an action if, among its rules, no denying rule (grant=false) is found and at least one granting rule (grant=true) is found. A general rule to remember is that if you would like to add a filter to an action that already has one or more filters, it has to hold constraining rules: a granting filter will be ignored if another filter is already too constraining.

If no rule is set, the filter will grant access by default.

The default filter implementation uses filter rules with the following properties:

  • grant: boolean indicating whether this is a granting rule or a denying rule.

  • permission: permission like "Write" that will be checked on the context for the given user. A rule can hold several permissions: it applies if user holds at least one of them.

  • facet: facet like "Folderish" that can be set on the document type (org.nuxeo.ecm.core.schema.types.Type) to describe the document type general behavior. A rule can hold several facets: it applies if current document in context has at least one of them.

  • condition: EL expression that can be evaluated against the context. The Seam context is made available for conditions evaluation. A rule can hold several conditions: it applies if at least one of the conditions is verified.

  • type: document type to check against current document in context. A rule can hold several types: it applies if current document is one of them. The fake 'Server' type is used to check the server context.

  • schema: document schema to check against current document in context. A rule can hold several schemas: it applies if current document has one of them.

  • group: group like "members" to check against current user in context. A rule can hold several groups: it applies if current user is in one of them.

Filters do not support merging, so if you define a filter with an id that is already used in another contribution, only the first contribution will be taken into account.

7.2.2.4. Adapt templates to display an action

It is important to understand that an action does *not* define the way it will be rendered: This is left to pages, templates and other components displaying it. Most of the time, actions will be rendered as command links or command buttons.

For instance, actions using the USER_SERVICES category will be rendered as action links:

<nxu:methodResult name="actions"
    value="#{webActions.getActionsList('USER_SERVICES')}">
  <nxu:dataList layout="simple" var="action" value="#{actions}"
    rowIndexVar="row" rowCountVar="rowCount">
    <h:outputText value=" | " rendered="#{row!=(rowCount-1)}" />
    <nxh:commandLink action="#{action.getLink()}">
      <t:htmlTag value="br" rendered="#{row==(rowCount-1)}" />
      <h:outputText value="#{messages[action.label]}" />
    </nxh:commandLink>
  </nxu:dataList>
</nxu:methodResult>

The nxu:methodResult tag is only used to retrieve the list of actions declared for the USER_SERVICES category. The nxh:commandLink is used instead of a simple h:commandLink so that it executes commands that where described as action expression methods.

Another use case is the document tabs: actions using the VIEW_ACTION_LIST category will be rendered as action links too, but actions are managed by a specific seam component that will hold the information about the selected tab. When clicking on an action, this selected tab will be changed and the link it points to will be displayed.

7.3. Views

7.3.1. UI Views

First of all, we have to make the difference between a view in a standard JSF way (navigation case view id, navigation case output) and views in Nuxeo 5 (document type view, creation view)

7.3.2. Manage views

7.3.2.1. Standard JSF navigation concepts

A standard JSF navigation rule can be defined in the OSGI-INF/deployment-fragment.xml files, inside the faces-config#NAVIGATION directive.

<extension target="faces-config#NAVIGATION">

    <navigation-case>
      <from-outcome>create_document</from-outcome>
      <to-view-id>/create_document.xhtml</to-view-id>
      <redirect />
    </navigation-case>

    <navigation-case>
      <from-outcome>view_documents</from-outcome>
      <to-view-id>/view_documents.xhtml</to-view-id>
      <redirect />
    </navigation-case>

</extension>

Example 7.4. Example of a navigation rule case definitions


7.3.2.2. Nuxeo 5 views

A certain Nuxeo document type, can have defined a default view (used to view/edit the document) and a create view (used to create the document). These views are specified in the OSGI-INF/ecm-types-contrib.xml file, as in the following example.

<extension target="org.nuxeo.ecm.platform.types.TypeService" point="types">    
    <type id="Workspace" coretype="Workspace">
      <label>Workspace</label>
      <icon>/icons/workspace.gif</icon>
      <icon-expanded>/icons/workspace_open.gif</icon-expanded>
      <default-view>view_documents</default-view>
      <create-view>create_workspace</create-view>
    </type>
</extension>

Example 7.5. Example of view definitions for a document type


The default view of a document is rendered as a list of tabs. As mentioned before, the document tabs are defined as actions in the OSGI-INF/actions-contrib file, having as category VIEW_ACTION_LIST. A tab can be added to a document default view as shown in the following example.

<extension target="org.nuxeo.ecm.platform.actions.ActionService" point="actions">   
    <action id="TAB_EDIT" link="/incl/tabs/document_edit.xhtml" enabled="true"
      order="20" label="action.view.edit" icon="/icons/file.gif">
      <category>VIEW_ACTION_LIST</category>
      <filter-id>edit</filter-id>
      <filter-id>mutable_document</filter-id>
    </action>
</extension>

Example 7.6. Example of tab definition for a default view of a document type


7.4. Navigation URLs

There are two services that help building GET URLs to restore a Nuxeo context. The default configuration handle restoring the current document, the view, current tab and current sub tab.

7.4.1. Document view codec service

The service handling document views allows registration of codecs. Codecs manage coding of a document view (holding a document reference, repository name as well as key-named string parameters) in to a URL, and decoding of this URL into a document view.

<extension
  target="org.nuxeo.ecm.platform.url.service.DocumentViewCodecService"
  point="codecs">

  <documentViewCodec name="docid" enabled="true" default="true" prefix="nxdoc"
    class="org.nuxeo.ecm.platform.url.codec.DocumentIdCodec" />
  <documentViewCodec name="docpath" enabled="true" default="false" prefix="nxpath"
    class="org.nuxeo.ecm.platform.url.codec.DocumentPathCodec" />

</extension>

Example 7.7. Example of a document view codec registration


In this example, the docid codec uses the document uid to resolve the context. Urls are of the form http://site/nuxeo/nxdoc/demo/docuid/view. The docpath codec uses the document path to resolve the context. Urls are of the form http://site/nuxeo/nxpath/demo/path/to/my/doc@view.

Additional parameters are coded/decoded as usual request parameters.

Note that when building a document view, the url service will require a view id. The other information (document location and parameters) are optional, as long as they're not required for your context to be initialized correctly.

7.4.2. URL policy service

The service handling URLs allows registration of patterns. These patterns help saving the document context and restoring it thanks to information provided by codecs. The URL service will iterate through its patterns, and use the first one that returns an answer (proving decoding was possible).

<extension target="org.nuxeo.ecm.platform.ui.web.rest.URLService"
  point="urlpatterns">

  <urlPattern name="default" enabled="true">
    <defaultURLPolicy>true</defaultURLPolicy>
    <needBaseURL>true</needBaseURL>
    <needRedirectFilter>true</needRedirectFilter>
    <needFilterPreprocessing>true</needFilterPreprocessing>
    <codecName>docid</codecName>
    <actionBinding>#{restHelper.initContextFromRestRequest}</actionBinding>
    <documentViewBinding>#{restHelper.documentView}</documentViewBinding>
    <newDocumentViewBinding>#{restHelper.newDocumentView}</newDocumentViewBinding>
    <bindings>
      <binding name="tabId">#{webActions.currentTabId}</binding>
      <binding name="subTabId">#{webActions.currentSubTabId}</binding>
    </bindings>
  </urlPattern>

</extension>

Example 7.8. Example of a url pattern registration


In this example, the "default" pattern uses the above "docid" codec. Its is set as the default URL policy, so that it's used by default when caller does not specify a pattern to use. It needs the base URL: the docid codec only handles the second part if the URL. It needs redirect filter: it will be used to provide the context information to store. It needs filter preprocessing: it will be used to provide the context information to restore. It's using the docid codec.

The action binding method handles restoring of the context in the Seam context. It takes a document view as parameter. It requires special attention: if you're using conversations (as Nuxeo does by default), you need to annotate this method with a "@Begin" tag so that it uses the conversation identifier passed as a parameter if it's still valid, or initiates a new conversation in other cases. The method also needs to make sure it initializes all the seam components it needs (documentManager for instance) if they have not be in intialized yet.

The additional document view bindings are used to pass document view information through requests. The document view binding maps to corresponding getters and setters. The new document view binding is used to redirect to build GET URL in case request is a POST: it won't have the information in the URL so it needs to rebuild it.

Other bindings handle additional request parameters. In this example, they're used to store and restore tab and sub tab information (getters and setters have to be defined accordingly).

7.4.3. Additional configuration

The URL patterns used need to be registered on the authentication service so that they're considered as valid urls. Valid urls will be stored in the request, so that if authentication is required, user is redirected to the url after login.

<extension
  target="org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService"
  point="startURL">

  <startURLPattern>
    <patterns>
      <pattern>nxdoc/</pattern>
    </patterns>
  </startURLPattern>

</extension>

Example 7.9. Example of a start url pattern registration


Just the start of the url is required in this configuration. Contributions are merged: it is not possible to remove an existing start pattern.

The URL patterns used also need to be handled by the default nuxeo authentication service so that login mechanism (even for anonymous) applies for them.

<extension target="web#STD-AUTH-FILTER">
  <filter-mapping>
    <filter-name>NuxeoAuthenticationFilter</filter-name>
    <url-pattern>/nxdoc/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
  </filter-mapping>
</extension>

Example 7.10. Example authentication filter configuration


This is a standard filter mapping configuration.

7.4.4. URL JSF tags

There are some JSF tags and functions helping you to define what kind of GET URL should be displayed on the interface.

<nxd:restDocumentLink document="#{doc}">
  <nxh:outputText value="#{nxd:titleOrId(doc)}" />
</nxd:restDocumentLink>

Example 7.11. Example of nxd:restDocumentLink use


In this example, the tag will print a simple link, using the default pattern, and build the document view using given document model, using its default view.

Please refer to the tag library documentation available at http://doc.nuxeo.org/5.1/tlddoc/nxd/restDocumentLink.html for additional parameters: it's possible to set the tab, sub tab, and use a specific URL pattern.

Note that you can also use JSF functions to build the GET URL. This is what's done for file links: the function queries the URL policy service to build the URL.

<nxh:outputLink rendered="#{doc.hasSchema('file') and !empty doc.file.content}"
  value="#{nxd:fileUrl('downloadFile', doc, 'file:content', doc.file.filename)}">
  <nxh:graphicImage value="/icons/download.png" style="vertical-align:middle"
    title="#{doc.file.filename}" />
</nxh:outputLink>

Example 7.12. Example of a jsf function use


public static String fileUrl(String patternName, DocumentModel doc,
        String blobPropertyName, String filename) {
    try {
        DocumentLocation docLoc = new DocumentLocationImpl(doc);
        Map<String, String> params = new HashMap<String, String>();
        params.put(DocumentFileCodec.FILE_PROPERTY_PATH_KEY,
                blobPropertyName);
        params.put(DocumentFileCodec.FILENAME_KEY, filename);
        DocumentView docView = new DocumentViewImpl(docLoc, null, params);

        // generate url
        URLPolicyService service = Framework.getService(URLPolicyService.class);
        if (patternName == null) {
            patternName = service.getDefaultPatternName();
        }
        return service.getUrlFromDocumentView(patternName, docView,
                BaseURL.getBaseURL());

    } catch (Exception e) {
        log.error("Could not generate url for document file", e);
    }

    return null;
}

Example 7.13. fileUrl method code


Similar methods exist for more complex urls, when handling files in list for instance. Please refer to the list at http://doc.nuxeo.org/5.1/tlddoc/nxd/tld-summary.html.

7.5. Nuxeo Document Lists Manager

The Document List Manager provides a service to manage lists of Nuxeo documents.

These lists of documents can have properties such as:

  • a name, defined by name attribute.

  • a scope (session or conversation), defined by <isSession/> tag - it defines if the memory storage occurs in the Seam session context or in the Seam conversation context.

  • a persistence (SQL directory or not present), defined by <persistent/> tag - the service persists only the list of the document references, not the real documents; the lists of document references is persisted in a SQL directory, which is generic and does not need any configuration.

The lists of documents can be invalidated when Seam events are raised. This is usefull, for example, for resetting CURRENT_SELECTION lists when the user change the current folder or when a new search is performed.

Documents lists can be defined like in the following example (OSGI-INF/documentslists-contrib.xml):

<extension target="org.nuxeo.ecm.webapp.documentsLists.DocumentsListsService" point="list">  
    <documentsList name="CLIPBOARD">
      <category>CLIPBOARD</category>
      <imageURL>/img/clipboard.gif</imageURL>
      <title>workingList.clipboard</title>
      <defaultInCategory>false</defaultInCategory>
      <supportAppends>false</supportAppends>
    </documentsList>

    <documentsList name="CURRENT_SELECTION">
      <events>
        <event>folderishDocumentSelectionChanged</event>
        <event>searchPerformed</event>
      </events>
      <isSession>false</isSession>
    </documentsList>
</extension>

Example 7.14. Example of documents lists definition


7.6. Nuxeo File Manager

The File Manager provides a service which exposes a simple API in order to create a Nuxeo document model from a passed blob file. Also, this service exposes as extension point which can be used to define plugins.

When the File Manager service is called, it will detect the mime-type of the passed blob, and will try to find a plugin to hadle the creation of a Nuxeo document model based on the detected mime-type.

Typical usages:

  • txt/html/xml files - a Note document is created.

  • image files - a Picture document is created (if nuxeo-platform-imaging addon is deployed).

  • folder - a Folder document is created.

  • other files - a File document is created.

Pugins can be defined like in the following example (OSGI-INF/nxfilemanager-plugins-contrib.xml):

<extension target="org.nuxeo.ecm.platform.filemanager.service.FileManagerService" point="plugins">  
    <plugin name="Noteplugin"
      class="org.nuxeo.ecm.platform.filemanager.service.extension.NotePlugin">
      <filter>text/plain</filter>
      <filter>text/html</filter>
      <filter>application/xhtml+xml</filter>
      <filter>application/xml</filter>
      <filter>text/xml</filter>
    </plugin>
</extension>

Example 7.15. Example of File Manager plugins definition


As a client of the File Manager service can be used the browser plugins (for Firefox and Internet Explorer) which can be be downloaded through the links from the default Nuxeo 5 login page. These plugins enable the user to create Nuxeo documents just by dragging & dropping folders/files to the browser. The plugins use a restlet (HTTP API) to send files/folders to the Nuxeo 5 Platform. The restlets use the File Manager serivce in order to create a Nuxeo document from the passed file.

7.7. Nuxeo JSF tags

Please refer to the tag library documentation available at http://doc.nuxeo.org/5.1/tlddoc/.