From 3627a9718ee3deb5ff3c43524ff4a487267d8241 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 12:19:40 +0200 Subject: [PATCH 01/11] Sort documentation --- docs/#Project/Home.md | 17 +++++++++++++++++ docs/{ => #Project/Pages}/Behaviors.md | 0 docs/{ => #Project/Pages}/CICD.md | 0 .../Pages}/ComponentStructure.drawio | 0 docs/{ => #Project/Pages}/DataStructure.md | 0 docs/{ => #Project/Pages}/Dependencies.md | 0 docs/{ => #Project/Pages}/Project_Structure.md | 0 .../Pages/SmartComponent.md | 0 ...1017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf | 0 ...1017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf | 0 .../03_SYME KLINE cde BV.pdf | 0 .../04_ARC KL_K1485985-ARC-K1485985.pdf | 0 docs/{Eric BF => Documents}/05_DT_K1485985.pdf | 0 .../06_ Photo IMG_1406.jpg | 0 ...1837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg | 0 ...1837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf | 0 docs/{Eric BF => Documents}/image0000001.jpg | 0 docs/{DevDocs => Tutorial}/Home.md | 2 +- docs/{DevDocs => Tutorial}/Pages/BasesReact.md | 0 docs/{DevDocs => Tutorial}/Pages/Heroicon.md | 0 .../Pages/PourCommencer.md | 0 .../Pages/PremierComposantReact.md | 0 docs/{DevDocs => Tutorial}/Pages/Tailwind.md | 0 23 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 docs/#Project/Home.md rename docs/{ => #Project/Pages}/Behaviors.md (100%) rename docs/{ => #Project/Pages}/CICD.md (100%) rename docs/{ => #Project/Pages}/ComponentStructure.drawio (100%) rename docs/{ => #Project/Pages}/DataStructure.md (100%) rename docs/{ => #Project/Pages}/Dependencies.md (100%) rename docs/{ => #Project/Pages}/Project_Structure.md (100%) rename docs/{DevDocs => #Project}/Pages/SmartComponent.md (100%) rename docs/{Eric BF => Documents}/01_141017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf (100%) rename docs/{Eric BF => Documents}/02_141017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf (100%) rename docs/{Eric BF => Documents}/03_SYME KLINE cde BV.pdf (100%) rename docs/{Eric BF => Documents}/04_ARC KL_K1485985-ARC-K1485985.pdf (100%) rename docs/{Eric BF => Documents}/05_DT_K1485985.pdf (100%) rename docs/{Eric BF => Documents}/06_ Photo IMG_1406.jpg (100%) rename docs/{Eric BF => Documents}/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg (100%) rename docs/{Eric BF => Documents}/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf (100%) rename docs/{Eric BF => Documents}/image0000001.jpg (100%) rename docs/{DevDocs => Tutorial}/Home.md (78%) rename docs/{DevDocs => Tutorial}/Pages/BasesReact.md (100%) rename docs/{DevDocs => Tutorial}/Pages/Heroicon.md (100%) rename docs/{DevDocs => Tutorial}/Pages/PourCommencer.md (100%) rename docs/{DevDocs => Tutorial}/Pages/PremierComposantReact.md (100%) rename docs/{DevDocs => Tutorial}/Pages/Tailwind.md (100%) diff --git a/docs/#Project/Home.md b/docs/#Project/Home.md new file mode 100644 index 0000000..adc0850 --- /dev/null +++ b/docs/#Project/Home.md @@ -0,0 +1,17 @@ + +Bienvenue à la documentation du projet de SVGLayoutDesigner. + +Ici se trouve les documents qui explique en détail l'implémentation +des fonctionnalités du projet. + +Sélectionnez un lien ou un fichier pour lire la documentation + +Liens : + +- [Structure du projet](Pages/Project_Structure.md) +- [Structure des composants](Pages/ComponentStructure.drawio) (nécessite diagrams.net) +- [Dépendences du projet](Pages/Dependencies.md) +- [Structure de données des conteneurs](Pages/DataStructure.md) +- [Système de comportement](Pages/Behaviors.md) +- [Système de CI/CD](Pages/Behaviors.md) +- [Mise en place du SmartComponent sur Modeler](Pages/SmartComponent.md) \ No newline at end of file diff --git a/docs/Behaviors.md b/docs/#Project/Pages/Behaviors.md similarity index 100% rename from docs/Behaviors.md rename to docs/#Project/Pages/Behaviors.md diff --git a/docs/CICD.md b/docs/#Project/Pages/CICD.md similarity index 100% rename from docs/CICD.md rename to docs/#Project/Pages/CICD.md diff --git a/docs/ComponentStructure.drawio b/docs/#Project/Pages/ComponentStructure.drawio similarity index 100% rename from docs/ComponentStructure.drawio rename to docs/#Project/Pages/ComponentStructure.drawio diff --git a/docs/DataStructure.md b/docs/#Project/Pages/DataStructure.md similarity index 100% rename from docs/DataStructure.md rename to docs/#Project/Pages/DataStructure.md diff --git a/docs/Dependencies.md b/docs/#Project/Pages/Dependencies.md similarity index 100% rename from docs/Dependencies.md rename to docs/#Project/Pages/Dependencies.md diff --git a/docs/Project_Structure.md b/docs/#Project/Pages/Project_Structure.md similarity index 100% rename from docs/Project_Structure.md rename to docs/#Project/Pages/Project_Structure.md diff --git a/docs/DevDocs/Pages/SmartComponent.md b/docs/#Project/Pages/SmartComponent.md similarity index 100% rename from docs/DevDocs/Pages/SmartComponent.md rename to docs/#Project/Pages/SmartComponent.md diff --git a/docs/Eric BF/01_141017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf b/docs/Documents/01_141017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf similarity index 100% rename from docs/Eric BF/01_141017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf rename to docs/Documents/01_141017-WG-11328-SYME-VERNUCCI-DET BF ind A.pdf diff --git a/docs/Eric BF/02_141017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf b/docs/Documents/02_141017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf similarity index 100% rename from docs/Eric BF/02_141017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf rename to docs/Documents/02_141017-WG-11328-SYME-VERNUCCI-DET BF ind B.pdf diff --git a/docs/Eric BF/03_SYME KLINE cde BV.pdf b/docs/Documents/03_SYME KLINE cde BV.pdf similarity index 100% rename from docs/Eric BF/03_SYME KLINE cde BV.pdf rename to docs/Documents/03_SYME KLINE cde BV.pdf diff --git a/docs/Eric BF/04_ARC KL_K1485985-ARC-K1485985.pdf b/docs/Documents/04_ARC KL_K1485985-ARC-K1485985.pdf similarity index 100% rename from docs/Eric BF/04_ARC KL_K1485985-ARC-K1485985.pdf rename to docs/Documents/04_ARC KL_K1485985-ARC-K1485985.pdf diff --git a/docs/Eric BF/05_DT_K1485985.pdf b/docs/Documents/05_DT_K1485985.pdf similarity index 100% rename from docs/Eric BF/05_DT_K1485985.pdf rename to docs/Documents/05_DT_K1485985.pdf diff --git a/docs/Eric BF/06_ Photo IMG_1406.jpg b/docs/Documents/06_ Photo IMG_1406.jpg similarity index 100% rename from docs/Eric BF/06_ Photo IMG_1406.jpg rename to docs/Documents/06_ Photo IMG_1406.jpg diff --git a/docs/Eric BF/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg b/docs/Documents/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg similarity index 100% rename from docs/Eric BF/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg rename to docs/Documents/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.dwg diff --git a/docs/Eric BF/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf b/docs/Documents/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf similarity index 100% rename from docs/Eric BF/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf rename to docs/Documents/131421 KALIA - 15541 - PARVIS DE RODE - D0371837 - BANDE FILANTE PLAN 01 à 07 -IND B.pdf diff --git a/docs/Eric BF/image0000001.jpg b/docs/Documents/image0000001.jpg similarity index 100% rename from docs/Eric BF/image0000001.jpg rename to docs/Documents/image0000001.jpg diff --git a/docs/DevDocs/Home.md b/docs/Tutorial/Home.md similarity index 78% rename from docs/DevDocs/Home.md rename to docs/Tutorial/Home.md index b29d664..f90ca70 100644 --- a/docs/DevDocs/Home.md +++ b/docs/Tutorial/Home.md @@ -1,5 +1,5 @@ -Bienvenue à la documentation développeur de SVGLayoutDesigner. +Bienvenue au tutoriel de SVGLayoutDesigner. Cette documentation a pour objectif de familiariser les nouveaux développeur aux outils du projet et à apprendre à développer des composants sous React. diff --git a/docs/DevDocs/Pages/BasesReact.md b/docs/Tutorial/Pages/BasesReact.md similarity index 100% rename from docs/DevDocs/Pages/BasesReact.md rename to docs/Tutorial/Pages/BasesReact.md diff --git a/docs/DevDocs/Pages/Heroicon.md b/docs/Tutorial/Pages/Heroicon.md similarity index 100% rename from docs/DevDocs/Pages/Heroicon.md rename to docs/Tutorial/Pages/Heroicon.md diff --git a/docs/DevDocs/Pages/PourCommencer.md b/docs/Tutorial/Pages/PourCommencer.md similarity index 100% rename from docs/DevDocs/Pages/PourCommencer.md rename to docs/Tutorial/Pages/PourCommencer.md diff --git a/docs/DevDocs/Pages/PremierComposantReact.md b/docs/Tutorial/Pages/PremierComposantReact.md similarity index 100% rename from docs/DevDocs/Pages/PremierComposantReact.md rename to docs/Tutorial/Pages/PremierComposantReact.md diff --git a/docs/DevDocs/Pages/Tailwind.md b/docs/Tutorial/Pages/Tailwind.md similarity index 100% rename from docs/DevDocs/Pages/Tailwind.md rename to docs/Tutorial/Pages/Tailwind.md From 5a17f2ba6c43761fd738c2be67e120615e333dd7 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 12:20:31 +0200 Subject: [PATCH 02/11] Remove yule cake --- docs/#Project/Pages/Behaviors.md | 2 -- docs/assets/yule-log-cake.jpg | 3 --- 2 files changed, 5 deletions(-) delete mode 100644 docs/assets/yule-log-cake.jpg diff --git a/docs/#Project/Pages/Behaviors.md b/docs/#Project/Pages/Behaviors.md index 57b5905..cf55439 100644 --- a/docs/#Project/Pages/Behaviors.md +++ b/docs/#Project/Pages/Behaviors.md @@ -168,8 +168,6 @@ Nous avons initialement tout l'espace disponible : laissez `space` être cet esp Pour simplifier l'algorithme lors de l'ajout d'un conteneur, comparons cela à manger une bûche de Noël. -![buche](./assets/yule-log-cake.jpg) - Comme pour le gâteau, il faut le couper et en prendre une part. Il y a 5 façons possibles de le couper : diff --git a/docs/assets/yule-log-cake.jpg b/docs/assets/yule-log-cake.jpg deleted file mode 100644 index 79d2165..0000000 --- a/docs/assets/yule-log-cake.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:348ffea20dbd9b2a499dc84e0ddfb7d7220c91980ab7840c36847f6eedd18d6d -size 187625 From f1a9d912b8d24eb2b7ecbc385b1de689581b2b26 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 12:56:31 +0200 Subject: [PATCH 03/11] Added ContextMenu documentation + added some tl;dr --- docs/#Project/Pages/Behaviors.md | 20 +++++++--- docs/#Project/Pages/CICD.md | 2 +- docs/#Project/Pages/ContextMenu.md | 55 +++++++++++++++++++++++++++ docs/#Project/Pages/DataStructure.md | 5 ++- docs/#Project/Pages/SmartComponent.md | 4 +- 5 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 docs/#Project/Pages/ContextMenu.md diff --git a/docs/#Project/Pages/Behaviors.md b/docs/#Project/Pages/Behaviors.md index cf55439..47ce155 100644 --- a/docs/#Project/Pages/Behaviors.md +++ b/docs/#Project/Pages/Behaviors.md @@ -1,3 +1,16 @@ +> TL;DR +> Behaviors.ts définis les comportements qui sont utilisés. + +> Actuellement sont activés par défaut : +> - Corps rigide (simple) : Est restraint dans le parent +> - Ancrage : Impose la priorité de position et de taille +> - Flex : se redimensionne automatiquement + +> Désactivés: +> - Corps rigide (complet) : Est restraint par les parents et par ses voisins (fonctionne mais pas intuitif) +> - Poussé : quand un conteneur est ajouté au bout de la bande filante, pousse tous les conteneurs à sa gauche (fonctionne mais pas intuitif) +> - Swap : échange de place avec un autre conteneur lorsqu'ils sont superposés (buggué ne pas utiliser) + # Comportements des conteneurs Ce document traite des comportements spéciaux et uniques qu'un conteneur peut avoir. @@ -21,8 +34,6 @@ Cependant, il a une règle commune pour tout comportement qui s'applique à ses Il s'agit d'appliquer les comportements spéciaux de ses enfants (rigide ou ancré). -Traduit avec www.DeepL.com/Translator (version gratuite) - ## Applications @@ -37,11 +48,10 @@ An example would be trying to overlap an element in order to use it as a layer. ## Références de code et algorithmes -Dans le module `PropertiesOperations.ts` dans les fonctions suivantes : +Dans le module `ContainerOperations.ts` dans les fonctions suivantes : - `OnPropertyChange()` -- `OnPropertiesSubmit()` -et dans le module `ContainerOperation.ts` dans `AddContainer()`, +et dans le module `AddContainer.ts` dans `AddContainer()`, il utilise la fonction `ApplyBehaviors` du module `Behaviors.ts` pour appliquer les comportements spéciaux de ses enfants. diff --git a/docs/#Project/Pages/CICD.md b/docs/#Project/Pages/CICD.md index 4aee2bf..55b74db 100644 --- a/docs/#Project/Pages/CICD.md +++ b/docs/#Project/Pages/CICD.md @@ -5,7 +5,7 @@ This project uses Azure Pipelines to runs automatic tests. Its `azure-pipelines.yml` configuration file can be found at the root project folder. -# Drone.io +# Drone.io (deprecated) Due to the limitations of Azure Pipelines (limited free usage, no parallel, no dockerhub...), it might be more useful to use Drone.io. However `pnpm` will not be as useful as in Azure Pipelines since we cannot cache on the parent machine. diff --git a/docs/#Project/Pages/ContextMenu.md b/docs/#Project/Pages/ContextMenu.md new file mode 100644 index 0000000..2e5420b --- /dev/null +++ b/docs/#Project/Pages/ContextMenu.md @@ -0,0 +1,55 @@ +> TL;DR: Menu.tsx est le composant qui affiche et qui traite l'event contextmenu sur la page +> InitActions de Editor.tsx prépare le modèle pour Menu.tsx +> ContextMenuActions définient les actions de l'API + +# Context Menu + +Ce document présente comment le menu contextuel est implémenté. + + +# Event listener + +Pour implémenter le menu contextuel, il faut en premier ajouter un event listener sur `contextmenu`. + +Cela se fait dans le composant `Menu.tsx` via la fonction `UseMouseEvents()`. + +Elle équipe plusieurs events sur la page en plus de `contextmenu` afin de fermer correctement lorsque l'on clique ailleurs. + +Il n'existe donc qu'un seul menu contextuel pour toute la page. + + +# Affichage du contenu + +On a vu que `Menu.tsx` s'occupe de traiter l'event `contextmenu`. Regardons maintenant comment elle affiche le menu. + +Ce composant utilise une hashmap `actions: Map` pour lire les différentes actions possible, la clé servant d'identifiant et de pattern. + +En effet, la fonction `AddClassSpecificActions`, obtenant le composant html lit les *classes* et vérifie s'il est présent dans le dictionnaire avec `props.actions.get(className)`. + +S'il est présent, alors on itère sur les différentes actions possible pour cette classe pour ajouter des `MenuItem` représentant une ligne du menu contextuel. Chaque `MenuItem` possède un fonction qui sera exécutée lorsque la ligne est cliquée. Il possède également un texte, un titre qui sera affiché si le curseur survole la ligne, et, optionnellement, un raccourci qui sera affiché à droite de la ligne. + +En plus des actions de classes, il y a aussi des actions universelles comme le `undo` ou `redo` qui sont affichées n'importe où on clique. Celle-ci ont pour id `''`, une chaine de caractères vide. On itère sur cette liste d'action pour ajouter les lignes. + +L'ordre d'affichage est donc défini : + +1) actions de classes +2) actions universelles + +L'ordre des classes est l'ordre d'ajout dans le dictionnaire. + + +# Création du dictionnaire + +Parlons de l'initialisation du dictionnaire. + +Le composant `Menu` est utilisé dans `Editor`. C'est aussi ici que l'ont crée le dictionnaire. + +La fonction `InitActions` s'occupe d'enrichîr le dictionnaire des différentes actions. + +On peut voir qu'au début de la fonction que les actions universelles y sont initialisées. Ensuite, les actions spécifiques aux classes y sont ajoutés avec au début les actions définies dans SVGLayoutDesigner et après, les actions définies dans la configuration de l'API (donc `Diviser remplissage par exemple`). + +Chaque action provenant de l'API utilise la fonction `GetAction` du fichier utilitaire `ContextMenuActions.ts`. + +Cette fonction équipe l'action qui sera exécutée d'une autre fonction appelé `SetContainerList`. Cette autre fonction s'occupe de faire un appel REST vers l'api sur le point d'accès `Configuration.APIConfiguration.apiSetContainerListUrl` ou, si elle n'est pas définie, sur `VITE_API_SET_CONTAINER_LIST_URL`. + +Cela veut dire que pour l'instant toutes les actions provenant de l'API a pour but de remplacer, d'ajouter ou de supprimer des conteneurs. \ No newline at end of file diff --git a/docs/#Project/Pages/DataStructure.md b/docs/#Project/Pages/DataStructure.md index b04f245..1c57864 100644 --- a/docs/#Project/Pages/DataStructure.md +++ b/docs/#Project/Pages/DataStructure.md @@ -1,3 +1,6 @@ + +> TL;DR: Ce projet utilise un dictionnaire pour représenter un arbre/graphe + # Préface Ce document explique la structure de données utilisée pour les conteneurs. @@ -40,7 +43,7 @@ B: Node = { Donc le graphe est simplement `A <-> B` -Ceci est un graphe cyclique que nous ne verrons pas souvent dans ce projet. +Ceci est un graphe cyclique que nous ne verrons pas souvent dans ce projet. En effet, nous avons plutôt quelque chose comme ça: ``` diff --git a/docs/#Project/Pages/SmartComponent.md b/docs/#Project/Pages/SmartComponent.md index e632da8..38460b6 100644 --- a/docs/#Project/Pages/SmartComponent.md +++ b/docs/#Project/Pages/SmartComponent.md @@ -1,3 +1,5 @@ +Source: https://dev.azure.com/techformsa/SmartConfigurator/_wiki?pageId=122&friendlyName=Int%C3%A9grer-le-projet-en-tant-que-composant-dans-Modeler# + - [Préface](#préface) - [Customiser et build le projet (recommandé)](#customiser-et-build-le-projet-(recommandé)) * [Configurer les options de build](#configurer-les-options-de-build) @@ -92,7 +94,7 @@ Cliquez sur le menu hamburger et cliquez sur **Download Artifacts** :
- + ``` From df94e7904dc2cd736f360632a85f4f8d8a7af216 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 13:10:44 +0200 Subject: [PATCH 04/11] Add web worker documentation --- docs/#Project/Home.md | 2 ++ docs/#Project/Pages/WebWorkers.md | 38 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 docs/#Project/Pages/WebWorkers.md diff --git a/docs/#Project/Home.md b/docs/#Project/Home.md index adc0850..b97a2c8 100644 --- a/docs/#Project/Home.md +++ b/docs/#Project/Home.md @@ -13,5 +13,7 @@ Liens : - [Dépendences du projet](Pages/Dependencies.md) - [Structure de données des conteneurs](Pages/DataStructure.md) - [Système de comportement](Pages/Behaviors.md) +- [Implémentation du menu contextuel](Pages/ContextMenu.md) +- [Web workers](Pages/WebWorkers.md) - [Système de CI/CD](Pages/Behaviors.md) - [Mise en place du SmartComponent sur Modeler](Pages/SmartComponent.md) \ No newline at end of file diff --git a/docs/#Project/Pages/WebWorkers.md b/docs/#Project/Pages/WebWorkers.md new file mode 100644 index 0000000..6b42c0f --- /dev/null +++ b/docs/#Project/Pages/WebWorkers.md @@ -0,0 +1,38 @@ +# Web workers + +Cette page explique la raison d'utiliser un web worker. + + +# Qu'est-ce qu'un web worker ? + +Rapidement, c'est juste un fichier js qui est exécuté côté dans un Thread différent. + +Il attend un réponse, la traite et peut répondre ensuite. + + +# Pourquoi en utiliser ? + +Cela permet du véritable code asynchrone évitant le freeze du navigateur lorsqu'il fait des calculs compliqués ou lorsqu'il attend. + +Exemple: https://mdn.github.io/dom-examples/web-workers/fibonacci-worker/ + + +# Comment sont-ils utilisés ? + +## Sauvegarde + +Le premier web worker, situé dans [`public/workers/worker.js`](../../../public/workers/worker.js) s'occupe de faire une seule est unique tâche : `JSON.stringify` cependant on fonction de la taille de l'objet à stringifier en JSON cela peut prendre plusieurs secondes auquel cas l'utilisateur peut croire que son navigateur à bloqué. + +On le met donc dans un web worker pour éviter cela. + +Dans `Save.ts`, on crée le web worker avec `new Worker('workers/worker.js')` et on le termine quand il a fini sa tache avec `terminate()` + +## Envois de message + +Le deuxième web worker, situé dans [`public/workers/worker.js`](../../../public/workers/message_worker.js) s'occupe de faire des appels REST en stringifiant l'état de l'application. + +Pour la même raison que la sauvegarde, on le met pour éviter un freeze. + +Il est évidemment moins utile que la sauvegarde qui prends un objet beaucoup plus lourd. + +Contrairement à la sauvegarde, le web worker est crée dans `UI.tsx` avec `UseWorker()` et existe sur tout le long de la durée de vie de l'application. Il est initialisé dans l'utilisation du module `UseWorker.tsx`. \ No newline at end of file From 41dd1192004ced8b66bce0c1bbb74afc7d2919ec Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 15:42:53 +0200 Subject: [PATCH 05/11] Added Application.md + add more TODOs --- docs/#Project/Pages/Application.md | 179 +++++++++++++++++++++++++++++ src/Interfaces/IContainerModel.ts | 4 + src/utils/saveload.ts | 2 + 3 files changed, 185 insertions(+) create mode 100644 docs/#Project/Pages/Application.md diff --git a/docs/#Project/Pages/Application.md b/docs/#Project/Pages/Application.md new file mode 100644 index 0000000..cb731f3 --- /dev/null +++ b/docs/#Project/Pages/Application.md @@ -0,0 +1,179 @@ +# Cycle de vie de l'application + +# Menu principal + +Lorsque l'on lance l'application pour la première fois, +le premier composant qui s'affiche est `App.tsx`. + +En fonction de la valeur de `FAST_BOOT`, +il peut soit afficher un menu principal (composant `MainMenu`) si `FAST_BOOT=false` +ou soit afficher l'editeur directement (composant `Editor`). + +Lorsque le menu principal est affiché il y a 3 états : *Main*, *Load* ou *Loading*. + +Lorsqu'on est dans Main, nous avons les deux boutons principaux affiché : *Start from scratch* ou *Load* + +## Start from scratch + +Lorsque l'on clique sur *Start from scratch*, +l'action qui se fait est de charger une configuration depuis l'API +(ou d'utiliser une configuration préchargée via un event custom). +On passe à l'état *Loading*. + +Après chargement, `isLoaded` est `true` et le composant `Editor` est affiché. + +## Load + +Quand on veut charger un json, on clique sur *Load* et l'état passe à *Load*. + +Ici, le composant `MainMenu` affichera un bouton pour charger un fichier. +Charger le fichier change l'état de la configuration dans `App` +et active `isLoaded` qui enfin affiche `Editor`. + + +# Editor + +Lorsque `Editor` est affiché, +il reçoit en props la configuration que l'on a chargé au menu principal. + +Il reçoit également un historique par défaut pour avoir au moins quelque chose d'affiché. + +Il reçoit `root` un element HTML où l'on insert SVGLayoutDesigner par `main.tsx`. +`root` est utilisé pour lui donner des events qui seront utilisé pour communiquer avec le SmartComponent. + +Plusieurs sous-composant sont affichés ensuite. +Vous pouvez en savoir plus sur [la structure de composants](./ComponentStructure.drawio) +avec dragrams.net. + + +# Save and load + +Pour enregistrer le travail fait, il existe plusieurs méthode de le faire. + +## SmartComponent + +La première, en passant par le SmartComponent `svg-layout-designer.ts`, est de stringifier l'état de l'éditeur +et de le sauvegarder quelque part. + +On utilise `GetEditorAsString` pour obtenir une version stringifié du projet +que l'on peut ensuite sauvegarder dans un fichier, bdd ou autre. +On peut également utiliser GetEditorState et le sauvegarder tel quel dans le JS +mais on ne peut pas le stringifier à un object json ne peut pas avoir deux références +(sauf si on a le code source de saveload.ts, +utilisant un *replacer* éliminant les références circulaires, +voir [JSON par interaction](#json-par-interaction). + +Pour charger l'état de l'éditeur, il faut en premier le parser avec `JSON.parse` (pas de soucis à ce niveau là); +Enfin, on peut ensuite utiliser `LoadEditor` du SmartComponent pour charger l'état. + +`LoadEditor` est une macro de trois autres appels : +- `ReviveEditorState` qui fait revivre tous les doublons de références +- `SetEditor` qui charge la configuration de l'application +- `SetHistory` qui charge l'historique de l'editeur + +La raison que l'on utilise `SetHistory` en plus de `SetEditor` est parce que, +`SetEditor` ne fait que charger une configuration par défaut de `App.tsx` +(exemple: lorsque l'on crée un conteneur, l'éditeur va lire cette configuration). +Si l'application est déjà chargée, c'est-à-dire que *isLoaded* de `App` est `true`, +alors l'application ne va pas relire `history` et `historyCurrentStep` et l'application n'aura pas *chargé*. +C'est pourquoi on a besoin de `SetHistory` pour charger l'état courant dans `Editor.tsx` (à l'opposé de `App.tsx`). + +Note: Pour rappel, *App* n'est qu'un menu principal. +Comme dans un menu principal de jeu vidéo, +écraser une sauvegarde ne fait pas charger la sauvegarde. +C'est en chargeant la sauvegarde en cours de jeu ou dans le menu principal, +que la partie change. + + +## JSON par interaction + +On peut charger un fichier JSON manuellement. + +Pour cela il faut que `FAST_BOOT` de `default.ts` soit désactivé. + +Dans l'éditeur, on peut exporter une configuration par fichier JSON grâce au composant `Settings.tsx`. +Cette sauvegarde, comme pour sauvegarder avec le SmartComponent, utilise `JSON.stringify`. +Et donc utilise un *replacer* pour supprimer les dépendances circulaires. + +Ce *replacer* se trouve dans `worker.js` mais +un fallback est également donné dans `saveload.ts` +dans le cas où la fonctionnalité de Web Worker n'est pas supportée par le navigateur web. +Pour corriger des bugs sur la sauvegarde, il faudra donc modifier ces deux fichiers. + +Décrivons rapidement ce qu'elle fait : + +```typescript +export function GetCircularReplacer(): (key: any, value: object | Map | null) => object | null | undefined { + return (key: any, value: object | null) => { + if (key === 'parent') { + return; + } + + if (key === 'containers') { + return Array.from((value as Map).entries()); + } + + if (key === 'symbols') { + return Array.from((value as Map).entries()); + } + + if (key === 'linkedContainers') { + return Array.from(value as Set); + } + + return value; + }; +} +``` + +Nous faisons les actions suivantes pour supprimer les types non supportés par le stringify : +- nous transformons les *Map* `containers` et `symbols` en tableau de vecteur clés-valeurs +- nous transformons les *Set* `linkedContainers` en tableau de clés. + +Nous supprimons toutes les références de `parent` qui sont déjà référencés dans `containers`. + +Enfin, nous retournons `value` si tout est bon. + +Normalement, le JSON retourné ressemble à l'objet qu'était EditorState +mais sans les références de parent et avec des tableaux partout. + + +Pour le charger, il faut revenir au menu principal et +cliquer sur Load pour charger avec l'input. + +Charger le fichier JSON, utilisera ce qu'on appelle un *reviver* +qui s'occupe de recréer les types non supportés par JSON et de remettre les références dupliquées. + +Ce reviver se trouve dans `saveload.ts` avec la fonction `Revive()`. + +`Revive` change la valeur de `historyCurrentStep` avec de faire revivre l'historique + +`ReviveHistory` itère sur chaque état de `history` pour les revivre. + +`ReviveState` fait revivre en premier les *Map* et les *Set*. +Ensuite, il va itérer sur tous les conteneurs existants, +pour remettre leur parent. + +Comme vous pouvez vous en douter cette algorithme coûte O(n) juste pour revivre les parents. +avec *n* le nombre total de conteneurs sur toute la durée de vie de l'application. +Surtout qu'il n'est plus très utile depuis que tous les conteneurs sont dans une hash *Map* +(et que donc parent est accessible avec un coût O(1)). + +On pourrait juste utiliser `GetContainerById` au lieu de la référence. + + +## JSON par requête GET HTTP + +Pour charger un JSON via HTTP GET, +il faut que le serveur web distant autorise notre domaine +dans le méchanisme *cross-origin resource sharing (CORS)* +et qu'il nous autorise à faire des requêtes *GET*. + +Après cela pour charger le JSON, +il faut que l'url de SVGLayoutDesigner soit paramétrée avec l'url de la resource : + +``` +http://localhost:5173/?state=http://other-server.com/state.json +``` + +Après cela, l'éditeur chargera directement le fichier. diff --git a/src/Interfaces/IContainerModel.ts b/src/Interfaces/IContainerModel.ts index ff24d67..8e38efa 100644 --- a/src/Interfaces/IContainerModel.ts +++ b/src/Interfaces/IContainerModel.ts @@ -2,6 +2,8 @@ import { IContainerProperties } from './IContainerProperties'; export interface IContainerModel { children: string[] + // TODO: Remove parent now that accessing the parent by id is faster. + // TODO: Use GetContainerById(container.properties.parentId) as the better alternative. parent: IContainerModel | null properties: IContainerProperties userData: Record @@ -13,6 +15,8 @@ export interface IContainerModel { */ export class ContainerModel implements IContainerModel { public children: string[]; + // TODO: Remove parent now that accessing the parent by id is faster. + // TODO: Use GetContainerById(container.properties.parentId) as the better alternative. public parent: IContainerModel | null; public properties: IContainerProperties; public userData: Record; diff --git a/src/utils/saveload.ts b/src/utils/saveload.ts index 7250500..ed1f57c 100644 --- a/src/utils/saveload.ts +++ b/src/utils/saveload.ts @@ -40,6 +40,8 @@ export function ReviveState(state: IHistoryState): void { return; } + // TODO: remove parent and remove this bloc of code + // TODO: See IContainerModel.ts for more detail const it = MakeDFSIterator(root, state.containers); for (const container of it) { const parentId = container.properties.parentId; From 67864173495ebbef42ac67eea95b42e0ec5fca7c Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 15:43:55 +0200 Subject: [PATCH 06/11] Add missing link to Home.md --- docs/#Project/Home.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/#Project/Home.md b/docs/#Project/Home.md index b97a2c8..f10a985 100644 --- a/docs/#Project/Home.md +++ b/docs/#Project/Home.md @@ -13,7 +13,8 @@ Liens : - [Dépendences du projet](Pages/Dependencies.md) - [Structure de données des conteneurs](Pages/DataStructure.md) - [Système de comportement](Pages/Behaviors.md) +- [Cycle de vie de l'application](Pages/Application.md) - [Implémentation du menu contextuel](Pages/ContextMenu.md) - [Web workers](Pages/WebWorkers.md) - [Système de CI/CD](Pages/Behaviors.md) -- [Mise en place du SmartComponent sur Modeler](Pages/SmartComponent.md) \ No newline at end of file +- [Mise en place du SmartComponent sur Modeler](Pages/SmartComponent.md) From 621dc9b53f8d0b13c4f1175bdae6c35053d9f524 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 16:13:34 +0200 Subject: [PATCH 07/11] Deprecate GetCircularReplacer and make GetCircularReplacer dotnet by default. Format of the save is now incompatible with old versions. --- public/workers/worker.js | 6 ++-- src/Components/API/api.ts | 4 +-- src/Components/Messages/Messages.tsx | 2 +- src/Components/UI/UseWorker.tsx | 4 +-- src/utils/default.ts | 2 +- src/utils/saveload.ts | 44 ++++++---------------------- 6 files changed, 19 insertions(+), 43 deletions(-) diff --git a/public/workers/worker.js b/public/workers/worker.js index 11246a0..a933fc2 100644 --- a/public/workers/worker.js +++ b/public/workers/worker.js @@ -10,11 +10,13 @@ const getCircularReplacer = () => { } if (key === 'containers') { - return Array.from(value.entries()); + return [...value.entries()] + .map(([Key, Value]) => ({ Key, Value })); } if (key === 'symbols') { - return Array.from(value.entries()); + return [...value.entries()] + .map(([Key, Value]) => ({ Key, Value })); } if (key === 'linkedContainers') { diff --git a/src/Components/API/api.ts b/src/Components/API/api.ts index 6d5ac3b..fd91133 100644 --- a/src/Components/API/api.ts +++ b/src/Components/API/api.ts @@ -1,7 +1,7 @@ import { IConfiguration } from '../../Interfaces/IConfiguration'; import { ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest'; import { ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse'; -import { GetCircularReplacerToDotnet } from '../../utils/saveload'; +import { GetCircularReplacer } from '../../utils/saveload'; /** * Fetch the configuration from the API @@ -35,7 +35,7 @@ export async function FetchConfiguration(): Promise { export async function SetContainerList(request: ISetContainerListRequest, configurationUrl?: string): Promise { const url = configurationUrl ?? import.meta.env.VITE_API_SET_CONTAINER_LIST_URL; - const dataParsed = JSON.stringify(request, GetCircularReplacerToDotnet()); + const dataParsed = JSON.stringify(request, GetCircularReplacer()); // The test library cannot use the Fetch API // @ts-expect-error // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions diff --git a/src/Components/Messages/Messages.tsx b/src/Components/Messages/Messages.tsx index 9e04670..4fe95ce 100644 --- a/src/Components/Messages/Messages.tsx +++ b/src/Components/Messages/Messages.tsx @@ -5,7 +5,7 @@ import { MessageType } from '../../Enums/MessageType'; import { IHistoryState } from '../../Interfaces/IHistoryState'; import { IMessage } from '../../Interfaces/IMessage'; import { DISABLE_API } from '../../utils/default'; -import { GetCircularReplacerToDotnet } from '../../utils/saveload'; +import { GetCircularReplacer } from '../../utils/saveload'; import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar'; interface IMessagesProps { diff --git a/src/Components/UI/UseWorker.tsx b/src/Components/UI/UseWorker.tsx index 7a6a8f0..c231f07 100644 --- a/src/Components/UI/UseWorker.tsx +++ b/src/Components/UI/UseWorker.tsx @@ -3,7 +3,7 @@ import { IHistoryState } from '../../Interfaces/IHistoryState'; import { IGetFeedbackRequest } from '../../Interfaces/IGetFeedbackRequest'; import { IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse'; import { IMessage } from '../../Interfaces/IMessage'; -import { GetCircularReplacerToDotnet } from '../../utils/saveload'; +import { GetCircularReplacer } from '../../utils/saveload'; // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions const myWorker = window.Worker && new Worker('workers/message_worker.js'); @@ -38,7 +38,7 @@ export function UseAsync( // eslint-disable-next-line @typescript-eslint/naming-convention ApplicationState: state }; - const dataParsed = JSON.stringify(request, GetCircularReplacerToDotnet()); + const dataParsed = JSON.stringify(request, GetCircularReplacer()); fetch(import.meta.env.VITE_API_GET_FEEDBACK_URL, { method: 'POST', headers: new Headers({ diff --git a/src/utils/default.ts b/src/utils/default.ts index 253610b..1264b95 100644 --- a/src/utils/default.ts +++ b/src/utils/default.ts @@ -12,7 +12,7 @@ import { Position } from '../Enums/Position'; /// EDITOR DEFAULTS /// /** Enable fast boot and disable main menu (default = false) */ -export const FAST_BOOT = true; +export const FAST_BOOT = false; /** Disable any call to the API (default = false) */ export const DISABLE_API = false; diff --git a/src/utils/saveload.ts b/src/utils/saveload.ts index ed1f57c..5033fab 100644 --- a/src/utils/saveload.ts +++ b/src/utils/saveload.ts @@ -1,6 +1,8 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { FindContainerById, MakeDFSIterator } from './itertools'; import { IEditorState } from '../Interfaces/IEditorState'; import { IHistoryState } from '../Interfaces/IHistoryState'; +import { IContainerModel } from '../Interfaces/IContainerModel'; /** * Revive the Editor state @@ -32,7 +34,9 @@ export function ReviveState(state: IHistoryState): void { for (const symbol of state.symbols.values()) { symbol.linkedContainers = new Set(symbol.linkedContainers); } - state.containers = new Map(state.containers); + + const containers: Array<{ Key: string, Value: IContainerModel }> = (state.containers) as any; + state.containers = new Map(containers.map(({ Key, Value }: {Key: string, Value: IContainerModel}) => [Key, Value])); const root = FindContainerById(state.containers, state.mainContainer); @@ -64,43 +68,13 @@ export function GetCircularReplacer(): (key: any, value: object | Map).entries()); + return [...(value as Map).entries()] + .map(([Key, Value]: [string, any]) => ({ Key, Value })); } if (key === 'symbols') { - return Array.from((value as Map).entries()); - } - - if (key === 'linkedContainers') { - return Array.from(value as Set); - } - - return value; - }; -} - -export function GetCircularReplacerToDotnet(): (key: any, value: object | Map | null) => object | null | undefined { - return (key: any, value: object | null) => { - if (key === 'parent') { - return; - } - - if (key === 'containers') { - return [...(value as Map).entries()].map((keyPair: [string, any]) => { - return { - Key: keyPair[0], - Value: keyPair[1] - }; - }); - } - - if (key === 'symbols') { - return [...(value as Map).entries()].map((keyPair: [string, any]) => { - return { - Key: keyPair[0], - Value: keyPair[1] - }; - }); + return [...(value as Map).entries()] + .map(([Key, Value]: [string, any]) => ({ Key, Value })); } if (key === 'linkedContainers') { From 25e1033c564e5a589457c5158c21372f3c9dc570 Mon Sep 17 00:00:00 2001 From: Eric Nguyen Date: Mon, 17 Oct 2022 14:29:31 +0000 Subject: [PATCH 08/11] Updated default.ts: Reenable FAST_BOOT --- src/utils/default.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/default.ts b/src/utils/default.ts index 1264b95..253610b 100644 --- a/src/utils/default.ts +++ b/src/utils/default.ts @@ -12,7 +12,7 @@ import { Position } from '../Enums/Position'; /// EDITOR DEFAULTS /// /** Enable fast boot and disable main menu (default = false) */ -export const FAST_BOOT = false; +export const FAST_BOOT = true; /** Disable any call to the API (default = false) */ export const DISABLE_API = false; From d011a1ef291f8d831165ee6877a3eecca0991019 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 17:03:45 +0200 Subject: [PATCH 09/11] Vite: Change base directory to './' --- vite.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vite.config.ts b/vite.config.ts index f4b4d95..3df6f17 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,5 +5,6 @@ import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [ react() - ] + ], + base: './' }); From c693fc9a2068cfb087ea9f744f12cfed19172a92 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Mon, 17 Oct 2022 17:04:25 +0200 Subject: [PATCH 10/11] Update SmartComponent.md --- docs/#Project/Pages/SmartComponent.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/docs/#Project/Pages/SmartComponent.md b/docs/#Project/Pages/SmartComponent.md index 38460b6..07c880c 100644 --- a/docs/#Project/Pages/SmartComponent.md +++ b/docs/#Project/Pages/SmartComponent.md @@ -76,29 +76,6 @@ Cliquez sur le menu hamburger et cliquez sur **Download Artifacts** : - Puis copier les fichiers de build dans le dossier. (copiez l'entièreté du dossier `dist` ou extrayez le zip selon la méthode). -- Modifiez le fichier `index.html` du composant pour changer les chemins absolus en relatifs: - -```diff - - - - - - - - Vite + React + TS -- -+ -- -+ - - -
- - - -``` - - Si **besoin**, modifier le fichier `smartcomponent/svg-layout-designer.html` pour avoir la bonne url relative à la basename de l'url : ```diff From d40cd8cf8e18d9bff3d819a373685043eb3063c1 Mon Sep 17 00:00:00 2001 From: Guillaume Tauzin Date: Mon, 17 Oct 2022 17:36:00 +0200 Subject: [PATCH 11/11] Fix SetHistory in SmartComponent --- src/Events/EditorEvents.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Events/EditorEvents.ts b/src/Events/EditorEvents.ts index aa90c79..c572bda 100644 --- a/src/Events/EditorEvents.ts +++ b/src/Events/EditorEvents.ts @@ -54,7 +54,6 @@ function SetHistory(root: Element | Document, eventInitDict?: CustomEventInit): void { const history: IHistoryState[] = eventInitDict?.detail.history; const historyCurrentStep: number | undefined = eventInitDict?.detail.historyCurrentStep; - ReviveHistoryAction(history); setNewHistory(history, historyCurrentStep); const customEvent = new CustomEvent('setHistory', { detail: editorState }); root.dispatchEvent(customEvent);