The theme configuration has changed on the Nuxeo Platform for the 7.4 version. This page provides information to help you migrate your custom Nuxeo themes to this version or above.
To get a presentation of how to handle pages and resources, please refer to the Theme documentation page.
Module Changes
The following modules have been removed from the default distribution:
- nuxeo-theme-bank
- nuxeo-theme-core
- nuxeo-theme-fragments
- nuxeo-theme-html
- nuxeo-theme-jsf
- nuxeo-theme-webengine
Also, the following addons have been deprecated:
- nuxeo-platform-splitpane
- nuxeo-webengine-sites
- nuxeo-webengine-blogs
Two new compatibility modules have been added:
- nuxeo-theme-migration, present in the default distribution
- nuxeo-theme-webapp-compat, not present in the default distribution
Migration is very easy with JSF pages, and has not been provided for WebEngine modules.
If you'd like to get back the old behavior for the 7.4 version, you should:
- add back old theme modules
- remove the
nuxeo-theme-migration
module
This will be simplified when a compatibility Nuxeo Package is made available, see NXP-17562.
Runtime Bundle and Component Changes
The following runtime bundles have been removed from the default distribution:
org.nuxeo.theme.bank
org.nuxeo.theme.core
org.nuxeo.theme.fragments
org.nuxeo.theme.html
org.nuxeo.theme.jsf
org.nuxeo.theme.webengine
The runtime component org.nuxeo.theme.nuxeo.default
, holding the default web application main contributions, has been renamed to org.nuxeo.theme.nuxeo.webapp
: update your files requirements when overriding or contributing to its resources.
Setup dev mode by adding org.nuxeo.dev=true
to your nuxeo.conf
file: deprecation logs will help you migrate.
Migrating Page Layouts
Previous Page Layout Definition
Page layouts used to be defined through contributions to the themes
extension point like:
<extension target="org.nuxeo.theme.services.ThemeService" point="themes">
<theme>
<src>themes/document-management.xml</src>
</theme>
</extension>
Fragments on the pages defined inside the theme were included through contributions to the views
extension point, sometimes referencing resources like:
<extension target="org.nuxeo.theme.services.ThemeService" point="views">
<view name="Nuxeo header" template-engine="jsf-facelets">
<format-type>widget</format-type>
<template>incl/nuxeo_header.xhtml</template>
<resource>screen.css</resource>
</view>
</extension>
Then, the tag nxthemes:composition
allowed using the theme pages on a given page, using negotiators or other contributions to the applications
extension point like:
<extension target="org.nuxeo.theme.services.ThemeService" point="applications">
<application root="${org.nuxeo.ecm.contextPath}"
template-engine="jsf-facelets">
<negotiation>
<strategy>nuxeo5</strategy>
<default-engine>default</default-engine>
<default-theme>galaxy/default</default-theme>
<default-perspective>default</default-perspective>
</negotiation>
[...]
<view id="/info_view.xhtml">
<theme>galaxy/popup</theme>
</view>
</application>
</extension>
New Page Layout Definition
Now the page layout is handled completely by the XHTML template defining the page: instead of defining fragments and referencing them in the theme XML definition, fragments are included using standard facelets. Some default templates have been designed to help you include JavaScript and CSS resources that are still contributed to runtime extension points.
Here is an example of the default theme page template workspace_page.xhtml
, showing a header, a footer, and a left column, after migration:
<ui:composition template="/pages/basic_page.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:param name="pageName" value="#{themeActions.currentPage}" />
<ui:param name="pageFlavor" value="#{themeActions.currentFlavor}" />
<ui:define name="basic body includes">
<ui:include src="/incl/includes.xhtml" />
</ui:define>
<ui:define name="basic body">
<ui:decorate template="/pages/header_footer_template.xhtml">
<ui:define name="main content">
<div class="column">
<ui:include src="/incl/import.xhtml" />
<ui:include src="/incl/multi_tree_explorer.xhtml" />
<ui:include src="/incl/user_clipboard.xhtml" />
</div>
<div class="content">
<ui:include src="/incl/breadcrumb.xhtml" />
<ui:insert name="body" />
</div>
<div class="clear" />
</ui:define>
</ui:decorate>
</ui:define>
</ui:composition>
Then this template can be used similarly to the nxthemes:composition
tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<nxthemes:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:nxthemes="http://nuxeo.org/nxthemes"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:nxd="http://nuxeo.org/nxweb/document"
xmlns:nxl="http://nuxeo.org/nxforms/layout"
xmlns:nxu="http://nuxeo.org/nxweb/util">
<ui:define name="page title">
<h:outputText value="#{nuxeoApplicationName} - #{nxd:titleOrId(currentDocument)}"/>
</ui:define>
<ui:define name="bookmark">
<link rel="bookmark" href="#{navigationContext.currentDocumentFullUrl}"/>
</ui:define>
<ui:define name="body">
<div>
<h:form id="document_header_layout_form" class="titleBlock">
<nxl:documentLayout documentMode="header" mode="view"
value="#{currentDocument}" defaultLayout="document_header"
includeAnyMode="false" />
</h:form>
<ui:include src="/incl/document_actions_upperbuttons.xhtml"/>
<ui:include src="/incl/message_banner.xhtml"/>
<nxl:widget name="documentTabs" mode="view" value="#{currentDocument}" />
</div>
</ui:define>
</nxthemes:composition>
<ui:composition template="/pages/workspace_page.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:nxd="http://nuxeo.org/nxweb/document"
xmlns:nxl="http://nuxeo.org/nxforms/layout"
xmlns:nxu="http://nuxeo.org/nxweb/util">
<ui:define name="page title">
<h:outputText value="#{nuxeoApplicationName} - #{nxd:titleOrId(currentDocument)}"/>
</ui:define>
<ui:define name="bookmark">
<link rel="bookmark" href="#{navigationContext.currentDocumentFullUrl}"/>
</ui:define>
<ui:define name="body">
<div class="mainFragment">
<h:form id="document_header_layout_form" class="titleBlock">
<nxl:documentLayout documentMode="header" mode="view"
value="#{currentDocument}" defaultLayout="document_header"
includeAnyMode="false" />
</h:form>
<ui:include src="/incl/document_actions_upperbuttons.xhtml"/>
<ui:include src="/incl/message_banner.xhtml"/>
<nxl:widget name="documentTabs" mode="view" value="#{currentDocument}" />
</div>
</ui:define>
</ui:composition>
The basic_page.xhtml
template allows to include some resources on this page. It needs a page name and a flavor name, provided through the themeActions
Seam component logics, relying on negotiators (see below).
Migrating Resources
Resources have been included to the page using different means in the past. They can be migrated to use the WebResources extension point (available since 7.3).
Generic Resources to Include
Override of the includes.xhtml Template
The template at /incl/includes.xhtml
used to gather a lot of resources to include on all pages. Now it only holds resources that should go to the page body (as of 7.4, only Drag&Drop resources, that cannot be included in the page head, are handled by this template).
You can keep your override (adapting it to the file current content) if you need to insert resources to the page body. If you need to insert resources to the page head, you can contribute to the nuxeo_includes
resource bundle (see below).
Contributions to All Pages
Contributions that were needed on all pages used to be added to the nuxeo5 includes
view by runtime extension point contributions. This view was included in all theme page layouts. Now the default resource bundle named nuxeo_includes
is taking up this new role:
<require>org.nuxeo.theme.nuxeo.default</require>
<extension target="org.nuxeo.theme.services.ThemeService" point="views">
<view name="nuxeo5 includes" template-engine="jsf-facelets" merge="true">
<format-type>widget</format-type>
<resource>seamjsf-monitor.js</resource>
</view>
</extension>
<extension target="org.nuxeo.theme.services.ThemeService" point="resources">
<resource name="seamjsf-monitor.js">
<path>scripts/seamjsf-monitor.js</path>
</resource>
</extension>
<require>org.nuxeo.theme.nuxeo.webapp</require>
<extension target="org.nuxeo.ecm.platform.WebResources" point="bundles">
<bundle name="nuxeo_includes">
<resources append="true">
<resource>seamjsf-monitor.js</resource>
</resources>
</bundle>
</extension>
<extension target="org.nuxeo.ecm.platform.WebResources" point="resources">
<resource name="seamjsf-monitor.js">
<path>scripts/seamjsf-monitor.js</path>
</resource>
</extension>
Theme Page Definition With Styles Holding Flavor Variables
A theme page definition does not change much: it now accepts a charset and links definitions, but its style, referencing flavor variables, has been migrated to use resources and resources bundles contributed to the WebResources service.
<extension target="org.nuxeo.theme.styling.service" point="pages">
<themePage name="galaxy/default">
<defaultFlavor>default</defaultFlavor>
<flavors>
<flavor>default</flavor>
<flavor>rainbow</flavor>
</flavors>
<styles>
<style>basics</style>
<style>buttons_and_actions</style>
<style>header</style>
<style>body</style>
<style>footer</style>
<style>grids_and_widgets</style>
<style>navigation</style>
<style>tables</style>
<style>forms</style>
<style>popups</style>
<style>breadcrumb</style>
<style>messages_and_tooltips</style>
<style>foldable_boxes</style>
<style>drag_and_drop</style>
<style>richfaces_components</style>
<style>tabs_content</style>
<style>helpers</style>
<style>nuxeo_dm_specific</style>
</styles>
</themePage>
</extension>
<extension target="org.nuxeo.theme.styling.service" point="pages">
<page name="galaxy/default" charset="utf-8">
<favorites>
<icon name="icon">/icons/favicon.png</icon>
<icon name="shortcut icon">/icons/favicon.ico</icon>
</favorites>
<defaultFlavor>default</defaultFlavor>
<flavors>
<flavor>default</flavor>
<flavor>rainbow</flavor>
</flavors>
<resources>
<bundle>nuxeo_includes</bundle>
<bundle>nuxeo_base</bundle>
<bundle>nuxeo_dm</bundle>
</resources>
</page>
</extension>
The style registration has changed too: styles holding flavor variables used to be defined on the page directly, they can now be defined as standard resources, declaring the flavor
processor:
<extension target="org.nuxeo.theme.styling.service" point="styles">
<style name="breadcrumb">
<src>themes/css/breadcrumb.css</src>
</style>
</extension>
<extension target="org.nuxeo.ecm.platform.WebResources" point="resources">
<resource name="breadcrumb.css">
<path>themes/css/breadcrumb.css</path>
<processors>
<processor>flavor</processor>
</processors>
</resource>
</extension>
Migrating resources
Several kinds of resources can now contributed to the WebResources service:
Theme service
resources
contributionsBefore migration<extension target="org.nuxeo.theme.services.ThemeService" point="resources"> <resource name="static-styles.css"> <path>css/static-styles.css</path> </resource> </extension>
After migration<extension target="org.nuxeo.ecm.platform.WebResources" point="resources"> <resource name="static-styles.css"> <uri>/css/static-styles.css</uri> </resource> </extension>
Theme styling
resources
contributionsBefore migration<extension target="org.nuxeo.theme.styling.service" point="resources"> <resource name="static-styles.css"> <path>css/static-styles.css</path> </resource> </extension>
After migration<extension target="org.nuxeo.ecm.platform.WebResources" point="resources"> <resource name="static-styles.css"> <uri>/css/static-styles.css</uri> </resource> </extension>
Theme styling
styles
contributionsBefore migration<extension target="org.nuxeo.theme.styling.service" point="styles"> <style name="breadcrumb"> <src>themes/css/breadcrumb.css</src> </style> </extension>
After migration<extension target="org.nuxeo.ecm.platform.WebResources" point="resources"> <resource name="breadcrumb.css"> <path>themes/css/breadcrumb.css</path> <processors> <processor>flavor</processor> </processors> </resource> </extension>
When migrating resources to the WebResources service, the following rule can be observed:
- When the resource is deployed to the WAR directory, the absolute file path (starting with a slash
/
character) can be used as an URL like/style/my_style.css
. - When the resource is kept in the JAR contributing to the service, the local path to the resource can be used like
style/my_style.css
. - Old style resources contributed to the theme styling service used the
src
attribute now renamed topath
. Note that styles referencing flavor variables could not be placed in the WAR directory before, otherwise flavor replacement could not be done correctly. This restriction is not valid anymore.
For more details, check out the resources
extension point documentation.
SASS Styles Definition
The styles of the Platform are now written in .scss thanks to Sass and its variables. The styles still rely on flavors to use the relevant variables.
Here is an example of how you can declare your own .scss file to use the common variables.
<extension target="org.nuxeo.theme.styling.service" point="styles">
<style name="my-styles">
<src>themes/css/my-styles.css</src>
</style>
</extension>
<extension target="org.nuxeo.theme.styling.service" point="pages">
<themePage name="*">
<styles append="true">
<style>my-styles.css</style>
</styles>
</themePage>
</extension>
<extension target="org.nuxeo.ecm.platform.WebResources" point="resources">
<resource name="my-styles.scss" type="css">
<path>themes/sass/my-styles.scss</path>
<processors>
<processor>sassCss</processor>
</processors>
</resource>
</extension>
<extension target="org.nuxeo.ecm.platform.WebResources" point="bundles">
<bundle name="nuxeo_sassCss">
<resources append="true">
<resource>my-styles.scss</resource>
</resources>
</bundle>
</extension>
Example of Styles & Variables Migration
Update your style sheet in Sass and update your old presets files to use a one single variable file. To define your colors & font in a variable file, you can rely on the file we use to define the default colors of the platform, update the values, then add yours. If you were using old presets in your style sheet, don't forget to update them.
<-- Old Logo Declaration -->
<extension target="org.nuxeo.ecm.platform.WebResources" point="views">
<view name="my logo" template-engine="jsf-facelets">
<format-type>widget</format-type>
<template>incl/my-logo.xhtml</template>
</view>
</extension>
<-- Old Styles Declaration -->
<extension target="org.nuxeo.ecm.platform.WebResources" point="resources">
<resource name="my_static_styles.css">
<path>themes/css/my_static_styles.css</path>
</resource>
</extension>
<-- Old Styles Definitions -->
<extension target="org.nuxeo.theme.styling.service" point="pages">
<themePage name="galaxy/default">
<styles append="true">
<style>my_styles</style>
</styles>
</themePage>
<themePage name="admin/default">
<styles append="true">
<style>my_styles</style>
</styles>
</themePage>
<themePage name="userCenter/default">
<styles append="true">
<style>my_styles</style>
</styles>
</themePage>
</extension>
<-- Old Presets Definition -->
<extension target="org.nuxeo.theme.services.ThemeService" point="presets">
<palette name="my borders" category="border" src="themes/palettes/my-borders.properties" />
<palette name="my backgrounds" category="background" src="themes/palettes/my-backgrounds.properties" />
<palette name="my fonts" category="font"src="themes/palettes/my-fonts.properties" />
<palette name="my colors" category="color" src="themes/palettes/my-colors.properties" />
</extension>
<!-- 1\. Define the default flavor the application will use -->
<extension target="org.nuxeo.theme.styling.service" point="flavors">
<flavor name="my_theme" extends="default">
<!-- define your logo here if necessary -->
<logo>
<path>/img/my_logo.png</path>
<previewPath>/img/my_logo.png</previewPath>
<width>120px</width>
<height>40px</height>
<title>My Logotype</title>
</logo>
<sass append="true">
<!-- call the nuxeo default variables, common_variables -->
<import src="themes/palettes/common_variables.scss"/>
<!-- and add yours -->
<import src="themes/palettes/my_variables.scss"/>
</sass>
</flavor>
</extension>
<!-- 2\. Declare your Sass and / or CSS styles -->
<extension target="org.nuxeo.ecm.platform.WebResources" point="resources">
<resource name="my_static_styles.css">
<uri>/css/my_static_styles.css</uri>
</resource>
<resource name="my_sass_styles.scss" type="css">
<path>themes/sass/my_sass_styles.scss</path>
<processors>
<processor>sassCss</processor>
</processors>
</resource>
</extension>
<!-- 3\. Then, add your styles to the default app styles -->
<extension target="org.nuxeo.ecm.platform.WebResources" point="bundles">
<bundle name="nuxeo_sassCss">
<resources append="true">
<resource>my_sass_styles.scss</resource>
<resource>my_static_styles.css</resource>
</resources>
</bundle>
</extension>
Migrating Negotiations
Theme negotiators can be used to define the page and flavor that will be applied to the current page.
Since the page layout is not defined by the page anymore, this cannot be changed by negotiators anymore. Simlarly, prespectives cannot be handled by the theme feature anymore, and now need to now be implemented by the facelet template logics.
The current flavor negotiation has been migrated to handle local configuration of the flavor (handling logo, CSS variables, etc...), on a new extension point:
<extension target="org.nuxeo.theme.services.ThemeService" point="negotiations">
<negotiation object="collection" strategy="nuxeo5">
<scheme>
org.nuxeo.theme.jsf.negotiation.collection.RequestParameter
</scheme>
<scheme>
org.nuxeo.theme.jsf.negotiation.collection.CookieValue
</scheme>
<scheme>
org.nuxeo.theme.jsf.negotiation.collection.RequestAttribute
</scheme>
<scheme>
org.nuxeo.theme.jsf.negotiation.collection.ViewId
</scheme>
<!-- local flavor/collection (specific to nuxeo5) -->
<scheme>
org.nuxeo.ecm.localconf.LocalThemeFlavor
</scheme>
<!-- default flavor/collection (specific to nuxeo5) -->
<scheme>
org.nuxeo.ecm.webapp.webcontainer.DefaultThemeFlavor
</scheme>
<scheme>
org.nuxeo.theme.jsf.negotiation.collection.UnspecifiedCollection
</scheme>
</negotiation>
</extension>
<extension target="org.nuxeo.theme.styling.service" point="negotiations">
<negotiation target="jsfDefaultPage">
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.DefaultPage"
order="100">
<property name="jsfDefaultPage">galaxy/default</property>
</negotiator>
</negotiation>
<negotiation target="jsfPage">
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.RequestParameter"
order="10">
<property name="param">page</property>
</negotiator>
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.RequestAttribute"
order="10">
<property name="param">page</property>
</negotiator>
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.DefaultPage"
order="100">
<property name="jsfPage">galaxy/default</property>
</negotiator>
</negotiation>
<negotiation target="jsfFlavor">
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.RequestParameter"
order="10">
<property name="param">flavor</property>
</negotiator>
<negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.RequestAttribute"
order="20">
<property name="param">flavor</property>
</negotiator>
<negotiator class="org.nuxeo.ecm.localconf.LocalThemeFlavor"
order="30">
<property name="negotiatedPageVariable">jsfPage</property>
</negotiator>
<negotiator
class="org.nuxeo.ecm.web.resources.jsf.negotiators.DefaultPageFlavor"
order="100">
<property name="negotiatedPageVariable">jsfPage</property>
</negotiator>
</negotiation>
</extension>
The new negotiators handle fallback on default page and flavor using explicit properties and variables. The negotiation element does not handle merge.
Troubleshoot
Here is an explanation for error and warn logs that you can run into while migrating themes.
Resource registration error:
Resource 'automation.js' on component service:org.nuxeo.document.routing.web.themes should now be contributed to extension point 'org.nuxeo.ecm.platform.WebResources': a compatibility registration was performed but it may not be accurate.
Just change the extension point for this resource contribution, and use the uri or path element depending on whether the resource is deployed to the WAR directory or not.
Theme style registration error:
Style 'nuxeo_usercenter_specific' on component service:org.nuxeo.ecm.user.center.theme should now be contributed to extension point 'org.nuxeo.ecm.platform.WebResources': a compatibility registration was performed but it may not be accurate. Note that the 'flavor' processor should be used with this resource.
Just change the extension point for this resource contribution, and use the path element instead of src, since this resource was probably not deployed to the WAR directory, to handle flavor variables replacement.
Startup warnings about unknow extension points on component
org.nuxeo.theme.services.ThemeService
:* Warning: target extension point 'themes' of 'org.nuxeo.theme.services.ThemeService' is unknown. Check your extension in component service:org.nuxeo.ecm.user.center.theme * Warning: target extension point 'applications' of 'org.nuxeo.theme.services.ThemeService' is unknown. Check your extension in component service:org.nuxeo.ecm.user.center.theme * Warning: target extension point 'views' of 'org.nuxeo.theme.services.ThemeService' is unknown. Check your extension in component service:org.nuxeo.ecm.user.center.oauth.themes
These extension points are not used anymore: the theme definition should be replaced by a standard JSF facelet template (see above), views should be included directly in it, and resources should be contributed to pages or resource bundles defined for the corresponding page.
Warnings during navigation when dev mode is enabled:
14:07:19,483 WARN [DeprecationLogger] Since version 7.4: Tag nxthemes:composition is deprecated, will use a composition of template at /pages/workspace_page.xhtml for /view_documents.xhtml @12,43
The template
/view_documents.xhtml
is still using anxthemes:composition
tag: this will use the template at/pages/workspace_page.xhtml
instead to handle compatibility.If you cannot migrate all your pages at once, and would like to use another default template than
/pages/workspace_page.xhtml
, the following contribution can be added to use the template at/pages/my_default_page_template.xhtml
instead:<require>org.nuxeo.theme.services.ThemeService</require> <extension target="org.nuxeo.theme.styling.service" point="negotiations"> <negotiation target="jsfThemeCompatTemplate"> <negotiator class="org.nuxeo.ecm.web.resources.jsf.negotiators.DefaultPage" order="100"> <property name="jsfThemeCompatTemplate">/pages/my_default_page_template.xhtml</property> </negotiator> </negotiation> </extension>