Skip to content

Commit

Permalink
ref: rebase tracked changes on develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Grafikart committed Oct 4, 2023
1 parent 84c923e commit 2efcb4c
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 41 deletions.
44 changes: 22 additions & 22 deletions src/hooks/use-track-changes.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import { useCallback, useRef } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { useRefSync } from './use-ref-sync';
import { getQuestionnaireData } from '../use-lunatic/commons/get-data';

type getDataType = (
withRefreshedCalculated: boolean,
variableNames?: string[]
) => ReturnType<typeof getQuestionnaireData>;
import type {
LunaticVariablesStore,
LunaticVariablesStoreEvent,
} from '../use-lunatic/commons/variables/lunatic-variables-store';
import type { LunaticData } from '../use-lunatic/type';

/**
* Allow tracking changed while interacting with Lunatic forms
*/
export function useTrackChanges(enabled: boolean, getData: getDataType) {
export function useTrackChanges(
enabled: boolean,
store: LunaticVariablesStore,
getData: (names: string[]) => LunaticData
) {
// Saves the list of changed variable
const changedVariables = useRef(new Set<string>());
// Use ref to avoid dependencies in useCallback
const enabledRef = useRefSync(enabled);
const getDataRef = useRefSync(getData);

// Add a new variable in the changeList
const addChange = useCallback(
(name: string) => {
if (enabledRef.current) {
changedVariables.current.add(name);
}
},
[enabledRef, changedVariables]
);
useEffect(() => {
if (!enabled || !store) {
return;
}
const handleChange = (e: LunaticVariablesStoreEvent<'change'>) => {
changedVariables.current.add(e.detail.name);
};
store.on('change', handleChange);
return () => store.off('change', handleChange);
}, [enabled, store]);

// Reset list of changed variables
const resetChangedData = useCallback(() => {
Expand All @@ -39,10 +43,7 @@ export function useTrackChanges(enabled: boolean, getData: getDataType) {
'getChangedData() cannot be used without enabling tracking mode, add "trackChanges: true" to useLunatic options'
);
}
const data = getDataRef.current(
false,
Array.from(changedVariables.current)
);
const data = getDataRef.current(Array.from(changedVariables.current));
if (reset) {
resetChangedData();
}
Expand All @@ -52,7 +53,6 @@ export function useTrackChanges(enabled: boolean, getData: getDataType) {
);

return {
addChange,
getChangedData,
resetChangedData,
};
Expand Down
27 changes: 24 additions & 3 deletions src/use-lunatic/commons/variables/get-questionnaire-data.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { LunaticVariablesStore } from './lunatic-variables-store';
import type { LunaticSource } from '../../type-source';
import type { LunaticData } from '../../type';

export function getQuestionnaireData(
store: LunaticVariablesStore,
variables: LunaticSource['variables'],
withCalculated: boolean = false
) {
withCalculated: boolean = false,
variableNames?: string[]
): LunaticData {
const result = {
EXTERNAL: {} as Record<string, unknown>,
CALCULATED: {} as Record<string, unknown>,
Expand All @@ -22,7 +24,26 @@ export function getQuestionnaireData(
};

if (!variables) {
return {};
return result;
}

// Only return requested variables
if (variableNames) {
return {
...result,
COLLECTED: Object.fromEntries(
variableNames.map((name) => [
name,
{
EDITED: null,
FORCED: null,
INPUTED: null,
PREVIOUS: null,
COLLECTED: store.get(name),
},
])
),
};
}

for (const variable of variables) {
Expand Down
17 changes: 10 additions & 7 deletions src/use-lunatic/commons/variables/lunatic-variables-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { isNumber } from '../../../utils/number';
let interpretCount = 0;

type IterationLevel = number[];
type Events = {
type EventArgs = {
change: {
// Name of the changed variable
name: string;
Expand All @@ -23,6 +23,9 @@ type Events = {
iteration?: IterationLevel | undefined;
};
};
export type LunaticVariablesStoreEvent<T extends keyof EventArgs> = {
detail: EventArgs[T];
};

export class LunaticVariablesStore {
private dictionary = new Map<string, LunaticVariable>();
Expand Down Expand Up @@ -84,7 +87,7 @@ export class LunaticVariablesStore {
public set(
name: string,
value: unknown,
args: Pick<Events['change'], 'iteration'> = {}
args: Pick<EventArgs['change'], 'iteration'> = {}
): LunaticVariable {
if (!this.dictionary.has(name)) {
this.dictionary.set(
Expand All @@ -102,7 +105,7 @@ export class LunaticVariablesStore {
...args,
name: name,
value: value,
} satisfies Events['change'],
} satisfies EventArgs['change'],
})
);
}
Expand Down Expand Up @@ -149,19 +152,19 @@ export class LunaticVariablesStore {
/**
* Bind event listeners
*/
public on<T extends keyof Events>(
public on<T extends keyof EventArgs>(
eventName: T,
cb: (e: CustomEvent<Events[T]>) => void
cb: (e: CustomEvent<EventArgs[T]>) => void
): void {
this.eventTarget.addEventListener(eventName, cb as EventListener);
}

/**
* Detach a listener
*/
public off<T extends keyof Events>(
public off<T extends keyof EventArgs>(
eventName: T,
cb: (e: CustomEvent<Events[T]>) => void
cb: (e: CustomEvent<EventArgs[T]>) => void
): void {
this.eventTarget.removeEventListener(eventName, cb as EventListener);
}
Expand Down
11 changes: 6 additions & 5 deletions src/use-lunatic/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ export type LunaticControl = ControlType;

export type VTLBindings = { [variableName: string]: unknown };

export type LunaticData = Partial<
Record<Exclude<VariableType, 'COLLECTED'>, Record<string, unknown>> & {
COLLECTED: Record<string, LunaticCollectedValue>;
}
>;
export type LunaticData = Record<
Exclude<VariableType, 'COLLECTED'>,
Record<string, unknown>
> & {
COLLECTED: Record<string, LunaticCollectedValue>;
};

export type LunaticValues = {
[variableName: string]: unknown;
Expand Down
4 changes: 2 additions & 2 deletions src/use-lunatic/use-lunatic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,11 @@ describe('use-lunatic()', () => {
hookRef.current.resetChangedData();
expect(hookRef.current.getChangedData().COLLECTED).toEqual({});
act(() => {
hookRef.current.onChange({ name: 'READY' }, true);
hookRef.current.onChange({ name: 'READY' }, false);
});
expect(hookRef.current.getChangedData().COLLECTED).toMatchObject({
READY: {
COLLECTED: true,
COLLECTED: false,
},
});
});
Expand Down
20 changes: 18 additions & 2 deletions src/use-lunatic/use-lunatic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useLoopVariables } from './hooks/use-loop-variables';
import reducer from './reducer';
import { useSuggesters } from './use-suggesters';
import { getQuestionnaireData } from './commons/variables/get-questionnaire-data';
import { useTrackChanges } from '../hooks/use-track-changes';

const empty = {}; // Keep the same empty object (to avoid problem with useEffect dependencies)
const emptyFn = () => {};
Expand Down Expand Up @@ -56,6 +57,7 @@ function useLunatic(
missingShortcut = DEFAULT_SHORTCUT,
dontKnowButton = DEFAULT_DONT_KNOW,
refusedButton = DEFAULT_REFUSED,
trackChanges = false,
}: {
features?: LunaticState['features'];
preferences?: LunaticState['preferences'];
Expand All @@ -75,6 +77,8 @@ function useLunatic(
missingShortcut?: { dontKnow: string; refused: string };
dontKnowButton?: string;
refusedButton?: string;
// Enable change tracking to keep a track of what variable changed (allow using getChangedData())
trackChanges?: boolean;
}
) {
const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
Expand Down Expand Up @@ -179,14 +183,24 @@ function useLunatic(
[dispatch, onChange]
);

const getData = (withRefreshedCalculated: boolean) => {
const getData = (
withRefreshedCalculated: boolean,
variableNames?: string[]
) => {
return getQuestionnaireData(
state.variables,
source.variables,
withRefreshedCalculated
withRefreshedCalculated,
variableNames
);
};

const { resetChangedData, getChangedData } = useTrackChanges(
trackChanges,
state.variables,
(variableNames?: string[]) => getData(false, variableNames)
);

const buildedOverview = useMemo(
() => overviewWithChildren(overview),
[overview]
Expand Down Expand Up @@ -259,6 +273,8 @@ function useLunatic(
onChange: handleChange,
overview: buildedOverview,
loopVariables: useLoopVariables(pager, state.pages),
getChangedData,
resetChangedData,
};
}

Expand Down

0 comments on commit 2efcb4c

Please sign in to comment.