Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# Documentation ngHyd pour les développeurs
Voir aussi :
* [ngHyd installation instructions](README.md)
* [JaLHyd developers documentation](https://gitlab.irstea.fr/cassiopee/jalhyd/blob/master/DEVELOPERS.md)
## Description
ngHyd est une interface Web pour [JaLHyd](https://gitlab.irstea.fr/cassiopee/jalhyd) écrite en Angular/typescript.
Elle est déclinée à l'aide d'Electron et Cordova sous forme d'application hors-ligne pour Linux, Mac, Windows et Android.
Les tests unitaires sont réalisés avec Protractor.
La documentation est générée avec Mkdocs.
## Pile logicielle
* typescript
* angular
* angular-material
* protractor
* electron
* cordova
* mkdocs
## Prérequis
### pour le développement
* nodejs / npm
* python (pour mkdocs)
* wine (pour Electron / windows)
* java (pour cordova / Android)
* SDK Android (pour cordova / Android)
### pour l'exécution
* version Web : une connexion Internet et un navigateur à jour (Firefox, Chrome/Chromium, Safari, Edge…)
* version hors-ligne : Linux, MacOS, Windows 7 ou plus récent, Android 7 ou plus récent
## Grands principes
### interface
ngHyd propose deux vues principales : la **page d'accueil** `/list` qui permet de créer de nouveaux modules de calcul, et la **vue module** `/calculator/{id}` qui affiche un des modules de la session.
Une **barre de navigation** en haut de l'écran permet de passer d'un module à l'autre, et de revenir à la page d'accueil.
Un **volet latéral** permet d'accéder à des commandes et vues supplémentaires.
L'interface s'appuie sur les principes de **material design** et de **responsive design**. Le contenu est supposé s'afficher correctement à partir d'une largeur d'écran de **360px**.
### modèle
L'état de la session, des modules, des paramètres et des résultats numériques est conservé par JaLHyd. Seules les représentations graphiques sont conservées par la couche ngHyd.
#### formulaires
nodes
ngparam
form*, form-compute*, form-result*
#### résultats
### configuration
#### générale
La configuration générale se trouve dans `app/config.json`.
Dans `params` on trouve les valeurs par défaut des réglages.
Dans `themes` on trouve l'organisation des modules en thèmes sur la page d'accueil. Dans chaque thème, la clé `calculators` doit contenir une liste de valeurs numériques correspondant à des éléments de l'enum `CalculatorType` de JaLHyd. Un même module peut être présent dans plusieurs thèmes. Si un module n'est présent dans aucun thème, i apparaîtra automatiquement dans un thème "autres" qui n'est visible que dans un tel cas.
#### modules
Chaque module de calcul JaLHyd doit être configuré dans `app/calculators`, dans un dossier portant le nom du module.
Le fichier de configuration principal est `app/calculators/lemodule/lemodule.config.json` (exemple pour le module "bief" : `app/calculators/bief/bief.config.json`). Il contient la liste des composants graphiques à afficher à l'écran, de haut en bas (généralement des "fieldset"), la répartition des paramètres du module dans ces éléments, et un bloc de configuration à la fin.
Pour chaque langue, un fichier supplémentaire est présent contenant les traductions contextualisées pour le module (voir "langues et traduction" plus bas).
### exemples de sessions
Des exemples de sessions prêtes à charger sont présents sous forme de fichiers JSON dans `app/examples`. Lors de l'ajout d'un nouveau fichier d'exemple, celui-ci doit être référencé dans la méthode `get exampleFiles()` dans le fichier `app/components/calculator-list.component.ts`. Ces exemples sont affichés sur la page d'accueil dans la dernière carte, lorsqu'aucun module n'a encore été créé.
### langues et traduction
Les chaînes de l'application sont traduites à l'aide du service `I18nService`, méthodes `localizeText()` pour les chaînes en général et `localizeMessage()` pour les messages de log de JaLHyd.
Les traductions doivent être placées dans les fichiers de langues du dossier `locale`.
Lorsqu'un module de calcul a besoin d'une traduction contextualisée, par exemple dans le cas d'une variable ayant le même symbole que dans d'autres modules de calcul, les traductions doivent être placées dans `app/calculators/lemodule/lemodule.lalangue.json` (exemple pour le module "bief" en anglais : `app/calculators/bief/bief.en.json`).
### electron
Le déploiement de ngHyd sous forme d'application de bureau se fait à l'aide d'Electron. Les fichiers concernés sont `main.js`, `electron-builder.yml`, les dossier `electron` et `release`.
`main.js` est le fichier de "bootstrap" d'Electron. Contient la création de la fenêtre de l'application, et le mécanisme de détection de mises à jour.
Pour débugger, on peut décommenter `win.webContents.openDevTools()`.
`electron-builder.yml` contient la configuration de l'empaquetage pour les différentes plateformes cibles.
Le dossier `electron` contient l'icône de l'application.
Le dossier `release` contient (entre autres) les paquets générés par electron-builder.
### cordova
Le déploiement de ngHyd sous forme d'application mobile se fait à l'aide de Cordova. Les fichiers et dossiers concernés sont `hooks`, `platforms`, `plugins` et `config.xml`.
### documentation
La documentation est générée à l'aide de MkDocs.
Les fichiers source pour une langue donnée se trouvent dans le dossier `docs-lang` (ex: `docs-fr`). Pour traduire la documentation dans une autre langue, il faut recopier l'intégralité des fichiers source puis les traduire. Afin de faciliter les liens de l'application vers la documentation, les noms des fichiers ne sont pas traduits et restent en français pour toutes les langues.
L'organisation hiérarchique de la documentation est définie dans les fichiers `mkdocs-lang.yml` (ex: `mkdocs-fr.yml`).
### tests unitaires
Les tests unitaires dits "end-to-end" ou "e2e" sont réalisés avec Protractor, basé sur Selenium et fourni avec Angular. Les tests se trouvent dans le dossier `e2e` et sont configurés dans `protractor.conf.js`.
Bien qu'elle soit supposée fonctionner avec d'autres navigateurs, l'exécution des tests n'est garantie qu'avec Chrome / Chromium. Le pilote Selenium pour Chrome ("chromedriver") posant parfois problème, `protractor.conf.js` contient une astuce qui recherche le pilote dans le système avant de le rechercher dans node_modules.
### scripts
Le dossier `scripts` contient des scripts d'aide à la compilation, utilisés par les commandes `npm` déclarées dans `package.json`.
## Ajouter un module de calcul
Dans cet exemple nous considérerons le module fictif "Addition" proposé dans la documentation de JaLHyd (voir ci-dessous).
### JaLHyd
Voir la [documentation JaLHyd pour les développeurs](https://gitlab.irstea.fr/cassiopee/jalhyd/blob/master/DEVELOPERS.md) (en anglais)
### configuration du module
Créer les fichiers de configuration du module de calcul :
Dans `app/calculators`, créer un dossier portant le nom du module : `app/calculators/addition`. Dans ce nouveau dossier, créer le fichier `addition.config.json`, comme suit :
```json
[
{
"id": "fs_addition",
"type": "fieldset",
"fields": [
"A",
"B",
"Y"
]
},
{
"type": "options",
"idCal": "Y",
"help": "addition.html"
}
]
```
Dans cet exemple, on définit un seul groupe de champs nommé arbitrairement "fs_addition", dans lequel on ajoute tous les paramètres de l'équation, désignés par leur symbole, qui doit correspondre au symbole fourni comme deuxième argument de `ParamDefinition()` dans JaLHyd.
Le deuxième et dernier bloc contient les options pour ce module: le paramètre à calculer par défaut (`idCal`) qui peut être différent de celui choisi dans JaLHyd, et le lien vers la page de documentation pour ce module (`help`).
Les options peuvent également contenir :
* `defaultNodeType` : le type de noeud par défaut du module de calcul. Ce champ sert par exemple pour les sections paramétrées à déterminer le type de section à afficher lors de la création du module. Si ce champ est absent, sa valeur est `ComputeNodeType.None`.
* les valeurs par défaut des **propriétés** du module
* les identifiants des listes déroulantes
Ces options sont utilisées par exemple dans `bief.config.json`.
#### inscription du nouveau module
Dans le constructeur de `FormulaireService` dans le fichier `src/app/services/formulaire.service.ts`, ajouter une entrée dans `this.calculatorPaths` pour fournir le préfixe des fichiers de configuration :
```TypeScript
this.calculatorPaths[CalculatorType.Addition] = "addition";
```
#### aide contextuelle
Différents éléments de la configuration peuvent contenir une clé `help` donnant l'URL de l'aide pour l'élément de l'interface graphique concerné :
* pour un champ de saisie numérique : `{... "type": "input", "id": "ID", "help": "aide.html", ...}` (remplace la forme courte `"ID"`)
* pour n'importe quelle entrée d'un champ de type "select" : `{... "type": "select", "help": "aide.html", ...}`
* pour des entrées spécifiques d'un champ de type "select" : `{... "type": "select", "help": { "IdDeLOption": "aide.html", ...}, ...}` (se référer au fichier de traduction du module pour la liste des ID des options, par exemple "SeuilTriangulaireTrunc_TriangularTruncWeirFree")
* pour un groupe de champs ("fieldset") : `{... "type": "fieldset", "help": "aide.html", ...}`
* pour tous les _fieldset_ d'un _fieldset_template_: `{... "type": "fieldset_template", "help": "aide.html", ...}`
* pour l'entête d'un groupe de champs répétables ("template_container") : `{... "type": "template_container", "help": "aide.html", ...}`
* éventuellement l'URL de l'aide pour un résultat en particulier, dans le bloc d'options de la configuration :
```json
{
"type": "options",
…
"resultsHelp": {
"HG": "devalaison/grille.html#hauteur-de-grille"
}
```
#### traduction
Dans le dossier de configuration `src/app/calculators/addition`, créer les fichiers d'internationalisation, par exemple `addition.fr.json` pour le français. Il doivent reprendre tous les identifiants utilisés dans le fichier de configuration (paramètres, groupes de champs, listes déroulantes…) et fournir leur traduction ainsi que leur unité si nécessaire, comme suit :
```json
{
"fs_addition": "Paramètres de l'équation",
"A": "Premier nombre",
"B": "Deuxième nombre",
"Y": "Somme",
"UNIT_A": "",
"UNIT_B": "",
"UNIT_Y": ""
}
```
Ici les mentions `UNIT_*` pourraient être omises.
### thème
Dans `config.json`, ajouter si nécessaire le numéro de `CalculatorType` à un ou plusieurs thèmes afin de classer le module sur la page de liste; dans le cas contraire le nouveau module apparaîtra dans une section "Autres".
### traduction du titre et des messages de log
Dans les fichiers `locale/messages.*.json` :
* ajouter deux champs pour le titre et le titre court du module de calcul. Par exemple pour un module "Addition" :
* `"INFO_ADDITION_TITRE": "Addition de deux nombres"`
* `"INFO_ADDITION_TITRE_COURT": "Addition"`
* si le module produit des messages de log qui n'existaient pas jusqu'alors, ajouter leur traduction en utilisant la chaîne complète du code de message comme clé. Exemple :
* `"ERROR_LOADING_SESSION": "Impossible de charger la session"`
### classes de formulaire personnalisées
2. **Si nécessaire** créer la classe du formulaire dans _src/app/formulaire/definition/concrete_ . Une classe de base gérant la majorité des cas est déjà disponible, en général cette étape n'est pas nécessaire
- Par ex : _FormulaireMaCalculette_ dans _src/app/formulaire/definition/concrete/form-ma-calculette.ts_
Ces classes concrètes sont construites par composition des classes dans _src/app/formulaire/definition_ :
- _form-def-*_ : définition/description du formulaire.
- _FormDefSection_ : avec paramètre à varier
- _FormDefParamToCalculate_ : avec paramètre à calculer
- etc...
- _form-compute-*_ : aspects calculatoires
- _form-result-*_ : affichage des résultats
On peut soit composer la classe concrète directement avec ces classes, soient dériver ces dernières et composer avec.
5. **Si une nouvelle classe a été créée à l'étape 2**, dans la méthode _FormulaireService.newFormulaire()_, compléter le _switch_ pour fournir la classe à instancier.
### si le module agrège des modules enfants
### si le formulaire comprend des listes déroulantes
### documentation
Pour chaque langue, ajouter un fichier .md dans les dossiers `docs-*/calculators`, puis placer ce nouveau fichier dans la hiérarchie de la documentation, en ajoutant son chemin dans les fichiers `mkdocs-*.yml`.
Lier ce fichier au module via la clé `help` du bloc d'options de la configuration du module. Exemple pour un fichier de documentation dont le chemin est `calculators/math/addition.md` : `"help" : "math/addition.html"` (MkDocs convertit les fichiers MarkDown en HTML)