Frontend

Il se base sur Angular avec un store géré par NGRX.

Il utilise la librairie @provoly/dashboard, et se présente sous la forme d’un portail dans lequel seront insérables différents widgets.

La librairie offre la gestion des multi-fenêtres, la recherche, les widgets, toute en étant hautement configurable (se rapporter à la documentation de la librairie pour plus de détail)

Les widgets disponibles permettent d’afficher des

  • graphes

  • tables

  • cartes

  • diagramme de relation

  • …​

Plusieurs fenêtres pourront être utilisées et la représentation globale multi-fenêtre sera représentée par un manifest. L’architecture de base utilise NGRX pour faciliter l’intégration de différentes vues affichant le même jeu de données éditable. Les widgets seront instanciés dynamiquement, et leur partie de manifest leur sera injectée pour leur permettre de connaitre les options, etc…​

La librairie permet de gérer un ensemble de requêtes/résultats qui pourront être associées à chaque widget, de sorte qu’il est possible d’afficher chaque résultat dans 1 ou plusieurs widgets, sans pour autant effectuer plusieurs fois ces recherches car les données sont partagées.

Manifests

Général

Un manifest se présentera sous la forme d’un contenu JSON. Celui contiendra la représentation complète de l’ensemble des widgets affichés sur l’ensemble des fenêtres. Il conviendra de les stocker (backend) /importer/exporter simplement.

Il pourra être sous la forme suivante:

{
  "windows": [
    {
      "route": "/dashboard",
      "grid": {
        "columns": 12,
        "gap": "10px",
        "rows": 10
      },
      "widgets": [
        {
          "type": "image",
          "layout": {
            "x": 1,
            "y": 1,
            "width": 1,
            "height": 1
          },
          "options": {
            "url": "http://...",
            "link": "http://..."
          }
        },
        {
          "type": "map",
          "layout": {
            "x": 2,
            "y": 3,
            "width": 5,
            "height": 2
          },
          "options": {
            "specific_for_type_options": true
          },
          "datasource": "id_dataset"
        }
      ]
    }
  ]
}

Ce manifest pourra être amené à évoluer en fonction des besoins.

Certains widgets pourront être associés à une ou plusieurs namedQueries, ce que l’on pourrait appeler "recherches et résultats" plus communément. Tant que faire se peut et sauf demande expresse, les recherches sont réutilisées pour ne pas surcharger le serveur. Par contre, tout widget indiquant une recherche non encore chargée déclenchera alors la récupération automatique du résultat de recherche en question.

Bus d’échange de données entre fenêtres/iframes/…​

Généralités

Il y a un besoin évident de partager des messages et des données entre les différentes fenêtres de l’application. Pour cela un bus de messages va être mis en place, et le fonctionnement sera le suivant:

Bus de messages

En réalité, celui-ci sera réparti en 2 bus distinct:

  • le premier, le bus "data", servira pour la synchronisation des différents stores. Dans celui-ci seront poussées les actions NGRX effectuées par n’importe quel store de n’importe quelle fenêtre (hors parties de store locale, ou action de déclenchement de recherche par exemple). En écoute de ce bus, chaque fenêtre en réception fera un dispatch de cette action dans son propre store. Les actions poussées dans ce store contiendront au minimum:

    • les actions de modification du manifest

    • les actions de stockage des résultats de requêtes

  • le 2e, le bus "message" servira pour échanger tout ce qui n’entre pas dans la première catégorie

La cinématique sera la suivante:

  • chaque fois qu’une nouvelle instance de l’application se présente:

    • elle génère un uuid d’identification

    • elle se connecte aux 2 bus.

    • elle se signale ensuite par un message de type "join" dans le bus de message

    • si d’autres fenêtres sont présentes dans le bus, elles répondent avec un état d’initialisation (comprenant éventuellement un manifest…​).

    • elle réceptionne/envoie des messages d’actions

    • à la fermeture de fenêtre, un message "leave" est envoyé dans ce bus

Chaque message transitant dans le bus sera identifié par l’uuid de l’expéditeur. Cela permettra d’éviter de redispatcher un message provenant d’un autre émetteur sous peine de voir les navigateurs partir en vacances forcées.

Mécanisme d’élection

Les différents états sont synchronisés par un partage d’action. Par exemple, l’action déclaenchant une requête au backend est réalisée par le noeud (fenêtre ou onglet) de rang 0. Puis l’action résultante (permettant de mettre à jour le store), est elle porteuse d’un tag (bus) qui indique qu’il faut la partager avec les autres fenêtres. L’effet de action bus se charge de cet envoi.

Pour déterminer le rang d’un noeud, un mécanisme simple est mis en place: lors de l’initialisation de l’application, le noeud se déclare en tant que seul présent, en s’attribuant un uuid, et s’associe (localement) de rang 0. Il envoie en parallèle un message de type "join" sur l’action bus, en indiquant son uuid. Sur ce message, si d’autres noeuds sont présents, alors le noeud réel de rang 0 répondra à ce noeud, en ayant intégré ce nouveau noeud dans la liste.

Un mécanisme du même type existe sur un événement de type "leave" lancé juste avant la fermeture d’un noeud. permettant de garder en permanence une liste correcte des noeuds.

Partage et manifests

Tout au long de la vie de l’application (multi-onglet), le manifest sera partagé globalement entre tous les onglets. Cela permet de nous assurer que lorsqu’un onglet se déconnecte, les autres peuvent alors continuer à fonctionner de manière correcte, avec une élection de noeud principal immédiate (car ils sont ordonnés par leurs uuid).

Seules les pages de chaque onglet sont ajoutés au moment de la sauvegarde par un mécanisme spécifique.

Partage de données

Le front étant disponible en multi-vues, multi-écran:

alt

  • Un utilisateur utilise plusieurs instances de la solution dans plusieurs onglets d’un même navigateur: une application web (Single Page Application) développée en utilisant le framework Angular

  • L’authentification des utilisateurs est gérée au travers d’un système d’identification Keycloak

  • Les données seront récupérées sur le client web en utilisant les API des services backend de virtualisation des données (pour permettre d’accéder à différentes sources de données) incluant les modules de gestion de la sécurité

  • Les données et actions entre les instances (les onglets de l’application client) sont partagées au travers de bus de messages et d’actions

Par exemple, lorsqu’une recherche est effectuée, c’est l’onglet principal qui s’occupe de faire la requête, et il fait transiter le résultat vers tous les autres, évitant ainsi la duplication de traffic réseau.

Choix de la technologie d’affichage cartographique et architecture

  • OpenLayers

  • OpenMapTiles

Il est à noter que de nombreuses adaptations manuelles ont été faites hors plugins dans OpenLayers, afin d’exposer un maximum de fonctionalités.