Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [3.1.0](https://github.com/InseeFr/Pogues/releases/tag/3.1.0) - 2026-05-13

### Added

- In a unique choice question with modalities computed from a variable, you can now add a VTL expression for filtering modalities.

### Fixed

- Questionnaire loading no longer crash when a question uses a code list (or nomenclature) that does not exist anymore. It could happen when an existing question used a previous version of a nomenclature.
Expand Down
4 changes: 4 additions & 0 deletions legacy/src/constants/dictionary/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ export const codesDictionary: Dictionary = {
fr: `Modifier le filtre`,
en: `Modify filter`,
},
modalityFilter: {
fr: `Filtre de modalités`,
en: `Modality filter`,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const defaultState = {
codeListReferenceLabel: '',
variableReference: '',
variableReferenceLabel: '',
optionFilter: '',
choiceType: '',
isCollected: '1',
alternativeLabel: '',
Expand All @@ -33,6 +34,7 @@ export const defaultForm = {
codeListReferenceLabel: '',
variableReference: '',
variableReferenceLabel: '',
optionFilter: '',
choiceType: '',
isCollected: '1',
alternativeLabel: '',
Expand All @@ -58,6 +60,7 @@ export function formToState(form, codesListsStore = {}) {
codeListReferenceLabel,
variableReference,
variableReferenceLabel,
optionFilter,
choiceType,
isCollected,
alternativeLabel,
Expand All @@ -83,6 +86,7 @@ export function formToState(form, codesListsStore = {}) {
codeListReferenceLabel,
variableReference,
variableReferenceLabel: resolvedVariableReferenceLabel,
optionFilter,
choiceType,
};
}
Expand Down Expand Up @@ -119,6 +123,7 @@ export function storeToForm(currentStore) {
codeListReferenceLabel,
variableReference,
variableReferenceLabel,
optionFilter,
choiceType,
} = currentStore[key];
return {
Expand All @@ -137,6 +142,7 @@ export function storeToForm(currentStore) {
codeListReferenceLabel,
variableReference,
variableReferenceLabel,
optionFilter,
choiceType,
};
});
Expand Down
4 changes: 4 additions & 0 deletions legacy/src/model/formToState/component-new-edit/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export function formToState(form, transformers) {
occurrenceDescription,
locked,
codeFilters = [],
optionFilter,
} = form;

let newName;
Expand Down Expand Up @@ -107,6 +108,7 @@ export function formToState(form, transformers) {
occurrenceDescription: occurrenceDescription,
locked: locked,
codeFilters,
optionFilter,
};
if (res.responseFormat.type) {
transformers.codesList.formToComponentState(
Expand Down Expand Up @@ -140,6 +142,7 @@ export function stateToForm(currentState, transformers, activeQuestionnaire) {
locked,
selectedComponent,
codeFilters = [],
optionFilter,
} = currentState;

let target = '';
Expand Down Expand Up @@ -176,6 +179,7 @@ export function stateToForm(currentState, transformers, activeQuestionnaire) {
occurrenceDescription: occurrenceDescription || '',
locked: locked,
codeFilters,
optionFilter,
};

if (type === QUESTION) {
Expand Down
8 changes: 4 additions & 4 deletions legacy/src/model/formToState/lists/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export function createListFactory(
currentState = {},
) {
if (codesListsStore && currentState.id) {
currentState = merge(
cloneDeep(defaultState),
codesListsStore[currentState.id],
);
currentState = merge(cloneDeep(defaultState), {
...codesListsStore[currentState.id],
optionFilter: currentState.optionFilter,
});
} else {
currentState = cloneDeep(defaultState);
}
Expand Down
6 changes: 5 additions & 1 deletion legacy/src/model/formToState/lists/variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ export const defaultState = {
label: '',
name: '',
scope: '',
optionFilter: '',
};

export function formToState(form) {
const { id, label, name, scope } = form;
const { id, label, name, scope, optionFilter } = form;

return {
id,
name,
label,
scope,
optionFilter,
};
}

Expand All @@ -23,12 +25,14 @@ export function stateComponentToForm({
name = '',
label = '',
scope = '',
optionFilter = '',
}) {
return {
id,
name,
label,
scope,
optionFilter,
};
}

Expand Down
3 changes: 3 additions & 0 deletions legacy/src/model/transformations/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ function remoteToState(remote, componentGroup, codesListsStore) {
Locked: locked,
Loop: loop,
codeFilters: codeFilters,
OptionFilter: optionFilter,
sourceVariableReferences,
} = remote;
const redirectionClar =
Expand Down Expand Up @@ -387,6 +388,7 @@ function remoteToState(remote, componentGroup, codesListsStore) {
dynamiqueSpecified:
flowLogic && flowLogic === FILTER ? Filtres : Redirections,
codeFilters,
optionFilter,
};
if (genericName) {
state.label = label;
Expand Down Expand Up @@ -422,6 +424,7 @@ function remoteToState(remote, componentGroup, codesListsStore) {
scope,
mandatory,
sourceVariableReferences,
optionFilter,
);
state.collectedVariables =
CollectedVariable.remoteToComponentState(responseFinal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ describe('response format single', () => {
choiceType: CHOICE_TYPE.VARIABLE,
},
],
optionFilter: 'nice filter',
};
const output = remoteToState(remote);
const expected = {
Variable: { id: 'my-variable-id' },
Variable: { id: 'my-variable-id', optionFilter: 'nice filter' },
id: 'my-response-id',
mandatory: true,
choiceType: 'VARIABLE',
Expand Down Expand Up @@ -167,7 +168,7 @@ describe('stateToRemote', () => {
mandatory: true,
visHint: DATATYPE_VIS_HINT.RADIO,
choiceType: CHOICE_TYPE.VARIABLE,
Variable: { id: 'my-variable-id' },
Variable: { id: 'my-variable-id', optionFilter: 'nice filter' },
};
const collectedVariables = ['my-var-id'];
const output = stateToRemote(state, collectedVariables);
Expand All @@ -187,6 +188,7 @@ describe('stateToRemote', () => {
mandatory: true,
},
],
optionFilter: 'nice filter',
};
expect(output).toEqual(expected);
});
Expand Down
14 changes: 11 additions & 3 deletions legacy/src/model/transformations/response-format-single.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ export type StateResponseFormatSingle = {
| DATATYPE_VIS_HINT.CHECKBOX
| DATATYPE_VIS_HINT.RADIO
| DATATYPE_VIS_HINT.DROPDOWN;
[DEFAULT_VARIABLE_SELECTOR_PATH]: { id: string };
[DEFAULT_VARIABLE_SELECTOR_PATH]: { id: string; optionFilter?: string };
}
);

export function remoteToState(remote: {
responses: RemoteResponseFormatSingle;
optionFilter?: string;
}): StateResponseFormatSingle {
const {
responses: [
Expand All @@ -68,6 +69,7 @@ export function remoteToState(remote: {
id,
},
],
optionFilter,
} = remote;

const baseState = {
Expand All @@ -94,7 +96,10 @@ export function remoteToState(remote: {
if (choiceType === CHOICE_TYPE.VARIABLE) {
return {
...baseState,
[DEFAULT_VARIABLE_SELECTOR_PATH]: { id: VariableReference as string },
[DEFAULT_VARIABLE_SELECTOR_PATH]: {
id: VariableReference as string,
optionFilter,
},
visHint,
};
}
Expand All @@ -111,12 +116,13 @@ export function remoteToState(remote: {
export function stateToRemote(
state: StateResponseFormatSingle,
collectedVariables: string[],
): { Response: RemoteResponseFormatSingle } {
): { Response: RemoteResponseFormatSingle; optionFilter?: string } {
const { allowArbitraryResponse, visHint, mandatory, id, choiceType } = state;

let nomenclatureId;
let codesListId;
let variableReferenceId;
let optionFilter;

if (
choiceType === CHOICE_TYPE.SUGGESTER &&
Expand All @@ -128,6 +134,7 @@ export function stateToRemote(
DEFAULT_VARIABLE_SELECTOR_PATH in state
) {
variableReferenceId = state[DEFAULT_VARIABLE_SELECTOR_PATH]?.id;
optionFilter = state[DEFAULT_VARIABLE_SELECTOR_PATH]?.optionFilter;
} else if (
choiceType === CHOICE_TYPE.CODE_LIST &&
DEFAULT_CODES_LIST_SELECTOR_PATH in state
Expand All @@ -150,5 +157,6 @@ export function stateToRemote(
collectedVariable: collectedVariables[0],
}),
],
optionFilter,
};
}
7 changes: 6 additions & 1 deletion legacy/src/model/transformations/response-format-table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,12 @@ function remoteToStateMeasure(remote) {
state.type = SINGLE_CHOICE;
state[SINGLE_CHOICE] = ResponseFormatSingle.remoteToState({
responses: [
{ Datatype, VariableReference, choiceType, CollectedVariableReference },
{
Datatype,
VariableReference,
choiceType,
CollectedVariableReference,
},
],
});
} else {
Expand Down
43 changes: 37 additions & 6 deletions legacy/src/model/transformations/response-format-table.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { describe, expect, it } from 'vitest';

import { CHOICE_TYPE } from '@/constants/pogues-constants';

import { remoteToState, stateToRemote } from './response-format-table';

const { CODE_LIST, SUGGESTER, VARIABLE } = CHOICE_TYPE;

describe('remoteToState', () => {
it('should use an offset equal to 1', () => {
const remote = {
Expand Down Expand Up @@ -230,7 +234,7 @@ describe('remoteToState', () => {
type: 'TextDatatypeType',
MaxLength: 1,
},
choiceType: 'SUGGESTER',
choiceType: SUGGESTER,
CollectedVariableReference: 'mbz5jjxv',
},
{
Expand All @@ -242,7 +246,19 @@ describe('remoteToState', () => {
type: 'TextDatatypeType',
MaxLength: 1,
},
choiceType: 'CODE_LIST',
choiceType: CODE_LIST,
CollectedVariableReference: 'mbz5crwv',
},
{
id: 'mbh8ke14',
VariableReference: 'kdyg5y7',
Datatype: {
typeName: 'TEXT',
visualizationHint: 'RADIO',
type: 'TextDatatypeType',
MaxLength: 1,
},
choiceType: VARIABLE,
CollectedVariableReference: 'mbz5crwv',
},
],
Expand All @@ -260,7 +276,11 @@ describe('remoteToState', () => {
},
{
dimensionType: 'MEASURE',
Label: 'measure-radio',
Label: 'measure-codeList-radio',
},
{
dimensionType: 'MEASURE',
Label: 'measure-variable-radio',
},
],
};
Expand All @@ -283,7 +303,7 @@ describe('remoteToState', () => {
id: undefined,
mandatory: undefined,
visHint: 'SUGGESTER',
choiceType: 'SUGGESTER',
choiceType: SUGGESTER,
},
label: 'measure-suggester',
type: 'SINGLE_CHOICE',
Expand All @@ -294,9 +314,20 @@ describe('remoteToState', () => {
id: undefined,
mandatory: undefined,
visHint: 'RADIO',
choiceType: 'CODE_LIST',
choiceType: CODE_LIST,
},
label: 'measure-codeList-radio',
type: 'SINGLE_CHOICE',
},
{
SINGLE_CHOICE: {
Variable: { id: 'kdyg5y7' },
id: undefined,
mandatory: undefined,
visHint: 'RADIO',
choiceType: VARIABLE,
},
label: 'measure-radio',
label: 'measure-variable-radio',
type: 'SINGLE_CHOICE',
},
],
Expand Down
8 changes: 7 additions & 1 deletion legacy/src/model/transformations/response-format.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
const { SIMPLE, SINGLE_CHOICE, MULTIPLE_CHOICE, TABLE, PAIRING } =
QUESTION_TYPE_ENUM;

export function remoteToState(

Check warning on line 11 in legacy/src/model/transformations/response-format.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Function 'remoteToState' has too many parameters (8). Maximum allowed is 7.

See more on https://sonarcloud.io/project/issues?id=InseeFr_Pogues&issues=AZ6sUJHslZga0k7GRjPU&open=AZ6sUJHslZga0k7GRjPU&pullRequest=1151
type,
responses,
dimensions,
Expand All @@ -18,13 +18,18 @@
mandatory,
/** Add source variable references to response format if the response format is pairing. */
sourceVariableReferences,
/** filter for modalities based on a variable. Only for unique choice questions */
optionFilter = '',
) {
let datatypeState = {};

if (type === SIMPLE) {
datatypeState = ResponseFormatSimple.remoteToState({ responses });
} else if (type === SINGLE_CHOICE) {
datatypeState = ResponseFormatSingle.remoteToState({ responses });
datatypeState = ResponseFormatSingle.remoteToState({
responses,
optionFilter,
});
} else if (type === MULTIPLE_CHOICE) {
datatypeState = ResponseFormatMultiple.remoteToState({
responses,
Expand Down Expand Up @@ -72,6 +77,7 @@
collectedVariables,
);
remote.Response = dataTypeRemote.Response;
remote.OptionFilter = dataTypeRemote.optionFilter;
} else if (type === MULTIPLE_CHOICE) {
dataTypeRemote = ResponseFormatMultiple.stateToRemote(
responseFormatState,
Expand Down
Loading
Loading