Trick Out Nuxeo with Serious Bling


Tue 18 October 2016 By Josh Fletcher

Introduction

In a previous blog, I explained how to use a Polymer application located in a Nuxeo plugin as a JSF widget via Nuxeo Studio. Today I’ll run through how to create a custom Polymer app using only Nuxeo Studio.

The plugin solution works well for handling complex use cases and augmenting the Nuxeo application with super cool, customized, modern user experiences. However I was unsatisfied with the complexity. For a Studio user, or a web developer, a small amount of Java tooling is necessary to build a Nuxeo Package even for a Polymer application; nonetheless this represents a significant extra learning curve. Our code scaffolding tool helps a lot, but for simple use cases it is still way too much overhead. I wanted something simpler.

Note that for the purposes of brevity I’ll refer to Polymer widgets or dashboards generically as “Polymer apps”. This is technically accurate because what I describe here, even if displayed as a widget or dashboard within a Nuxeo application, is nonetheless it’s own encapsulated Polymer application.

Keys to the Kingdom

The reason it’s possible to define custom Polymer content in Nuxeo Studio is because the Nuxeo Platform already includes some out-of-the-box Polymer apps. Specifically, there are two embedded applications.

Permissions

The Permissions Tab is an embedded Polymer app:

Analytics

The Analytics Tabs are also embedded Polymer apps:

Reusable Resources

The key to taking advantage of these existing features is to import the necessary files from one of these apps via your XHTML template. For example, to use the dependencies for the Permissions tab, the correct imports are:

<h:outputScript src="/bower_components/webcomponentsjs/webcomponents-lite.js" target="" />
<h:outputScript src="/bower_components/moment/min/moment-with-locales.min.js" target="" />
<nxr:import src="/permissions/elements/elements.vulcanized.html" target="" />

To use the dependencies from the Analytics Tabs, the last line should be changed to:

<nxr:import src="/analytics/elements/elements.vulcanized.html" target="" />

These imports provide a Widget or Layout template with the necessary framework for building Polymer apps via Nuxeo Studio.

The difference between the two imports is in the list of available Polymer elements. Both apps provide the necessary framework but each app has a unique set of elements as well (defined in the “elements.vulcanized.html” file). If you’d like to dig deeper and see the list of individual elements I recommend checking out the “elements.html” file for either app. These are located within the “nuxeo.war” folder on your server, and are also accessible on github:

Wiring Things Up

The biggest difference between the plugin-based solution and this one is that the XHTML template needs to contain everything for the Polymer app (e.g. CSS, HTML, and JavaScript all in the same file). Here is an example layout that displays a pie chart of the content distribution in the repository:

<h:panelGroup layout="block"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:nxr="http://nuxeo.org/nxweb/resources"
    style="overflow: hidden">

  <h:outputScript src="/bower_components/webcomponentsjs/webcomponents-lite.js"
      target="" />
  <h:outputScript src="/bower_components/moment/min/moment-with-locales.min.js"
      target="" />

  <nxr:import src="/analytics/elements/elements.vulcanized.html"
      target="" />

  <style is="custom-style">
    chart-bar,
    chart-line,
    chart-pie {
      height: 100%;
      margin: 25px auto 0 auto;
      width: 100%;
      display: block;
      font-size: 0.8em;
    }
  </style>

  <template is="dom-bind">

    <nuxeo-connection url="/nuxeo"></nuxeo-connection>

      <!-- Entity Types -->
      <nuxeo-repository-data          ecm-primary-type="File,Note,Folder,Collection,Workspace"
          grouped-by="ecm:primaryType"
          group-limit="10"
          data="">
      </nuxeo-repository-data>


      <paper-card heading="Entity Types">
        <div class="card-content">
          <chart-pie values="[[_values(typeCount)]]"
              series="[[_series(typeCount)]]"
              options='{"responsive": true, "animation": false}'>
          </chart-pie>
        </div>
      </paper-card>

  </template>

  <script>
    var t = document.querySelector('template');

    /**
     * Copied from nuxeo-chart-data-behavior.
     * https://github.com/nuxeo/nuxeo/blob/master/nuxeo-features/nuxeo-admin-center/nuxeo-admin-center-analytics/src/main/elements/nuxeo-chart-data-behavior/nuxeo-chart-data-behavior.html
     */
    t._series = function(data) {
      return data.map(function(obj) {
        return obj.key;
      });
    };

    /**
     * Copied from nuxeo-chart-data-behavior.
     * https://github.com/nuxeo/nuxeo/blob/master/nuxeo-features/nuxeo-admin-center/nuxeo-admin-center-analytics/src/main/elements/nuxeo-chart-data-behavior/nuxeo-chart-data-behavior.html
     */
    t._values = function(data) {
      return [data.map(function(entry) {
        if (Array.isArray(entry.value)) {
          return entry.value.map(this._values.bind(this));
        } else {
          return entry.value;
        }
      })];
    };
  </script>

</h:panelGroup>

As you can see this single HTML template contains CSS to control the look at feel of the app, HTML to wire up the Polymer content, and JavaScript to massage the data returned by the calls to the nuxeo-repository-data element.

A more fleshed out example is available here. This example adds a Dashboard as a new Tab under Home.

Tips

What widgets are available?

I recommend checking out the “elements.html” file for either app. These are located within the “nuxeo.war” folder on your server, or on github:

Disable Ajax Tabs

Integrating Polymer apps with JSF can be tricky because, with Ajax support enabled, JSF makes destructive changes to the DOM tree. For this reason it is best to disable Ajax support for any Tab that contains Polymer content. For example given a Tab named “DomainSummary” this XML Extension will disable Ajax support:

<extension target="org.nuxeo.ecm.platform.actions.ActionService" point="actions">
  <action id="DomainSummary">
    <properties>
      <!-- NXP-18320: disable ajax support on Polymer tabs -->
      <property name="ajaxSupport">false</property>
    </properties>
  </action>
</extension>

What if you need a little more?

Check out nuxeo-labs-studio-elements. This plugin has a more extensive library of Polymer elements (including Google Chart). To use it you just need to make a few adjustments:

Conclusion

Most of the blogs I’ve written this year relate to Polymer and Web Components in some way so you might be thinking I’m kind of excited about it. It’s true, working with Polymer has been one of the most rewarding experiences of my career.

I’m super stoked that we are able to leverage this technology via Nuxeo Studio and breath new life into the Nuxeo application with modern, responsive content and amazing flexibility.

Another cool advantage to this kind of work is your Polymer skills will be useful for working with the new Nuxeo Web UI, which is Web Component-based using Polymer as well. We definitely live in exciting times for Nuxeo.


Tagged: Nuxeo Studio, Polymer, How to, Analytics
Check out the features of our latest Nuxeo Platform Download Nuxeo