API Client
Présentation
L'API client expose les éléments suivants (named exports) :
- la méthode start qui permet d'initialiser l'application React ;
- le hook useProcess qui permet la gestion des transitions et des tĂąches depuis les composants des vues de l'OAV ;
- le hook useCommitMutation qui permet la gestion d'une mutation graphQL depuis les composants des vue de l'OAV ;
- le hook useSubscription qui permet la gestion d'une subscription graphQL depuis les composants des vue de l'OAV ;
- la définition des queries graphQL TaskSubscription et TaskWorkflowSubscription qui permettent de souscrire à l'état d'une tùche ou d'un workflow de tùches (à utiliser avec le hook useSubscription) ;
- le composant Router qui permet d'initialiser les routes de l'OAV et de configurer la navigation navigateur ;
- le hook useClientSync lié à la fonctionnalité de la synchronisation des connexions clientes ;
- le hook useBlockBrowserNav qui permet de désactiver la navigation navigateur pour la vue appelante.
Les imports depuis l'OAV :
import {
start,
useProcess,
Router,
useCommitMutation,
useSubscription,
TaskSubscription,
TaskWorkflowSubscription,
useClientSync,
useBlockBrowserNav,
} from '@fasstech/oip-starter-utils/app';Méthode start
La méthode start initialise l'application React de l'OAV. Elle prend en paramÚtre un objet de configuration.
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// Init client app
(() => {
start({ /* properties */ })();
})();Propriétés requises
app
Le composant App de l'OAV est attendu en valeur. Le composant App doit impérativement charger le composant Router fournit par la lib.
Exemple :
import { start, Router } from '@fasstech/oip-starter-utils/app';
// App component
const App = () => {
// ...
return (
<>
<OtherProvider>
{/* Router component must be returned */}
<Router views={views} />
</OtherProvider>
</>
);
};
// Init client app
(() => {
start({
app: App,
// ...
});
})();processFragment
La définition du fragment graphQL de l'objet Process est attendue en valeur.
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
import { gql } from '@apollo/client';
// Process fragment def
const ProcessFragment = gql`
fragment ProcessFragment on ExtendedProcess {
# required fields
projectId
viewId
viewData
sessionId
clientId
# additional fields
# requested fields must match type definition at server/graphql/types/extended-process-type.mjs
# add your custom fields here
# ...
}
`;
// Init client app
(() => {
start({
processFragment: ProcessFragment,
// ...
});
})();Propriétés optionnelles
ctx
Définit la maniÚre dont le token du contexte client est récupéré lors du décrochage sur l'OAV.
Valeurs possibles : 'local-storage' | 'session-storage' | 'shadow-crm' | 'url' | { token: string } | { projectId: string }
Par défaut ou si la méthode spécifiée échoue, le token est recherché dans les paramÚtres de l'URL (paramÚtre token ou projectId)
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// from local storage
(() => {
localStorage.setItem('ctxToken', 'my-ctx-client-token');
// or
localStorage.setItem('fasstProjectId', 'my-fasst-project-id');
start({
// ...
ctx: 'local-storage'
});
})();
// from session storage
(() => {
sessionStorage.setItem('ctxToken', 'my-ctx-client-token');
// or
sessionStorage.setItem('fasstProjectId', 'my-fasst-project-id');
start({
// ...
ctx: 'session-storage'
});
})();
// as parameter
(() => {
start({
// ...
ctx: {
token: 'my-ctx-client-token',
// or
projectId: 'my-fasst-project-id'
}
});
})();
// default like
// URL: https://my.oav.fasst/?token=my-ctx-client-token
// or
// URL: https://my.oav.fasst/?projectId=my-fasst-project-id
(() => {
start({
// ...
ctx: 'url'
});
})();redirectOnError
Boolean. Permet d'activer ou de désactiver la redirection vers la page d'erreur relative lors d'une erreur HTTP lors de la navigation sur l'OAV. Activé par défaut.
Redirections gérées :
- erreur 400 => redirection vers /bad-request
- erreur 401 => redirection vers /unauthorized
- erreur 403 => redirection vers /forbidden
- erreur 404 => redirection vers /not-found
- erreur 500 => redirection vers /internal-server-error
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// Init client app
(() => {
startApp({
// ...
redirectOnError: false
});
})();errorPages
Un objet contenant les pages d'erreurs est attendu en valeur :
type ErrorPages = {
badRequestPage?: () => ReactNode;
unauthorizedPage?: () => ReactNode;
forbiddenPage?: () => ReactNode;
notFoundPage?: () => ReactNode;
internalServerErrorPage?: () => ReactNode;
};Si redirectOnError est activé, le composant relatif sera chargé lors de la redicrection en cas d'erreur lors de la navigation sur l'OAV.
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// bad request component
const BadRequestPage = () => {
// some logic here
return (
<div>
<h2>OOPS..</h2>
<p>Bad request!</p>
</div>
);
};
(() => {
start({
// ...
redirectOnError: true,
errorPages: {
badRequestPage: BadRequestPage
},
});
})();rootElementId
String. Permet de personnaliser l'id de l'élément HTML racine de l'application client. Par défaut l'id de l'élément racine est fasst-oav-root
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// index.html file
<!doctype html>
<html lang="fr">
<head>
<!-- ... -->
</head>
<body>
<!-- change root id here -->
<div id="my-custom-root-id"></div>
<script type="module" src="/app/index.js"></script>
</body>
</html>
// Init client app
(() => {
start({
// ...
rootElementId: 'my-custom-root-id'
});
})();customHandlers
Un objet qui contient les handlers personnalisés est attendu en valeur. Les handlers personnalisés seront injectés dans l'objet processHandlers (hook useProcess)
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
const myCustomHandler = () => {
// some logic
};
const myOtherCustomHandler = () => {
// some logic
};
// Init client app
(() => {
start({
customHandlers: { myCustomHandler, myOtherCustomHandler },
// ...
});
})();isBundle
Boolean, false par défaut. Si défini à true l'application client sera démarrée en mode bundle et l'objet context (hook useProcess) du composant d'une vue contiendra la propriété isBundle définit à true
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// init
(() => {
start({
// ...
isBundle: true
});
})();routerBasename
Type String. Permet de définir la propriété basename du router interne de l'application client.
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// init
(() => {
start({
// ...
routerBasename: '/fasst'
});
})();clientSyncEnabled
Type Boolean, false par défaut.
Permet d'activer la fonctionnalité de la synchronisation des connexions clientes cÎté client. Si activée :
- l'application instancie une connexion websocket avec le serveur pour garantir le contrÎle d'un projet (identifié par projectId) par un seul client à la fois ;
- permet de consommer le hook useClientSync qui notifie en temps réel du changement de statut de la connexion courante.
Exemple :
import { start } from '@fasstech/oip-starter-utils/app';
// init
(() => {
start({
// ...
clientSyncEnabled: true
});
})();Hook useProcess
Le hook useProcess exposé par la lib permet de récupérer à partir d'un composant d'une vue le contexte (Process) de l'OAV ainsi que les handlers responsables de la gestion des transitions et des tùches.
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const MyView = () => {
const { context, processHandlers } = useProcess();
const onNext = () => {
processHandlers.onNext();
};
return (
<div>
<h2>{context.viewId}</h2>
<button onClick={onNext}>NEXT</button>
</div>
);
};
export default MyView;Handlers de la gestion des transitions
onNext
Déclenche la transition vers la vue suivante.
Signature de la fonction : async ({ transitionData, resolvedViewData }) => Promise<void>
ParamĂštres :
- transitionData (objet) optionnel, ces données sont reçues en paramÚtres de :
- l'handler relatif pour la résolution de la transition
- les hooks de transition relatifs before et after
- resolvedViewData (objet) optionnel, ces données sont injectées à l'objet context field viewData (hook useProcess) de la vue suivante
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onNext = () => {
processHandlers.onNext({
transitionData: { isSomething: true },
resolvedViewData: { someData: 42 },
});
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onNext}>NEXT</button>
</div>
);
};
export default Demo;onPrev
Déclenche la transition vers la vue précédente.
Signature de la fonction : async ({ transitionData, resolvedViewData }) => Promise<void>
ParamĂštres : cf. onNext
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onPrev = () => {
processHandlers.onPrev({
transitionData: { isSomething: true },
resolvedViewData: { someData: 42 },
});
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onPrev}>PREV</button>
</div>
);
};
export default Demo;Handlers de la gestion des tĂąches
onGetTask
RécupÚre les informations d'une tùche précédemment exécutée.
Signature : *async ({ taskName: string; workflowName?: string }) => *Promise<Task|null>
ParamĂštres :
- taskName le nom de la tĂąche (requis)
- workflowName le nom du workflow de tĂąches auquel appartient la tĂąche (optionnel)
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const someLogic = () => {
processHandlers.onGetTask({
taskName: 'magicTask',
}).then((task) => {
// logic
});
};
return (
<div>
<h2>DEMO</h2>
...
</div>
);
};
export default Demo;onRunTask
Déclenche l'exécution d'une tùche.
Signature : *async ({ taskName: string; metadata?: object }) => *Promise<void>
ParamĂštres :
- taskName le nom de la tĂąche (requis)
- metadata les métadonnées de la tùche (optionnel)
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onRunTask = () => {
processHandlers.onRunTask({
taskName: 'magicTask',
metadata: { something: 'That\'s all Folks!' }
});
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onRunTask}>RUN TASK</button>
</div>
);
};
export default Demo;onRunTaskWorkflow
Déclenche l'exécution d'un workflow de tùches.
Signature : *async ({ workflowName: string; metadata?: object }) => *Promise<void>
ParamĂštres :
- workflowName le nom du workflow de tĂąches (requis)
- metadata les métadonnées (optionnel)
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onRunTaskWorkflow = () => {
processHandlers.onRunTaskWorkflow({
workflowName: 'magicWorkflow',
metadata: { something: 'That\'s all Folks!' }
});
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onRunTaskWorkflow}>RUN WORKFLOW</button>
</div>
);
};
export default Demo;onCancelTask
Annule une tùche en cours d'exécution.
Signature : *async ({ taskId: string }) => *Promise<void>
ParamĂštres : taskId l'id de la tĂąche (requis)
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const someLogic = () => {
processHandlers.onCancelTask({ taskId: 'xxx-xxx-xxx' });
};
return (
<div>
<h2>DEMO</h2>
...
</div>
);
};
export default Demo;Autres handlers
onLogout
Cet handler permet de détruire la session de navigation actuelle cÎté server.
Signature de la fonction : async () => Promise<void>
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onLogout = () => {
// some logic (redirect, etc.)
processHandlers.onLogout();
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onLogout}>LOGOUT</button>
</div>
);
};
export default Demo;destroyApp
Quand l'application client est démarrée en « mode bundle » cet handler permet de libérer la mémoire lors d'une transition d'un bundle de vues à un autre.
Signature de la fonction : () => void
Exemple :
import { useProcess } from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { processHandlers } = useProcess();
const onNext = () => {
processHandlers.onNext()
// unmount react app from DOM
processHandlers.destroyApp()
};
return (
<div>
<h2>DEMO</h2>
<button onClick={onNext}>NEXT</button>
</div>
);
};
export default Demo;Composant Router
Le composant Router exposĂ© par la lib permet d'initialiser les routes des vues de l'OAV. Ce composant doit ĂȘtre impĂ©rativement dĂ©fini en tant que children du composant App de l'OAV.
Propriétés
views
Le tableau de la définition des vues de l'OAV ou d'un bundle est attendu en valeur. Propriété requise.
Exemple :
import { Router } from '@fasstech/oip-starter-utils/app';
import { views } from './views';
const App = () => {
// some logic
return (
<>
<SomeProvider>
{/* Router component must be returned */}
<Router views={views} />
</SomeProvider>
</>
);
};disableQueryStringParams
Si définie à true, le paramÚtre d'URL projectId n'est plus affiché au niveau de l'URL de l'OAV. Propriété optionnelle, false par défaut.
Exemple :
import { Router } from '@fasstech/oip-starter-utils/app';
export const App = () => {
// some logic
return (
<>
<SomeProvider>
{/* Router component must be returned */}
<Router views={views} disableQueryStringParams={true} />
</SomeProvider>
</>
);
};browserNavigationMode
Défini la maniÚre dont la navigation via l'interface du navigateur est gérée.
Trois modes disponibles :
- standard (défaut) - la navigation navigateur ignore le moteur de transition OIP, l'application charge la vue liée à l'entrée cible de l'historique de navigation ;
- oip - la navigation navigateur utilise le moteur de transition OIP pour résoudre la vue cible, une nouvelle entrée est ajoutée à la pile de l'historique de navigation lors de chaque événement popstate ;
- disabled - désactive de maniÚre silencieuse la navigation navigateur.
Exemple :
import { Router } from '@fasstech/oip-starter-utils/app';
export const App = () => {
// some logic
return (
<>
<SomeProvider>
{/* Router component must be returned */}
<Router views={views} browserNavigationMode="oip" />
</SomeProvider>
</>
);
};Hook useCommitMutation
Hook consommé par les hooks générés (responsables de la gestion des mutations d'une vue).
Hook useSubscription
Le hook useSubscription permet de souscrire à l'état d'une tùche depuis un composant d'une vue de l'OAV.
ParamĂštres attendus :
- la query TaskSubscription ou TaskWorkflowSubscription (ou autre)
- les variables relatives Ă la query : taskName ou workflowName
Exemple :
import {
useProcess,
useSubscription,
TaskSubscription,
} from '@fasstech/oip-starter-utils/app';
const Demo = () => {
const { context, processHandlers } = useProcess();
const {
data, // subscription data
loading,
error,
} = useSubscription(TaskSubscription, { taskName: 'magic' });
const onNext = () => () => {
processHandlers.onNext();
};
const onRunTask = () => {
processHandlers.onRunTask({
taskName: 'magic',
metadata: { foo: 'bar' }
});
};
return (
<div>
<h2>{context.viewId.toUpperCase()}</h2>
<div>
<p>Context</p>
<pre>{JSON.stringify(context, null, 2)}</pre>
</div>
<div className="mt-3">
<button onClick={onRunTask}>RUN TASK</button>
</div>
<div className="mt-3">
<button onClick={onNext()}>NEXT</button>
</div>
</div>
);
};
export default Demo;Hook useClientSync
ImplĂ©menter le hook useClientSync pour bĂ©nĂ©ficier de la fonctionnalitĂ© de la synchronisation des connexions clientes. Le hook permet d'ĂȘtre notifiĂ© en temps rĂ©el des changements de statut de la connexion cliente courante et d'agir en consĂ©quence (afficher un message, proposer la reprise du contrĂŽle, etc.).
Le hook peut ĂȘtre consommer dans n'importe quel composant de l'application.
Valeurs exposées :
- instanceId identifiant unique de la connexion courante ;
- status statut courant du client, valeurs possibles : IN_CONTROL | OUT_OF_SYNC | SESSION_EXPIRED ;
- message message associé au dernier événement reçu ;
- reclaimControl fonction permettant de demander la reprise du contrĂŽle.
Exemple d'implémentation du hook dans le composant App.jsx :
import { Router, useClientSync } from "@fasstech/oip-starter-utils/app";
import views from "./views.mjs";
export const App = () => {
const { instanceId, status, message, reclaimControl } = useClientSync();
console.log(">> instanceId", instanceId);
const onReclaimControl = () => {
reclaimControl();
};
if (status === "SESSION_EXPIRED") {
return (
<>
<div>Session Expired...</div>
</>
);
}
if (status === "OUT_OF_SYNC") {
return (
<>
<div>{message}</div>
<button onClick={onReclaimControl}>[RECLAIM CONTROL]</button>
</>
);
}
return <Router views={views} />;
};Hook useBlockBrowserNav
Le hook useBlockBrowserNav permet de bloquer la navigation navigateur (Précédent / Suivant) pour une vue spécifique :
- useBlockBrowserNav() appelé sans argument dans le composant d'une vue bloque en permanence la navigation navigateur de la vue ;
- useBlockBrowserNav(state) appelé avec une valeur d'état de type boolean conditionne le blocage de la navigation navigateur de la vue.
Ce hook est efficace en mode oip et standard. cf. browserNavigationMode
Exemple :
import { useState } from "react";
import { useProcess, useBlockBrowserNav } from "@fasstech/oip-starter-utils/app";
const MyView = () => {
const { context, processHandlers } = useProcess();
const [isDirty, setIsDirty] = useState(false);
// Block always
useBlockBrowserNav();
// OR Block conditionally (e.g. unsaved changes)
useBlockBrowserNav(isDirty);
return (
<div>
<h1>MY FORM</h1>
...
</div>
);
};