Build a Workflow Based Application with Polymer


Wed 10 February 2016 By Arnaud Kervern

Most of you must already be familiar with the Nuxeo REST API, and Automation API and I am sure you must have already tried our Workflow Engine in Studio. Today, I will show you how you can put all of these in a magic cauldron and transform them to a simple and great looking single page application using Polymer with Material Design. Let’s get started!

Start the Polymer Application

Generate the Skeleton


Boilerplate, Scaffolding, CopyPasta - there are so many words to bootstrap an application. Let me introduce you to a very common tool in the JavaScript world: Yeoman.

Yeoman helps you to kickstart new projects, prescribing best practices and tools to help you stay productive.

It sounds like something that could be useful to start with. So let's use it to generate the Polymer boilerplate.

First, make sure that node and Yeoman are correctly installed in your system (assuming you are using OSX):

$ brew install node
$ npm install -g yo generator-polymer

Then generate the project:

$ yo polymer

Now let the magic happen, aka install all npm and Bower dependencies and start our newly generated application:

$ cd app
$ gulp serve

TA DA! You can now start customizing your new Polymer-based application.

Proxying the Nuxeo Platform


As our target application will be hosted inside a Nuxeo Platform server, while developing we need to simulate the environment and have a running Nuxeo Platform behind /nuxeo path on the development server.

To do so, we will tweak the gulpfile.js a little to create a proxy while serving the files:


Start the Nuxeo Platform (on http://localhost:8080/nuxeo), and execute a gulp serve to start your application (on http://localhost:5000/). You should be able to access the Nuxeo Platform with http://localhost:5000/nuxeo.

Querying the Workflow Endpoint


Now that we have a working Polymer application, we want to interact with the Nuxeo Platform and the workflow engine.

Workflow

Working up the Magic


The infrastructure is ready and you can now open your awesome customized (better than your neighbor) JavaScript editor and start coding. But before that, add the nuxeo-elements to the dependency because it will allow you to use our components for requesting the Nuxeo Platform server.

$ bower install --save nuxeo/nuxeo-elements

Add the element list to the app/elements/elements.html like we did in our sample app. We can now add components to call Operation, REST endpoint, Workflow, etc. See the full list on the online demo page.

Abracadabra!


It's always easier to explain a trick using a real use case and I have just the right one for you! Open the timeoff-pending.html web component and I'll walk you through the steps.

Authentication?


The target we have is an application running inside the Nuxeo Platform, which means that besides our Authentication filter, we can assume that the current user is already authenticated with his HTTP session. So, no need to worry about that in this configuration.

nuxeo-resource Element


Here’s a sample from the sources:

<nuxeo-resource id="nxoPending"
auto
path="workflow"
response=true></nuxeo-resource>

This element defines a request to the workflow endpoint with id nxoPending, which binds his response to the data property. It is executed automatically when the component is loaded. In the Nuxeo playground workflow endpoint documentation, you can see that the data property contains all workflow instances launched by the current user.

Looping Through the Data Property


Here’s another sample from the sources. Using the property binding, the template element will be rendered when data contains something and loop over it:

<template id="tmplentries" is="dom-repeat" items='[[data.entries]]' as="item" filter="timeOffWkf">
<div class="request flex">
<timeoff-entry data$=[[item]] id="entry
[[item.id]]"></timeoff-entry>
<div class="actions">
<button-edit-workflow class="button" on-edited="refreshTasks" workflow="[[item]]"></button-edit-workflow>
<button-delete-workflow class="button" on-deleted="refresh"
workflow-id="[[item.id]]"></button-delete-workflow>
</div>
</div>
</template>

For each entry, a timeoff-entry component is rendered, which displays the state of the current workflow. And, as you can see, we are using the same principle to handle edit-workflow and delete-workflow actions bound to the current workflow.

Note that we do not want to display all the workflows, and we use a dom-repeat attribute filter which will filter the displayed item.

Screenshot 2016-02-05 14.30.42

And Voila!


This is how you can use a component to request a workflow endpoint to have all the current user instances, filter them and display them using an other component. It's kind of magical, isn't it?

Something More to Try out


If you want to do more with the workflow API, like validating or rejecting a task, you can look at our timeoff-pending-task component and more precisely the timeoff-accept-task or the timeoff-reject-task. To go further, clone our sample application nuxeo-timeoff which contains Task validation, Workflow creation, Content Enricher, and more.

Polymer Tricks


Let me show you some more tricks that might be useful as you start delving deeper into Polymers.

Behaviors


This is a really useful one. Sharing some code using behaviors is great.

For instance, you can easily mutualize non-lifecycle methods between several components like we did in our timeoff-helper behavior. Or you can do something even better, for instance sharing some properties or lifecycle method like our timeoff-task-comment behavior. This makes it possible to have several components with the ability to prepare a request for the Workflow API with a comment in their variables.

Write it once, use it everywhere! That must be your thought when using the Polymer Behaviors mechanism.

Styling Custom Property


Styling Custom Property could be useful if you'd like not to hard code anything in your style, especially in the shadow DOM. Let's dig deeper into how timeoff-entry-user handles the color for the user's initials.

Unique color for a username

The goal is to have a unique color for a username. We can use a simple array of hardcoded colors, then calculate a simple index for a username, pick the color and that's all. But, we have something better! CSS is providing a variable system implemented in Polymer, and Polymer provides us some color variables that are great with Material Design. But due to the component lifecycle, the CSS variables are rendered before the loaded state and we are not able to know the username before that. So, we need to recompute the component style when we finish calculating the username's color. That's where the custom property API come to our rescue!

CSS:

#badge {
background: var(--user-color);
}

JavaScript Observer:
_userChanged: function() {
// names[this.username].color contains a CSS variable name
this.customStyle['--user-color'] = this.getComputedStyleValue(names[this.username].color) + ';';
this.updateStyles();
},


If you'd like to play with the full nuxeo-timoff plugin, it's available as a public Nuxeo Package. Install it, browse to http://localhost:8080/nuxeo/timeoff, and have fun!


Tagged: Nuxeo Automation, Polymer, REST API, Workflow