@inseefr/lunatic 3.8.1-rc.0 → 3.9.0

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 (28) hide show
  1. package/README.md +7 -13
  2. package/components/Suggester/Suggester.js +12 -16
  3. package/components/Suggester/Suggester.js.map +1 -1
  4. package/components/Suggester/Suggester.spec.js +68 -25
  5. package/components/Suggester/Suggester.spec.js.map +1 -1
  6. package/components/Suggester/useSuggestions.js +2 -2
  7. package/components/Suggester/useSuggestions.js.map +1 -1
  8. package/esm/components/Suggester/Suggester.js +13 -17
  9. package/esm/components/Suggester/Suggester.js.map +1 -1
  10. package/esm/components/Suggester/Suggester.spec.js +71 -25
  11. package/esm/components/Suggester/Suggester.spec.js.map +1 -1
  12. package/esm/components/Suggester/useSuggestions.js +3 -3
  13. package/esm/components/Suggester/useSuggestions.js.map +1 -1
  14. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js +23 -23
  15. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  16. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js +95 -0
  17. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  18. package/package.json +4 -2
  19. package/src/components/Suggester/Suggester.spec.tsx +86 -26
  20. package/src/components/Suggester/Suggester.tsx +11 -16
  21. package/src/components/Suggester/useSuggestions.ts +2 -2
  22. package/src/use-lunatic/commons/variables/lunatic-variables-store.spec.ts +106 -0
  23. package/src/use-lunatic/commons/variables/lunatic-variables-store.ts +24 -29
  24. package/tsconfig.build.tsbuildinfo +1 -1
  25. package/use-lunatic/commons/variables/lunatic-variables-store.js +21 -25
  26. package/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  27. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js +95 -0
  28. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
@@ -44,7 +44,7 @@ export function WrappedSuggester({
44
44
  // so we can break the rule of hooks here
45
45
  const computeSelectedOptions = (): [SuggesterOptionType] | [] => {
46
46
  if (arbitraryValue) {
47
- return [{ id: 'OTHER', label: arbitraryValue, value: 'OTHER' }];
47
+ return [{ id: OTHER_VALUE, label: arbitraryValue, value: OTHER_VALUE }];
48
48
  }
49
49
  if (!value) {
50
50
  return [];
@@ -62,13 +62,7 @@ export function WrappedSuggester({
62
62
  if (typeof label !== 'string') {
63
63
  return [{ id: value, label: value, value: value }];
64
64
  }
65
- return [
66
- {
67
- id: value,
68
- label: label,
69
- value: value,
70
- },
71
- ];
65
+ return [{ id: value, label: label, value: value }];
72
66
  };
73
67
 
74
68
  const [selectedOptions, setSelectedOptions] = useState<
@@ -153,15 +147,16 @@ export function WrappedSuggester({
153
147
 
154
148
  useEffect(() => {
155
149
  // Fix display issue (when handleChanges is called outside this component (in management mode, return to FORCED value by example)
156
- // "value" does'nt match selectedOption's "id"
157
- if (value && selectedOptions[0]?.id !== value) {
150
+ // "value" doesn't match selectedOption's "id"
151
+ if (selectedOptions[0]?.id !== value) {
158
152
  const actualSelection = computeSelectedOptions();
159
- const selectedOptionsWithLabel = [
160
- {
161
- ...actualSelection[0],
162
- label: getLabelById(actualSelection[0]?.id),
163
- },
164
- ] as [SuggesterOptionType];
153
+ const selectedOptionsWithLabel = actualSelection.map((selection) => {
154
+ if (selection.id === OTHER_VALUE) return selection;
155
+ return {
156
+ ...selection,
157
+ label: getLabelById(selection.id),
158
+ };
159
+ }) as [SuggesterOptionType];
165
160
  setSelectedOptions(selectedOptionsWithLabel);
166
161
  }
167
162
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -25,7 +25,7 @@ export function useStore({ storeName }: { storeName: string }) {
25
25
  const [state, setState] = useState<State>(
26
26
  store.error !== null
27
27
  ? 'error'
28
- : store?.search.isIndexed()
28
+ : store.search.isIndexed()
29
29
  ? 'success'
30
30
  : 'loading'
31
31
  );
@@ -51,7 +51,7 @@ export function useStore({ storeName }: { storeName: string }) {
51
51
  setStoreState: setState,
52
52
  getLabelById: (id: any) => {
53
53
  if (!id) return '';
54
- return store.search?.getFieldsById(id).label ?? '';
54
+ return store.search?.getFieldsById(id)?.label ?? '';
55
55
  },
56
56
  };
57
57
  }
@@ -984,5 +984,111 @@ describe('lunatic-variables-store', () => {
984
984
 
985
985
  expect(store.get('GLOBAL_ENFANTS_PRENOMS', [4])).toBe(undefined);
986
986
  });
987
+
988
+ it('should compute correctly GLOBAL array variable across calculated variables, even if not intialize', () => {
989
+ // Given a source with a pairwise component
990
+ const pairwiseComponent = {
991
+ id: 'm8ob5u9l',
992
+ page: '3',
993
+ symLinks: {
994
+ LINKS: {
995
+ '1': '1',
996
+ '2': '3',
997
+ '3': '2',
998
+ },
999
+ },
1000
+ components: [
1001
+ {
1002
+ id: 'm8ob5u9l-pairwise-dropdown',
1003
+ label: {
1004
+ type: 'VTL|MD',
1005
+ value: '"Qui est " || yAxis || " pour " || xAxis || " ?"',
1006
+ },
1007
+ options: [
1008
+ {
1009
+ label: {
1010
+ type: 'VTL',
1011
+ value: '"Son conjoint, sa conjointe"',
1012
+ },
1013
+ value: '1',
1014
+ },
1015
+ {
1016
+ label: { type: 'VTL', value: '"Sa mère, son père"' },
1017
+ value: '2',
1018
+ },
1019
+ {
1020
+ label: { type: 'VTL', value: '"Sa fille, son fils"' },
1021
+ value: '3',
1022
+ },
1023
+ ],
1024
+ response: { name: 'LINKS' },
1025
+ isMandatory: false,
1026
+ componentType: 'Dropdown',
1027
+ conditionFilter: {
1028
+ type: 'VTL',
1029
+ value: '(nvl(xAxis, "") <> "") and (nvl(yAxis, "") <> "")',
1030
+ },
1031
+ },
1032
+ ],
1033
+ sourceVariables: {
1034
+ name: 'PRENOM',
1035
+ gender: 'SEXE',
1036
+ },
1037
+ componentType: 'PairwiseLinks',
1038
+ xAxisIterations: { type: 'VTL', value: 'count(PRENOM)' },
1039
+ yAxisIterations: { type: 'VTL', value: 'count(PRENOM)' },
1040
+ } as ComponentDefinitionWithPage;
1041
+
1042
+ // When we create the store
1043
+ const store = LunaticVariablesStore.makeFromSource(
1044
+ {
1045
+ components: [pairwiseComponent],
1046
+ variables: [
1047
+ {
1048
+ name: 'PRENOM',
1049
+ values: { COLLECTED: [] },
1050
+ dimension: 1,
1051
+ variableType: 'COLLECTED',
1052
+ iterationReference: 'm8ob7c76',
1053
+ },
1054
+ {
1055
+ name: 'SEXE',
1056
+ values: { COLLECTED: [] },
1057
+ dimension: 1,
1058
+ variableType: 'COLLECTED',
1059
+ iterationReference: 'm8ob7c76',
1060
+ },
1061
+ {
1062
+ name: 'LINKS',
1063
+ values: { COLLECTED: [[]] },
1064
+ dimension: 2,
1065
+ variableType: 'COLLECTED',
1066
+ iterationReference: 'm8ob7c76',
1067
+ },
1068
+ ],
1069
+ },
1070
+ {},
1071
+ { changeHandler: { current: () => {} } }
1072
+ );
1073
+
1074
+ // When pairwise link is updated
1075
+ store.set('PRENOM', ['Child', 'Dad']);
1076
+ store.set('SEXE', ['1', '1']);
1077
+ store.set('LINKS', [
1078
+ [null, '2'],
1079
+ ['3', null],
1080
+ ]);
1081
+ store.commit();
1082
+ expect(
1083
+ store.run('"Your children are : " || GLOBAL_ENFANTS_PRENOMS', {
1084
+ iteration: [0],
1085
+ })
1086
+ ).toBe('Your children are : null');
1087
+ expect(
1088
+ store.run('"Your children are : " || GLOBAL_ENFANTS_PRENOMS', {
1089
+ iteration: [1],
1090
+ })
1091
+ ).toBe('Your children are : Child');
1092
+ });
987
1093
  });
988
1094
  });
@@ -540,21 +540,28 @@ export class LunaticVariable {
540
540
  opts: { iteration?: IterationLevel; ignoreIterationOnScalar?: boolean }
541
541
  ): boolean {
542
542
  const { iteration, ignoreIterationOnScalar } = opts;
543
- if (value === this.getSavedValue(iteration)) {
544
- return false;
545
- }
546
- // Decompose arrays, to only update items that changed
547
- if (Array.isArray(value) && !Array.isArray(iteration)) {
548
- return this.setValueForArray(value);
549
- }
550
- // We want to save a value at a specific iteration, but the value is not an array yet
543
+
544
+ // We want to save a value at a specific iteration
545
+ // but the value is not an array yet
546
+ // we have to initialize the array even if we want to set an `null` or `undefined` value
547
+ // (if no, issue with getCalculatedAt that check if this.value is an array, it return global updatedValue instead of the iteration one)
551
548
  if (iteration !== undefined && !Array.isArray(this.value)) {
552
549
  // Ignore the iteration since the value is not an array
553
550
  if (ignoreIterationOnScalar) {
554
551
  return this.setValue(value, {});
555
552
  }
553
+ // we have to set empty array at first before compare the with the SavedValue
556
554
  this.value = [];
557
555
  }
556
+
557
+ if (value === this.getSavedValue(iteration)) {
558
+ return false;
559
+ }
560
+ // Decompose arrays, to only update items that changed
561
+ if (Array.isArray(value) && !Array.isArray(iteration)) {
562
+ return this.setValueForArray(value);
563
+ }
564
+
558
565
  this.value = !Array.isArray(iteration)
559
566
  ? value
560
567
  : setAtIndex(this.value, iteration, value);
@@ -680,33 +687,21 @@ export class LunaticVariable {
680
687
  }
681
688
 
682
689
  public getUpdatedAt(iteration?: IterationLevel): number {
683
- if (this.dimension === 0) {
684
- return this.updatedAt.get(undefined) ?? 0;
685
- }
686
690
  // The value is an array, do not look at the root updatedAt if an iteration is provided
687
- if (Array.isArray(this.value)) {
688
- return this.updatedAt.get(iteration?.join('.')) ?? 0;
691
+ if (iteration !== undefined && Array.isArray(this.value)) {
692
+ return this.updatedAt.get(iteration.join('.')) ?? 0;
689
693
  }
690
- return (
691
- this.updatedAt.get(iteration?.join('.')) ??
692
- this.updatedAt.get(undefined) ??
693
- 0
694
- );
694
+ // undefined key is for root level
695
+ return this.updatedAt.get(undefined) ?? 0;
695
696
  }
696
697
 
697
698
  public getCalculatedAt(iteration?: IterationLevel): number {
698
- if (this.dimension === 0) {
699
- return this.calculatedAt.get(undefined) ?? 0;
699
+ // The value is an array, do not look at the root calculatedAt if an iteration is provided
700
+ if (iteration !== undefined && Array.isArray(this.value)) {
701
+ return this.calculatedAt.get(iteration.join('.')) ?? 0;
700
702
  }
701
- // The value is an array, do not look at the root updatedAt if an iteration is provided
702
- if (Array.isArray(this.value)) {
703
- return this.calculatedAt.get(iteration?.join('.')) ?? 0;
704
- }
705
- return (
706
- this.calculatedAt.get(iteration?.join('.')) ??
707
- this.calculatedAt.get(undefined) ??
708
- 0
709
- );
703
+ // undefined key is for root level
704
+ return this.calculatedAt.get(undefined) ?? 0;
710
705
  }
711
706
  }
712
707