Ce document est le tutoriel du module Dynacase Document UIs.
Anakeen propose des prestations de formation à l'utilisation de la plateforme Dynacase.
Ces formations, d'une durée de 5 jours en standard, permettent d'aborder les points de ce tutoriel.
Elles peuvent aussi être adaptées pour aborder des thèmes non présentés dans ce document.
Elles alternent parties théoriques et applications pratiques. Les parties pratiques s'appuient sur un projet standard
ou peuvent être basées sur votre propre projet.
Elles se déroulent en intra entreprise sur Paris ou Toulouse.
Après la mise en place de l'environnement de travail, ce tutoriel est organisé en 5 chapitres principaux :
Chaque partie (et ses sous-parties) s'organisent de la même manière :
Vous pouvez suivre ce tutoriel de 2 manières différentes :
comme une visite guidée :
Regardez les moyens mis en œuvre pour chaque besoin, mais n'écrivez pas le code, regardez les interfaces correspondantes, mais ne créez pas les documents.
Cette approche vous donne une vue d'ensemble des possibilités offertes par Dynacase Document UIS en 1 journée.
comme une mini-formation :
Chaque présentation des moyens d'atteindre l'objectif fait des liens vers les manuels de référence utiles. Vous pouvez suivre ces liens, et tenter de développer tout ou partie du code correspondant.
Cette approche est plus longue.
Au terme de ce tutoriel, vous connaîtrez les principales fonctionnalités de Dynacase Document UIs.
Vous serez également en mesure d'explorer plus en détails les possibilités offertes par Dynacase Document UIs, et de réaliser des applications HTML5 tirant parti des derniers standards du web.
Pour dérouler ce tutoriel, il est nécessaire d'avoir un contexte dynacase.
Ce contexte peut être obtenu de 3 manières différentes.
Une appliance virtualbox est disponible sur notre site : dynacase-quick-start-ddui.ova
.
Il suffit de l'importer et de la démarrer.
L'appliance mappe le port 80 de l'invité sur le port 8080 de l'hôte.
Suivre le manuel d'installation de Dynacase pour créer un environnement de votre choix.
Pour suivre ce tutoriel, il vous faudra
les sources de l'application
Ces sources sont disponibles sur le compte github d'Anakeen. Chaque étape du tutoriel est disponible sous la forme d'un tag, et pourra être téléchargée directement depuis la page des releases.
les devtools
Pour linux :
le developer toolkit est distribué sous la forme d'un phar téléchargeable ici.
Il est ensuite utilisable avec votre interpréteur php (php dynacase-devtool.phar
).
Pour Windows :
le developer toolkit est distribué sous la forme d'une archive téléchargeable ici.
Une fois dézippé, vous obtenez un fichier dynacase-devtool.bat
qui doit être exécuté via la console windows.
pour plus de détails sur le developer toolkit, se reporter au manuel de référence
Les sources de ce tutoriel sont sur github.
Au cours du tutoriel, les fichiers modifiés pourront être téléchargés directement depuis github via un lien.
De plus, chaque étape est identifiée par un tag. Vous pouvez accéder à ce tag au moyen de git si vous avez cloné le dépot, ou vous pouvez télécharger directement une archive pour chaque étape depuis github via un lien.
Dynacase Document UIs est un module Dynacase permettant de générer une représensation des documents au moyen des technologies HTML5.
Le rendu des documents sans ce module est fait par le serveur, sous la forme d'une page HTML4 monolithique. Dynacase Document UIs permet à la génération de se faire côté client au moyen de Javascript, HTML5 et CSS.
Cela apporte les avantages suivants :
Répartition de la charge entre les clients
Puisque le serveur n'envoie plus que les données, et ne construit plus la page, cela allège la charge du serveur.
Souplesse
Puisque le rendu est fait en javascript au dernier moment, il est facile de prendre en compte des éléments de contexte, et de faire un rendu extrêmement personnalisé.
Comportement surchargeable
De par cette souplesse, il devient très facile de surcharger le comportement du document pour implémenter des fonctionnalités avancées (telles que le wizard que nous verrons dans un prochain chapitre, ou encore le fonctionnement en mode déconnecté).
Pour une présentation plus détaillée de Dynacase Document UIs, se reporter au manuel de référence
Au cours de ce tutoriel, nous allons construire une application de gestion des contacts.
Figure 2. Application de gestion des contacts
Cette application sera composée des éléments Dynacase suivants :
Les sources avant cette étape correspondent au tag step-20-00
.
L'étape de départ de ce tutoriel contient déjà la famille (avec son workflow), ainsi que le contact John Doe. Dans un premier temps, nous allons travailler directement sur le document.
Il suffit donc de déployer les sources.
Les sources telles que déployées à cette étape correspondent au tag step-20-00
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation) :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Il est possible de consulter le document
Pour plus d'explications sur l'application DOCUMENT
, voir le manuel de référence ddui
Figure 3. Comparaison des rendus
Si vous connaissiez Dynacase avant la sortie de Dynacase Document UIs, voici les éléments clés différenciant la représentation traditionnelle et la représentation HTML5.
La représentation HTML5 utilise Bootstrap pour sa mise en page.
Cela amène une présentation plus moderne, et plus espacée.
De plus, les documents sont responsive par défaut : en dessous de 480px, les libellés passent au dessus des attributs.
Les menus ont été revus
Le changement d'état se fait depuis un menu sur l'état courant (à droite de la barre de menus)
En modification, les attributs sont construits au moyen de la version open source de la librairie Kendo UI.
Cela amène une meilleure homogénéité des différents types d'attributs, ainsi qu'une plus grande souplesse.
Au-delà de ces aspects visuels, chaque attribut a été construit de manière à ce que ses éléments soient facilement adressables par CSS, facilement surchargeables au moyen de JavaScript. Nous allons exploiter cette nouvelle souplesse dans les chapitres suivants.
Nous avons vu dans le chapitre précédent que le document est responsive par défaut : en dessous de 480px, les libellés passent au dessus des attributs. Nous allons voir dans ce chapitre comment aller plus loin.
Nous allons injecter une CSS qui change la mise en forme du document, afin de le rendre responsive. L'objet de ce chapitre n'est pas d'expliquer la CSS, mais de montrer comment on peut
Voici à quoi ressemblera le document final :
Figure 4. Fiche de contact
Nous allons créer un contrôle de rendu afin de surcharger le rendu du document. Pour rappel, le contrôle de rendu se manipule de la même manière que le contrôle de vue :
Les sources avant cette étape correspondent au tag step-30-00
.
Le contrôle de rendu fera référence à une classe de rendu. Cette classe de configuration rendu doit être initialisée avant création du contrôle de rendu. Elle sera utilisée pour modifier le rendu du document dans les étapes suivantes.
Voici le contenu du fichier DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactRenderConfigView.php
:
<?php namespace DduiTuto; class ContactRenderConfigView extends \Dcp\Ui\DefaultView { }
Une fois cette classe déployée, le contrôle de rendu peut être créé à cette adresse : http://localhost:8080/?app=GENERIC&action=GENERIC_EDIT&classid=CVRENDER
Nous allons le compléter avec les informations suivantes :
Contact (Contrôle de rendu)
Contact
DEFAULT_VIEW
Consultation
Consultation
\DduiTuto\ContactRenderConfigView
10
Non
Figure 5. Contrôle de rendu
Une fois ajouté dans le workflow de la famille Contact pour chacun des états, exporté,
et correctement ajouté au fichier DDUI_TUTO/Families/DDUI_TUTO_CONTACT/DDUI_TUTO_CONTACT__DATA.csv
,
il peut être déployé.
Les sources telles que déployées à cette étape correspondent au tag step-30-10
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation) :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Puisque le contrôle de rendu a été associé au cycle de vie après la création du document que nous manipulons, il n'est pas associé automatiquement. Il faudrait soit écrire un script de migration, soit créer un nouveau document. Pour plus de simplicité, nous avons intégré une méthode à notre document pour refaire l'association.
il suffit de se connecter à l'adresse http://localhost:8080/?app=FDL&action=FDL_METHOD&id=CONTACT_JOHN_DOE&method=updateCR
En consultant le contact John DOE à l'adresse http://localhost:8080/api/v1/documents/CONTACT_JOHN_DOE.html, aucun changement n'est perceptible. En effet, nous avons juste mis en place les points d'entrée pour nos personnalisation à venir.
Nous allons dans cette partie voir comment surcharger le rendu uniquement par CSS.
L'objectif est de
Soit, en images :
Figure 6. Résolution inférieure à 480px
Figure 7. Résolution entre 480px et 1024px
Figure 8. Résolution entre 1024px et 1280px
Figure 9. Résolution supérieure à 1280px
Les sources avant cette étape correspondent au tag step-30-10
.
Nous devons en premier lieu injecter la nouvelle CSS dans le document en plus des CSS qu'il utilise déjà.
Pour ce faire, ajoutons une méthode getCssReferences
à notre classe de configuration de rendu dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactRenderConfigView.php
:
public function getCssReferences(\Doc $document = null) { $version = \ApplicationParameterManager::getParameterValue( "CORE", "WVERSION" ); $cssReferences = parent::getCssReferences($document); $cssReferences['DDUI_TUTO_CONTACT_view'] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/view.css?ws=" . $version; return $cssReferences; }
Nous pouvons maintenant écrire la CSS correspondante dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/view.css
:
/****************************************************************************** cadre identité ******************************************************************************/ /* masquage du label de la photo */ label[data-attrid="dc_photo"] { display: none; } @media (min-width: 480px) { /* Positionnement de la photo à gauche */ .dcpAttribute[data-attrid="dc_photo"] { float: left; width: 66px; } .dcpAttribute__content[data-attrid="dc_photo"] { padding: 0; } /* Restauration de la position initiale de tous les attributs autres que la photo */ .dcpFrame__content[data-attrid=dc_fr_ident] .dcpAttribute:not([data-attrid="dc_photo"]) { float: right; width: calc(100% - 66px); } .dcpFrame__content[data-attrid=dc_fr_ident] label:not([data-attrid="dc_photo"]) { width: calc((100% / 3) - 44px); } } /****************************************************************************** cadre Société ******************************************************************************/ @media (max-width: 1024px), (min-width: 1280px) { /* masquage du label du logo */ label[data-attrid="dc_logo"] { display: none; } } @media (min-width:480px) and (max-width:1024px), (min-width: 1280px) { /* Positionnement du logo à gauche */ .dcpAttribute[data-attrid="dc_logo"] { float: left; width: 66px; } .dcpAttribute__content[data-attrid="dc_logo"] { padding: 0; } /* Restauration de la position initiale de tous les attributs autres que le logo */ .dcpFrame__content[data-attrid=dc_fr_society] .dcpAttribute:not([data-attrid="dc_logo"]) { float: right; width: calc(100% - 66px); } .dcpFrame__content[data-attrid=dc_fr_society] label:not([data-attrid="dc_logo"]) { width: calc((100% / 3) - 44px); } } /****************************************************************************** Positionnement côte à côte des cadres "Société" et "Coordonnées professionnelles" ******************************************************************************/ @media (min-width: 1024px) { .dcpFrame[data-attrid=dc_fr_society], .dcpFrame[data-attrid=dc_fr_coord] { float: right; width: calc(50% - 10px); } .dcpFrame[data-attrid=dc_fr_society] { float: left; } .dcpFrame[data-attrid=dc_fr_coord] { float: right; } }
Les sources telles que déployées à cette étape correspondent au tag step-30-20
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation) :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En consultant le contact John DOE à l'adresse http://localhost:8080/api/v1/documents/CONTACT_JOHN_DOE.html, on constate bien que les éléments sont réorganisés en fonction de la résolution.
Dans la partie précédente, nous avons changé la mise en page uniquement au moyen de CSS. Toutefois, il peut être nécessaire d'aller plus loin et de revoir entièrement la disposition des éléments. Dans ce cas, la CSS n'est plus suffisante, et il faut alors passer par des templates.
Il est possible de définir un template pour un attribut en particulier, ou tout ou partie du document (voir le manuel de référence pour plus d'explications sur les templates).
Nous allons définir un template qui surcharge l'intégralité du corps du document pour arriver à ce résultat :
Figure 10. Fiche de contact
Les sources avant cette étape correspondent au tag step-30-20
.
La première étape est d'indiquer le template à utiliser dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactRenderConfigView.php
.
Cela se fait au moyen de la méthode getTemplates
.
Nous allons également injecter 2 fichiers javascript, qui seront utilisés par la suite, au moyen de
la méthode getJsReferences
.
Voici le fichier final :
<?php namespace DduiTuto; class ContactRenderConfigView extends \Dcp\Ui\DefaultView { public function getTemplates(\Doc $document = null) { $templates = parent::getTemplates($document); $templates["sections"]["content"]["file"] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/contactContent.mustache"; return $templates; } public function getJsReferences(\Doc $document = null) { $version = \ApplicationParameterManager::getParameterValue( "CORE", "WVERSION" ); $jsReferences = parent::getJsReferences(); $jsReferences["bootstrap_collapse"] = "lib/bootstrap/3/js/collapse.js?ws=" . $version; $jsReferences["jsqr"] = "lib/jsqr/jsqr-1.0.2-min.js?ws=" . $version; return $jsReferences; } public function getCssReferences(\Doc $document = null) { $version = \ApplicationParameterManager::getParameterValue( "CORE", "WVERSION" ); $cssReferences = parent::getCssReferences($document); $cssReferences['DDUI_TUTO_CONTACT_view'] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/view.css?ws=" . $version; return $cssReferences; } }
Nous pouvons maintenant définir notre template. Ce template utilisera des variables mustache pour récupérer les valeurs du document. Ces variables sont présentées dans le manuel de référence.
Le template ainsi obtenu dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/contactContent.mustache
est le suivant :
<div class="container dc__main"> <div class="well clearfix"> <div class="dc__summary"> <div class="media"> <div class="media-left media-middle"> <img src="{{document.attributes.dc_photo.attributeValue.url}}&width=150" alt="Pas de photo de contact"> </div> <div class="media-body"> <div class="media"> <div class="media-body"> <h1 class="media-heading pull-right"> {{document.attributes.dc_society.attributeValue.displayValue}} </h1> </div> <div class="media-right media-middle"> <img src="{{{document.attributes.dc_logo.attributeValue.thumbnail}}}" alt="pas de logo de la société"> </div> </div> {{{document.attributes.dc_civility.attributeValue.displayValue}}} <h2 class="media-heading"> {{{document.attributes.dc_firstname.attributeValue.displayValue}}} {{{document.attributes.dc_lastname.attributeValue.displayValue}}} </h2> {{{document.attributes.dc_service.attributeValue.displayValue}}} ({{{document.attributes.dc_role.attributeValue.displayValue}}}) </div> </div> </div> <div id="qrcontainer" class="dc__qrCode"></div> </div> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="headingMore"> <h3 class="panel-title"> <a class="collapsed" role="button" data-toggle="collapse" href="#collapseMore" aria-expanded="true" aria-controls="collapseOne"> <i class="collapseMore__icon fa" /> En savoir plus </a> </h3> </div> <div id="collapseMore" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingMore"> <div class="panel-body"> <div class="row dc__coord"> <div class="col-sm-4"> <i class="fa fa-phone"></i> {{{document.attributes.dc_workphone.htmlContent}}} </div> <div class="col-sm-4"> <i class="fa fa-mobile"></i> {{{document.attributes.dc_mobilephone.htmlContent}}} </div> <div class="col-sm-4"> <i class="fa fa-envelope"></i> {{{document.attributes.dc_workmail.htmlContent}}} </div> </div> <div class="row"> <div class="col-sm-6 "> {{{document.attributes.dc_fr_workaddr.htmlView}}} </div> <div class="col-sm-6 "> {{{document.attributes.dc_fr_homeaddr.htmlView}}} </div> </div> </div> </div> </div> </div>
En bonus dans la version corrigée, vous avez accès au code permettant de générer le QRcode.
Enfin, ce template s'accompagne de CSS. Nous allons donc réécrire le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/view.css
:
.dc__main { font-size: 16px; padding-top: 20px; } .dc__coord { text-align: center; } .dc__coord .dcpCustomTemplate--content { display: inline-block; } .dc__coord .fa { font-size: 150%; vertical-align: top; padding-top: 0.2em; width: 2em; text-align: center; } .dcpAttribute[data-attrid="dc_workpostalcode"], .dcpAttribute[data-attrid="dc_workcity"], .dcpAttribute[data-attrid="dc_homepostalcode"], .dcpAttribute[data-attrid="dc_homecity"] { float: left; display: inline-block; margin-right: 2px; } .dcpAttribute__content[data-attrid="dc_workpostalcode"], .dcpAttribute__content[data-attrid="dc_workcity"], .dcpAttribute__content[data-attrid="dc_homepostalcode"], .dcpAttribute__content[data-attrid="dc_homecity"] { width: auto; } .dcpAttribute__label { display:none; } .panel-heading[data-id="dc_fr_workaddr"], /* because of http://dev.dynacase.org/issues/6107 */ .panel-heading[data-attrid="dc_fr_workaddr"], .panel-heading[data-id="dc_fr_homeaddr"], /* because of http://dev.dynacase.org/issues/6107 */ .panel-heading[data-attrid="dc_fr_homeaddr"] { font-size: 14px; } .collapseMore__icon::before { content: "\f0da"; /* fa-caret-right */ } a:not(.collapsed) .collapseMore__icon::before { content: "\f0d7"; /* fa-caret-down */ } .panel-title a:hover { text-decoration: none; } .dc__qrCode { margin-top: 10px; text-align: center; } @media (min-width:768px) { .dc__summary, .dc__qrCode { float: left; } .dc__summary { width: calc(100% - 210px); padding-right: 10px; } .dc__qrCode { width: 210px; text-align: right; margin-top: 0; } }
Les sources telles que déployées à cette étape correspondent au tag step-30-30
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation) :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En consultant le contact John DOE à l'adresse http://localhost:8080/api/v1/documents/CONTACT_JOHN_DOE.html, la page ressemble à ce qui était attendu. De plus, le redimensionnement de la page réorganise bien les éléments.
Vous avez vu dans cette partie qu'il est simple de changer la disposition des éléments d'un document au moyen de CSS, que chaque attribut, ou même chaque sous-élément d'un attribut (libellé, valeur, etc.) est facilement adressable en CSS, et que vous pouvez aussi définir des templates pour des mises en page plus complexes.
De plus, tout ce travail a été accompli en n'écrivant aucun autre php que le code nécessaire pour définir notre template, et ajouter les assets au document.
Dans la partie suivante, nous allons voir comment travailler avec du code Javascript et php pour personnaliser le comportement des documents.
Le wizard permet de découper la saisie du document en plusieurs étapes. Chaque étape définit un ensemble de conditions pour pouvoir passer à l'étape suivante.
Chaque étape est implémentée au moyen d'une vue, accompagnée d'un masque. Ces vues sont pilotées au moyen d'un contrôle de rendu, et d'une classe d'accès à un rendu.
La dernière étape atteinte est mémorisée dans un paramètre applicatif du document.
La partie serveur sélectionne la vue en se basant sur les informations envoyées par le client
au moyen des customClientData
.
Pendant le wizard, le document est à l'état Création
.
À la fin du wizard, le document est passé à l'état À jour
.
L'état Création
n'est plus accessible après achèvement du wizard.
Voici à quoi ressemble le document pendant le wizard :
Figure 11. Wizard
Les étapes sont les suivantes :
3 vues vont être ajoutées sur le contrôle de rendu. Le contrôle de rendu va également préciser une classe d'accès à un rendu, qui va déterminer la vue suivante en fonction de :
Les sources avant cette étape correspondent au tag step-40-00
.
Chaque vue est composée de :
De plus, le contrôle de rendu est associé à une classe d'accès à un rendu.
Ces éléments doivent donc être initialisés avant création du contrôle de rendu.
Nous allons donc commencer par initialiser notre classe de rendu, commune aux 3 nouvelles vues :
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
<?php namespace DduiTuto; class ContactWizardRenderConfigEdit extends \Dcp\Ui\DefaultEdit { }
Nous allons ensuite initialiser la classe d'accès à un rendu dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactCvrenderRenderConfigAccess.php
:
<?php namespace DduiTuto; use Dcp\Ui\IRenderConfig; use Dcp\Ui\IRenderConfigAccess; class ContactCvrenderRenderConfigAccess implements IRenderConfigAccess { /** * @param string $mode * * @return IRenderConfig */ public function getRenderConfig($mode, \Doc $document) { return null; } }
Nous allons également initialiser les 3 masques qui seront utilisés par chacune des vues. Chaque masque peut être initialisé à l'adresse suivante : http://localhost:8080/?app=GENERIC&action=GENERIC_EDIT&classid=MASK&msk_famid=DDUI_TUTO_CONTACT
Une fois exportés, et correctement ajoutés au fichier DDUI_TUTO/Families/DDUI_TUTO_CONTACT/DDUI_TUTO_CONTACT__DATA.csv
, il peuvent être déployés.
Il est maintenant possible de rajouter nos 3 vues dans le contrôle de rendu, à l'adresse http://localhost:8080/?app=FDL&action=OPENDOC&mode=view&id=DDUI_TUTO_CONTACT__CVRENDER. Les vues sont donc maintenant au nombre de 4 :
DEFAULT_VIEW
DEFAULT_VIEW
Consultation
Consultation
\DduiTuto\ContactRenderConfigView
10
Non
WIZARD_IDENT
WIZARD_IDENT
Identité
Edition
\DduiTuto\ContactWizardRenderConfigEdit
Contact (masque WIZARD_IDENT) Contact
10
Non
WIZARD_WORKINFO
WIZARD_WORKINFO
Professionnel
Edition
\DduiTuto\ContactWizardRenderConfigEdit
Contact (masque WIZARD_WORKINFO) Contact
20
Non
WIZARD_HOMEINFO
WIZARD_HOMEINFO
Personnel
Edition
\DduiTuto\ContactWizardRenderConfigEdit
Contact (masque WIZARD_HOMEINFO) Contact
30
Non
Figure 12. Contrôle de rendu
Une fois exporté, et correctement ajouté au fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/DDUI_TUTO_CONTACT__DATA.csv
,
il peut être déployé.
Les sources telles que déployées à cette étape correspondent au tag step-40-10
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que seul le cadre identité est présenté. En effet, notre classe d'accès à un rendu retourne null, laissant le contrôle de rendu afficher sa vue par défaut, c'est à dire la première vue de modification.
La partie serveur sélectionnera la vue en se basant sur les informations suivantes,
envoyées par le client au moyen des customClientData
:
currentWizardStepName
le nom de l'étape en cours
Si ce nom est vide, alors on sélectionne la dernière vue atteinte (mémorisée au moyen d'un paramètre applicatif), et la première vue si le paramètre applicatif n'est pas renseigné.
goto
Une consigne sur l'étape à atteindre, parmi :
wizard.previous
wizard.next
wizard.targetStep
Indique que l'utilisateur veut accéder à une étape spécifique.
Dans ce cas, l'étape en question est passée par le paramètre targetStep
.
Les sources avant cette étape correspondent au tag step-40-10
.
Le code de sélection de la vue en fonction des vues disponibles dans le contrôle de rendu,
et des consignes envoyées par le client
est fourni au moyen de la méthode initWizardInfos
depuis la trait TContactWizardRenderConfigEdit
.
Il suffit de charger cette trait dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
.
La méthode initWizardInfos
est une manière d'implémenter un wizard.
Sa complexité n'a aucun intérêt particulier pour le compréhension du tutoriel,
et elle n'est fournie qu'à titre d'exemple.
<?php namespace DduiTuto; use Dcp\AttributeIdentifiers\cvrender as CvrenderAttributes; use Dcp\Family\Cvrender as CvrenderFamily; class ContactWizardRenderConfigEdit extends \Dcp\Ui\DefaultEdit { use TContactWizardRenderConfigEdit; }
Nous pouvons maintenant définir cette configuration de rendu comme étant
la configuration de rendu à utiliser pour les vues de création et de modification.
Cela se fait dans la classe ContactCvrenderRenderConfigAccess
du fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactCvrenderRenderConfigAccess.php
:
<?php namespace DduiTuto; use Dcp\Ui\IRenderConfig; use Dcp\Ui\IRenderConfigAccess; use Dcp\Ui\RenderConfigManager; class ContactCvrenderRenderConfigAccess implements IRenderConfigAccess { /** * @param string $mode * @param \Doc $document * * @return IRenderConfig */ public function getRenderConfig($mode, \Doc $document) { switch($mode) { case RenderConfigManager::ViewMode: //let the CV RENDER do the job return null; default: $wizardRenderConfig = new ContactWizardRenderConfigEdit(); $wizardRenderConfig->initWizardInfos($document); return $wizardRenderConfig; } } }
Les sources telles que déployées à cette étape correspondent au tag step-40-20
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que seul le cadre identité est présenté. En effet, en l'absence de données du client, la première vue est sélectionnée et appliquée.
Le menu est surchargé au moyen d'un template personnalisé pour afficher les différentes étapes du wizard au dessus du menu.
Les sources avant cette étape correspondent au tag step-40-20
.
Le template utilisé est le suivant, à enregistrer dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/contactWizardHeader.mustache
:
[[#wizardInfos]]<div class="wizard_summary clearfix">[[#steps]] <div class="wizard_summary__step [[#current]]wizard_summary__step_current[[/current]]" data-viewid="[[cv_idview]]" style="width:calc(100% / [[nbSteps]])"> <div class="wizard_summary__step__label [[#current]]wizard_summary__step__label_current[[/current]]" title="[[#i18n]]ddui_tuto:wizard::goto step[[/i18n]] [[cv_lview]]" data-viewid="[[cv_idview]]">[[cv_lview]] </div> <div class="wizard_summary__step__attributes">[[#attributes]][[#fields]] <div class="wizard_summary__step__attribute [[#required]]wizard_summary__step__attribute_required[[/required]] [[#filled]]wizard_summary__step__attribute_filled[[/filled]]" data-viewid="[[cv_idview]]" data-attrid="[[attrid]]" data-attrlabel="[[label]]" style="width: calc(100% / [[nbFields]])" title="[[label]]"> </div> [[/fields]][[/attributes]] </div> </div> [[/steps]]</div>[[/wizardInfos]] <nav class="dcpDocument__menu"></nav>
La css correspondante, à enregistrer dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.css
,
est la suivante :
.wizard_summary__step { float: left; padding: 2px 0px; text-align: center; cursor: pointer; } .wizard_summary__step::before { content: "\f054"; /* fa-chevron-right */ font-size: 2em; font-family: FontAwesome; font-style: normal; font-weight: normal; float: right; vertical-align: middle; width: 30px; text-align: center; color: green; } .wizard_summary__step:first-child { padding-left: 5px; } .wizard_summary__step:last-child { padding-right: 5px; } .wizard_summary__step:last-child::before { content: "\f024"; /* fa-flag */ } .wizard_summary__step_optional_unfilled::before { color: orange; } .wizard_summary__step_required_unfilled::before { color: red; } .wizard_summary__step:hover, .wizard_summary__step:active { font-style: italic; text-decoration: underline; } .wizard_summary__step_current { background-color: WhiteSmoke; } .wizard_summary__step__label { font-weight: bold; font-size: 120%; padding: 3px; } .wizard_summary__step__label_current { font-style: italic; } .wizard_summary__step__attributes { width: calc(100% - 30px); float: left; } .wizard_summary__step__attribute { height: 3px; background-clip: content-box; float: left; padding: 0 2px; background-color: orange; } .wizard_summary__step__attribute_required { background-color: red; } .wizard_summary__step__attribute_filled { background-color: green; }
Enfin, 3 méthodes sont surchargées dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
getCssReferences
getTemplates
getContextController
Soit :
public function getContextController(\Doc $document) { $this->initWizardInfos($document); $controller = parent::getContextController($document); $controller["wizardInfos"] = $this->wizardInfos; return $controller; } public function getTemplates(\Doc $document = null) { $this->initWizardInfos($document); $templates = parent::getTemplates($document); $templates["sections"]["menu"]["file"] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/contactWizardHeader.mustache"; return $templates; } public function getCssReferences(\Doc $document = null) { $version = \ApplicationParameterManager::getParameterValue( "CORE", "WVERSION" ); $cssReferences = parent::getCssReferences($document); $cssReferences['DDUI_TUTO_CONTACT_WIZARD'] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.css?ws=" . $version; return $cssReferences; }
Les sources telles que déployées à cette étape correspondent au tag step-40-30
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que le bandeau de navigation entre les différentes étapes est maintenant visible.
Ce bandeau n'est pas fonctionnel pour le moment. Les chapitres suivants feront petit à fonctionner chacun des éléments de ce bandeau.
Les entrées de menu vont être surchargées :
Les sources avant cette étape correspondent au tag step-40-30
.
La méthode getMenu
est surchargée dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
public function getMenu(\Doc $document) { $this->initWizardInfos($document); $menu = parent::getMenu($document); //Hide some menus foreach(['save', 'create', 'createAndClose', 'close', 'workflow'] as $elementId) { $element = $menu->getElement($elementId); if (!is_null($element)) { $element->setVisibility(ElementMenu::VisibilityHidden); } } //add custom menus $item = new ItemMenu( "wizard_end", ___("End creation", "ddui_tuto:wizard"), "#action/wizard.end" ); $item->setBeforeContent('<div class="fa fa-check" />'); $item->setHtmlAttribute("class", "menu--right"); if (!empty($this->wizardInfos['nextStep'])) { $item->setVisibility($item::VisibilityHidden); } $item->useConfirm(___("Confirm end creation", "ddui_tuto:wizard")); $menu->appendElement($item); $item = new ItemMenu( "wizard_next", ___("Next step", "ddui_tuto:wizard"), "#action/wizard.next" ); $item->setBeforeContent('<div class="fa fa-step-forward" />'); $item->setHtmlAttribute("class", "menu--right"); if (\DduiTuto\DDUI_TUTO_CONTACT__WFL::e_up_to_date === $document->getState() || !empty($this->wizardInfos['nextStep'])) { $item->setVisibility($item::VisibilityHidden); } $menu->appendElement($item); $item = new ItemMenu( "wizard_previous", ___("Previous step", "ddui_tuto:wizard"), "#action/wizard.previous" ); $item->setBeforeContent('<div class="fa fa-step-backward" />'); $item->setHtmlAttribute("class", "menu--right"); if (empty($this->wizardInfos['previousStep'])) { $item->setVisibility($item::VisibilityDisabled); } $menu->appendElement($item); $item = new ItemMenu( "wizard_cancel", ___("Cancel", "ddui_tuto:wizard"), "#action/wizard.cancel" ); $item->setBeforeContent('<div class="fa fa-undo" />'); $item->setHtmlAttribute("class", "menu--left"); $menu->appendElement($item); return $menu; }
Les sources telles que déployées à cette étape correspondent au tag step-40-40
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que le menu présente de nouvelles entrées en lieu et place des anciennes.
Le corps du document sera rendu au moyen d'un template personnalisé afin d'afficher les frames sans afficher les onglets. Ce template sera généré à la volée à partir des informations des vues.
Les sources avant cette étape correspondent au tag step-40-40
.
La méthode getTemplates
est mise à jour
dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
public function getTemplates(\Doc $document = null) { $this->initWizardInfos($document); $templates = parent::getTemplates($document); $templates["sections"]["menu"]["file"] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/contactWizardHeader.mustache"; $contentTemplate = ""; foreach($this->wizardInfos['currentStep']['attributes']['frames'] as $frame) { $contentTemplate .= "{{{document.attributes." . $frame['attrid'] . ".htmlView}}}"; } $templates["sections"]["content"]["content"] = $contentTemplate; return $templates; }
Les sources telles que déployées à cette étape correspondent au tag step-40-50
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Aucun changement n'est perceptible dans cette étape puisque la vue affichée ne contient pas d'onglet.
Les informations sur les vues seront rendues disponibles au client au moyen des customServerData
Les sources avant cette étape correspondent au tag step-40-50
.
La méthode getCustomServerData
est surchargée
dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
public function getCustomServerData(\Doc $document) { $this->initWizardInfos($document); $customServerData = parent::getCustomServerData($document); $customServerData["wizardInfos"] = $this->wizardInfos; return $customServerData; }
Les sources telles que déployées à cette étape correspondent au tag step-40-60
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Aucun changement n'est perceptible dans cette étape car ces données seront utilisées plus tard par le code javascript.
Les sources avant cette étape correspondent au tag step-40-60
.
Le code javascript va être enregistré dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js
:
(function wizardContact(window, $){ "use strict"; var updateSummaryStatus = function updateSummaryStatus() { $('.wizard_summary__step').each(function updateSummaryStatus_stepIteratee() { var $this = $(this), $unfilledStepAttributes = $('.wizard_summary__step__attribute', $this) .not('.wizard_summary__step__attribute_filled'); $this.toggleClass( 'wizard_summary__step_required_unfilled', 0 < $unfilledStepAttributes.filter('.wizard_summary__step__attribute_required').length ).toggleClass( 'wizard_summary__step_optional_unfilled', 0 < $unfilledStepAttributes.not('.wizard_summary__step__attribute_required').length ); }); }; window.dcp.document.documentController( "addEventListener", "ready", { "name": "addWizardEvents", "documentCheck": function addWizardEventsDocumentCheck(documentObject) { return documentObject.family.name === "DDUI_TUTO_CONTACT" && documentObject.renderMode === "edit"; } }, function addWizardEvents(/*event, documentObject*/) { updateSummaryStatus(); } ); })(window, $);
Ce fichier javascript est ensuite injecté en surchargeant la méthode getJsReferences
dans la classe ContactWizardRenderConfigEdit
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactWizardRenderConfigEdit.php
:
public function getJsReferences(\Doc $document = null) { $version = \ApplicationParameterManager::getParameterValue( "CORE", "WVERSION" ); $jsReferences = parent::getJsReferences($document); $jsReferences['DDUI_TUTO_CONTACT_WIZARD'] = "DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js?ws=" . $version; return $jsReferences; }
Les sources telles que déployées à cette étape correspondent au tag step-40-70
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que les chevrons sont colorés en fonction des attributs renseignés.
Lors du click sur les éléments de menu, un événement de type action est déclenché.
Les sources avant cette étape correspondent au tag step-40-70
.
L'événement déclenché au click sur un menu événement sera capturé
par l'ajout d'un écouteur actionClick.wizard.contact
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js
:
this.documentController( "addEventListener", "actionClick", { "name": "actionClick.wizard.contact", "documentCheck": function actionClickWizardContactDocumentCheck(documentObject) { return documentObject.family.name === "DDUI_TUTO_CONTACT" && documentObject.renderMode === "edit"; } }, function actionClickWizardContact(event, documentObject, options) { var customServerData = this.documentController("getCustomServerData"), currentWizardStepName = null; if(customServerData && customServerData.wizardInfos && customServerData.wizardInfos.currentStep) { currentWizardStepName = customServerData.wizardInfos.currentStep.cv_idview; } switch (options.eventId) { case 'wizard.cancel': this.documentController( "reinitDocument", { viewId: '!defaultConsultation' } ); break; case 'wizard.previous': case 'wizard.next': // save document and send customClientData with goto and currentStepName this.documentController( "saveDocument", { customClientData: { goto: options.eventId, currentWizardStepName: currentWizardStepName } } ).then(function actionClickWizardContact_success(successInfos) { successInfos.element.documentController( "showMessage", "Document has been saved" ); }, function actionClickWizardContact_error(errorInfos) { errorInfos.element.documentController( "showMessage", { type: 'error', message: 'an error occured: ' + errorInfos.errorMessage.contentText } ); }); break; case 'wizard.end': //TODO break; default: return; } event.preventDefault(); } );
Les sources telles que déployées à cette étape correspondent au tag step-40-80
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons qu'il est possible de naviguer d'étape en étape au moyen du menu.
Les sources avant cette étape correspondent au tag step-40-80
.
Nous utiliserons JQuery pour déclencher un événement lors du clic sur une étape
Cet événement sera capturé par l'ajout d'un écouteur actionClick.wizard.contact
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js
:
this.documentController( "addEventListener", "custom:wizardgotostep", { "name": "gotoStep.wizard.contact", "documentCheck": function gotoStepWizardContactDocumentCheck(documentObject) { return documentObject.family.name === "DDUI_TUTO_CONTACT" && documentObject.renderMode === "edit"; } }, function gotoStepWizardContact(event, targetStep) { var customServerData = this.documentController("getCustomServerData"), currentWizardStepName = null; event.preventDefault(); if (customServerData && customServerData.wizardInfos && customServerData.wizardInfos.currentStep) { currentWizardStepName = customServerData.wizardInfos.currentStep.cv_idview; } this.documentController( "reinitDocument", { customClientData: { goto: 'wizard.targetStep', currentWizardStepName: currentWizardStepName, targetStep: targetStep } } ); } ); $('.wizard_summary').on('click', '.wizard_summary__step', function stepLabelClick() { window.dcp.document.documentController( "triggerEvent", "custom:wizardgotostep", $(this).data('viewid') ); });
Les sources telles que déployées à cette étape correspondent au tag step-40-90
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons qu'il est possible de naviguer d'étape en étape en cliquant sur le libellé des étapes.
Les sources avant cette étape correspondent au tag step-40-90
.
Un écouteur change.wizard.contact
, déclenché à chaque changement de valeur, est ajouté au fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js
:
this.documentController( "addEventListener", "change", { "name": "change.wizard.contact", "documentCheck": function changeWizardContactDocumentCheck(documentObject) { return documentObject.family.name === "DDUI_TUTO_CONTACT" && documentObject.renderMode === "edit"; } }, function changeWizardContact(event, documentObject, attributeObject, values) { $('.wizard_summary__step__attribute[data-attrid=' + attributeObject.id + ']') .toggleClass( 'wizard_summary__step__attribute_filled', values.current.value !== '' ); updateSummaryStatus(); } );
Les sources telles que déployées à cette étape correspondent au tag step-40-100
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que le bandeau de navigation est bien rafraîchi lors de l'ajout ou de la suppression d'une valeur dans le document.
Lorsque l'utilisateur clique sur le bouton de fin de wizard, le document est enregistré et change d'état.
Les sources avant cette étape correspondent au tag step-40-100
.
Le clic sur ce bouton émet un événement de type action.
Cet événement est traité en ajoutant la gestion de l'action wizard.end
dans l'écouteur actionClick.wizard.contact
dans le fichier
DDUI_TUTO/Families/DDUI_TUTO_CONTACT/Layout/wizard.js
.
Il suffit de sauver le document puis d'appeler la méthode changeStateDocument
du contrôleur de document :
this.documentController( "addEventListener", "actionClick", { "name": "actionClick.wizard.contact", "documentCheck": function actionClickWizardContactDocumentCheck(documentObject) { return documentObject.family.name === "DDUI_TUTO_CONTACT" && documentObject.renderMode === "edit"; } }, function actionClickWizardContact(event, documentObject, options) { var customServerData = this.documentController("getCustomServerData"), currentWizardStepName = null; if(customServerData && customServerData.wizardInfos && customServerData.wizardInfos.currentStep) { currentWizardStepName = customServerData.wizardInfos.currentStep.cv_idview; } switch (options.eventId) { case 'wizard.cancel': this.documentController( "reinitDocument", { viewId: '!defaultConsultation' } ); break; case 'wizard.previous': case 'wizard.next': this.documentController( "saveDocument", { customClientData: { goto: options.eventId, currentWizardStepName: currentWizardStepName } } ); break; case 'wizard.end': this.documentController( "saveDocument", { customClientData: { currentWizardStepName: currentWizardStepName } ).then(function wizardEnd_changeState() { window.dcp.document.documentController( "changeStateDocument", { "nextState": "ctc_e2", "transition": "ctc_t_e1__e2" }, { viewId: '!defaultConsultation', revision: -1 } ); } }); break; default: return; } event.preventDefault(); } );
Les sources telles que déployées à cette étape correspondent au tag step-40-110
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en modification à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultEdition.html, nous constatons que le bouton de fin de wizard est fonctionnel.
En consultation, le menu de modification doit afficher l'étape en cours.
Les sources avant cette étape correspondent au tag step-40-110
.
Cela se fait en modifiant le libellé du menu de modification par une surcharge de la méthode getMenu
dans le fichier DDUI_TUTO/Families/DDUI_TUTO_CONTACT/ContactRenderConfigView.php
:
public function getMenu(\Doc $document) { $menu = parent::getMenu($document); $modifLabel = ___("Modify", "UiMenu"); $wizardTags = $document->getUTag('wizard'); if (false === $wizardTags) { $wizardTags = []; } else { $wizardTags = json_decode($wizardTags->comment, true); } if (isset($wizardTags['currentWizardStepName'])) { $modifLabel .= " (" . $wizardTags['currentWizardStepLabel'] . ")"; } $modifMenu = $menu->getElement("modify"); if (!is_null($modifMenu)) { $modifMenu->setTextLabel($modifLabel); } return $menu; }
Les sources telles que déployées à cette étape correspondent au tag step-40-120
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
En accédant au contact Thomas ANDERSON en consultation à l'adresse http://localhost:8080/api/v1/documents/CONTACT_THOMAS_ANDERSON/views/!defaultConsultation.html, nous constatons que le bouton de modification reflète bien la dernière étape consultée.
Vous avez vu dans cette partie que tous les comportements par défaut du document sont personnalisables, au niveau serveur par du code PHP, et au niveau client par du code Javascript.
Ce code peut intercepter l'ensemble des comportements prédéfinis pour les modifier, mais il est également possible d'ajouter des données supplémentaires et de les traiter pour non seulement modifier, mais aussi étendre le comportement par défaut.
Enfin, couplés aux fonctionnalités de CSS vues au chapitre précédent, ces surcharges permettent de changer profondément la façon dont les documents sont présentés à l'utilisateur.
Dans la partie suivante, vous apprendrez à intégrer ces documents enrichis à une interface applicative complexe.
Le but est ici de manipuler le document depuis une autre interface. Il est ainsi possible de présenter des documents dans une interface spécifique, ainsi que de les manipuler simplement, sans devoir injecter de code dans la famille manipulée.
Ce tutoriel est livré avec une interface minimaliste de gestion des contacts, accessible à l'adresse http://localhost:8080/?app=SIMPLE_LIST.
Cette application affiche en colonne de gauche tous les documents de la famille Contact
.
Pour simplifier le déroulement de ce chapitre, l'application génère déjà des événements et en écoute d'autres, aussi l'objet de ce chapitre est-il uniquement de manipuler le document lui-même.
Figure 13. Application de gestion des contacts
Lors du clic sur une fiche résumé, l'application déclenche un événement documentElementClicked
sur la window.
Nous allons écouter cet événement et afficher le document dans la zone .documentWrapper
.
Les sources avant cette étape correspondent au tag step-50-00
.
Dans le fichier SIMPLE_LIST/Layout/custom.js
,
ajoutons un écouteur de l'événement documentElementClicked
, qui charge le document demandé.
Créons également la méthode addDocumentListeners
, déclenchée lors de l'initialisation du widget,
et chargée d'attacher les écouteurs d'événements au widget.
En particulier, cette méthode écoute l'événement ready
du widget
pour signaler à l'application que ce document est affiché.
var loadDocument = function loadDocument(fetchOptions) { //check if the widget has already been initialised if (_.isUndefined($documentWrapper.document("instance"))) { //if not, initialize it $documentWrapper.document(fetchOptions) //and attach listeners to the newly created widget .on("documentloaded", addDocumentListeners); } else { //if yes, reuse it $documentWrapper.document("fetchDocument", fetchOptions); } }, addDocumentListeners = function addDocumentListeners() { // propagate that this document is opened each time it is reloaded $documentWrapper.document( "addEventListener", "ready", { "name": "ready.simple_list" }, function simpleList_propagateReady(event, documentObject) { // refresh the currently selected document $window.trigger('documentOpened', $documentWrapper.document("getProperties")); } ); }; $window.on('documentElementClicked', function onDocumentElementClicked(event, options) { var fetchOptions = { "initid": options.initid, "viewId": "!defaultConsultation" }; loadDocument(fetchOptions) });
Les sources telles que déployées à cette étape correspondent au tag step-50-10
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, un clic sur un document de la liste de gauche l'ouvre dans la zone de droite.
Nous allons réagir à l'événement change
du widget.
Les sources avant cette étape correspondent au tag step-50-10
.
Enrichissons la méthode addDocumentListeners
du fichier
SIMPLE_LIST/Layout/custom.js
en écoutant l'événement change
du widget
pour signaler à l'application que ce document est modifié :
// propagate that this document has changed $documentWrapper.document( "addEventListener", "change", { "name": "change.simple_list" }, function simpleList_propagateChange(event, documentObject) { $window.trigger('documentChanged', documentObject); } );
Ici, nous nous contentons de déclencher l'événement en charge de la mise à
jour de l'application. Le comportement de l'application étant en dehors du scope de ce tutoriel, son contenu n'est pas
présenté. Il est néanmoins accessible dans le code source dans le fichier
SIMPLE_LIST/Layout/main.js
.
Les sources telles que déployées à cette étape correspondent au tag step-50-20
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, lors de la modification d'un document ouvert, le statut modifié (matérialisé par une astérisque jaune) est reporté dans la liste de gauche.
Nous allons réagir à l'événement afterSave
du widget.
Les sources avant cette étape correspondent au tag step-50-20
.
Enrichissons la méthode addDocumentListeners
du fichier
SIMPLE_LIST/Layout/custom.js
en écoutant l'événement afterSave
du widget
pour signaler à l'application que ce document a été sauvegardé :
// propagate that this document has been saved $documentWrapper.document( "addEventListener", "afterSave", { "name": "afterSave.simple_list" }, function simpleList_propagateAfterSave(event, documentObject) { $window.trigger('documentSaved', documentObject); } );
Ici, nous nous contentons de déclencher l'événement en charge de la mise à
jour de l'application. Le comportement de l'application étant en dehors du scope de ce tutoriel, son contenu n'est pas
présenté. Il est néanmoins accessible dans le code source dans le fichier
SIMPLE_LIST/Layout/main.js
.
Les sources telles que déployées à cette étape correspondent au tag step-50-30
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, lors de la modification du nom ou du prénom d'un contact, le nouveau titre est reporté dans la liste de gauche après la sauvegarde du document.
Lors du clic sur le bouton Nouveau Contact
, l'application déclenche un événement buttonCreateClicked
.
Écoutons cet événement et affichons l'interface de création dans la zone .documentWrapper
.
Les sources avant cette étape correspondent au tag step-50-30
.
Dans le fichier SIMPLE_LIST/Layout/custom.js
,
ajoutons un écouteur de l'événement buttonCreateClicked
, qui charge l'interface de création de la famille demandée :
$window.on('buttonCreateClicked', function onButtonCreateClicked(event, options) { var fetchOptions = { "initid": options.famid, "viewId": "!defaultCreation" }; loadDocument(fetchOptions); });
Les sources telles que déployées à cette étape correspondent au tag step-50-40
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, un clic sur le bouton Nouveau Contact ouvre l'interface de création.
Il n'existe pas d'événement spécifique à la création d'un document.
Pour détecter une création, nous allons écouter l'événement afterSave
du widget,
et signaler une création à l'interface dans le cas où le document n'avait pas d'initid
.
Les sources avant cette étape correspondent au tag step-50-40
.
Modifions l'écouteur de l'événement afterSave
dans la méthode addDocumentListeners
du fichier
SIMPLE_LIST/Layout/custom.js
:
// propagate that this document has been saved $documentWrapper.document( "addEventListener", "afterSave", { "name": "afterSave.simple_list" }, function simpleList_propagateAfterSave(event, currentDocumentObject, previousDocumentObject) { if(previousDocumentObject.initid === 0) { // if previous document had no initid, it is a creation $window.trigger('documentCreated', currentDocumentObject); } else { // otherwise, it is a simple save $window.trigger('documentSaved', currentDocumentObject); } } );
Les sources telles que déployées à cette étape correspondent au tag step-50-50
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, lors de la création d'un contact, le nouveau contact est ajouté à la liste de gauche.
Nous allons réagir à l'événement afterDelete
du widget.
Les sources avant cette étape correspondent au tag step-50-50
.
Enrichissons la méthode addDocumentListeners
du fichier
SIMPLE_LIST/Layout/custom.js
en écoutant l'événement afterDelete
du widget
pour signaler à l'application que ce document a été supprimé:
// propagate that this document has been deleted $documentWrapper.document( "addEventListener", "afterDelete", { "name": "afterDelete.simple_list" }, function simpleList_propagateAfterDelete(event, documentObject) { $window.trigger('documentDeleted', documentObject); } );
Ici, nous nous contentons de déclencher l'événement en charge de la mise à
jour de l'application. Le comportement de l'application étant en dehors du scope de ce tutoriel, son contenu n'est pas
présenté. Il est néanmoins accessible dans le code source dans le fichier
SIMPLE_LIST/Layout/main.js
.
Les sources telles que déployées à cette étape correspondent au tag step-50-60
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, lors de la suppression d'un contact, sa fiche est supprimée de la liste de gauche.
Nous allons réagir à l'événement afterRestore
du widget.
Les sources avant cette étape correspondent au tag step-50-60
.
Enrichissons la méthode addDocumentListeners
du fichier
SIMPLE_LIST/Layout/custom.js
en écoutant l'événement afterRestore
du widget
pour signaler à l'application que ce document a été restauré :
// propagate that this document has been restored $documentWrapper.document( "addEventListener", "afterRestore", { "name": "afterRestore.simple_list" }, function simpleList_propagateAfterRestore(event, documentObject) { $window.trigger('documentRestored', documentObject); } )
Ici, nous nous contentons de déclencher l'événement en charge de la mise à
jour de l'application. Le comportement de l'application étant en dehors du scope de ce tutoriel, son contenu n'est pas
présenté. Il est néanmoins accessible dans le code source dans le fichier
SIMPLE_LIST/Layout/main.js
.
Les sources telles que déployées à cette étape correspondent au tag step-50-70
.
Le déploiement se fait au moyen du developer toolkit (pour plus d'explications sur les outils de développement, se rendre sur leur documentation).
La commande est donc :
pour linux :
php dynacase-devtool.phar deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
pour windows :
dynacase-devtool.bat deploy -u localhost -p 8080 -c dynacase -s path/to/sources --auto-release
Depuis l'application à l'adresse http://localhost:8080/?app=SIMPLE_LIST, immédiatement après la suppression d'un contact et que sa fiche ait été supprimée de la liste de gauche, il est possible de le restaurer. Sa fiche est alors ajoutée à nouveau à la liste de gauche.
Dans cette partie, vous avez appris à utiliser le widget de document.
Ce composant permet de simplement intégrer un ou plusieurs documents dans une interface complexe, en ayant une abstraction du fonctionnement interne du document. Il est piloté par des méthodes et émet des événements auxquels votre interface peut réagir.
Ce document est publié sous licence CC http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
Vous êtes libres :
Selon les conditions suivantes :
Quick Start
© Anakeen, Anakeen Labs <labs@anakeen.com>
Module Document User Interface, version 1.0
Édition 1
Publié le 03/08/2018
Ce livre a été produit avec easybook 4.8, logiciel libre et open source développé par Javier Eguiluz à l'aide de différents composants Symfony.