From 596a54ea3b96f5fd969df7a0f39f530c02b39026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Thu, 12 Sep 2024 11:51:18 +0100 Subject: [PATCH] refactor: Import `Node` type from `planx-core` (#3656) --- editor.planx.uk/.eslintrc | 31 ++++- .../@planx/components/Calculate/logic.test.ts | 4 +- .../@planx/components/Confirmation/Public.tsx | 2 +- .../components/DrawBoundary/Public/index.tsx | 2 +- .../@planx/components/FileUpload/Public.tsx | 6 +- .../FileUploadAndLabel/model.test.ts | 42 +++---- .../components/FileUploadAndLabel/model.ts | 18 +-- .../components/FindProperty/Public/index.tsx | 2 +- .../@planx/components/Pay/Public/Pay.test.tsx | 4 +- .../src/@planx/components/Pay/Public/Pay.tsx | 4 +- .../components/PlanningConstraints/Public.tsx | 6 +- .../components/PropertyInformation/Public.tsx | 4 +- .../components/Question/Public/Question.tsx | 6 +- .../components/Result/Public/ResultReason.tsx | 6 +- .../@planx/components/Result/Public/index.tsx | 17 +-- .../Review/Public/Presentational.tsx | 15 +-- .../src/@planx/components/Section/Public.tsx | 10 +- .../src/@planx/components/Section/model.ts | 6 +- .../src/@planx/components/Send/model.ts | 2 +- .../@planx/components/SetValue/utils.test.ts | 8 +- .../src/@planx/components/SetValue/utils.ts | 4 +- .../components/shared/Preview/SummaryList.tsx | 35 +++--- editor.planx.uk/src/@planx/components/ui.tsx | 6 +- editor.planx.uk/src/@planx/graph/types.d.ts | 10 +- editor.planx.uk/src/lib/feedback.ts | 8 +- .../components/Flow/components/Node.tsx | 2 +- .../lib/__tests__/advancedAutomations.test.ts | 2 +- .../lib/__tests__/granularity.test.ts | 2 +- .../FlowEditor/lib/__tests__/ordering.test.ts | 2 +- .../lib/__tests__/preview/canGoBack.test.ts | 2 +- .../lib/__tests__/preview/changeAnswer.ts | 8 +- .../removeNodesDependentOnPassport.test.ts | 14 +-- .../__tests__/preview/upcomingCardIds.test.ts | 2 +- .../FlowEditor/lib/__tests__/setValue.test.ts | 2 +- .../FlowEditor/lib/__tests__/unseen.test.ts | 2 +- .../lib/__tests__/useNotValues.test.ts | 2 +- .../FlowEditor/lib/analytics/provider.tsx | 2 +- .../pages/FlowEditor/lib/analytics/utils.ts | 32 ++--- .../src/pages/FlowEditor/lib/store/editor.ts | 25 ++-- .../src/pages/FlowEditor/lib/store/index.ts | 27 +++-- .../pages/FlowEditor/lib/store/navigation.ts | 10 +- .../src/pages/FlowEditor/lib/store/preview.ts | 110 ++++++++++-------- .../src/pages/FlowEditor/lib/store/shared.ts | 14 +-- editor.planx.uk/src/pages/Preview/Node.tsx | 6 +- .../src/pages/Preview/Questions.tsx | 4 +- editor.planx.uk/src/routes/utils.ts | 4 +- .../src/routes/views/published.tsx | 2 +- editor.planx.uk/src/types.ts | 20 +--- .../src/ui/public/NextStepsList.tsx | 6 +- 49 files changed, 290 insertions(+), 270 deletions(-) diff --git a/editor.planx.uk/.eslintrc b/editor.planx.uk/.eslintrc index c28f6e85f2..ff48a856e5 100644 --- a/editor.planx.uk/.eslintrc +++ b/editor.planx.uk/.eslintrc @@ -42,16 +42,22 @@ }, { "name": "@testing-library/react", - "importNames": ["render"], + "importNames": [ + "render" + ], "message": "Please import setup() from testUtils to render test component" }, { "name": "@mui/styles", - "importNames": ["styled"], + "importNames": [ + "styled" + ], "message": "Please import styled from '@mui/material/styles'. Reason: https://mui.com/system/styled/#what-problems-does-it-solve" } ], - "patterns": ["@mui/*/*/*"] + "patterns": [ + "@mui/*/*/*" + ] } ], "@typescript-eslint/no-unused-vars": [ @@ -68,6 +74,19 @@ "@typescript-eslint/no-empty-function": "warn", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "typeLike", + "format": [ + "PascalCase" + ], + "custom": { + "regex": "^[A-Z]", + "match": true + } + } + ], "no-nested-ternary": "error" }, "settings": { @@ -80,7 +99,9 @@ "files": [ "**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)" ], - "extends": ["plugin:testing-library/react"] + "extends": [ + "plugin:testing-library/react" + ] } ] -} +} \ No newline at end of file diff --git a/editor.planx.uk/src/@planx/components/Calculate/logic.test.ts b/editor.planx.uk/src/@planx/components/Calculate/logic.test.ts index 2dde552b55..d8d96d0260 100644 --- a/editor.planx.uk/src/@planx/components/Calculate/logic.test.ts +++ b/editor.planx.uk/src/@planx/components/Calculate/logic.test.ts @@ -41,7 +41,7 @@ test("When formatOutputForAutomations is false, Calculate writes a number and fu expect(upcomingCardIds()).toEqual(["Question"]); }); -const flowWithAutomation: Store.flow = { +const flowWithAutomation: Store.Flow = { _root: { edges: ["Calculate", "Question"], }, @@ -95,7 +95,7 @@ const flowWithAutomation: Store.flow = { }, }; -const flowWithoutAutomation: Store.flow = { +const flowWithoutAutomation: Store.Flow = { _root: { edges: ["Calculate", "Question"], }, diff --git a/editor.planx.uk/src/@planx/components/Confirmation/Public.tsx b/editor.planx.uk/src/@planx/components/Confirmation/Public.tsx index bdb2db967f..25f2e19a7f 100644 --- a/editor.planx.uk/src/@planx/components/Confirmation/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Confirmation/Public.tsx @@ -142,7 +142,7 @@ export function Presentational(props: PresentationalProps) { } // TODO - Retire in favor of ODP Schema application type descriptions or fallback to flowName -function getWorkStatus(passport: Store.passport): string | undefined { +function getWorkStatus(passport: Store.Passport): string | undefined { switch (passport?.data?.["application.type"]?.toString()) { case "ldc.existing": return "existing"; diff --git a/editor.planx.uk/src/@planx/components/DrawBoundary/Public/index.tsx b/editor.planx.uk/src/@planx/components/DrawBoundary/Public/index.tsx index e8875a6a95..7c944f0fc8 100644 --- a/editor.planx.uk/src/@planx/components/DrawBoundary/Public/index.tsx +++ b/editor.planx.uk/src/@planx/components/DrawBoundary/Public/index.tsx @@ -138,7 +138,7 @@ export default function Component(props: Props) { }, [boundary]); const validateAndSubmit = () => { - const newPassportData: Store.userData["data"] = {}; + const newPassportData: Store.UserData["data"] = {}; // Used the map if (page === "draw") { diff --git a/editor.planx.uk/src/@planx/components/FileUpload/Public.tsx b/editor.planx.uk/src/@planx/components/FileUpload/Public.tsx index fbe600753c..c99eee5035 100644 --- a/editor.planx.uk/src/@planx/components/FileUpload/Public.tsx +++ b/editor.planx.uk/src/@planx/components/FileUpload/Public.tsx @@ -2,7 +2,7 @@ import { MoreInformation } from "@planx/components/shared"; import Card from "@planx/components/shared/Preview/Card"; import CardHeader from "@planx/components/shared/Preview/CardHeader"; import { Store, useStore } from "pages/FlowEditor/lib/store"; -import type { handleSubmit } from "pages/Preview/Node"; +import type { HandleSubmit } from "pages/Preview/Node"; import React, { useEffect, useRef, useState } from "react"; import { FileWithPath } from "react-dropzone"; import ErrorWrapper from "ui/shared/ErrorWrapper"; @@ -17,8 +17,8 @@ interface Props extends MoreInformation { title?: string; fn: string; description?: string; - handleSubmit: handleSubmit; - previouslySubmittedData?: Store.userData; + handleSubmit: HandleSubmit; + previouslySubmittedData?: Store.UserData; } export interface FileUploadSlot { 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..4a1dca7ce1 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.test.ts @@ -30,7 +30,7 @@ import { describe("createFileList function", () => { it("adds 'AlwaysRequired' FileTypes to the 'required' array", () => { const fileTypes = [mockFileTypes[Condition.AlwaysRequired]]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [mockFileTypes[Condition.AlwaysRequired]], @@ -44,7 +44,7 @@ describe("createFileList function", () => { it("adds 'AlwaysRecommended' FileTypes to the 'recommended' array", () => { const fileTypes = [mockFileTypes[Condition.AlwaysRecommended]]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [], @@ -58,7 +58,7 @@ describe("createFileList function", () => { it("adds 'RequiredIf' FileTypes to the 'required' array if the rule is met", () => { const fileTypes = [mockFileTypes[Condition.RequiredIf]]; - const passport: Store.passport = { data: { testFn: "testVal" } }; + const passport: Store.Passport = { data: { testFn: "testVal" } }; const expected: FileList = { required: [mockFileTypes[Condition.RequiredIf]], @@ -72,7 +72,7 @@ describe("createFileList function", () => { it("does not add 'RequiredIf' FileTypes to the 'required' array if the rule is not met", () => { const fileTypes = [mockFileTypes[Condition.RequiredIf]]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [], @@ -86,7 +86,7 @@ describe("createFileList function", () => { it("adds 'RecommendedIf' FileTypes to the 'recommended' array if the rule is met", () => { const fileTypes = [mockFileTypes[Condition.RecommendedIf]]; - const passport: Store.passport = { data: { testFn: "testVal" } }; + const passport: Store.Passport = { data: { testFn: "testVal" } }; const expected: FileList = { required: [], @@ -100,7 +100,7 @@ describe("createFileList function", () => { it("does not add 'RecommendedIf' FileTypes to the 'recommended' array if the rule is not met", () => { const fileTypes = [mockFileTypes[Condition.RecommendedIf]]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [], @@ -114,7 +114,7 @@ describe("createFileList function", () => { it("adds 'NotRequired' FileTypes to the 'optional' array", () => { const fileTypes = [mockFileTypes[Condition.NotRequired]]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [], @@ -132,7 +132,7 @@ describe("createFileList function", () => { mockFileTypes[Condition.AlwaysRequired], mockFileTypes[Condition.AlwaysRequired], ]; - const passport: Store.passport = { data: {} }; + const passport: Store.Passport = { data: {} }; const expected: FileList = { required: [mockFileTypes[Condition.AlwaysRequired]], @@ -152,7 +152,7 @@ describe("createFileList function", () => { mockFileTypes[Condition.RecommendedIf], mockFileTypes[Condition.NotRequired], ]; - const passport: Store.passport = { data: { testFn: "testVal" } }; + const passport: Store.Passport = { data: { testFn: "testVal" } }; const expected: FileList = { required: [mockFileTypes[Condition.AlwaysRequired]], @@ -197,7 +197,7 @@ describe("createFileList function", () => { }, }, ]; - const passport: Store.passport = { + const passport: Store.Passport = { data: { "documentA.required": ["true"], "documentB.recommended": ["true"], @@ -280,7 +280,7 @@ describe("createFileList function", () => { }, }, ]; - const passport: Store.passport = { + const passport: Store.Passport = { data: { "required.file": "true", "recommended.file": ["true"] }, }; @@ -355,7 +355,7 @@ describe("createFileList function", () => { }, }, ]; - const passport: Store.passport = { + const passport: Store.Passport = { data: { "required.file": "true", "recommended.file": ["true"] }, }; @@ -433,7 +433,7 @@ describe("getRecoveredData function", () => { }; // Mock breadcrumb data with FileType.fn -> UserFile mapped - const previouslySubmittedData: Store.userData = { + const previouslySubmittedData: Store.UserData = { data: { requiredFileFn: [ { @@ -592,21 +592,21 @@ describe("isRuleMet function", () => { }; it("matches on an exact value", () => { - const mockPassport: Store.passport = { data: { testFn: "testValue" } }; + const mockPassport: Store.Passport = { data: { testFn: "testValue" } }; const result = isRuleMet(mockPassport, mockRule); expect(result).toBe(true); }); it("does not match if an exact value is not present", () => { - const mockPassport: Store.passport = { data: { testFn: "missingValue" } }; + const mockPassport: Store.Passport = { data: { testFn: "missingValue" } }; const result = isRuleMet(mockPassport, mockRule); expect(result).toBe(false); }); it("does not match if the passport key is not present", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { missingKey: "missingValue" }, }; const result = isRuleMet(mockPassport, mockRule); @@ -615,7 +615,7 @@ describe("isRuleMet function", () => { }); it("matches on an exact value in an array", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { testFn: ["value1", "value2", "testValue"] }, }; const result = isRuleMet(mockPassport, mockRule); @@ -624,7 +624,7 @@ describe("isRuleMet function", () => { }); it("matches on an granular value", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { testFn: ["value1.more.value", "value2", "testValue.more.detail"], }, @@ -635,7 +635,7 @@ describe("isRuleMet function", () => { }); it("does not match on a partial granular value (prefix)", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { testFn: ["somethingtestValue.more.detail"] }, }; const result = isRuleMet(mockPassport, mockRule); @@ -644,7 +644,7 @@ describe("isRuleMet function", () => { }); it("does not match on a partial granular value (suffix)", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { testFn: ["testValueSomething.more.detail"] }, }; const result = isRuleMet(mockPassport, mockRule); @@ -653,7 +653,7 @@ describe("isRuleMet function", () => { }); it("does not match on a granular which is not a 'parent'", () => { - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { testFn: ["parent.child.testValue"] }, }; const result = isRuleMet(mockPassport, mockRule); diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts index 4b4aea3c5c..1cd082dd8f 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts @@ -122,7 +122,7 @@ export const createFileList = ({ passport, fileTypes, }: { - passport: Readonly; + passport: Readonly; fileTypes: FileType[]; }): FileList => { const fileList: FileList = { required: [], recommended: [], optional: [] }; @@ -160,7 +160,7 @@ const populateFileList = ({ }: { fileList: FileList; fileType: FileType; - passport: Store.passport; + passport: Store.Passport; }): boolean => { switch (fileType.rule.condition) { case Condition.AlwaysRequired: @@ -192,7 +192,7 @@ const populateFileList = ({ }; export const isRuleMet = ( - passport: Store.passport, + passport: Store.Passport, rule: ConditionalRule, ): boolean => { const passportVal = passport.data?.[rule.fn]; @@ -254,8 +254,8 @@ const getUpdatedRequestedFiles = (fileList: FileList) => { * Generate payload for FileUploadAndLabel breadcrumb * Not responsible for validation - this happens at the component level */ -export const generatePayload = (fileList: FileList): Store.userData => { - const newPassportData: Store.userData["data"] = {}; +export const generatePayload = (fileList: FileList): Store.UserData => { + const newPassportData: Store.UserData["data"] = {}; const uploadedFiles = [ ...fileList.required, @@ -279,14 +279,14 @@ export const generatePayload = (fileList: FileList): Store.userData => { const getCachedSlotsFromPreviousData = ( userFile: UserFile, - previouslySubmittedData: Store.userData | undefined, + previouslySubmittedData: Store.UserData | undefined, ): FileUploadSlot[] => previouslySubmittedData?.data?.[userFile.fn]?.map( (file: FormattedUserFile) => file.cachedSlot, ); const getRecoveredSlots = ( - previouslySubmittedData: Store.userData | undefined, + previouslySubmittedData: Store.UserData | undefined, fileList: FileList, ) => { const allFiles = [ @@ -307,7 +307,7 @@ const getRecoveredSlots = ( }; const getRecoveredFileList = ( - previouslySubmittedData: Store.userData | undefined, + previouslySubmittedData: Store.UserData | undefined, fileList: FileList, ) => { const recoveredFileList = cloneDeep(fileList); @@ -327,7 +327,7 @@ const getRecoveredFileList = ( }; export const getRecoveredData = ( - previouslySubmittedData: Store.userData | undefined, + previouslySubmittedData: Store.UserData | undefined, fileList: FileList, ) => { const recoveredSlots = getRecoveredSlots(previouslySubmittedData, fileList); diff --git a/editor.planx.uk/src/@planx/components/FindProperty/Public/index.tsx b/editor.planx.uk/src/@planx/components/FindProperty/Public/index.tsx index d3828330cf..f5f76f4f19 100644 --- a/editor.planx.uk/src/@planx/components/FindProperty/Public/index.tsx +++ b/editor.planx.uk/src/@planx/components/FindProperty/Public/index.tsx @@ -140,7 +140,7 @@ function Component(props: Props) { } if (address) { - const newPassportData: Store.userData["data"] = {}; + const newPassportData: Store.UserData["data"] = {}; newPassportData["_address"] = address; if (address?.planx_value) { newPassportData["property.type"] = [address.planx_value]; diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.test.tsx b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.test.tsx index bcf1120763..b58c3774c1 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.test.tsx +++ b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.test.tsx @@ -24,7 +24,7 @@ vi.spyOn(ReactNavi, "useCurrentRoute").mockImplementation( const resumeButtonText = "Resume an application you have already started"; const saveButtonText = "Save and return to this application later"; -const flowWithUndefinedFee: Store.flow = { +const flowWithUndefinedFee: Store.Flow = { _root: { edges: ["setValue", "pay"], }, @@ -44,7 +44,7 @@ const flowWithUndefinedFee: Store.flow = { }, }; -const flowWithZeroFee: Store.flow = { +const flowWithZeroFee: Store.Flow = { _root: { edges: ["setValue", "pay"], }, diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx index 4cd9951ecc..629782b3ed 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx +++ b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx @@ -8,7 +8,7 @@ import axios from "axios"; import DelayedLoadingIndicator from "components/DelayedLoadingIndicator"; import { setLocalFlow } from "lib/local.new"; import { useStore } from "pages/FlowEditor/lib/store"; -import { handleSubmit } from "pages/Preview/Node"; +import { HandleSubmit } from "pages/Preview/Node"; import React, { useEffect, useReducer } from "react"; import { useErrorHandler } from "react-error-boundary"; import type { Session } from "types"; @@ -19,7 +19,7 @@ import Confirm from "./Confirm"; export default Component; interface Props extends Pay { - handleSubmit: handleSubmit; + handleSubmit: HandleSubmit; } type ComponentState = diff --git a/editor.planx.uk/src/@planx/components/PlanningConstraints/Public.tsx b/editor.planx.uk/src/@planx/components/PlanningConstraints/Public.tsx index e4d30a18ca..f93b0a1edc 100644 --- a/editor.planx.uk/src/@planx/components/PlanningConstraints/Public.tsx +++ b/editor.planx.uk/src/@planx/components/PlanningConstraints/Public.tsx @@ -11,7 +11,7 @@ import type { PublicProps } from "@planx/components/ui"; import DelayedLoadingIndicator from "components/DelayedLoadingIndicator"; import capitalize from "lodash/capitalize"; import { useStore } from "pages/FlowEditor/lib/store"; -import { handleSubmit } from "pages/Preview/Node"; +import { HandleSubmit } from "pages/Preview/Node"; import React, { useState } from "react"; import useSWR, { Fetcher } from "swr"; import ReactMarkdownOrHtml from "ui/shared/ReactMarkdownOrHtml"; @@ -368,7 +368,7 @@ interface ConstraintsFetchErrorProps { title: string; description: string; refreshConstraints: () => void; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; } const ConstraintsFetchError = (props: ConstraintsFetchErrorProps) => ( @@ -400,7 +400,7 @@ const ConstraintsFetchError = (props: ConstraintsFetchErrorProps) => ( interface ConstraintsGraphErrorProps { title: string; description: string; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; } const ConstraintsGraphError = (props: ConstraintsGraphErrorProps) => ( diff --git a/editor.planx.uk/src/@planx/components/PropertyInformation/Public.tsx b/editor.planx.uk/src/@planx/components/PropertyInformation/Public.tsx index 8efca976e1..5502fc42aa 100644 --- a/editor.planx.uk/src/@planx/components/PropertyInformation/Public.tsx +++ b/editor.planx.uk/src/@planx/components/PropertyInformation/Public.tsx @@ -12,7 +12,7 @@ import { publicClient } from "lib/graphql"; import find from "lodash/find"; import { useAnalyticsTracking } from "pages/FlowEditor/lib/analytics/provider"; import { useStore } from "pages/FlowEditor/lib/store"; -import { handleSubmit } from "pages/Preview/Node"; +import { HandleSubmit } from "pages/Preview/Node"; import React from "react"; import type { SiteAddress } from "../FindProperty/model"; @@ -89,7 +89,7 @@ export interface PresentationalProps { titleBoundary?: Feature; blpuCodes?: any; overrideAnswer: (fn: string) => void; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; } // Export this component for testing visual presentation with mocked props diff --git a/editor.planx.uk/src/@planx/components/Question/Public/Question.tsx b/editor.planx.uk/src/@planx/components/Question/Public/Question.tsx index 4affc032a3..a17e5573ec 100644 --- a/editor.planx.uk/src/@planx/components/Question/Public/Question.tsx +++ b/editor.planx.uk/src/@planx/components/Question/Public/Question.tsx @@ -10,7 +10,7 @@ import DescriptionRadio from "@planx/components/shared/Radio/DescriptionRadio"; import ImageRadio from "@planx/components/shared/Radio/ImageRadio"; import { useFormik } from "formik"; import { Store } from "pages/FlowEditor/lib/store"; -import { handleSubmit } from "pages/Preview/Node"; +import { HandleSubmit } from "pages/Preview/Node"; import React from "react"; import FormWrapper from "ui/public/FormWrapper"; import FullWidthWrapper from "ui/public/FullWidthWrapper"; @@ -33,8 +33,8 @@ export interface IQuestion { description?: string; img?: string; }[]; - previouslySubmittedData?: Store.userData; - handleSubmit: handleSubmit; + previouslySubmittedData?: Store.UserData; + handleSubmit: HandleSubmit; } export enum QuestionLayout { diff --git a/editor.planx.uk/src/@planx/components/Result/Public/ResultReason.tsx b/editor.planx.uk/src/@planx/components/Result/Public/ResultReason.tsx index 6cd4782813..227ec3318d 100644 --- a/editor.planx.uk/src/@planx/components/Result/Public/ResultReason.tsx +++ b/editor.planx.uk/src/@planx/components/Result/Public/ResultReason.tsx @@ -9,16 +9,14 @@ import { styled } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; import { visuallyHidden } from "@mui/utils"; import { useAnalyticsTracking } from "pages/FlowEditor/lib/analytics/provider"; -import { useStore } from "pages/FlowEditor/lib/store"; +import { Store, useStore } from "pages/FlowEditor/lib/store"; import React, { useLayoutEffect, useRef, useState } from "react"; import Caret from "ui/icons/Caret"; import ReactMarkdownOrHtml from "ui/shared/ReactMarkdownOrHtml"; -import type { Node } from "../../../../types"; - interface IResultReason { id: string; - question: Node; + question: Store.Node; response: string; showChangeButton?: boolean; flagColor?: string; diff --git a/editor.planx.uk/src/@planx/components/Result/Public/index.tsx b/editor.planx.uk/src/@planx/components/Result/Public/index.tsx index 2200fbe0f6..4822e28520 100644 --- a/editor.planx.uk/src/@planx/components/Result/Public/index.tsx +++ b/editor.planx.uk/src/@planx/components/Result/Public/index.tsx @@ -6,17 +6,18 @@ import Card from "@planx/components/shared/Preview/Card"; import SimpleExpand from "@planx/components/shared/Preview/SimpleExpand"; import { WarningContainer } from "@planx/components/shared/Preview/WarningContainer"; import { Store, useStore } from "pages/FlowEditor/lib/store"; -import type { handleSubmit } from "pages/Preview/Node"; +import { Response } from "pages/FlowEditor/lib/store/preview"; +import type { HandleSubmit } from "pages/Preview/Node"; import React from "react"; import { FONT_WEIGHT_SEMI_BOLD } from "theme"; -import type { Node, TextContent } from "types"; +import type { TextContent } from "types"; import ResultReason from "./ResultReason"; import ResultSummary from "./ResultSummary"; export interface Props { allowChanges?: boolean; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; headingColor: { text: string; background: string; @@ -26,13 +27,7 @@ export interface Props { reasonsTitle?: string; responses: Array; disclaimer?: TextContent; - previouslySubmittedData?: Store.userData; -} - -interface Response { - question: Node; - selections: Array; - hidden: boolean; + previouslySubmittedData?: Store.UserData; } const DisclaimerContent = styled(Typography)(({ theme }) => ({ @@ -85,7 +80,7 @@ const Responses = ({ id={question.id} question={question} showChangeButton={allowChanges && !breadcrumbs[question.id].auto} - response={selections.map((s) => s.data.text).join(",")} + response={selections.map((s) => s.data?.text).join(",")} flagColor={flagColor} /> ))} diff --git a/editor.planx.uk/src/@planx/components/Review/Public/Presentational.tsx b/editor.planx.uk/src/@planx/components/Review/Public/Presentational.tsx index 15c006629c..2e91e7e86a 100644 --- a/editor.planx.uk/src/@planx/components/Review/Public/Presentational.tsx +++ b/editor.planx.uk/src/@planx/components/Review/Public/Presentational.tsx @@ -1,9 +1,10 @@ +import { NodeId } from "@opensystemslab/planx-core/types"; import Card from "@planx/components/shared/Preview/Card"; import CardHeader from "@planx/components/shared/Preview/CardHeader"; import SummaryListsBySections from "@planx/components/shared/Preview/SummaryList"; import { Store } from "pages/FlowEditor/lib/store"; import { sortBreadcrumbs } from "pages/FlowEditor/lib/store/preview"; -import type { handleSubmit } from "pages/Preview/Node"; +import type { HandleSubmit } from "pages/Preview/Node"; import React from "react"; export default Component; @@ -11,17 +12,17 @@ export default Component; interface Props { title: string; description: string; - breadcrumbs: Store.breadcrumbs; - flow: Store.flow; - passport: Store.passport; - handleSubmit?: handleSubmit; - changeAnswer: (id: Store.nodeId) => void; + breadcrumbs: Store.Breadcrumbs; + flow: Store.Flow; + passport: Store.Passport; + handleSubmit?: HandleSubmit; + changeAnswer: (id: NodeId) => void; showChangeButton: boolean; } function Component(props: Props) { // ensure questions & answers display in expected order - const sortedBreadcrumbs: Store.breadcrumbs = sortBreadcrumbs( + const sortedBreadcrumbs: Store.Breadcrumbs = sortBreadcrumbs( props.breadcrumbs, props.flow, ); diff --git a/editor.planx.uk/src/@planx/components/Section/Public.tsx b/editor.planx.uk/src/@planx/components/Section/Public.tsx index eab14c9496..55206a5fa1 100644 --- a/editor.planx.uk/src/@planx/components/Section/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Section/Public.tsx @@ -63,7 +63,7 @@ interface RootProps currentSectionIndex: number; flowName: string; sectionNodes: Record; - currentCard: Store.node | null; + currentCard: Store.Node | null; sectionCount: number; } @@ -102,14 +102,14 @@ export const Root = ({ ); type SectionsOverviewListProps = { - flow: Store.flow; + flow: Store.Flow; showChange: boolean; changeAnswer: (sectionId: string) => void; nextQuestion: () => void; sectionNodes: Record; - currentCard: Store.node | null; - breadcrumbs: Store.breadcrumbs; - cachedBreadcrumbs?: Store.cachedBreadcrumbs; + currentCard: Store.Node | null; + breadcrumbs: Store.Breadcrumbs; + cachedBreadcrumbs?: Store.CachedBreadcrumbs; isReconciliation?: boolean; alteredSectionIds?: string[]; }; diff --git a/editor.planx.uk/src/@planx/components/Section/model.ts b/editor.planx.uk/src/@planx/components/Section/model.ts index 6a19c940ac..bedfeb8711 100644 --- a/editor.planx.uk/src/@planx/components/Section/model.ts +++ b/editor.planx.uk/src/@planx/components/Section/model.ts @@ -25,9 +25,9 @@ export function computeSectionStatuses({ alteredSectionIds, }: { sectionNodes: Record; - currentCard: Store.node | null; - breadcrumbs: Store.breadcrumbs; - cachedBreadcrumbs?: Store.cachedBreadcrumbs; + currentCard: Store.Node | null; + breadcrumbs: Store.Breadcrumbs; + cachedBreadcrumbs?: Store.CachedBreadcrumbs; isReconciliation?: boolean; alteredSectionIds?: string[]; }): Record { diff --git a/editor.planx.uk/src/@planx/components/Send/model.ts b/editor.planx.uk/src/@planx/components/Send/model.ts index cd1082b4a5..61153fbb93 100644 --- a/editor.planx.uk/src/@planx/components/Send/model.ts +++ b/editor.planx.uk/src/@planx/components/Send/model.ts @@ -38,7 +38,7 @@ export function getCombinedEventsPayload({ }: { destinations: Destination[]; teamSlug: string; - passport: Store.passport; + passport: Store.Passport; sessionId: string; }) { const combinedEventsPayload: Record = {}; diff --git a/editor.planx.uk/src/@planx/components/SetValue/utils.test.ts b/editor.planx.uk/src/@planx/components/SetValue/utils.test.ts index 9fb490626d..2fb75bdfa1 100644 --- a/editor.planx.uk/src/@planx/components/SetValue/utils.test.ts +++ b/editor.planx.uk/src/@planx/components/SetValue/utils.test.ts @@ -21,7 +21,7 @@ describe("calculateNewValues() helper function", () => { fn: mockKey, val: "lion", }; - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { mockNode: mockSetValue, [mockKey]: previous }, }; @@ -57,7 +57,7 @@ describe("calculateNewValues() helper function", () => { fn: mockKey, val: "lion", }; - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { mockNode: mockSetValue, [mockKey]: previous }, }; @@ -93,7 +93,7 @@ describe("calculateNewValues() helper function", () => { fn: mockKey, val: "lion", }; - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { mockNode: mockSetValue, [mockKey]: previous }, }; @@ -129,7 +129,7 @@ describe("calculateNewValues() helper function", () => { fn: mockKey, val: "lion", }; - const mockPassport: Store.passport = { + const mockPassport: Store.Passport = { data: { mockNode: mockSetValue, [mockKey]: previous }, }; diff --git a/editor.planx.uk/src/@planx/components/SetValue/utils.ts b/editor.planx.uk/src/@planx/components/SetValue/utils.ts index 46530bfbcd..f4585db917 100644 --- a/editor.planx.uk/src/@planx/components/SetValue/utils.ts +++ b/editor.planx.uk/src/@planx/components/SetValue/utils.ts @@ -7,8 +7,8 @@ type PreviousValues = string | string[] | undefined; type HandleSetValue = (params: { nodeData: SetValue; previousValues: PreviousValues; - passport: Store.passport; -}) => Store.passport; + passport: Store.Passport; +}) => Store.Passport; /** * Handle modifying passport values when passing through a SetValue component diff --git a/editor.planx.uk/src/@planx/components/shared/Preview/SummaryList.tsx b/editor.planx.uk/src/@planx/components/shared/Preview/SummaryList.tsx index 05c4dea092..83fba08678 100644 --- a/editor.planx.uk/src/@planx/components/shared/Preview/SummaryList.tsx +++ b/editor.planx.uk/src/@planx/components/shared/Preview/SummaryList.tsx @@ -3,7 +3,10 @@ import Link from "@mui/material/Link"; import { styled } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; import { visuallyHidden } from "@mui/utils"; -import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; +import { + ComponentType as TYPES, + NodeId, +} from "@opensystemslab/planx-core/types"; import { PASSPORT_UPLOAD_KEY } from "@planx/components/DrawBoundary/model"; import { PASSPORT_REQUESTED_FILES_KEY } from "@planx/components/FileUploadAndLabel/model"; import { ConfirmationDialog } from "components/ConfirmationDialog"; @@ -119,25 +122,25 @@ const presentationalComponents: { [TYPES.TextInput]: TextInput, } as const; -type BreadcrumbEntry = [Store.nodeId, Store.breadcrumbs]; +type BreadcrumbEntry = [NodeId, Store.Breadcrumbs]; interface SummaryListBaseProps { - flow: Store.flow; - passport: Store.passport; - changeAnswer: (id: Store.nodeId) => void; + flow: Store.Flow; + passport: Store.Passport; + changeAnswer: (id: NodeId) => void; showChangeButton: boolean; } interface SummaryListsBySectionsProps extends SummaryListBaseProps { - breadcrumbs: Store.breadcrumbs; + breadcrumbs: Store.Breadcrumbs; sectionComponent: React.ElementType | undefined; } interface SummaryBreadcrumb { component: React.FC; - nodeId: Store.nodeId; - userData: Store.userData; - node: Store.node; + nodeId: NodeId; + userData: Store.UserData; + node: Store.Node; } interface SummaryListProps extends SummaryListBaseProps { @@ -166,7 +169,7 @@ function SummaryListsBySections(props: SummaryListsBySectionsProps) { }; const removeNonPresentationalNodes = ( - section: Store.breadcrumbs, + section: Store.Breadcrumbs, ): BreadcrumbEntry[] => { // Typecast to preserve Store.userData const entries = Object.entries(section) as BreadcrumbEntry[]; @@ -247,7 +250,7 @@ function SummaryListsBySections(props: SummaryListsBySectionsProps) { function SummaryList(props: SummaryListProps) { const { trackEvent } = useAnalyticsTracking(); const [isDialogOpen, setIsDialogOpen] = useState(false); - const [nodeToChange, setNodeToChange] = useState( + const [nodeToChange, setNodeToChange] = useState( undefined, ); @@ -264,7 +267,7 @@ function SummaryList(props: SummaryListProps) { } }; - const handleChange = (nodeId: Store.nodeId) => { + const handleChange = (nodeId: NodeId) => { setNodeToChange(nodeId); setIsDialogOpen(true); }; @@ -332,10 +335,10 @@ function SummaryList(props: SummaryListProps) { interface ComponentProps { node: any; - userData?: Store.userData; - flow: Store.flow; - passport: Store.passport; - nodeId: Store.nodeId; + userData?: Store.UserData; + flow: Store.Flow; + passport: Store.Passport; + nodeId: NodeId; } function List(props: ComponentProps) { diff --git a/editor.planx.uk/src/@planx/components/ui.tsx b/editor.planx.uk/src/@planx/components/ui.tsx index 4411cbadfe..1ea5486a9d 100644 --- a/editor.planx.uk/src/@planx/components/ui.tsx +++ b/editor.planx.uk/src/@planx/components/ui.tsx @@ -28,7 +28,7 @@ import SquareFoot from "@mui/icons-material/SquareFoot"; import TextFields from "@mui/icons-material/TextFields"; import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; import { Store } from "pages/FlowEditor/lib/store"; -import type { handleSubmit } from "pages/Preview/Node"; +import type { HandleSubmit } from "pages/Preview/Node"; import React, { ChangeEvent } from "react"; import ImgInput from "ui/editor/ImgInput"; import InputGroup from "ui/editor/InputGroup"; @@ -47,11 +47,11 @@ export interface EditorProps { export type PublicProps = Data & { id?: string; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; resetButton?: boolean; resetPreview?: () => void; autoFocus?: boolean; - previouslySubmittedData?: Store.userData; + previouslySubmittedData?: Store.UserData; }; // XXX: We define the Icon type in terms of one of the Icons so as not to have to repeat ourselves diff --git a/editor.planx.uk/src/@planx/graph/types.d.ts b/editor.planx.uk/src/@planx/graph/types.d.ts index afbb94a491..b9b903c24a 100644 --- a/editor.planx.uk/src/@planx/graph/types.d.ts +++ b/editor.planx.uk/src/@planx/graph/types.d.ts @@ -1,15 +1,15 @@ declare module "nanoid-good"; export namespace OT { - export type path = Array; + export type Path = Array; export namespace Object { export interface Add { - p: OT.path; + p: OT.Path; oi: any; } export interface Remove { - p: OT.path; + p: OT.Path; od: any; } export type Replace = OT.Object.Remove & OT.Object.Add; @@ -17,11 +17,11 @@ export namespace OT { export namespace Array { export interface Add { - p: OT.path; + p: OT.Path; li: any; } export interface Remove { - p: OT.path; + p: OT.Path; ld: any; } export type Replace = OT.Array.Remove & OT.Array.Add; diff --git a/editor.planx.uk/src/lib/feedback.ts b/editor.planx.uk/src/lib/feedback.ts index f4e6464512..d8fe32393e 100644 --- a/editor.planx.uk/src/lib/feedback.ts +++ b/editor.planx.uk/src/lib/feedback.ts @@ -6,8 +6,8 @@ import { Store, useStore } from "pages/FlowEditor/lib/store"; import { publicClient } from "./graphql"; type UserData = { - breadcrumbs: Store.breadcrumbs; - passport: Store.passport; + breadcrumbs: Store.Breadcrumbs; + passport: Store.Passport; }; export type FeedbackMetadata = { @@ -17,7 +17,7 @@ export type FeedbackMetadata = { nodeType?: string | null; device: Bowser.Parser.ParsedResult; userData: UserData; - nodeData: Store.node["data"]; + nodeData: Store.Node["data"]; }; export async function getInternalFeedbackMetadata(): Promise { @@ -56,7 +56,7 @@ export async function insertFeedbackMutation(data: { userContext?: string; userComment: string; feedbackType: string; - nodeData?: Store.node["data"]; + nodeData?: Store.Node["data"]; }) { const result = await publicClient.mutate({ mutation: gql` diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx index 3b57d4bb73..4656a67170 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx @@ -147,7 +147,7 @@ const Node: React.FC = (props) => { } }; -const getSetValueText = ({ operation, fn, val }: Store.node["data"]) => { +const getSetValueText = ({ operation, fn, val }: Store.Node["data"]) => { switch (operation) { case "append": return `Append ${val} to ${fn}`; diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/advancedAutomations.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/advancedAutomations.test.ts index ac20d92923..f9774e5d9b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/advancedAutomations.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/advancedAutomations.test.ts @@ -4,7 +4,7 @@ import { Store, useStore } from "../store"; const { getState, setState } = useStore; -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: [ "Imks7j68BD", diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/granularity.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/granularity.test.ts index 95aaa41af7..2f57d9ba6d 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/granularity.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/granularity.test.ts @@ -4,7 +4,7 @@ import { Store, useStore } from "../store"; const { getState, setState } = useStore; -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["whatisit"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/ordering.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/ordering.test.ts index d27323334a..0a0d7db64a 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/ordering.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/ordering.test.ts @@ -4,7 +4,7 @@ import { Store, useStore } from "../store"; const { getState, setState } = useStore; -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["QuestionTrolley", "ChecklistTrolley"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/canGoBack.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/canGoBack.test.ts index 22f0af6d53..0dff26f62f 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/canGoBack.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/canGoBack.test.ts @@ -7,7 +7,7 @@ const { canGoBack, getCurrentCard, resetPreview, record, changeAnswer } = getState(); // https://imgur.com/VFV64ax -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["Question", "Pay", "Content", "Confirmation"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/changeAnswer.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/changeAnswer.ts index fe9bf87b80..fde43a1211 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/changeAnswer.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/changeAnswer.ts @@ -5,7 +5,7 @@ import flowWithAutoAnswersMock from "../mocks/flowWithAutoAnswers.json"; const { getState, setState } = useStore; -const flowWithAutoAnswers = cloneDeep(flowWithAutoAnswersMock) as Store.flow; +const flowWithAutoAnswers = cloneDeep(flowWithAutoAnswersMock) as Store.Flow; const { record, changeAnswer, computePassport } = getState(); @@ -25,8 +25,8 @@ describe("changeAnswer", () => { answers: ["X9JjnbPpnd"], auto: true, }, - } as Store.breadcrumbs; - const cachedBreadcrumbs = {} as Store.cachedBreadcrumbs; + } as Store.Breadcrumbs; + const cachedBreadcrumbs = {} as Store.CachedBreadcrumbs; setState({ flow, @@ -62,7 +62,7 @@ describe("changeAnswer", () => { answers: ["X9JjnbPpnd"], auto: true, }, - } as Store.cachedBreadcrumbs; + } as Store.CachedBreadcrumbs; // Confirm that our original answer is still preserved in cachedBreadcrumbs, but not included in current breadcrumbs expect(getState().breadcrumbs).not.toContain(originalAnswer); diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/removeNodesDependentOnPassport.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/removeNodesDependentOnPassport.test.ts index bcc4415941..deff110ec2 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/removeNodesDependentOnPassport.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/removeNodesDependentOnPassport.test.ts @@ -9,11 +9,11 @@ const { getState, setState } = useStore; let breadcrumbsDependentOnPassport = cloneDeep( breadcrumbsDependentOnPassportMock, -) as Store.breadcrumbs; +) as Store.Breadcrumbs; let flowWithPassportComponents = cloneDeep( flowWithPassportComponentsMock, -) as Store.flow; +) as Store.Flow; const { record, @@ -28,10 +28,10 @@ beforeEach(() => { resetPreview(); breadcrumbsDependentOnPassport = cloneDeep( breadcrumbsDependentOnPassportMock, - ) as Store.breadcrumbs; + ) as Store.Breadcrumbs; flowWithPassportComponents = cloneDeep( flowWithPassportComponentsMock, - ) as Store.flow; + ) as Store.Flow; }); describe("removeNodesDependentOnPassport", () => { @@ -57,7 +57,7 @@ describe("removeNodesDependentOnPassport", () => { const breadcrumbs = { ...mockBreadcrumbs }; const { breadcrumbsWithoutPassportData, removedNodeIds } = - removeNodesDependentOnPassport(mockFlowData as Store.flow, breadcrumbs); + removeNodesDependentOnPassport(mockFlowData as Store.Flow, breadcrumbs); const expectedBreadcrumbs = { ...mockBreadcrumbs }; @@ -70,7 +70,7 @@ describe("nodesDependentOnPassport with record", () => { test("should remove Draw Boundary and Planning constraints from cachedBreadcrumbs", () => { const cachedBreadcrumbs = { ...breadcrumbsDependentOnPassport, - } as Store.cachedBreadcrumbs; + } as Store.CachedBreadcrumbs; const userData = { data: { _address: { @@ -118,7 +118,7 @@ describe("nodesDependentOnPassport with record", () => { test("should remove Planning constraints from cachedBreadcrumbs", () => { const cachedBreadcrumbs = { ...breadcrumbsDependentOnPassport, - } as Store.cachedBreadcrumbs; + } as Store.CachedBreadcrumbs; const userData = { data: { "property.boundary.site": { diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/upcomingCardIds.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/upcomingCardIds.test.ts index b166ce5463..ef25f2fb86 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/upcomingCardIds.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/upcomingCardIds.test.ts @@ -5,7 +5,7 @@ import { Store, useStore } from "../../store"; const { getState, setState } = useStore; const { upcomingCardIds, resetPreview, record, getCurrentCard } = getState(); -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["SetValue", "Content", "AutomatedQuestion"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/setValue.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/setValue.test.ts index 7aae5da40a..b9f140077e 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/setValue.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/setValue.test.ts @@ -6,7 +6,7 @@ import { Store, useStore } from "../store"; const { getState, setState } = useStore; const { resetPreview, record, computePassport, getCurrentCard } = getState(); -const baseFlow: Store.flow = { +const baseFlow: Store.Flow = { _root: { edges: ["setValue1", "middleOfService", "setValue2", "endOfService"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/unseen.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/unseen.test.ts index 4ea8774a75..b8bb32b230 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/unseen.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/unseen.test.ts @@ -3,7 +3,7 @@ import { Store, useStore } from "../store"; const { getState, setState } = useStore; // https://github.com/theopensystemslab/planx-new/pull/430#issue-625111571 -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["Dq7qLvn9If", "GZAmDGuV3J"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/useNotValues.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/useNotValues.test.ts index cb74d0cebc..7de640f186 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/useNotValues.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/useNotValues.test.ts @@ -2,7 +2,7 @@ import { Store, useStore } from "../store"; // flow preview: https://i.imgur.com/nCov5CE.png -const flow: Store.flow = { +const flow: Store.Flow = { _root: { edges: ["NS7QFc7Cjc", "3cNtq1pLmt", "eTBHJsbJKc"], }, diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/analytics/provider.tsx b/editor.planx.uk/src/pages/FlowEditor/lib/analytics/provider.tsx index 6a0cf6cafa..e109d2bedd 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/analytics/provider.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/lib/analytics/provider.tsx @@ -321,7 +321,7 @@ export const AnalyticsProvider: React.FC<{ children: React.ReactNode }> = ({ async function updateLastVisibleNodeLogWithAllowListAnswers( nodeId: string, - breadcrumb: Store.userData, + breadcrumb: Store.UserData, ) { if (shouldSkipTracking()) return; diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/analytics/utils.ts b/editor.planx.uk/src/pages/FlowEditor/lib/analytics/utils.ts index 2e0eeb07d6..483f6c08cb 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/analytics/utils.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/analytics/utils.ts @@ -13,7 +13,7 @@ import { /** * Generate meaningful title for content analytic log */ -export function getContentTitle(node: Store.node): string { +export function getContentTitle(node: Store.Node): string { const dom = new DOMParser().parseFromString(node.data.content, "text/html"); const h1 = dom.body.getElementsByTagName("h1")[0]?.textContent; const text = h1 || dom.body.textContent; @@ -25,7 +25,7 @@ export function getContentTitle(node: Store.node): string { return title; } -export function extractNodeTitle(node: Store.node): string { +export function extractNodeTitle(node: Store.Node): string { const nodeTitle = node?.type === TYPES.Content ? getContentTitle(node) @@ -35,7 +35,7 @@ export function extractNodeTitle(node: Store.node): string { export function getTargetNodeDataFromFlow( nodeId: string, - flow: Store.flow, + flow: Store.Flow, ): BackwardsTargetMetadata { const node = flow[nodeId]; const nodeType = node?.type ? TYPES[node.type] : null; @@ -49,7 +49,7 @@ export function getTargetNodeDataFromFlow( export function generateBackwardsNavigationMetadata( initiator: BackwardsNavigationInitiatorType, - flow: Store.flow, + flow: Store.Flow, nodeId?: string, ): BackwardsNavigationMetadata { const targetNodeMetadata = nodeId @@ -63,10 +63,10 @@ export function generateBackwardsNavigationMetadata( } export function getNodeMetadata( - node: Store.node, + node: Store.Node, resultData: any, nodeId: string, - breadcrumbs: Store.breadcrumbs, + breadcrumbs: Store.Breadcrumbs, ) { const isAutoAnswered = breadcrumbs[nodeId]?.auto || false; switch (node?.type) { @@ -102,8 +102,8 @@ export function isAllowListKey(key: any): key is AllowListKey { */ export function getAnswers( nodeId: string, - flow: Store.flow, - breadcrumbs: Store.breadcrumbs, + flow: Store.Flow, + breadcrumbs: Store.Breadcrumbs, ): Partial> | undefined { const { data } = flow[nodeId]; const nodeFn: string | undefined = data?.fn || data?.val; @@ -129,7 +129,7 @@ export function getAnswers( * e.g. data set automatically by components such as DrawBoundary */ export function getData( - breadcrumb: Store.userData, + breadcrumb: Store.UserData, ): Partial> | undefined { const dataSetByNode = breadcrumb.data; if (!dataSetByNode) return; @@ -145,8 +145,8 @@ export function getData( } export function determineLogDirection( - breadcrumbs: Store.breadcrumbs, - previousBreadcrumbs: Store.breadcrumbs | undefined, + breadcrumbs: Store.Breadcrumbs, + previousBreadcrumbs: Store.Breadcrumbs | undefined, ) { if (!previousBreadcrumbs) return; const curLength = Object.keys(breadcrumbs).length; @@ -156,8 +156,8 @@ export function determineLogDirection( } export function findUpdatedBreadcrumbKeys( - breadcrumbs: Store.breadcrumbs, - previousBreadcrumbs: Store.breadcrumbs, + breadcrumbs: Store.Breadcrumbs, + previousBreadcrumbs: Store.Breadcrumbs, ): string[] | undefined { const currentKeys = Object.keys(breadcrumbs); const previousKeys = Object.keys(previousBreadcrumbs); @@ -174,9 +174,9 @@ export function findUpdatedBreadcrumbKeys( */ export function getAllowListAnswers( nodeId: string, - breadcrumb: Store.userData, - flow: Store.flow, - breadcrumbs: Store.breadcrumbs, + breadcrumb: Store.UserData, + flow: Store.Flow, + breadcrumbs: Store.Breadcrumbs, ): Partial> | undefined { const answers = getAnswers(nodeId, flow, breadcrumbs); const data = getData(breadcrumb); diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts index 2f830c778f..bae0c5f446 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts @@ -3,6 +3,7 @@ import { getPathForNode, sortFlow } from "@opensystemslab/planx-core"; import { ComponentType, FlowGraph, + NodeId, OrderedFlow, } from "@opensystemslab/planx-core/types"; import { @@ -69,38 +70,38 @@ export const editorUIStore: StateCreator< }); interface PublishFlowResponse { - alteredNodes: Store.node[]; + alteredNodes: Store.Node[]; message: string; } export interface EditorStore extends Store.Store { addNode: (node: any, relationships?: any) => void; - connect: (src: Store.nodeId, tgt: Store.nodeId, object?: any) => void; - connectTo: (id: Store.nodeId) => void; + connect: (src: NodeId, tgt: NodeId, object?: any) => void; + connectTo: (id: NodeId) => void; copyFlow: (flowId: string) => Promise; - copyNode: (id: Store.nodeId) => void; + copyNode: (id: NodeId) => void; createFlow: (teamId: any, newSlug: any, newName: string) => Promise; deleteFlow: (teamId: number, flowSlug: string) => Promise; validateAndDiffFlow: (flowId: string) => Promise; getFlows: (teamId: number) => Promise; - isClone: (id: Store.nodeId) => boolean; + isClone: (id: NodeId) => boolean; lastPublished: (flowId: string) => Promise; lastPublisher: (flowId: string) => Promise; isFlowPublished: boolean; - makeUnique: (id: Store.nodeId, parent?: Store.nodeId) => void; + makeUnique: (id: NodeId, parent?: NodeId) => void; moveFlow: (flowId: string, teamSlug: string) => Promise; moveNode: ( - id: Store.nodeId, - parent?: Store.nodeId, - toBefore?: Store.nodeId, - toParent?: Store.nodeId, + id: NodeId, + parent?: NodeId, + toBefore?: NodeId, + toParent?: NodeId, ) => void; - pasteNode: (toParent: Store.nodeId, toBefore: Store.nodeId) => void; + pasteNode: (toParent: NodeId, toBefore: NodeId) => void; publishFlow: ( flowId: string, summary?: string, ) => Promise; - removeNode: (id: Store.nodeId, parent: Store.nodeId) => void; + removeNode: (id: NodeId, parent: NodeId) => void; updateNode: (node: any, relationships?: any) => void; undoOperation: (ops: OT.Op[]) => void; orderedFlow?: OrderedFlow; 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 20f94837b4..6613b83e54 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/index.ts @@ -1,4 +1,7 @@ -import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; +import { + Node as PlanXCoreNode, + NodeId, +} from "@opensystemslab/planx-core/types"; import { isPreviewOnlyDomain } from "routes/utils"; import { create, StoreApi, UseBoundStore } from "zustand"; @@ -19,23 +22,23 @@ import { UserStore, userStore } from "./user"; // eslint-disable-next-line @typescript-eslint/no-namespace export declare namespace Store { export type Store = Record; - export type nodeId = string; - export type flow = Record; - export type userData = { + export type Flow = Record; + export type UserData = { answers?: Array; data?: Record; auto?: boolean; override?: Record; }; - export type breadcrumbs = Record; - export type cachedBreadcrumbs = Record | undefined; - export type node = { - id?: nodeId; - type?: TYPES; + export type Breadcrumbs = Record; + export type CachedBreadcrumbs = Record | undefined; + /** + * Looser Node type with `any` data + * @deprecated Should share type with PlanX core once `Value` is retired and Flow Graph is typed + */ + export interface Node extends PlanXCoreNode { data?: any; - edges?: nodeId[]; - }; - export interface passport { + } + export interface Passport { data?: Record; } } diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts index 6e764b075b..ae1279c840 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts @@ -6,7 +6,7 @@ import type { StateCreator } from "zustand"; import { PreviewStore } from "./preview"; import { SharedStore } from "./shared"; -export interface SectionNode extends Store.node { +export interface SectionNode extends Store.Node { data: { title: string; }; @@ -20,8 +20,8 @@ export interface NavigationStore { sectionNodes: Record; initNavigationStore: () => void; updateSectionData: () => void; - filterFlowByType: (type: TYPES) => Store.flow; - getSortedBreadcrumbsBySection: () => Store.breadcrumbs[]; + filterFlowByType: (type: TYPES) => Store.Flow; + getSortedBreadcrumbsBySection: () => Store.Breadcrumbs[]; getSectionForNode: (nodeId: string) => SectionNode; } @@ -93,7 +93,7 @@ export const navigationStore: StateCreator< * Get a subset of the full flow, by type * Returned in correct order, based on _root node's edges */ - filterFlowByType: (type: TYPES): Store.flow => { + filterFlowByType: (type: TYPES): Store.Flow => { const flow = get().flow; const rootEdges = flow._root.edges || []; const filteredFlow = Object.fromEntries( @@ -110,7 +110,7 @@ export const navigationStore: StateCreator< // so we can render section node titles as h2s and the following nodes as individual SummaryLists getSortedBreadcrumbsBySection: () => { const { breadcrumbs, sectionNodes, hasSections } = get(); - const sortedBreadcrumbsBySection: Store.breadcrumbs[] = []; + const sortedBreadcrumbsBySection: Store.Breadcrumbs[] = []; if (hasSections) { const sortedNodeIdsBySection: string[][] = []; Object.keys(sectionNodes).forEach((sectionId, i) => { 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 464751c8b4..14ab3086a8 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts @@ -3,6 +3,7 @@ import type { FlagSet, GovUKPayment, Node, + NodeId, } from "@opensystemslab/planx-core/types"; import { DEFAULT_FLAG_CATEGORY, @@ -33,24 +34,31 @@ import type { SharedStore } from "./shared"; const SUPPORTED_DECISION_TYPES = [TYPES.Checklist, TYPES.Question]; let memoizedPreviousCardId: string | undefined = undefined; -let memoizedBreadcrumb: Store.breadcrumbs | undefined = undefined; +let memoizedBreadcrumb: Store.Breadcrumbs | undefined = undefined; + +export interface Response { + question: Node & { id: NodeId }; + selections: Array; + hidden: boolean; +} + export interface PreviewStore extends Store.Store { collectedFlags: ( - upToNodeId: Store.nodeId, + upToNodeId: NodeId, visited?: Array, ) => Array; - currentCard: ({ id: Store.nodeId } & Store.node) | null; + currentCard: ({ id: NodeId } & Store.Node) | null; setCurrentCard: () => void; - getCurrentCard: () => ({ id: Store.nodeId } & Store.node) | null; + getCurrentCard: () => ({ id: NodeId } & Store.Node) | null; hasPaid: () => boolean; previousCard: ( - node: Store.node | null, - upcomingCardIds?: Store.nodeId[], - ) => Store.nodeId | undefined; - canGoBack: (node: Store.node | null) => boolean; - getType: (node: Store.node | null) => TYPES | undefined; - computePassport: () => Readonly; - record: (id: Store.nodeId, userData?: Store.userData) => void; + node: Store.Node | null, + upcomingCardIds?: NodeId[], + ) => NodeId | undefined; + canGoBack: (node: Store.Node | null) => boolean; + getType: (node: Store.Node | null) => TYPES | undefined; + computePassport: () => Readonly; + record: (id: NodeId, userData?: Store.UserData) => void; resultData: ( flagSet?: string, overrides?: { @@ -59,17 +67,17 @@ export interface PreviewStore extends Store.Store { ) => { [category: string]: { flag: Flag; - responses: any[]; + responses: Array; displayText: { heading: string; description: string }; }; }; resumeSession: (session: Session) => void; sessionId: string; - upcomingCardIds: () => Store.nodeId[]; + upcomingCardIds: () => NodeId[]; isFinalCard: () => boolean; govUkPayment?: GovUKPayment; setGovUkPayment: (govUkPayment: GovUKPayment) => void; - cachedBreadcrumbs?: Store.cachedBreadcrumbs; + cachedBreadcrumbs?: Store.CachedBreadcrumbs; analyticsId?: number; setAnalyticsId: (analyticsId: number) => void; restore: boolean; @@ -158,7 +166,7 @@ export const previewStore: StateCreator< ); }, - previousCard: (node: Store.node | null) => { + previousCard: (node: Store.Node | null) => { const { breadcrumbs, flow, _nodesPendingEdit, changedNode } = get(); const goBackable = Object.entries(breadcrumbs) .filter(([, v]) => !v.auto) @@ -188,14 +196,14 @@ export const previewStore: StateCreator< return previousCardId; }, - canGoBack: (node: Store.node | null) => { + canGoBack: (node: Store.Node | null) => { // XXX: node is a required param until upcomingNodes().shift() is // optimised/memoized, see related isFinalCard() comment below const { hasPaid, previousCard } = get(); return Boolean(node?.id) && Boolean(previousCard(node)) && !hasPaid(); }, - getType: (node: Store.node | null) => { + getType: (node: Store.Node | null) => { const { flow } = get(); if (!node?.id) return; const currentNodeType = flow[node.id]?.type; @@ -210,7 +218,7 @@ export const previewStore: StateCreator< const key = flow[id].data?.fn; - const passportData: Store.passport["data"] = {}; + const passportData: Store.Passport["data"] = {}; if (key) { const passportValue = answers @@ -244,10 +252,10 @@ export const previewStore: StateCreator< _acc![id] = value; return _acc; }, - {} as Store.passport["data"], + {} as Store.Passport["data"], ); - let passport: Store.passport = { + let passport: Store.Passport = { ...acc, data: { ...acc.data, @@ -269,7 +277,7 @@ export const previewStore: StateCreator< }, { data: {}, - } as Store.passport, + } as Store.Passport, ); return passport; @@ -295,7 +303,7 @@ export const previewStore: StateCreator< // add breadcrumb const { answers = [], data = {}, auto = false, override } = userData; - const breadcrumb: Store.userData = { auto: Boolean(auto) }; + const breadcrumb: Store.UserData = { auto: Boolean(auto) }; if (answers?.length > 0) breadcrumb.answers = answers; const filteredData = objectWithoutNullishValues(data); @@ -396,10 +404,10 @@ export const previewStore: StateCreator< computePassport().data?._nots, ); - const ids: Set = new Set(); - const visited: Set = new Set(); + const ids: Set = new Set(); + const visited: Set = new Set(); - const nodeIdsConnectedFrom = (source: Store.nodeId): void => { + const nodeIdsConnectedFrom = (source: NodeId): void => { return (flow[source]?.edges ?? []) .filter((id) => { if (visited.has(id)) return false; @@ -542,8 +550,8 @@ export const previewStore: StateCreator< return acc; }, { edges: [] } as { - responseWithNoValueId?: Store.nodeId; - edges: Array; + responseWithNoValueId?: NodeId; + edges: Array; }, ); @@ -570,7 +578,7 @@ export const previewStore: StateCreator< // of all the answers collected so far Object.values(breadcrumbs) // in reverse order - .flatMap(({ answers }) => answers as Array) + .flatMap(({ answers }) => answers as Array) // .filter(Boolean) .reverse() // ending with _root @@ -661,8 +669,8 @@ export const previewStore: StateCreator< }); const knownNots = ( - flow: Store.flow, - breadcrumbs: Store.breadcrumbs, + flow: Store.Flow, + breadcrumbs: Store.Breadcrumbs, nots = {}, ) => Object.entries(breadcrumbs).reduce( @@ -671,7 +679,7 @@ const knownNots = ( const _knownNotVals = difference( flow[id].edges, - answers as Array, + answers as Array, ); if (flow[id].data?.fn) { @@ -692,9 +700,9 @@ const knownNots = ( interface RemoveOrphansFromBreadcrumbsProps { id: string; - flow: Store.flow; - userData: Store.userData; - breadcrumbs: Store.cachedBreadcrumbs | Store.breadcrumbs; + flow: Store.Flow; + userData: Store.UserData; + breadcrumbs: Store.CachedBreadcrumbs | Store.Breadcrumbs; } export const removeOrphansFromBreadcrumbs = ({ @@ -703,8 +711,8 @@ export const removeOrphansFromBreadcrumbs = ({ userData, breadcrumbs, }: RemoveOrphansFromBreadcrumbsProps): - | Store.cachedBreadcrumbs - | Store.breadcrumbs => { + | Store.CachedBreadcrumbs + | Store.Breadcrumbs => { // this will prevent a user from "Continuing", therefore log error don't throw it if (!flow[id]) { logger.notify( @@ -728,13 +736,13 @@ export const removeOrphansFromBreadcrumbs = ({ breadcrumbs: acc, }); }, - { ...breadcrumbs } as Store.cachedBreadcrumbs | Store.breadcrumbs, + { ...breadcrumbs } as Store.CachedBreadcrumbs | Store.Breadcrumbs, ); }; export const getResultData = ( - breadcrumbs: Store.breadcrumbs, - flow: Store.flow, + breadcrumbs: Store.Breadcrumbs, + flow: Store.Flow, flagSet: Parameters[0] = DEFAULT_FLAG_CATEGORY, overrides?: Parameters[1], ) => { @@ -815,20 +823,20 @@ export const getResultData = ( return acc; }, - {} as ReturnType, + {}, ); }; export const sortBreadcrumbs = ( - nextBreadcrumbs: Store.breadcrumbs, - flow: Store.flow, + nextBreadcrumbs: Store.Breadcrumbs, + flow: Store.Flow, editingNodes?: string[], ) => { return editingNodes?.length ? nextBreadcrumbs : sortIdsDepthFirst(flow)(new Set(Object.keys(nextBreadcrumbs))).reduce( (acc, id) => ({ ...acc, [id]: nextBreadcrumbs[id] }), - {} as Store.breadcrumbs, + {} as Store.Breadcrumbs, ); }; @@ -840,15 +848,15 @@ function handleNodesWithPassport({ currentNodesPendingEdit, breadcrumbs, }: { - flow: Store.flow; + flow: Store.Flow; id: string; - cachedBreadcrumbs: Store.cachedBreadcrumbs; - userData: Store.userData; + cachedBreadcrumbs: Store.CachedBreadcrumbs; + userData: Store.UserData; currentNodesPendingEdit: string[]; - breadcrumbs: Store.breadcrumbs; + breadcrumbs: Store.Breadcrumbs; }) { let nodesPendingEdit = [...currentNodesPendingEdit]; - let newBreadcrumbs: Store.cachedBreadcrumbs = { ...cachedBreadcrumbs }; + let newBreadcrumbs: Store.CachedBreadcrumbs = { ...cachedBreadcrumbs }; const POPULATE_PASSPORT = [TYPES.FindProperty, TYPES.DrawBoundary]; const breadcrumbPopulatesPassport = @@ -884,10 +892,10 @@ function handleNodesWithPassport({ // when changing answers from review component to guarantee that their values are updated. // XXX: This logic assumes only one "FindProperty" component per flow. export const removeNodesDependentOnPassport = ( - flow: Store.flow, - breadcrumbs: Store.breadcrumbs, + flow: Store.Flow, + breadcrumbs: Store.Breadcrumbs, ): { - breadcrumbsWithoutPassportData: Store.breadcrumbs; + breadcrumbsWithoutPassportData: Store.Breadcrumbs; removedNodeIds: string[]; } => { const DEPENDENT_TYPES = [ diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/shared.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/shared.ts index fcef4a95f8..c03d953024 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/shared.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/shared.ts @@ -1,6 +1,6 @@ import { CoreDomainClient } from "@opensystemslab/planx-core"; import { Auth } from "@opensystemslab/planx-core/dist/requests/graphql"; -import { FlowStatus } from "@opensystemslab/planx-core/types"; +import { FlowStatus, NodeId } from "@opensystemslab/planx-core/types"; import { ROOT_NODE_KEY } from "@planx/graph"; import { removeSessionIdSearchParam } from "utils"; import type { StateCreator } from "zustand"; @@ -10,14 +10,14 @@ import { NavigationStore } from "./navigation"; export type PreviewEnvironment = "editor" | "standalone"; export interface SharedStore extends Store.Store { - breadcrumbs: Store.breadcrumbs; - childNodesOf: (id?: Store.nodeId) => Store.node[]; - flow: Store.flow; + breadcrumbs: Store.Breadcrumbs; + childNodesOf: (id?: NodeId) => Store.Node[]; + flow: Store.Flow; flowSlug: string; flowName: string; flowAnalyticsLink: string | null; id: string; - getNode: (id: Store.nodeId) => Store.node | undefined; + getNode: (id: NodeId) => Store.Node | undefined; resetPreview: () => void; setFlow: ({ id, @@ -27,12 +27,12 @@ export interface SharedStore extends Store.Store { flowStatus, }: { id?: string; - flow?: Store.flow; + flow?: Store.Flow; flowSlug?: string; flowName?: string; flowStatus?: FlowStatus; }) => void; - wasVisited: (id: Store.nodeId) => boolean; + wasVisited: (id: NodeId) => boolean; previewEnvironment: PreviewEnvironment; setPreviewEnvironment: (previewEnvironment: PreviewEnvironment) => void; setFlowSlug: (flowSlug: string) => void; diff --git a/editor.planx.uk/src/pages/Preview/Node.tsx b/editor.planx.uk/src/pages/Preview/Node.tsx index 239511cd57..0d851a4adb 100644 --- a/editor.planx.uk/src/pages/Preview/Node.tsx +++ b/editor.planx.uk/src/pages/Preview/Node.tsx @@ -36,11 +36,11 @@ import { exhaustiveCheck } from "utils"; import type { Store } from "../FlowEditor/lib/store"; import { useStore } from "../FlowEditor/lib/store"; -export type handleSubmit = (userData?: Store.userData | Event) => void; +export type HandleSubmit = (userData?: Store.UserData | Event) => void; interface Props { - handleSubmit: handleSubmit; - node: Store.node; + handleSubmit: HandleSubmit; + node: Store.Node; data?: any; } diff --git a/editor.planx.uk/src/pages/Preview/Questions.tsx b/editor.planx.uk/src/pages/Preview/Questions.tsx index 2f69cc4c60..f287939af9 100644 --- a/editor.planx.uk/src/pages/Preview/Questions.tsx +++ b/editor.planx.uk/src/pages/Preview/Questions.tsx @@ -14,7 +14,7 @@ import { ApplicationPath, Session } from "types"; import ErrorFallback from "../../components/ErrorFallback"; import { useStore } from "../FlowEditor/lib/store"; -import Node, { handleSubmit } from "./Node"; +import Node, { HandleSubmit } from "./Node"; const BackBar = styled(Box)(() => ({ top: 0, @@ -123,7 +123,7 @@ const Questions = ({ previewEnvironment }: QuestionsProps) => { }, [breadcrumbs]); const handleSubmit = - (id: string): handleSubmit => + (id: string): HandleSubmit => (userData) => { const { data = undefined, diff --git a/editor.planx.uk/src/routes/utils.ts b/editor.planx.uk/src/routes/utils.ts index a61b6463a1..39846a2ab3 100644 --- a/editor.planx.uk/src/routes/utils.ts +++ b/editor.planx.uk/src/routes/utils.ts @@ -18,10 +18,10 @@ export const rootFlowPath = (includePortals = false) => { export const rootTeamPath = () => window.location.pathname.split("/").slice(0, 2).join("/"); -export const isSaveReturnFlow = (flowData: Store.flow): boolean => +export const isSaveReturnFlow = (flowData: Store.Flow): boolean => Boolean(Object.values(flowData).find((node) => node.type === NodeTypes.Send)); -export const setPath = (flowData: Store.flow, req: NaviRequest) => { +export const setPath = (flowData: Store.Flow, req: NaviRequest) => { // XXX: store.path is SingleSession by default if (!isSaveReturnFlow(flowData)) return; diff --git a/editor.planx.uk/src/routes/views/published.tsx b/editor.planx.uk/src/routes/views/published.tsx index 914bd79369..f6eb47037e 100644 --- a/editor.planx.uk/src/routes/views/published.tsx +++ b/editor.planx.uk/src/routes/views/published.tsx @@ -18,7 +18,7 @@ interface PublishedViewSettings { } interface PublishedFlow extends Flow { - publishedFlows: Record<"data", Store.flow>[]; + publishedFlows: Record<"data", Store.Flow>[]; } /** diff --git a/editor.planx.uk/src/types.ts b/editor.planx.uk/src/types.ts index 8837621420..d783b6eed7 100644 --- a/editor.planx.uk/src/types.ts +++ b/editor.planx.uk/src/types.ts @@ -41,16 +41,6 @@ export interface TextContent { show: boolean; } -export interface Node { - id: string; - data: { - text: string; - flag?: string; - info?: string; - policyRef?: string; - }; -} - /** * Describes the different paths through which a flow can be navigated by a user */ @@ -72,8 +62,8 @@ export interface SendEmailPayload { }; } export type Session = { - passport: Store.passport; - breadcrumbs: Store.breadcrumbs; + passport: Store.Passport; + breadcrumbs: Store.Breadcrumbs; sessionId: string; // TODO: replace `id` with `flow: { id, published_flow_id }` id: SharedStore["id"]; @@ -88,8 +78,8 @@ export interface ReconciliationResponse { } // re-export store types -export type Passport = Store.passport; -export type Breadcrumbs = Store.breadcrumbs; +export type Passport = Store.Passport; +export type Breadcrumbs = Store.Breadcrumbs; export enum SectionStatus { NeedsUpdated = "NEW INFORMATION NEEDED", @@ -100,7 +90,7 @@ export enum SectionStatus { Completed = "COMPLETED", } -export interface SectionNode extends Store.node { +export interface SectionNode extends Store.Node { data: { title: string; description?: string; diff --git a/editor.planx.uk/src/ui/public/NextStepsList.tsx b/editor.planx.uk/src/ui/public/NextStepsList.tsx index 1cfd1d1000..f0820b2215 100644 --- a/editor.planx.uk/src/ui/public/NextStepsList.tsx +++ b/editor.planx.uk/src/ui/public/NextStepsList.tsx @@ -6,16 +6,16 @@ import { styled, Theme } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; import type { Step as StyledListItem } from "@planx/components/NextSteps/model"; import { useAnalyticsTracking } from "pages/FlowEditor/lib/analytics/provider"; -import { handleSubmit } from "pages/Preview/Node"; +import { HandleSubmit } from "pages/Preview/Node"; import React, { useState } from "react"; interface NextStepsListProps { steps: StyledListItem[]; - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; } interface ListItemProps extends StyledListItem { - handleSubmit?: handleSubmit; + handleSubmit?: HandleSubmit; handleSelectingUrl?: (url: string) => void; }