La plupart d’entre vous connaissent déjà l’API REST et l’API d’automatisation de Nuxeo, et je suis sûr que vous avez déjà essayé notre moteur de workflow dans Studio. Aujourd’hui, je vais vous montrer comment, en les mettant tous dans un chaudron magique et en remuant un peu, il est possible d’obtenir une application Web monopage simple et agréable en utilisant Polymer et le Material Design. C’est parti !

Démarrer l’application Polymer

Générer le squelette

Boilerplate, Scaffolding (échafaudage) ou copier-coller : il y a tellement de façons de démarrer une application. Laissez-moi vous présenter un outil très courant dans le monde du JavaScript : Yeoman.

Yeoman vous permet de démarrer de nouveaux projets en prescrivant des bonnes pratiques et des outils pour vous aider à rester productif.

C’est le genre d’outil qui semble plutôt pratique pour commencer. Alors utilisons-le pour générer le boilerplate Polymer.

Commencez par vous assurer que node et Yeoman sont bien installés sur votre système (on part du principe que vous utilisez OSX) :

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

Puis générez le projet :

$ yo polymer

Laissez maintenant la magie opérer : installez toutes les dépendances nps et Bower et lancez l’application fraîchement générée :

$ cd app
$ gulp serve

TA DA ! Vous pouvez désormais commencer à personnaliser votre application Polymer.

Établir un proxy pour Nuxeo Platform

Puisque notre application cible sera hébergée sur un serveur Nuxeo Platform, nous devons simuler l’environnement et avoir une instance de Nuxeo Platform opérationnelle derrière le chemin /nuxeo sur le serveur de développement au cours du développement.

Pour y arriver, nous allons ajuster le fichier gulpfile.js pour créer un proxy tout en distribuant les fichiers :

Installez le module proxy-middleware et enregistrez-le en tant que dépendance dev :

```
 $ npm install --save-dev proxy-middleware
```

Localisez la tâche serve dans le fichier gulpfile.js et ajoutez les lignes suivantes :

```
// Also see https://github.com/nuxeo/nuxeo-timeoff/blob/96d09c478bef6da38c27ae80d59dfbb877851ae7/nuxeo-timeoff-web/gulpfile.js#L255-L256
// setup our local proxy var proxyOptions = require('url').parse('http://localhost:8080/nuxeo');
proxyOptions.route = '/nuxeo';
```

Ajoutez le proxy aux middlewares du serveur :

```
// Also see https://github.com/nuxeo/nuxeo-timeoff/blob/96d09c478bef6da38c27ae80d59dfbb877851ae7/nuxeo-timeoff-web/gulpfile.js#L276 middleware: [historyApiFallback(), require('proxy-middleware')(proxyOptions)],
```

Démarrez Nuxeo Platform (sur http://localhost:8080/nuxeo) et exécutez une commande gulp serve pour démarrer votre application (sur http://localhost:5000/). Vous devriez pouvoir accéder à Nuxeo Platform à l’adresse http://localhost:5000/nuxeo.

Requêter le point final du workflow

Maintenant que nous avons une application Polymer fonctionnelle, nous voulons interagir avec Nuxeo Platform et le moteur de workflow.

Workflow

Laisser opérer la magie

L’infrastructure est prête et vous pouvez désormais ouvrir votre éditeur JavaScript super personnalisé et commencer à coder. Mais avant ça, ajoutez nuxeo-elements à la dépendance car ça vous permettra d’utiliser nos composants pour effectuer des requêtes sur le serveur Nuxeo Platform.

$ bower install --save nuxeo/nuxeo-elements

Ajoutez la liste d’éléments au fichier app/elements/elements.html comme nous l’avons fait dans notre application modèle. Nous pouvons désormais ajouter les composants pour appeler Operation, le point final REST, le workflow, etc.

Abracadabra !

C’est toujours plus facile d’expliquer une astuce en la contextualisant dans un vrai cas d’utilisation, et j’ai pile ce qu’il faut ! Ouvrez le composant Web timeoff-pending.html et je vais vous expliquer les différentes étapes.

Authentification ?

Notre cible est une application fonctionnant sur Nuxeo Platform, ce qui signifie qu’en plus de notre filtre d’authentification, on peut assumer que l’utilisateur actuel est déjà authentifié avec sa session HTTP. Pas de soucis à se faire sur ce point avec cette configuration.

Élément nuxeo-resource

Voici un échantillon des sources :

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

Cet élément définit une requête vers le point final du workflow avec l’id nxoPending, ce qui relie sa réponse à la propriété des données. Elle est automatiquement exécutée lorsque le composant est chargé. Dans la documentation point final du workflow de Nuxeo playground, vous pouvez voir que les propriétés des données contiennent toutes les instances des workflows lancées par l’utilisateur actuel.

Créer une boucle pour la propriété

Voici un autre échantillon des sources. À l’aide de la liaison de la propriété, l’élément modèle sera généré lorsque des données sont présentes pour ensuite créer une boucle :

<template id="tmpl_entries" 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>

Pour chaque entrée, un composant timeoff-entry est généré et affiche l’état du workflow en cours. Et, comme vous pouvez le voir, nous utilisons le même principe pour gérer les actions edit-workflow et delete-workflow liées au workflow actuel.

Notez que nous ne voulons pas afficher tous les workflows et que nous utilisons un filtre d’attribut dom-repeat pour filtrer les éléments affichés.

Screenshot 2016-02-05 14.30.42

Et voilà le travail !

De cette façon, vous pouvez utiliser un composant pour requêter un point final de workflow et obtenir toutes les instances de l’utilisateur actuel, les filtrer et les afficher grâce à un autre composant. C’est magique, n’est-ce pas ?

Un petit quelque chose à essayer

Si vous voulez continuer à utiliser l’API de workflow, par exemple pour valider ou rejeter une tâche, vous pouvez jeter un œil à notre composant timeoff-pending-task, et plus précisément timeoff-accept-task ou timeoff-reject-task. Pour aller plus loin, clonez notre application modèle nuxeo-timeoff qui contient la validation de tâches, la création de workflows, l’enrichissement du contenu et bien plus.

Astuces Polymer

Laissez-moi vous montrer quelques astuces qui peuvent s’avérer utiles lorsque vous commencez à vous aventurer plus en détail dans le fonctionnement de Polymer.

Comportements

C’est une fonctionnalité très pratique. Partager du code en utilisant des comportements (behaviors) est vraiment génial.

Par exemple, vous pouvez facilement mutualiser des méthodes non liées au cycle de vie entre plusieurs composants comme nous l’avons fait dans notre comportement timeoff-helper. Ou, encore mieux, vous pouvez par exemple partager certaines propriétés ou des méthodes de cycle de vie comme notre comportement timeoff-task-comment. Cela permet d’avoir plusieurs composants avec la possibilité de préparer une requête pour l’API de workflow avec un commentaire dans les variables.

Écrivez une fois, réutilisez à l’infini ! Gardez ce principe à l’esprit lorsque vous utilisez le mécanisme de comportements de Polymer.

Modifier le style des propriétés personnalisées

Modifier le style des propriétés personnalisées peut être pratique si ne voulez pas coder en dur les éléments de style, en particulier dans le shadow DOM. Voyons plus en détail comment timeoff-entry-user gère la couleur des initiales des utilisateurs.

Unique color for a username

L’objectif est d’avoir une couleur unique pour chaque nom d’utilisateur. Il est possible d’utiliser une simple palette de couleurs codées en dur, puis de calculer un index simple pour un nom d’utilisateur et de choisir une couleur. Mais il y a mieux ! CSS fournit un système de variables implémenté dans Polymer, et Polymer nous fournit des variables de couleurs qui fonctionnent bien avec le Material Design. Mais en raison du cycle de vie du composant, les variables CSS sont générées avant le chargement et il est impossible de connaître le nom d’utilisateur au préalable. Nous devons donc recalculer le style du composant après avoir calculé la couleur du nom d’utilisateur. C’est là que l’API de propriétés personnalisées vient à notre secours !

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();
},

Si vous voulez découvrir le plug-in nuxeo-timoff dans son intégralité, il est disponible en tant que package Nuxeo public. Installez-le, saisissez l’URL http://localhost:8080/nuxeo/timeoff et amusez-vous !