JSF UI Framework

JSF Page Layout System Overview

Updated: July 17, 2023

A Nuxeo Platform page is made up of several layers:

  • Nuxeo Theme (aka NXTheme)

    • Defines a page level layout (slots)
    • Defines CSS resources
  • XHTML/facelet

    • Fills the NXTheme slots
    • Uses Nuxeo Tags to render Layouts, Widgets, Actions
  • Layouts/Widgets/Actions
    • This is the application meta-model
    • This is the part that is configured via Nuxeo Studio

Here is a very quick walk-through of the main principles with some examples and links to code or documentation.

Nuxeo Theme

The Nuxeo Theme is a page layout engine that also handles resources management. See the page Theme for a general introduction. A part of the theme definition can be configured via Nuxeo Studio (the CSS and Flavor part).

As any other Nuxeo component, the Theme system uses extension points to define:

  • pages: Define what slots should be available in the page
  • styles: Define CSS styles
  • flavors: Define variables used in CSS
  • resources: Define JavaScript to be injected in the page

Let's see how Document Management and Digital Asset Management pages as examples.

Document Management Pages

The Document Management pages are using a Theme page layout defined in the document.xml definition.

nxMainContainer has two columns (i.e. <cell>):

  • The first column contains three slots (i.e. <fragment>).
  • The second column contains two slots (i.e. <fragment>).

The slots themselves (called view in NXTheme) are defined in the theme-contrib:

<view name="nuxeo5 tree explorer" template-engine="jsf-facelets">
  <format-type>widget</format-type>
  <template>incl/multi_tree_explorer.xhtml</template>
</view>

This extract shows you were to find the XHTML code corresponding to the tree explorer: The view nuxeo5 tree explorer is defined as incl/multi_tree_explorer.xhtml.

This view is referenced in the document.xml theme file via:

<widget element="page[1]/section[2]/cell[1]/fragment[2]">
  <view>nuxeo5 tree explorer</view>
</widget>

The XPath indicates what part of the page layout will be used to display the tree explorer.

<!-- tree view -->
<fragment perspectives="default,multiple_domains" type="generic fragment"/>

Digital Asset Management Pages

For Nuxeo DAM (and the current search view), the theme only defines the headers and footer. The actual content of the main slot will be handled by the application layer.

  • nuxeo-dam theme only defines a nxMainContainer that will be structured via layouts.
  • There is no specific view (structure of the nxMainContainer will be done via XHTML).

XHTML/Facelets

The XHTML Facelet templates are rendered through the Theme Engine. The XHTML calls the theme engine via the NXTheme composition page:

<nxthemes:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:nxthemes="http://nuxeo.org/nxthemes"
    xmlns:nxl="http://nuxeo.org/nxforms/layout">

  <ui:define name="page title">
    <h:outputText value="#{nuxeoApplicationName} - #{messages['label.main.tab.dam']}" />
  </ui:define>

  <ui:define name="body">
    <ui:include src="/incl/message_banner.xhtml"/>
    <nxl:layout value="#{currentDocument}" name="gridDamSingleAssetLayout" mode="view" />
  </ui:define>
</nxthemes:composition>

Document Management Example

See the sample DM view_documents.xhtml.

The main content of the page is actually defined via facelet templating (i.e. using native facelet composition engine to include and templatize)

<!--Document header -->  <h:form id="document_header_layout_form" class="titleBlock">
    <nxl:documentLayout documentMode="header" mode="view"
      value="#{currentDocument}" defaultLayout="document_header"
      includeAnyMode="false" />
  </h:form>

  <!-- buttons displayed in the upper right corder -->
  <ui:include src="/incl/document_actions_upperbuttons.xhtml"/>
  <ui:include src="/incl/message_banner.xhtml"/>

  <!-- widget to display the tabs-->
  <nxl:widget name="documentTabs" mode="view" value="#{currentDocument}" />

Digital Asset Management Example

See the sample DAM asset.xhtml.

Content is defined by a GridLayout:

<nxl:layout value="#{currentDocument}" name="gridDamSingleAssetLayout" mode="view" />

Layout / Widgets / Actions

This is the very core of the Nuxeo application level model: that's the part that is defined inside Nuxeo Studio.

There is plenty of documentation about this:

You can also use the Layout Showcase site.

Let's continue with the previous example pages for DM and DAM.

Digital Asset Management Pages

For DAM, the main layout is dam-layouts-contrib.xml, it defines:

  • Some widgets
  • The gridDamSingleAssetLayout that itself defines two columns:
    • The damSingleAssetPanelLeft widget
    • The damSingleAssetPanelRight widget

Both widgets are of type documentAction meaning they use the action system to resolve what are the subwidgets.

We use this Widget/Action association to provide a way to have Incremental Layouts: the idea being that the content of the screen is the result of the aggregation of:

  • What is contributed by the deployed plugin If workflow is deployed you will have some WF related information displayed.
  • What is contributed by your Studio configuration

Using that principle, the damSingleAssetPanelLeft will display all widgets associated to the action category DAM_SINGLE_ASSET_PANEL_LEFT: you will find 10 of them in the same dam-layouts-contrib.xml contribution file, each of them being displayed according to the type of content.

...
 <action id="damAssetViewTitle" type="widget" order="200">
  <category>DAM_PANEL_RIGHT</category>
  <category>DAM_SINGLE_ASSET_PANEL_LEFT</category>
  <properties>
    <property name="widgetName">damAssetViewTitle</property>
  </properties>
  <filter-id>hasAssetFacet</filter-id>
</action>

<action id="damAssetViewThumbnail" type="widget" order="250">
  <category>DAM_PANEL_RIGHT</category>
  <category>DAM_SINGLE_ASSET_PANEL_LEFT</category>
  <properties>
    <property name="widgetName">damAssetViewThumbnail</property>
  </properties>
  <filter-id>hasNotVideoFacet</filter-id>
  <filter-id>hasNotPictureFacet</filter-id>
  <filter-id>hasNotAudioFacet</filter-id>
  <filter-id>hasAssetFacet</filter-id>
</action>
...

Document Management Pages

For Document Management pages, a similar system is used to contribute the part of screens.

The documentTabs widget will display the tabs defined as actions contrib.

...
<action id="TAB_VIEW" link="/incl/tabs/document_view.xhtml" order="0"
  label="action.view.summary" icon="/icons/file.gif" accessKey="v"
  type="rest_document_link">
  <category>VIEW_ACTION_LIST</category>
  <filter-id>view</filter-id>
  <properties>
    <property name="ajaxSupport">true</property>
  </properties>
</action>

<action id="TAB_CONTENT" link="/incl/tabs/document_content.xhtml"
  order="10" label="action.view.content" icon="/icons/file.gif" accessKey="c"
  type="rest_document_link">
  <category>VIEW_ACTION_LIST</category>
  <filter-id>view_content</filter-id>
  <properties>
    <property name="ajaxSupport">true</property>
  </properties>
</action>
...

Each of these tab is associated with a XHTML, that itself will also use layouts and widgets. If we take the documentView.xhml that corresponds to the default Summary tab in the platform we see that it takes the "summary" layouts defined for the type of document being currently displayed. The widgets and different possible layouts are defined on the layouts-summary-contrib.xml. By default unless defined otherwise all summary layout use grid_summary_layout.

However, looking at the type to layout configuration you can see that each document type can be associated with different layout and that there are several categories of layout.

Seam and Navigation

So far we have defined view level components. These views will need to get some data from the Nuxeo service and have some UI specific controllers.

This is the role of the Seam layer:

  • Seam Beans can be used as Controllers that access the Nuxeo Service to push/retrieve data.
  • Seam Context is used to manage the web context and the associated transient state.

Because of the way the screen are rendered inside the Nuxeo Platform, all Nuxeo navigations do not correspond to JSF navigation. Actually, in a lot of cases you always render the same JSF view, but thanks to the Actions/Layout/Widget model the actual content displayed in the page will change according to the context:

  • What is the document you are looking at
  • What is the currently selected tab
  • What is the life cycle of the document
  • ...

However, sometimes, there is an actual JSF level navigation that relies on standard JSF navigation case. For that, each Nuxeo Bundle can contribute navigation cases to the JSF config via a deployment-fragment.

<extension target="faces-config#NAVIGATION">
 <navigation-case>
  <from-outcome>assets</from-outcome>
  <to-view-id>/dam/assets.xhtml</to-view-id>
  <redirect />
 </navigation-case>

 <navigation-case>
  <from-outcome>asset</from-outcome>
  <to-view-id>/dam/asset.xhtml</to-view-id>
  <redirect />
 </navigation-case>
</extension>

In addition, the Nuxeo Platform provides a system to manage REST URL that combine JSF navigation and Actions: see the page Navigation URLs for more details.

About Possible Approaches

Pure Studio

Nuxeo Studio provides a high level configuration UI to configure Actions, Layouts, Widgets, etc. It hides a lot of the complexity of the underlying model, as well as some details.

For now, Nuxeo Studio allows you to customize pretty much everything that is inside the "slots" defined by the target XHTML/Theme template (DM or DAM). However, Nuxeo Studio does not give you direct access to the "low level" model.

In the context of 7.x, we are working on replacing all the low level model by layouts only.

Custom Web Templates

As the rest of the framework, the JSF web framework is extensible:

  • You can contribute new XHTML pages
  • You can extend the theme
  • You can contribute to the Action/Widget/Layout system
  • You an contribute new Seam beans

At the same time, as long as your screens logic depends on Action/Widgets/Layouts, you will be able to use Studio to configure it.

However, going that road requires more knowledge and skills:

  • You have to be familiar with underlying technologies
    • Java/JSF/Seam
    • Nuxeo Extension Point model
    • Actions/Layout/Widget
  • On the Studio side, things will be less polished For example you will have to know the name of the layout you want to change since it won't be one of the default layout from DAM/DM

We are not saying that this road is not good, we just want to make it clear that the technical requirements are higher: more freedom but also more responsibilities.

If you are mainly interested in DAM, one option could be to review your mock-ups against the current Nuxeo DAM view. We switched from the 3 panes view to the 2 panes + lightbox because we think that from a user perspective it is better. It may be worth giving a try to this option since it would make things simpler.

However, if you think the custom UI is the way to go, we'll be happy to help you on that road. But you may want to consider a training.