5htp-core 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/package.json +4 -12
  2. package/src/client/app/component.tsx +11 -2
  3. package/src/client/assets/css/components/button.less +10 -10
  4. package/src/client/assets/css/components/other.less +0 -1
  5. package/src/client/assets/css/core.less +0 -4
  6. package/src/client/assets/css/text/text.less +1 -2
  7. package/src/client/assets/css/text/titres.less +0 -5
  8. package/src/client/assets/css/utils/layouts.less +5 -5
  9. package/src/client/assets/css/utils/sizing.less +6 -6
  10. package/src/client/components/Dialog/card.tsx +1 -1
  11. package/src/client/components/button.tsx +1 -1
  12. package/src/client/components/containers/Popover/index.tsx +2 -2
  13. package/src/client/components/index.ts +5 -16
  14. package/src/client/components/inputv3/index.tsx +2 -5
  15. package/src/client/services/router/components/Page.tsx +1 -2
  16. package/src/client/services/router/components/router.tsx +4 -8
  17. package/src/client/services/router/request/api.ts +31 -52
  18. package/src/client/services/router/response/index.tsx +2 -0
  19. package/src/common/data/dates.ts +50 -6
  20. package/src/common/router/layouts.ts +14 -5
  21. package/src/common/router/response/page.ts +12 -6
  22. package/src/common/validation/validators.ts +0 -4
  23. package/src/server/app/container/config.ts +2 -1
  24. package/src/server/services/router/http/index.ts +16 -22
  25. package/src/server/services/router/response/page/index.tsx +0 -0
  26. package/src/client/assets/fonts/Inter/index.less +0 -77
  27. package/src/client/assets/fonts/Inter/latin-500.woff2 +0 -0
  28. package/src/client/assets/fonts/Inter/latin-600.woff2 +0 -0
  29. package/src/client/assets/fonts/Inter/latin-800.woff2 +0 -0
  30. package/src/client/assets/fonts/Inter/latin-ext-500.woff2 +0 -0
  31. package/src/client/assets/fonts/Inter/latin-ext-600.woff2 +0 -0
  32. package/src/client/assets/fonts/Inter/latin-ext-800.woff2 +0 -0
  33. package/src/client/assets/fonts/Rubik/cyrillic-ext.woff2 +0 -0
  34. package/src/client/assets/fonts/Rubik/cyrillic.woff2 +0 -0
  35. package/src/client/assets/fonts/Rubik/hebrew.woff2 +0 -0
  36. package/src/client/assets/fonts/Rubik/index.less +0 -30
  37. package/src/client/assets/fonts/Rubik/latin-ext.woff2 +0 -0
  38. package/src/client/assets/fonts/Rubik/latin.woff2 +0 -0
  39. package/src/client/components/Amount.tsx +0 -38
  40. package/src/client/components/Form_old/index.tsx +0 -450
  41. package/src/client/components/Form_old/index.tsx.old +0 -436
  42. package/src/client/components/dropdown.old/Manager.tsx +0 -164
  43. package/src/client/components/dropdown.old/getPosition.ts +0 -137
  44. package/src/client/components/dropdown.old/index.tsx +0 -99
  45. package/src/client/components/dropdown.old/popover.less +0 -56
  46. package/src/client/components/input/Base/Choix.ts +0 -48
  47. package/src/client/components/input/Base/index.tsx +0 -432
  48. package/src/client/components/input/BaseV2/index.tsx +0 -72
@@ -1,436 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import React from 'react';
7
- import { ComponentChild } from 'preact';
8
- import dottie from 'dottie';
9
-
10
- // Libs
11
- import { TListeErreursSaisie, ErreurSaisieSchema } from '@erreurs';
12
- import { TPropsChamp as PropsChamp, propsDefautChampForm } from '@client/components/Champs/Base';
13
- import { Schema, TBaseComposantChamp, TObjetDonnees, TRetourValidation } from '@commun/donnees/schema';
14
- import { simpleDeepCopy } from '@commun/donnees/objets';
15
- import { ContexteOnglets } from '@client/components/Conteneurs/Onglets';
16
-
17
- /*----------------------------------
18
- - TYPES ENTREE
19
- ----------------------------------*/
20
-
21
- export type TComposantChamps<TDonnees> = { [nomChamp in keyof TDonnees]: ComponentChild };
22
-
23
- type TPropsHook<TDonnees extends TObjetDonnees> = {
24
-
25
- // Informations générales
26
- nom: string,
27
- donnees?: TDonnees,
28
- schema: Schema<TDonnees>,
29
-
30
- // Présentation & état
31
- progression?: false | number,
32
- autosave?: boolean,
33
- readOnly?: boolean,
34
-
35
- // Actions
36
- onChange?: (donnees: TDonnees, validation: TRetourValidation<TDonnees> | false) => void,
37
- afterValidation?: (validation: TRetourValidation<TDonnees>) => void,
38
- envoyer?: (donnees: TDonnees) => Promise<void>,
39
- refActions?: (actionsForm: TActionsForm<TDonnees>) => void,
40
- onSet?: { [nomChamp: string]: (anciennesDonnees: TDonnees, nouvellesDonnees: TDonnees) => TDonnees }
41
-
42
- // Champs
43
- propsChamps?: { [cle: string]: any }
44
- }
45
-
46
-
47
- /*----------------------------------
48
- - TYPES SORTIE
49
- ----------------------------------*/
50
- export type TEtatForm<TDonnees extends TObjetDonnees> = {
51
- saisie: Partial<TDonnees>,
52
- Champs: any,
53
- form: TActionsForm<TDonnees>,
54
- schema: Schema<TDonnees>,
55
- changes: number
56
- }
57
-
58
- export type TActionsForm<TDonnees> = {
59
- envoyer: (e?: any) => Promise<void>,
60
- set: (valeurs: Partial<TDonnees>) => void,
61
- get: (champ?: string) => any | TDonnees,
62
- }
63
-
64
- /*----------------------------------
65
- - COMPOSANTS
66
- ----------------------------------*/
67
- const debug = true;
68
- export const useForm = <TDonnees extends TObjetDonnees>(props: TPropsHook<TDonnees>): TEtatForm<TDonnees> => {
69
-
70
- const onglets = React.useContext(ContexteOnglets);
71
- const refChamps = React.useRef<{ [nomChamp: string]: HTMLElement }>({});
72
-
73
- /*----------------------------------
74
- - INIT
75
- ----------------------------------*/
76
-
77
- // State
78
- const [state, setState] = React.useState<{
79
- donnees: Partial<TDonnees>,
80
- erreurs: TListeErreursSaisie,
81
- errorsCount: number,
82
- progression: false | number,
83
- changed: Partial<TDonnees> // Nom des champs changés depuis le dernier enregistrement
84
- }>({
85
- donnees: props.donnees || {},
86
- erreurs: {},
87
- errorsCount: 0,
88
- progression: false,
89
- changed: {}
90
- });
91
-
92
- const donneesExternes = props.donnees !== undefined && props.onChange !== undefined;
93
- const donneesInit = ((donneesExternes ? props.donnees : state.donnees) || {}) as Partial<TDonnees>
94
- const schema = props.schema.generer(donneesInit);
95
- const donnees = schema.initDonnees(donneesInit, true);
96
-
97
- /*----------------------------------
98
- - METHODES
99
- ----------------------------------*/
100
- function get(champ: string): any;
101
- function get(): TDonnees;
102
- function get(champ?: string): any | TDonnees {
103
- return champ === undefined
104
- ? donnees
105
- : donnees[champ];
106
- }
107
-
108
- async function onChange(
109
- valeursInit: Partial<TDonnees>,
110
- newState: Partial<typeof state> = {},
111
- validerMaintenant: boolean = true
112
- ): Promise<{ erreurs: TListeErreursSaisie, errorsCount: number }> {
113
-
114
- // RAPPEL: donnees = anciennes données
115
-
116
- if (debug) console.log(`[form][saisie] onChange`, valeursInit);
117
-
118
- // Validation des données changées
119
- // TODO: conserver erreurs des champs n'ayant pas été changés
120
- let nouvellesDonnees: Partial<TDonnees>;
121
- let errorsCount: number = 0;
122
- let erreurs: TListeErreursSaisie = {}
123
- if (validerMaintenant) {
124
-
125
- ({
126
- valeurs: nouvellesDonnees,
127
- errorsCount,
128
- erreurs
129
- } = await valider(valeursInit));
130
-
131
- if (debug && errorsCount !== 0) console.log(`[form][saisie] erreurs`, erreurs);
132
-
133
- newState.erreurs = erreurs;
134
- newState.errorsCount = errorsCount;
135
-
136
- } else
137
- nouvellesDonnees = valeursInit;
138
-
139
- // Validation & mapping personnalisé
140
- /*if (props.filtres?.after)
141
- nouvellesDonnees = props.filtres.after(nouvellesDonnees, donnees);*/
142
-
143
- // Copie + fusion sans références
144
- const donneesCompletes = simpleDeepCopy(donnees, nouvellesDonnees);
145
-
146
- // Màj valeur + erreurs
147
- // Le passage d'une fonction permet de récupérer le dernier state, ce qui évite à composantChamps de redevenir undefined
148
- setState((stateA) => ({
149
- ...stateA,
150
- donnees: donneesCompletes,
151
- changed: { ...stateA.changed, ...nouvellesDonnees },
152
- ...newState
153
- }));
154
-
155
- if (props.onChange && errorsCount === 0)
156
- props.onChange(donneesCompletes, validerMaintenant ? { valeurs: nouvellesDonnees, errorsCount, erreurs } : false);
157
-
158
- /*if (valider && props.autosave === true) {
159
-
160
- if (props.envoyer === undefined)
161
- throw new Error("autosave = true, mais aucune fonction d'enregistrement n'est passée dans props.envoyer");
162
-
163
- await envoyer();
164
-
165
-
166
- }*/
167
-
168
- return { erreurs, errorsCount };
169
- }
170
-
171
- async function valider(
172
- donneesAvalider: Partial<TDonnees>
173
- ): Promise<TRetourValidation<TDonnees>> {
174
-
175
- console.log(`[form][saisie] Valider`, donneesAvalider, 'Données complètes =', donnees);
176
-
177
- // Pas de valeur pécifiées = on valide toutes les données du form
178
- const retour = await schema.valider(donneesAvalider, donnees, undefined, {
179
- corriger: true
180
- });
181
-
182
- // Focus sur le premier champ ayant déclenché une erreur
183
- if (retour.errorsCount !== 0) {
184
-
185
- const cheminChamp = Object.keys(retour.erreurs)[0]
186
- const champ = schema.get(cheminChamp);
187
-
188
- // Navig onglet
189
- if (onglets !== null) {
190
- onglets.navig(champ.onglet);
191
- }
192
-
193
- // Scroll
194
- const elemChamp = refChamps.current[cheminChamp];
195
- elemChamp?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'start' })
196
-
197
-
198
- }
199
-
200
- if (props.afterValidation !== undefined)
201
- props.afterValidation(retour, actions);
202
-
203
- return retour;
204
- }
205
-
206
- async function envoyer(e?: any): Promise<boolean> {
207
-
208
- if (e !== undefined)
209
- e.preventDefault();
210
-
211
- if (props.readOnly)
212
- return false;
213
-
214
- // Déjà en cours d'envoi
215
- if (props.progression !== undefined && props.progression !== false)
216
- return false;
217
-
218
- if (state.errorsCount !== 0)
219
- return false;
220
-
221
- console.log(`[form][saisie] Envoyer`, donnees);
222
-
223
- // Validation de l'ensemble des champs
224
- const { erreurs, errorsCount, valeurs } = await valider(donnees);
225
- if (errorsCount !== 0) {
226
- setState((stateA) => ({ ...stateA, erreurs, errorsCount }));
227
- console.error('Erreurs formulaire', erreurs);
228
- return false;
229
- }
230
-
231
- console.log("@@@ Envoi formulaire 2", valeurs);
232
-
233
- // Envoi
234
- if (props.envoyer) {
235
-
236
- if (!('progression' in props))
237
- setState((stateA) => ({ ...stateA, progression: 0 }));
238
-
239
- //Ayant été validée, on estime que les données sont complètes
240
- const envoi = props.envoyer(valeurs as TDonnees);
241
-
242
- if (envoi.then === undefined)
243
- throw new Error("La fonction passée dans props.envoyer doit retourner une promise.");
244
-
245
- return await envoi.then(() => {
246
-
247
- setState((stateA) => ({
248
- ...stateA,
249
- progression: ('progression' in props)
250
- ? stateA.progression
251
- : false,
252
- changed: {} // Reset de la liste des données changées
253
- }));
254
-
255
- return true;
256
-
257
- }).catch((e) => {
258
-
259
- if (debug) console.log("RETOUR ERREURS API", e);
260
-
261
- if (e instanceof ErreurSaisieSchema) {
262
-
263
- setState((stateA) => ({
264
- ...stateA,
265
- erreurs: e.erreursSaisie,
266
- progression: 'progression' in props ? stateA.progression : false
267
- }));
268
-
269
- } else
270
- throw e;
271
-
272
- return false;
273
-
274
- });
275
- }
276
-
277
- return false;
278
- }
279
-
280
- /*----------------------------------
281
- - RENDU CHAMPS
282
- ----------------------------------*/
283
- const rendreChamps = (schema: Schema<{}>, donnees: TObjetDonnees) => {
284
-
285
- const schemaPourRendu: {
286
- [champ: string]: {
287
- composant: TBaseComposantChamp,
288
- attrs: (propsBase: PropsChamp<unknown>) => PropsChamp<unknown>
289
- }
290
- } = {}
291
-
292
- for (const nomChamp in schema.champs) {
293
-
294
- // Désactivé = pas d'affichage
295
- if (schema.champs[nomChamp].activer === false)
296
- continue;
297
-
298
- // Sous-schema
299
- if (schema.champs[nomChamp] instanceof Schema) {
300
- schemaPourRendu[nomChamp] = rendreChamps(schema.champs[nomChamp], donnees[nomChamp] || {});
301
- continue;
302
- }
303
-
304
- const { rendu, as, ...attrs } = schema.champs[nomChamp];
305
-
306
- // Prérendu
307
- if (rendu === undefined)
308
- continue;
309
-
310
- // Correction valeur selon as
311
- const valeur = as === undefined
312
- ? donnees[nomChamp]
313
- // Champ composé de plusieurs valeurs
314
- : as.map((nomDonnee) => donnees[nomDonnee]);
315
-
316
- /*
317
- ATTENTION: Faire en sorte que les propriétés passées dans le composant soient bien
318
- fusionnées avec les prorpiétés injectées par le form. Ex: onChange, attrsChamp, ...
319
- */
320
-
321
- const cheminChamp = [...schema.chemin, nomChamp].join('.');
322
-
323
- schemaPourRendu[nomChamp] = {
324
- composant: rendu,
325
- attrs: (propsChamp) => ({
326
-
327
- // Config par défaut pour les champs appartenant au form (ex: label systèmatique)
328
- ...propsDefautChampForm,
329
-
330
- // Attributs définis via le schema
331
- ...(attrs || {}),
332
- // Attributs définis via l'appel du composant
333
- ...(propsChamp || {}),
334
-
335
- // Rattachement au form
336
- ref: (ref: HTMLElement) => refChamps.current[cheminChamp] = ref?.base,
337
- nom: nomChamp,
338
- valeur: valeur,
339
- as: as,
340
- valider: undefined, // Pas de validation dans le champ. On fait tous les champs em même temps depuis le form
341
- erreurs: state.erreurs[cheminChamp],
342
- readOnly: props.readOnly, // Si le form est readonly, alors tous ses champs le sont obligatoirement
343
- onChange: async (nouvelleValeur: any, validerMaintenant: boolean = false) => {
344
-
345
- // Aucun changement
346
- // NOTE: Quand executé depuis onFocus, la valeur a déjà été changée via onChange
347
- if (nouvelleValeur === valeur && !validerMaintenant)
348
- return;
349
-
350
- // Mapping données
351
- let nouvellesDonnees: Partial<TDonnees>;
352
- if (as !== undefined) {
353
- nouvellesDonnees = dottie.transform({
354
- [ [...schema.chemin, as[0]].join('.') ]: nouvelleValeur[0],
355
- [ [...schema.chemin, as[1]].join('.') ]: nouvelleValeur[1]
356
- });
357
- // Mapping classique
358
- } else
359
- nouvellesDonnees = dottie.transform({
360
- [cheminChamp]: nouvelleValeur
361
- });
362
-
363
- // Application des changements
364
- const { errorsCount } = await onChange(nouvellesDonnees, {}, validerMaintenant);
365
-
366
- // Si aucune erreur, onChange propre au champ + gestion erreurs
367
- if (propsChamp.onChange !== undefined && errorsCount === 0)
368
- await propsChamp.onChange(nouvelleValeur, true).catch((e) => {
369
- if (validerMaintenant)
370
- setState((stateA) => ({
371
- ...stateA,
372
- erreurs: {
373
- ...stateA.erreurs,
374
- [cheminChamp]: [e]
375
- }
376
- }));
377
- })
378
- },
379
- })
380
- }
381
- }
382
-
383
- return schemaPourRendu;
384
- }
385
-
386
- const champs = rendreChamps(schema, donnees);
387
-
388
- /*----------------------------------
389
- - RETOUR
390
- ----------------------------------*/
391
- const actions = {
392
- form: {
393
- envoyer,
394
- get,
395
- set: onChange,
396
- },
397
- saisie: donnees,
398
- Champs: champs,
399
- schema,
400
- changes: Object.keys(state.changed).length
401
- }
402
-
403
- return actions;
404
- }
405
-
406
- export default <TDonnees extends TObjetDonnees>({ children, className, style, ...optsHook }: {
407
-
408
- // Champs
409
- children: ComponentChild | ((
410
- form: TActionsForm<TDonnees>,
411
- donnees: Partial<TDonnees>,
412
- champs: TComposantChamps<TDonnees>
413
- ) => ComponentChild),
414
-
415
- // Présentation
416
- className?: string,
417
- style?: any,
418
-
419
- } & TPropsHook<TDonnees>) => {
420
-
421
- if (typeof children === 'function') {
422
- const { form, donnees, Champs } = useForm(optsHook);
423
- children = children(form, donnees, Champs);
424
- }
425
-
426
- return (
427
- <form className={className} style={style}/*onSubmit={envoyer}*/>
428
- {children}
429
- </form>
430
- );
431
-
432
- /*
433
- <Chargement progression={'progression' in props ? props.progression : state.progression}>
434
- </Chargement>
435
- */
436
- }
@@ -1,164 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import React from 'react';
7
- import { ComponentChild, JSX } from 'preact';
8
-
9
- // Libs
10
- import useContexte from '@client/context';
11
- import getPosition, { TSide, TPosition } from './getPosition';
12
- import { blurable, deepContains } from '@client/utils/dom';
13
-
14
- /*----------------------------------
15
- - TYPES: IMPORTATIONS
16
- ----------------------------------*/
17
-
18
- /*----------------------------------
19
- - TYPES: DECLARATIONS
20
- ----------------------------------*/
21
-
22
- export type PopoverProps = {
23
-
24
- origin: HTMLElement,
25
- content: JSX.Element,
26
- interactions?: boolean
27
- position?: TSide,
28
- frame?: React.Ref<HTMLDivElement>,
29
-
30
- onVisibilityChange?: (visible: boolean) => void,
31
- close: () => void,
32
- initialPosition: TPosition,
33
-
34
- immutable?: boolean, // If true, don't add classes, nor childrens
35
- }
36
-
37
- export type TPopover = PopoverProps & {
38
- id: number,
39
- close: () => void,
40
- visible: boolean,
41
- onVisibilityChange?: (visible: boolean) => void,
42
- }
43
-
44
- const Popover = ({ id, origin, content, interactions, position: side, frame, close, initialPosition, onVisibilityChange }: TPopover) => {
45
-
46
- const [position, setPosition] = React.useState<TPosition>(initialPosition);
47
- const refElement = React.createRef<HTMLElement>();
48
-
49
- React.useEffect(() => {
50
-
51
- if (!refElement.current)
52
- return console.warn("Unable to get the popover dom origin to compute the correct position");
53
-
54
- // Now the popover is shown and we know his dipensions,
55
- // we can set the correct position
56
- setPosition(
57
- getPosition(
58
- origin,
59
- refElement.current,
60
- side,
61
- frame?.current || (document.getElementById('#layout') as HTMLElement)
62
- )
63
- );
64
-
65
- }, [id]);
66
-
67
- return React.cloneElement(content, {
68
- className: (content.props.className || '') + ' popover' + (position ? ' pos_' + position.cote : ''),
69
- onClick: () => {
70
- if (!interactions) {
71
- close();
72
- }
73
- },
74
- ref: refElement,
75
- style: {
76
- ...(content.props.style || {}),
77
- ...(position ? {
78
- top: position.css.top,
79
- left: position.css.left,
80
- right: position.css.right,
81
- bottom: position.css.bottom,
82
- } : {}),
83
- }
84
- });
85
-
86
- }
87
-
88
- /*----------------------------------
89
- - COMPOSANT
90
- ----------------------------------*/
91
- let curId: number = 0;
92
- export default ({ }: {
93
-
94
- }) => {
95
-
96
- const ctx = useContexte();
97
-
98
- const [popover, setPopover] = React.useState<TPopover | null>(null);
99
-
100
- ctx.popover = (props: PopoverProps): TPopover => {
101
-
102
- const id = curId++;
103
- const close = () => {
104
- setPopover(p => p && p.id === id ? null : p);
105
- if (props.onVisibilityChange)
106
- props.onVisibilityChange(false);
107
- }
108
-
109
- const popover = {
110
- ...props,
111
-
112
- id,
113
- visible: true,
114
- close
115
- };
116
-
117
- if (props.onVisibilityChange)
118
- props.onVisibilityChange(true);
119
-
120
- setPopover(existing => {
121
-
122
- if (existing !== null && existing.onVisibilityChange)
123
- existing.onVisibilityChange(false);
124
-
125
- return popover;
126
-
127
- });
128
-
129
- return popover;
130
- }
131
-
132
- if (popover === null)
133
- return null;
134
-
135
- React.useEffect(() => {
136
- const blur = (e: MouseEvent) => {
137
-
138
- const clickedOnPopover = deepContains([".popover", '.btn.dropdown'], e.target);
139
- if (clickedOnPopover)
140
- return;
141
-
142
- if (popover.onVisibilityChange)
143
- popover.onVisibilityChange(false);
144
-
145
- setPopover(null);
146
- };
147
- document.addEventListener('mousedown', blur);
148
- return () => document.removeEventListener('mousedown', blur);
149
- });
150
-
151
- const initialPosition = getPosition(
152
- popover.origin,
153
- [200 /* = min-width .popover */, 100],
154
- popover.position,
155
- popover.frame?.current || (document.getElementById('#layout') as HTMLElement)
156
- )
157
-
158
- return (
159
- <div id="popover">
160
- <Popover {...popover} initialPosition={initialPosition} />
161
- </div>
162
- )
163
-
164
- }