diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts index 33f74b1189..eae965fe3d 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts @@ -2,6 +2,7 @@ import { Store } from "pages/FlowEditor/lib/store"; import { FileWithPath } from "react-dropzone"; import { FileUploadSlot } from "../FileUpload/Public"; +import { TYPES } from "../types"; import { mockFileList, mockFileListManyTagsOneSlot, @@ -419,6 +420,17 @@ describe("generatePayload function", () => { expect(result.data?.fileFn?.[1].filename).toEqual("second.jpg"); expect(result.data?.fileFn?.[2].filename).toEqual("third.jpg"); }); + + it("captures the original file list in state", () => { + const result = generatePayload(mockFileList); + + expect(result).toHaveProperty("state"); + expect(result.state).toHaveProperty("requestedFiles"); + expect(result.state?.requestedFiles).toMatchObject(mockFileList); + + expect(result.state).toHaveProperty("type"); + expect(result.state?.type).toEqual(TYPES.FileUploadAndLabel); + }); }); describe("getRecoveredData function", () => { diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts index a818f0e802..a3ee2c0c0f 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts @@ -6,6 +6,7 @@ import { FileWithPath } from "react-dropzone"; import { FileUploadSlot } from "../FileUpload/Public"; import { MoreInformation, parseMoreInformation } from "../shared"; +import { TYPES } from "../types"; /** * Conditions which can apply to a rule @@ -243,7 +244,13 @@ export const generatePayload = (fileList: FileList): Store.userData => { newPassportData[userFile.fn] = formatUserFiles(userFile); }); - return { data: newPassportData }; + return { + data: newPassportData, + state: { + requestedFiles: fileList, + type: TYPES.FileUploadAndLabel, + }, + }; }; const getCachedSlotsFromPreviousData = ( diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/captureNodeState.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/captureNodeState.test.ts new file mode 100644 index 0000000000..29636fdaee --- /dev/null +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/captureNodeState.test.ts @@ -0,0 +1,50 @@ +import { TYPES } from "@planx/components/types"; + +import { vanillaStore } from "../../store"; +import { Store } from './../../store/index'; + +const { getState, setState } = vanillaStore; +const { record } = getState(); + +test("record() captures state in breadcrumbs", () => { + setState({ + flow: { + _root: { + edges: ["a", "b"], + }, + a: { + type: TYPES.Statement, + edges: ["c"], + }, + b: { + type: TYPES.Statement, + }, + c: { + type: TYPES.Response, + edges: ["d"], + }, + d: { + type: TYPES.Statement, + edges: ["e", "f"], + }, + e: { type: TYPES.Response }, + f: { type: TYPES.Response }, + }, + }); + + const state: Store.NodeState = { + type: TYPES.Statement, someStateData: { hello: "world", number: 42, isLive: true, deepObject: { hello: "again" } } + }; + + const data: Store.userData = { data: { projectType: "extension" } }; + + record("a", { answers: ["c"], data, state }); + + // State captured in breadcrumbs + expect(getState().breadcrumbs).toEqual({ + a: { answers: ["c"], auto: false, data, state }, + }); + + // State not captured in passport + expect(getState().computePassport()).toEqual({ data }); +}); diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts index a2e0199329..a597ba1ac1 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts @@ -21,12 +21,21 @@ export declare namespace Store { export type Store = Record; export type nodeId = string; export type flow = Record; + /** + * State of node at time user visited it + * State will be stored to breadcrumbs, but not captured in passport + */ + export type NodeState = { + type: TYPES, + [key: string]: any, + }; export type userData = { answers?: Array; data?: Record; auto?: boolean; override?: Record; feedback?: string; + state?: NodeState; }; export type breadcrumbs = Record; export type cachedBreadcrumbs = Record | undefined; diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts index 0b4502213c..c463086140 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts @@ -284,11 +284,13 @@ export const previewStore: StateCreator< auto = false, override, feedback, + state, } = userData; const breadcrumb: Store.userData = { auto: Boolean(auto) }; if (answers?.length > 0) breadcrumb.answers = answers; if (feedback) breadcrumb.feedback = feedback; + if (state) breadcrumb.state = state; const filteredData = objectWithoutNullishValues(data); if (Object.keys(filteredData).length > 0) breadcrumb.data = filteredData; diff --git a/editor.planx.uk/src/pages/Preview/Questions.tsx b/editor.planx.uk/src/pages/Preview/Questions.tsx index 5f83ef110a..e2ce56d785 100644 --- a/editor.planx.uk/src/pages/Preview/Questions.tsx +++ b/editor.planx.uk/src/pages/Preview/Questions.tsx @@ -136,16 +136,17 @@ const Questions = ({ previewEnvironment }: QuestionsProps) => { answers = [], auto = false, feedback = undefined, + state = undefined, } = (() => { try { - const { answers = [], data, auto, feedback } = userData as any; - return { answers: answers.filter(Boolean), data, auto, feedback }; + const { answers = [], data, auto, feedback, state } = userData as any; + return { answers: answers.filter(Boolean), data, auto, feedback, state }; } catch (err) { return {}; } })(); - record(id, { answers, data, auto, feedback }); + record(id, { answers, data, auto, feedback, state }); }; const goBack = useCallback(() => {