Naviguer entre les vues
Vous pouvez trouver des informations complémentaires concernant les transitions dans la documentation de l'OIP Core et dans la documentation OIP par l'exemple
Les fichiers responsables de la logique de transition des vues se trouvent dans le dossier viewsConfig
viewsConfig/
ââ transitions-handlers/
â ââ altSummary.mjs
â ââ home.mjs
â ââ start.mjs
â ââ summary.mjs
ââ 01_home.yml
ââ 02_start.yml
ââ 03_summary.yml
ââ 04_alt_summary.yml
ââ transitions.mjs
ââ workflow.mjsLe fichier workflow.mjs liste les identifiants des vues du projet et dĂ©finit la premiĂšre vue du parcours. Les identifiants des vues sont l'identifiant viewId dĂ©clarĂ© dans le fichier de configuration de chacune des vues :
export default {
rootView: 'home',
views: ['home', 'start', 'summary', 'altSummary']
};Le fichier transitions.mjs définit la liste de toutes les transitions possibles entre les vues du projet :
export default [
{
srcViewId: 'home',
tgtViewId: 'start',
action: 'next',
conditionLabel: 'home_next',
conditionOrder: 1
},
{
srcViewId: 'start',
tgtViewId: 'summary',
action: 'next',
conditionLabel: 'start_to_summary',
conditionOrder: 1
},
{
srcViewId: 'start',
tgtViewId: 'altSummary',
action: 'next',
conditionLabel: 'start_to_altSummary',
conditionOrder: 2
},
{
srcViewId: 'start',
tgtViewId: 'home',
action: 'prev',
conditionLabel: 'start_prev',
conditionOrder: 1
},
{
srcViewId: 'summary',
tgtViewId: 'start',
action: 'prev',
conditionLabel: 'summary_prev',
conditionOrder: 1
},
{
srcViewId: 'altSummary',
tgtViewId: 'start',
action: 'prev',
conditionLabel: 'altSummary_prev',
conditionOrder: 1
}
];Chaque élément de la liste définit une transition possible :
- srcViewId l'id de la vue source
- tgtViewId l'id de la vue ciblée par la transition
- action l'action de la transition, deux choix possibles next et prev
- conditionLabel définit le nom de l'handler de cette transition
- conditionOrder définit l'ordre d'éxecution de la transition
Il peut y avoir plusieurs transitions possibles pour une mĂȘme vue source et pour une mĂȘme action. Dans ce cas conditionOrder dĂ©finit l'ordre d'Ă©valuation de ces transitions.
Logique de transition
La transition dâune vue Ă une autre est conditionnĂ©e par lâĂ©valuation de la logique dĂ©finie dans le handler associĂ© Ă la transition.
Si lâexĂ©cution du handler est un succĂšs, alors la transition est dĂ©clenchĂ©e. Dans le cas contraire, si le handler Ă©choue, le moteur teste la transition suivante (sâil en existe une). La transition suivante est identifiĂ©e par le mĂȘme srcViewId, la mĂȘme action, mais avec un conditionOrder incrĂ©mentĂ© (valeur n + 1).
Tant que lâexĂ©cution Ă©choue, le moteur continue de tester les transitions suivantes dans lâordre dĂ©fini par conditionOrder. Si aucune des transitions disponibles ne rĂ©ussit, le moteur retourne une erreur.
Les fichiers contenant les handlers sont situĂ©s dans le dossier viewsConfig/transitions-handlers. Par convention, chaque fichier correspond Ă une vue et porte pour nom lâidentifiant de cette vue.
Exemple : fichier du handler pour la vue start :
export default {
start: {
hooks: {
beforeNext: () => {
// add `message` to the context transition
return {
message: 'hello world!'
};
}
},
transitionConditions: {
start_to_summary: (ctx) => {
console.log(ctx.message); // => hello world!
const customer = ctx?.customer;
return customer && customer.firstName && customer.lastName;
},
start_to_altSummary: () => true,
start_prev: () => true
}
}
};Les hooks
L'objet hooks définit des logiques qui seront exécutées avant ou aprÚs l'évaluation des conditions de transition. Les hooks sont utiles pour exécuter des traitements asynchrones par exemple.
Lâobjet hooks permet de dĂ©finir des logiques Ă exĂ©cuter avant ou aprĂšs lâĂ©valuation des conditions de transition. Les hooks sont notamment utiles pour effectuer des traitements asynchrones (appels dâAPI, rĂ©cupĂ©ration de donnĂ©es, etc.).
Hooks disponibles
Quatre hooks peuvent ĂȘtre dĂ©finis :
- beforeNext â exĂ©cutĂ© avant chaque transition dont lâaction est next
- afterNext â exĂ©cutĂ© aprĂšs chaque transition dont lâaction est next
- beforePrev â exĂ©cutĂ© avant chaque transition dont lâaction est prev
- afterPrev â exĂ©cutĂ© aprĂšs chaque transition dont lâaction est prev
Fonctionnement
Un hook est une fonction recevant en paramÚtre un objet context, représentant le contexte de la transition. Les hooks beforeNext et beforePrev peuvent surcharger ce contexte : les propriétés ajoutées seront ensuite accessibles dans les handlers des transitions concernées.
Exemple
Dans lâexemple ci-dessous, un hook beforeNext est dĂ©fini. Il ajoute une propriĂ©tĂ© message au contexte. Les handlers liĂ©s Ă une transition de type next recevront ce contexte enrichi en paramĂštre.
Les handlers de transition
Signature d'un handler de transition : (ctx) => boolean
L'objet transitionConditions d'un fichier handler d'une vue définit les handlers de transition de la vue. Les propriétés de cet objet sont les valeurs des propriétés conditionLabel définies depuis le fichier transitions.mjs
Un handler est une fonction qui peut reçevoir en paramÚtre un objet context qui représente le context de la transition.
La fonction doit impérativement retourner un booléen. Si true est retourné alors le moteur valide la transition, si false est retourné alors la transition suivante est évaluée.
Contexte de transition
L'objet context reçu en paramÚtre d'un handler de transition est par défaut de la forme :
{
projectId
setup
...dataFromView
}- projectId contient l'id de l'entité Project en cours
- setup contient les champs ajoutés au contexte depuis les hooks beforeNext et beforePrev ou est undefined si le contexte n'est pas surchargé
- les informations passées depuis une vue (via les handlers de transition de processHandlers) sont ajoutées et accessibles depuis la racine de l'objet context
Déclencher une transition depuis une vue
Le hook client useProcess qui peut ĂȘtre importĂ© dans les composants des vues depuis la dĂ©pendance @fasstech/oip-starter-utils retourne en rĂ©ponse un objet dont la propriĂ©tĂ© processHandlers expose des mĂ©thodes relatives Ă la logique de transition :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Home = () => {
const { processHandlers } = useProcess();
// processHandlers.onAction
// processHandlers.onNext
// processHandlers.onPrev
return (
<div className="t-home">
...
</div>
);
}
export default Home;- onAction permet de déclencher une transition
Prend un objet en paramĂštre de type { action: 'NEXT'|'PREV', context: any }
- onNext permet de déclencher la transition vers la vue suivante
Prend un objet en paramĂštre de type { context: any }
- onPrev permet de déclencher la transition vers la vue précédente
Prend un objet en paramĂštre de type { context: any }
Lors de l'appel à une de ces méthodes, les informations de l'objet context passé en paramÚtre sont reçu par les hooks ainsi que par les handlers relatifs à la transition ciblée. Ce paramÚtre est optionnel.
Se référer au chapitre Process handlers pour la documentation complÚte des handlers de transition exposés par le hook useProcess
Passer de la metadata lors d'une transition
La gestion de metadata lors des transitions est disponible à partir de la version 3.5.0 de l'OIP Core combinée à une version de l'OIP Starter Utils >= 3.0.4
Il est possible de passer un objet metadata lors du déclenchement d'une transition depuis une vue. Cette metadata sera alors accessible depuis le contexte des composants ou depuis le contexte des resolvers de la vue suivante, cf. Process
Pour se faire il vous suffit de définir un objet metadata dans l'objet context passé en paramÚtre aux méthodes de transitions depuis le composant d'une vue :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onNext = () => {
processHandlers.onNext({
// transition context
context: {
logic: true,
// metadata definition
metadata: {
someId: 'azerty'
}
}
});
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onNext}>NEXT</button>
</div>
);
};
export default Demo;Explication de la logique depuis la vue start
Explication complĂšte de la logique de transition conditionnelle pour l'action next depuis la vue start :
- La transition next est déclenchée depuis le composant views/start/client/Start.jsx grùce à la méthode onNext exposée par la propriété processHandlers reçu en réponse du hook useProcess
import { useProcess } from '@fasstech/oip-starter-utils/app';
import useGetCustomerQuery from './hooks/useGetCustomerQuery.js';
const Start = () => {
const { processHandlers } = useProcess();
const {
getCustomer,
loading: isLoadingGetCustomer,
refetch
} = useGetCustomerQuery();
const $onNext = () => {
processHandlers.onNext({
context: {
customer: getCustomer
}
});
};
...
return (
<div className="t-home">
...
<button className="f-button ml-2" onClick={$onNext}>NEXT</button>
</div>
);
}
export default Start;- L'objet context passé en paramÚtre à la méthode onNext contient l'entité customer
- Deux transitions sont possibles pour l'action next depuis la vue start. Ces transitions sont définies comme suit dans le fichier transitions.mjs :
export default [
...
{
srcViewId: 'start',
tgtViewId: 'summary',
action: 'next',
conditionLabel: 'start_to_summary',
conditionOrder: 1
},
{
srcViewId: 'start',
tgtViewId: 'altSummary',
action: 'next',
conditionLabel: 'start_to_altSummary',
conditionOrder: 2
},
...
];- transition start -> summary - ordre d'évaluation 1
- transition start -> altSummary - ordre d'évaluation 2
- Lors de l'évaluation de la transition next depuis la vue start le moteur de transition va d'abord évaluer la premiÚre transition possible start -> summary
- Le hook beforeNext comme défini dans le fichier transitions-handlers/start.mjs est d'abord exécuté. Le context de transition est alors surchargé par l'ajout de la propriété message
export default {
start: {
hooks: {
beforeNext: () => {
return {
message: 'hello world!'
};
}
},
transitionConditions: {
start_to_summary: (ctx) => {
console.log(ctx.setup.message); // => hello world!
const customer = ctx?.customer;
return customer && customer.firstName && customer.lastName;
},
start_to_altSummary: () => true,
start_prev: () => true
}
}
};- Ensuite l'handler de la transition nommé start_to_summary comme défini en valeur de la propriété conditionLabel dans le fichier transitions.mjs est exécuté.
La logique de l'handler est définie dans le fichier des handlers de la vue start (comme ci-dessus) depuis la propriété transitionConditions.start_to_summary.
La fonction associée reçoit en paramÚtre l'entité customer définie depuis l'objet ctx
- Si l'entité customer est correctement définie alors l'évaluation est un succÚs. true est retourné par la fonction. Le moteur valide la transition vers la vue summary comme défini dans le fichier transitions.mjs propriété tgtViewId de la transition relative
start -> summary
- Si l'entité customer n'est pas complÚte alors l'évaluation échoue. false est retourné par la fonction. Le moteur évalue alors la transition suivante dans l'ordre défini par conditionOrder
Dans notre exemple la transition suivante à évaluer est donc start -> altSummary
export default [
...
{
srcViewId: 'start',
tgtViewId: 'altSummary',
action: 'next',
conditionLabel: 'start_to_altSummary',
conditionOrder: 2
},
...
];- Le moteur évalue alors l'handler start_to_altSummary. Cet handler réussit à chaque fois puisqu'il retourne toujours true. Le moteur valide la transition vers la vue altSummary
start -> altSummary
Lors de l'ajout d'une vue
Lors de l'ajout d'une vue il vous faut éditer / ajouter les différents fichiers relatifs aux transitions :
- éditer le fichier workflow.mjs et ajouter l'identifiant de la nouvelle vue à la liste views
- éditer le fichier transitions.mjs et ajouter les transitions relatives à la nouvelle vue
- ajouter le fichier des handlers de la nouvelle vue dans le dossier transitions-handlers
Choix conditionnel de la 1Ăšre vue du parcours
Cette fonctionnalité est disponible à partir de la version 3.4.0 de la dépendance OIP Starter Utils.
Cette fonctionnalité vous permet également de définir la vue souhaitée en fonction de la derniÚre vue active d'un projet lors d'une reprise du parcours.
Par défaut, le parcours démarre par la vue rootView définie dans le fichier viewsConfig/workflow.mjs sans configuration supplémentaire.
Mais vous pouvez également choisir de démarrer votre parcours par une vue différente en fonction de la valeur d'une propriété d'une entitié par exemple.
Pour ce faire, vous pouvez passer une callback resolveFirstView en paramÚtre de la méthode startServer du fichier server/index.mjs, ex. :
import { start as startServer } from '@fasstech/oip-starter-utils/server';
import { resolveFirstView } from './resolve-first-view.mjs';
const config = {
// ...
resolveFirstView,
};
const { app } = await startServer(config);La callback resolveFirstView est exécutée par le server à la suite de l'initialisation de l'entité Project. Par conséquent, vous pouvez accéder à l'entité Project dans le corps de la callback.
La callback resolveFirstView est appelée avec les paramÚtres suivants :
- en 1er paramÚtre, l'identifiant de l'entité Project actuelle est reçu
- en 2Úme paramÚtre, un objet { viewId, metadata } ou null est reçu. Cet objet correspond au process existant si il existe. Par exemple dans le cas de la reprise d'un projet existant, viewId contiendra l'identifiant de la derniÚre vue active du parcours lié à l'entité Project actuelle (identifiée par le 1er paramÚtre)
La callback doit toujours retourner l'identifiant d'une vue peu importe vos conditions.
Initialiser les transitions
Fichier viewsConfig/workflow.mjs
Le fichier viewsConfig/workflow.mjs contient deux informations :
- L'identifiant de la premiĂšre vue de l'OAV.
- La liste des identifiants de l'ensemble des vues.
export default {
rootView: 'home',
views: ['home', 'summary']
};Fichier viewsConfig/transitions.mjs
Le fichier viewsConfig/transitions.mjs contient les transitions entre toutes les vues de l'OAV.
export default [
{
srcViewId: 'home',
tgtViewId: 'summary',
action: 'next',
conditionOrder: 1
},
{
srcViewId: 'summary',
tgtViewId: 'home',
action: 'prev',
conditionOrder: 1
}
];Déclarer une transition conditionnelle
Une transition est conditionnelle si elle a la propriété conditionLabel.
Déclaration d'une transition conditionnelle Company => Grantee.
Fichier viewsConfig/transitions.mjs
export default [
{
srcViewId: 'home',
tgtViewId: 'company',
action: 'next',
conditionOrder: 1
},
{
srcViewId: 'company',
tgtViewId: 'home',
action: 'prev',
conditionOrder: 1
},
{
srcViewId: 'company',
tgtViewId: 'grantee',
action: 'next',
conditionOrder: 1,
conditionLabel: 'company_next_grantee'
},
{
srcViewId: 'company',
tgtViewId: 'summary',
action: 'next',
conditionOrder: 2
},
{
srcViewId: 'grantee',
tgtViewId: 'company',
action: 'prev',
conditionOrder: 1
},
{
srcViewId: 'grantee',
tgtViewId: 'summary',
action: 'next',
conditionOrder: 1
},
{
srcViewId: 'summary',
tgtViewId: 'grantee',
action: 'prev',
conditionOrder: 1
}
];Fichier viewsConfig/transitions-handlers/company.mjs
export default {
company: {
hooks: {},
transitionConditions: {
company_next_grantee: (ctx) => ctx.form.isActive
}
}
};Utiliser les hooks
Les hooks disponibles sont au nombre de quatre : beforeNext, beforePrev, afterNext, afterPrev.
export default {
company: {
hooks: {
beforeNext: (ctx) => {
// Récupération de données
// pour les mettre Ă disposition de tous les handlers
return foo(ctx);
}
},
transitionConditions: {
company_next_grantee: (ctx) => {
// `ctx.setup` contient la valeur de retour de `foo(ctx)`
}
}
}
};