@inseefr/lunatic 3.7.6-rc.alphanumeric-sorting.1 → 3.7.7-rc.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.
- package/components/Suggester/CustomSuggester.js +1 -1
- package/components/Suggester/CustomSuggester.js.map +1 -1
- package/components/Suggester/Suggester.js +11 -2
- package/components/Suggester/Suggester.js.map +1 -1
- package/components/shared/Combobox/Combobox.js +2 -1
- package/components/shared/Combobox/Combobox.js.map +1 -1
- package/esm/components/Suggester/CustomSuggester.js +1 -1
- package/esm/components/Suggester/CustomSuggester.js.map +1 -1
- package/esm/components/Suggester/Suggester.js +12 -3
- package/esm/components/Suggester/Suggester.js.map +1 -1
- package/esm/components/shared/Combobox/Combobox.js +2 -1
- package/esm/components/shared/Combobox/Combobox.js.map +1 -1
- package/esm/i18n/dictionary.d.ts +4 -0
- package/esm/i18n/dictionary.js +5 -1
- package/esm/i18n/dictionary.js.map +1 -1
- package/esm/i18n/index.d.ts +1 -1
- package/esm/use-lunatic/commons/page.js +53 -2
- package/esm/use-lunatic/commons/page.js.map +1 -1
- package/esm/use-lunatic/reducer/commons/auto-explore-loop.js +1 -1
- package/esm/use-lunatic/reducer/commons/auto-explore-loop.js.map +1 -1
- package/esm/utils/search/tokenizer.js +6 -3
- package/esm/utils/search/tokenizer.js.map +1 -1
- package/esm/utils/search/tokenizer.spec.js +10 -0
- package/esm/utils/search/tokenizer.spec.js.map +1 -1
- package/i18n/dictionary.d.ts +4 -0
- package/i18n/dictionary.js +5 -1
- package/i18n/dictionary.js.map +1 -1
- package/i18n/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/Suggester/CustomSuggester.tsx +1 -1
- package/src/components/Suggester/Suggester.tsx +16 -5
- package/src/components/shared/Combobox/Combobox.tsx +2 -1
- package/src/i18n/dictionary.ts +5 -1
- package/src/use-lunatic/commons/page.ts +72 -3
- package/src/use-lunatic/reducer/commons/auto-explore-loop.ts +1 -1
- package/src/utils/search/tokenizer.spec.ts +14 -0
- package/src/utils/search/tokenizer.ts +6 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/use-lunatic/commons/page.js +53 -2
- package/use-lunatic/commons/page.js.map +1 -1
- package/use-lunatic/reducer/commons/auto-explore-loop.js +1 -1
- package/use-lunatic/reducer/commons/auto-explore-loop.js.map +1 -1
- package/utils/search/tokenizer.js +6 -3
- package/utils/search/tokenizer.js.map +1 -1
- package/utils/search/tokenizer.spec.js +10 -0
- package/utils/search/tokenizer.spec.js.map +1 -1
|
@@ -13,6 +13,7 @@ import { ComboboxClearButton } from './Selection/ComboboxClearButton';
|
|
|
13
13
|
import { ComboboxSelection } from './Selection/ComboboxSelection';
|
|
14
14
|
import { between, forceInt } from '../../../utils/number';
|
|
15
15
|
import { Label } from '../Label/Label';
|
|
16
|
+
import D from '../../../i18n';
|
|
16
17
|
import { slottableComponent } from '../HOC/slottableComponent';
|
|
17
18
|
import type { LunaticError } from '../../../use-lunatic/type';
|
|
18
19
|
import { Declarations } from '../Declarations/Declarations';
|
|
@@ -45,7 +46,7 @@ function LunaticComboBox({
|
|
|
45
46
|
className,
|
|
46
47
|
classNamePrefix,
|
|
47
48
|
classStyle = 'default-style',
|
|
48
|
-
placeholder =
|
|
49
|
+
placeholder = D.PLACEHOLDER,
|
|
49
50
|
editable = false,
|
|
50
51
|
disabled,
|
|
51
52
|
readOnly,
|
package/src/i18n/dictionary.ts
CHANGED
|
@@ -5,7 +5,11 @@ const dictionary = {
|
|
|
5
5
|
MODAL_CORRECT: { fr: 'Corriger ma réponse', en: 'Correct' },
|
|
6
6
|
DK: { fr: 'Ne sais pas', en: "Don't know" },
|
|
7
7
|
RF: { fr: 'Refus', en: 'Refused' },
|
|
8
|
-
PLACEHOLDER: { fr: '
|
|
8
|
+
PLACEHOLDER: { fr: 'Sélectionnez une modalité', en: 'Select a modality' },
|
|
9
|
+
SUGGESTER_PLACEHOLDER: {
|
|
10
|
+
fr: 'Commencez votre saisie...',
|
|
11
|
+
en: 'Start typing...',
|
|
12
|
+
},
|
|
9
13
|
SUGGESTER_LOADING: {
|
|
10
14
|
fr: 'Liste en cours de chargement',
|
|
11
15
|
en: 'List is loading',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LunaticReducerState } from '../type';
|
|
1
|
+
import type { LunaticComponentDefinition, LunaticReducerState } from '../type';
|
|
2
2
|
import { getComponentsFromState } from './get-components-from-state';
|
|
3
3
|
import executeConditionFilter from './execute-condition-filter';
|
|
4
4
|
|
|
@@ -16,7 +16,69 @@ export function getPageId({
|
|
|
16
16
|
* Converts a page number (3.1.2) to an array of numbers [3, 1, 2]
|
|
17
17
|
*/
|
|
18
18
|
export function pageStringToNumbers(page: string): number[] {
|
|
19
|
-
return page.split('.').map((v) => parseInt(v, 10));
|
|
19
|
+
return page.split('.').map((v) => Number.parseInt(v, 10));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// see useLoopUtils.ts
|
|
23
|
+
function getIterationOfLoop(
|
|
24
|
+
component: LunaticComponentDefinition,
|
|
25
|
+
executeExpression: LunaticReducerState['executeExpression']
|
|
26
|
+
) {
|
|
27
|
+
const min =
|
|
28
|
+
'lines' in component ? executeExpression<number>(component.lines.min) : 0;
|
|
29
|
+
const iterations =
|
|
30
|
+
'iterations' in component
|
|
31
|
+
? executeExpression<number>(component.iterations)
|
|
32
|
+
: 0;
|
|
33
|
+
return Math.max(min, iterations);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Check if component has a conditionFilter defined
|
|
38
|
+
* @param component
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
41
|
+
function hasConditionFilter(component: LunaticComponentDefinition): boolean {
|
|
42
|
+
return 'conditionFilter' in component && !!component.conditionFilter;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if a not paginated Loop has at least one component to display
|
|
47
|
+
* @param component
|
|
48
|
+
* @param state
|
|
49
|
+
* @returns boolean indicating if the not paginated Loop is empty
|
|
50
|
+
*/
|
|
51
|
+
function hasAtLeastOneComponentVisible(
|
|
52
|
+
component: LunaticComponentDefinition,
|
|
53
|
+
state: LunaticReducerState
|
|
54
|
+
): boolean {
|
|
55
|
+
if (component.componentType === 'Loop' && !component.paginatedLoop) {
|
|
56
|
+
const nbIteration = getIterationOfLoop(component, state.executeExpression);
|
|
57
|
+
for (
|
|
58
|
+
let iterationOfLoop = 0;
|
|
59
|
+
iterationOfLoop < nbIteration;
|
|
60
|
+
iterationOfLoop++
|
|
61
|
+
) {
|
|
62
|
+
for (const c of component.components) {
|
|
63
|
+
// if no conditionFilter -> component is visible
|
|
64
|
+
if (!hasConditionFilter(c)) return true;
|
|
65
|
+
if (
|
|
66
|
+
executeConditionFilter(
|
|
67
|
+
// @ts-expect-error Seem to be a typescript issue since we check type with hasConditionFilter, c.conditionFilter is defined
|
|
68
|
+
c.conditionFilter,
|
|
69
|
+
state.executeExpression,
|
|
70
|
+
iterationOfLoop
|
|
71
|
+
)
|
|
72
|
+
) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// no component visible in all iterations
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// not a Loop
|
|
81
|
+
return true;
|
|
20
82
|
}
|
|
21
83
|
|
|
22
84
|
/**
|
|
@@ -27,6 +89,7 @@ export function isPageEmpty(state: LunaticReducerState): boolean {
|
|
|
27
89
|
const { executeExpression, pager, options } = state;
|
|
28
90
|
const { iteration } = pager;
|
|
29
91
|
const components = getComponentsFromState(state, true);
|
|
92
|
+
|
|
30
93
|
const visibleComponents = components.filter((component) => {
|
|
31
94
|
if (options.disableFilters) {
|
|
32
95
|
return true;
|
|
@@ -42,11 +105,17 @@ export function isPageEmpty(state: LunaticReducerState): boolean {
|
|
|
42
105
|
|
|
43
106
|
// Use condition filter if present
|
|
44
107
|
if ('conditionFilter' in component && component.conditionFilter) {
|
|
45
|
-
|
|
108
|
+
const conditionFilterResult = executeConditionFilter(
|
|
46
109
|
component.conditionFilter,
|
|
47
110
|
executeExpression,
|
|
48
111
|
iteration
|
|
49
112
|
);
|
|
113
|
+
// early return if the result of filter is false
|
|
114
|
+
if (!conditionFilterResult) return false;
|
|
115
|
+
// early return if the component is not a not Loop
|
|
116
|
+
if (component.componentType !== 'Loop') return conditionFilterResult;
|
|
117
|
+
// if the conditionFilter of NOT paginated Loop is true (have to be visible), we have to check if at least one component is visible inside
|
|
118
|
+
return hasAtLeastOneComponentVisible(component, state);
|
|
50
119
|
}
|
|
51
120
|
return true;
|
|
52
121
|
});
|
|
@@ -121,6 +121,13 @@ describe('tokenizeQuery', () => {
|
|
|
121
121
|
expect(result).toEqual(['eleve', 'etudiant']);
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
it('should normalize ligatures like œ and æ', () => {
|
|
125
|
+
const queryParser = { type: 'soft' } as SearchInfo['queryParser'];
|
|
126
|
+
|
|
127
|
+
const result = tokenizeQuery('œuvre Œuvre æternam Æternam', queryParser);
|
|
128
|
+
expect(result).toEqual(['oeuvre', 'oeuvre', 'aeternam', 'aeternam']);
|
|
129
|
+
});
|
|
130
|
+
|
|
124
131
|
it('should return an empty array for unmatched patterns', () => {
|
|
125
132
|
const queryParser = {
|
|
126
133
|
type: 'tokenized',
|
|
@@ -154,6 +161,13 @@ describe('tokenizeIndex', () => {
|
|
|
154
161
|
expect(result).toEqual(['eleve', 'etudiant']);
|
|
155
162
|
});
|
|
156
163
|
|
|
164
|
+
it('should normalize ligatures like œ and æ', () => {
|
|
165
|
+
const fieldInfo = mockSearchInfo.fields[0];
|
|
166
|
+
|
|
167
|
+
const result = tokenizeIndex('œuvre Œuvre æternam Æternam', fieldInfo);
|
|
168
|
+
expect(result).toEqual(['oeuvre', 'oeuvre', 'aeternam', 'aeternam']);
|
|
169
|
+
});
|
|
170
|
+
|
|
157
171
|
it('should filter out stopWords', () => {
|
|
158
172
|
const fieldInfo = { ...mockSearchInfo.fields[0], min: 1 };
|
|
159
173
|
const stopWords = ['is', 'the', 'of', 'this', 'a'];
|
|
@@ -70,14 +70,17 @@ export const tokenizeIndex = (
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Normalize a string
|
|
73
|
-
* - Remove accent (é => e, à => a
|
|
73
|
+
* - Remove accent (é => e, à => a)
|
|
74
|
+
* - remove ligatures (æ => ae, , Æ => ae, œ => oe, Œ => oe)
|
|
74
75
|
* - Lowercase
|
|
75
76
|
*/
|
|
76
77
|
const normalizeStr = (str: string) => {
|
|
77
78
|
return str
|
|
79
|
+
.toLowerCase()
|
|
80
|
+
.replaceAll('œ', 'oe')
|
|
81
|
+
.replaceAll('æ', 'ae')
|
|
78
82
|
.normalize('NFD')
|
|
79
|
-
.replace(/[\u0300-\u036f]/g, '')
|
|
80
|
-
.toLowerCase();
|
|
83
|
+
.replace(/[\u0300-\u036f]/g, '');
|
|
81
84
|
};
|
|
82
85
|
|
|
83
86
|
/**
|