@rsuci/shared-form-components 1.0.16 → 1.0.17
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.
- package/dist/components/roster/RosterPanel.d.ts +1 -0
- package/dist/components/roster/RosterPanel.d.ts.map +1 -1
- package/dist/components/roster/RosterPanel.js +22 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lib/roster-condition-engine.d.ts +57 -0
- package/dist/lib/roster-condition-engine.d.ts.map +1 -0
- package/dist/lib/roster-condition-engine.js +182 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RosterPanel.d.ts","sourceRoot":"","sources":["../../../src/components/roster/RosterPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"RosterPanel.d.ts","sourceRoot":"","sources":["../../../src/components/roster/RosterPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAOvC,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+J3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -7,12 +7,33 @@
|
|
|
7
7
|
*/
|
|
8
8
|
'use client';
|
|
9
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { useMemo } from 'react';
|
|
10
11
|
import VariableRenderer from '../VariableRenderer';
|
|
11
12
|
import { cn } from '../../lib/utils/cn';
|
|
13
|
+
import { RosterConditionEngine } from '../../lib/roster-condition-engine';
|
|
12
14
|
const RosterPanel = ({ option, rosterVariables, value, onChange, disabled, showCheckbox = false, isChecked = true, onCheckChange }) => {
|
|
13
15
|
// Trier les variables par ordre
|
|
14
16
|
const sortedVariables = [...rosterVariables].sort((a, b) => a.ordre - b.ordre);
|
|
15
|
-
|
|
17
|
+
// Calculer les variables masquées par les jumps
|
|
18
|
+
const jumpedVariables = useMemo(() => {
|
|
19
|
+
return RosterConditionEngine.computeJumpedVariables(sortedVariables.map(v => ({ code: v.code, ordre: v.ordre, conditionsAffichage: v.conditionsAffichage })), value);
|
|
20
|
+
}, [sortedVariables, value]);
|
|
21
|
+
// Filtrer les variables visibles (conditions + jumps)
|
|
22
|
+
const visibleVariables = useMemo(() => {
|
|
23
|
+
return sortedVariables.filter(rosterVar => {
|
|
24
|
+
// Variable masquée par un jump actif
|
|
25
|
+
if (jumpedVariables.has(rosterVar.code)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
// Pas de condition = visible
|
|
29
|
+
if (!rosterVar.conditionsAffichage) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
// Évaluer la condition avec les valeurs de cette ligne
|
|
33
|
+
return RosterConditionEngine.evaluate(rosterVar.conditionsAffichage, value);
|
|
34
|
+
});
|
|
35
|
+
}, [sortedVariables, jumpedVariables, value]);
|
|
36
|
+
return (_jsxs("div", { className: cn('border border-gray-200 rounded-lg p-4 bg-white', 'shadow-sm hover:shadow-md transition-shadow', disabled && 'opacity-60'), children: [_jsx("div", { className: "border-b border-gray-100 pb-3 mb-4", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center flex-1", children: [showCheckbox && (_jsx("input", { type: "checkbox", checked: isChecked, onChange: (e) => onCheckChange?.(e.target.checked), disabled: disabled, className: cn('w-5 h-5 mr-3 text-green-600 border-gray-300 rounded focus:ring-green-500', disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer') })), _jsxs("div", { children: [_jsxs("h3", { className: "font-semibold text-lg text-gray-800 flex items-center", children: [_jsx("span", { className: "mr-2", children: "\uD83D\uDCCC" }), option.designation] }), _jsxs("p", { className: "text-xs text-blue-600 font-mono mt-1", children: ["(", option.code, ")"] })] })] }) }) }), !showCheckbox || isChecked ? (_jsx("div", { className: "space-y-4", children: visibleVariables.map(rosterVar => {
|
|
16
37
|
// Créer un objet VariableFormulaire compatible avec VariableRenderer
|
|
17
38
|
// Rendre le code unique par panel pour éviter les conflits de radios/checkboxes
|
|
18
39
|
const uniqueCode = `${option.code}_${rosterVar.code}`;
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type { VariableNodeState, GroupNodeState, JumpRange, JumpError, IFormTree
|
|
|
38
38
|
export { VariableValueConverter } from './lib/utils/variableValueConverter';
|
|
39
39
|
export { interpolateVariableLabel } from './lib/utils/interpolateVariableLabel';
|
|
40
40
|
export { ConditionEngine } from './lib/condition-engine';
|
|
41
|
+
export { RosterConditionEngine, type RosterConditionError, type RosterConditionErrorType, type RosterConditionValidationResult, type RosterVariableRef } from './lib/roster-condition-engine';
|
|
41
42
|
export { FormTree } from './lib/form-tree';
|
|
42
43
|
export { useFormTree, type UseFormTreeOptions, type UseFormTreeReturn } from './hooks/useFormTree';
|
|
43
44
|
export { cn } from './lib/utils/cn';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,EACL,OAAO,IAAI,gBAAgB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACL,OAAO,IAAI,eAAe,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAOzC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAG3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAM5E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAM/E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAO9E,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,UAAU,EACV,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,SAAS,EACT,SAAS,EACT,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAG5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAGhF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAO3C,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGnG,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,8 @@ export { VariableValueConverter } from './lib/utils/variableValueConverter';
|
|
|
58
58
|
export { interpolateVariableLabel } from './lib/utils/interpolateVariableLabel';
|
|
59
59
|
// Moteur de conditions
|
|
60
60
|
export { ConditionEngine } from './lib/condition-engine';
|
|
61
|
+
// Moteur de conditions scopées pour les ROSTER
|
|
62
|
+
export { RosterConditionEngine } from './lib/roster-condition-engine';
|
|
61
63
|
// FormTree (arbre virtuel du formulaire)
|
|
62
64
|
export { FormTree } from './lib/form-tree';
|
|
63
65
|
// ========================================
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moteur d'évaluation des conditions scopées pour les variables ROSTER
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Ce moteur est ISOLÉ du ConditionEngine principal.
|
|
6
|
+
* Les conditions sont évaluées PAR LIGNE (par option de roster) indépendamment.
|
|
7
|
+
* Le scope est limité aux variables du même ROSTER uniquement.
|
|
8
|
+
*/
|
|
9
|
+
export type RosterConditionErrorType = 'variable_not_in_scope' | 'jump_out_of_scope' | 'backward_jump' | 'self_reference' | 'syntax_error';
|
|
10
|
+
export interface RosterConditionError {
|
|
11
|
+
type: RosterConditionErrorType;
|
|
12
|
+
variableCode: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
export interface RosterConditionValidationResult {
|
|
16
|
+
isValid: boolean;
|
|
17
|
+
errors: RosterConditionError[];
|
|
18
|
+
}
|
|
19
|
+
export interface RosterVariableRef {
|
|
20
|
+
code: string;
|
|
21
|
+
ordre: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Moteur de conditions scopées pour les ROSTER
|
|
25
|
+
* Toutes les méthodes sont statiques pour une utilisation sans état
|
|
26
|
+
*/
|
|
27
|
+
export declare class RosterConditionEngine {
|
|
28
|
+
/**
|
|
29
|
+
* Valide une condition au moment du design (admin)
|
|
30
|
+
* Vérifie que les références sont dans le scope et que les jumps sont valides
|
|
31
|
+
*/
|
|
32
|
+
static validateCondition(condition: string, availableVariables: RosterVariableRef[], currentVariableCode: string, currentVariableOrdre: number): RosterConditionValidationResult;
|
|
33
|
+
/**
|
|
34
|
+
* Évalue une condition au runtime (rendu)
|
|
35
|
+
* Utilise les valeurs de la ligne courante du roster
|
|
36
|
+
*/
|
|
37
|
+
static evaluate(condition: string, lineValues: Record<string, any>): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Extrait toutes les références de variables d'une condition
|
|
40
|
+
* Format: ${VAR_CODE}
|
|
41
|
+
*/
|
|
42
|
+
static extractVariableReferences(condition: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Extrait la cible d'un jump s'il existe dans la condition
|
|
45
|
+
* Format: jump(condition, ${TARGET})
|
|
46
|
+
*/
|
|
47
|
+
static extractJumpTarget(condition: string): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Calcule les variables qui doivent être masquées à cause des jumps actifs
|
|
50
|
+
*/
|
|
51
|
+
static computeJumpedVariables(sortedVariables: RosterVariableRef[], lineValues: Record<string, any>): Set<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Valide la syntaxe de base d'une condition
|
|
54
|
+
*/
|
|
55
|
+
private static validateSyntax;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=roster-condition-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster-condition-engine.d.ts","sourceRoot":"","sources":["../../src/lib/roster-condition-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,wBAAwB,GAChC,uBAAuB,GACvB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,GAChB,cAAc,CAAC;AAEnB,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,qBAAa,qBAAqB;IAEhC;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CACtB,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,iBAAiB,EAAE,EACvC,mBAAmB,EAAE,MAAM,EAC3B,oBAAoB,EAAE,MAAM,GAC3B,+BAA+B;IAgElC;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAyB5E;;;OAGG;IACH,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAO7D;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO1D;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAC3B,eAAe,EAAE,iBAAiB,EAAE,EACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9B,GAAG,CAAC,MAAM,CAAC;IA2Bd;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;CA0B9B"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moteur d'évaluation des conditions scopées pour les variables ROSTER
|
|
3
|
+
* RSU v2 - Moteur de Rendu des Formulaires d'Enquête
|
|
4
|
+
*
|
|
5
|
+
* Ce moteur est ISOLÉ du ConditionEngine principal.
|
|
6
|
+
* Les conditions sont évaluées PAR LIGNE (par option de roster) indépendamment.
|
|
7
|
+
* Le scope est limité aux variables du même ROSTER uniquement.
|
|
8
|
+
*/
|
|
9
|
+
import { ConditionEngine } from './condition-engine';
|
|
10
|
+
/**
|
|
11
|
+
* Moteur de conditions scopées pour les ROSTER
|
|
12
|
+
* Toutes les méthodes sont statiques pour une utilisation sans état
|
|
13
|
+
*/
|
|
14
|
+
export class RosterConditionEngine {
|
|
15
|
+
/**
|
|
16
|
+
* Valide une condition au moment du design (admin)
|
|
17
|
+
* Vérifie que les références sont dans le scope et que les jumps sont valides
|
|
18
|
+
*/
|
|
19
|
+
static validateCondition(condition, availableVariables, currentVariableCode, currentVariableOrdre) {
|
|
20
|
+
const errors = [];
|
|
21
|
+
if (!condition?.trim()) {
|
|
22
|
+
return { isValid: true, errors: [] };
|
|
23
|
+
}
|
|
24
|
+
const availableCodes = new Set(availableVariables.map(v => v.code));
|
|
25
|
+
// 1. Vérifier les références de variables
|
|
26
|
+
const refs = this.extractVariableReferences(condition);
|
|
27
|
+
for (const ref of refs) {
|
|
28
|
+
if (ref === currentVariableCode) {
|
|
29
|
+
errors.push({
|
|
30
|
+
type: 'self_reference',
|
|
31
|
+
variableCode: ref,
|
|
32
|
+
message: 'Une variable ne peut pas se référencer elle-même'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else if (!availableCodes.has(ref)) {
|
|
36
|
+
errors.push({
|
|
37
|
+
type: 'variable_not_in_scope',
|
|
38
|
+
variableCode: ref,
|
|
39
|
+
message: `La variable \${${ref}} n'existe pas dans ce Roster`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// 2. Vérifier le jump s'il existe
|
|
44
|
+
const jumpTarget = this.extractJumpTarget(condition);
|
|
45
|
+
if (jumpTarget) {
|
|
46
|
+
if (!availableCodes.has(jumpTarget)) {
|
|
47
|
+
errors.push({
|
|
48
|
+
type: 'jump_out_of_scope',
|
|
49
|
+
variableCode: jumpTarget,
|
|
50
|
+
message: `La variable cible \${${jumpTarget}} n'existe pas dans ce Roster`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const targetVar = availableVariables.find(v => v.code === jumpTarget);
|
|
55
|
+
if (targetVar && targetVar.ordre <= currentVariableOrdre) {
|
|
56
|
+
errors.push({
|
|
57
|
+
type: 'backward_jump',
|
|
58
|
+
variableCode: jumpTarget,
|
|
59
|
+
message: 'Le jump ne peut pas cibler une variable précédente'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// 3. Valider la syntaxe générale
|
|
65
|
+
const syntaxError = this.validateSyntax(condition);
|
|
66
|
+
if (syntaxError) {
|
|
67
|
+
errors.push({
|
|
68
|
+
type: 'syntax_error',
|
|
69
|
+
variableCode: '',
|
|
70
|
+
message: syntaxError
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
isValid: errors.length === 0,
|
|
75
|
+
errors
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Évalue une condition au runtime (rendu)
|
|
80
|
+
* Utilise les valeurs de la ligne courante du roster
|
|
81
|
+
*/
|
|
82
|
+
static evaluate(condition, lineValues) {
|
|
83
|
+
if (!condition?.trim()) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// Construire un contexte isolé pour cette ligne du roster
|
|
88
|
+
const responses = {};
|
|
89
|
+
for (const [code, value] of Object.entries(lineValues)) {
|
|
90
|
+
responses[code] = {
|
|
91
|
+
variableCode: code,
|
|
92
|
+
valeur: value,
|
|
93
|
+
dateModification: new Date()
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Utiliser le ConditionEngine en composition (pas héritage)
|
|
97
|
+
const engine = new ConditionEngine(responses);
|
|
98
|
+
return engine.evaluate(condition);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.warn('[RosterConditionEngine] Erreur évaluation:', condition, error);
|
|
102
|
+
return true; // En cas d'erreur, afficher par défaut
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extrait toutes les références de variables d'une condition
|
|
107
|
+
* Format: ${VAR_CODE}
|
|
108
|
+
*/
|
|
109
|
+
static extractVariableReferences(condition) {
|
|
110
|
+
if (!condition)
|
|
111
|
+
return [];
|
|
112
|
+
const matches = condition.match(/\$\{([A-Z_][A-Z0-9_]*)\}/g) || [];
|
|
113
|
+
return matches.map(m => m.slice(2, -1));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extrait la cible d'un jump s'il existe dans la condition
|
|
117
|
+
* Format: jump(condition, ${TARGET})
|
|
118
|
+
*/
|
|
119
|
+
static extractJumpTarget(condition) {
|
|
120
|
+
if (!condition)
|
|
121
|
+
return null;
|
|
122
|
+
const match = condition.match(/jump\s*\([^,]+,\s*\$\{([A-Z_][A-Z0-9_]*)\}\s*\)/);
|
|
123
|
+
return match ? match[1] : null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Calcule les variables qui doivent être masquées à cause des jumps actifs
|
|
127
|
+
*/
|
|
128
|
+
static computeJumpedVariables(sortedVariables, lineValues) {
|
|
129
|
+
const jumped = new Set();
|
|
130
|
+
for (const rosterVar of sortedVariables) {
|
|
131
|
+
const condition = rosterVar.conditionsAffichage;
|
|
132
|
+
if (!condition)
|
|
133
|
+
continue;
|
|
134
|
+
const jumpTarget = this.extractJumpTarget(condition);
|
|
135
|
+
if (!jumpTarget)
|
|
136
|
+
continue;
|
|
137
|
+
// Évaluer si le jump doit s'activer
|
|
138
|
+
if (this.evaluate(condition, lineValues)) {
|
|
139
|
+
const targetVar = sortedVariables.find(v => v.code === jumpTarget);
|
|
140
|
+
if (targetVar) {
|
|
141
|
+
// Masquer toutes les variables entre la source et la cible
|
|
142
|
+
for (const v of sortedVariables) {
|
|
143
|
+
if (v.ordre > rosterVar.ordre && v.ordre < targetVar.ordre) {
|
|
144
|
+
jumped.add(v.code);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return jumped;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Valide la syntaxe de base d'une condition
|
|
154
|
+
*/
|
|
155
|
+
static validateSyntax(condition) {
|
|
156
|
+
try {
|
|
157
|
+
// Vérifier les parenthèses équilibrées
|
|
158
|
+
let depth = 0;
|
|
159
|
+
for (const char of condition) {
|
|
160
|
+
if (char === '(')
|
|
161
|
+
depth++;
|
|
162
|
+
if (char === ')')
|
|
163
|
+
depth--;
|
|
164
|
+
if (depth < 0) {
|
|
165
|
+
return 'Parenthèses non équilibrées';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (depth !== 0) {
|
|
169
|
+
return 'Parenthèses non équilibrées';
|
|
170
|
+
}
|
|
171
|
+
// Vérifier les fonctions reconnues
|
|
172
|
+
const functionMatch = condition.match(/^(showMe|hideMe|jump)\s*\(/);
|
|
173
|
+
if (!functionMatch && !condition.includes('${')) {
|
|
174
|
+
return 'Condition invalide: utilisez showMe(), hideMe() ou jump()';
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
return `Erreur de syntaxe: ${error instanceof Error ? error.message : 'Erreur inconnue'}`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
package/package.json
CHANGED