From 349b41866560a3fbadb41caf5e778eafa3fdcfbe Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Mon, 4 Nov 2024 09:57:17 +0100 Subject: [PATCH 1/3] wip --- .../src/@planx/components/Question/Editor.tsx | 20 ++++++++++++++++--- .../src/pages/FlowEditor/lib/store/preview.ts | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/editor.planx.uk/src/@planx/components/Question/Editor.tsx b/editor.planx.uk/src/@planx/components/Question/Editor.tsx index d9a33237e0..9c027936df 100644 --- a/editor.planx.uk/src/@planx/components/Question/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Question/Editor.tsx @@ -1,3 +1,4 @@ +import { errors } from "@airbrake/browser/dist/http_req/api"; import FormControlLabel from "@mui/material/FormControlLabel"; import Switch from "@mui/material/Switch"; import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; @@ -109,7 +110,11 @@ const OptionEditor: React.FC<{ )} { props.onChange({ ...props.value, @@ -151,7 +156,15 @@ export const Question: React.FC = (props) => { alert(JSON.stringify({ type, ...values, children }, null, 2)); } }, - validate: () => { }, + validate: ({ options, ...values }) => { + const errors: Record = {}; + if (values.fn && !options.some((option) => option.data.val)) { + errors.fn = + "At least one option must set a data value when the question has a data field"; + } + + return errors; + }, }); const focusRef = useRef(null); @@ -201,6 +214,8 @@ export const Question: React.FC = (props) => { value={formik.values.fn} placeholder="Data Field" onChange={formik.handleChange} + error={Boolean(formik.errors?.fn)} + errorMessage={formik.errors?.fn} /> @@ -221,7 +236,6 @@ export const Question: React.FC = (props) => { - flow[nodeId].data?.fn === data.fn, ); - if (!visitedFns) return; + if (!visitedFns.length) return; // Get all options (aka edges or Answer nodes) for this node const options: Array = edges.map((edgeId) => ({ From 240e8499a062036aa642590e9139efca6018db7e Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Mon, 4 Nov 2024 10:26:46 +0100 Subject: [PATCH 2/3] final validation logic, account for previously seen checklists --- .../src/@planx/components/Checklist/Editor.tsx | 11 ++++++++++- .../src/pages/FlowEditor/lib/store/preview.ts | 5 +++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx index 28bbda8ce5..166d0fd765 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx @@ -312,7 +312,14 @@ export const ChecklistComponent: React.FC = (props) => { alert(JSON.stringify({ type, ...values, options }, null, 2)); } }, - validate: () => {}, + validate: ({ options, ...values }) => { + const errors: Record = {}; + if (values.fn && !options?.some((option) => option.data.val)) { + errors.fn = + "At least one option must set a data value when the checklist has a data field"; + } + return errors; + }, }); const focusRef = useRef(null); @@ -365,6 +372,8 @@ export const ChecklistComponent: React.FC = (props) => { value={formik.values.fn} placeholder="Data Field" onChange={formik.handleChange} + error={Boolean(formik.errors?.fn)} + errorMessage={formik.errors?.fn} /> 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 bf1042ba00..d07a012d87 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts @@ -514,9 +514,10 @@ export const previewStore: StateCreator< ) return; - // Only proceed if the user has seen at least one node with this fn before + // Only proceed if the user has seen at least one node with this fn (or `output` in case of Calculate nodes) before const visitedFns = Object.entries(breadcrumbs).filter( - ([nodeId, _breadcrumb]) => flow[nodeId].data?.fn === data.fn, + ([nodeId, _breadcrumb]) => + [flow[nodeId].data?.fn, flow[nodeId].data?.output].includes(data.fn), ); if (!visitedFns.length) return; From 74ab7240e2cd5e738ede6c154f32ff693df32717 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Mon, 4 Nov 2024 10:32:50 +0100 Subject: [PATCH 3/3] tidy imports & types --- editor.planx.uk/src/@planx/components/Checklist/Editor.tsx | 4 ++-- editor.planx.uk/src/@planx/components/Question/Editor.tsx | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx index 166d0fd765..8c52fd02fd 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx @@ -5,7 +5,7 @@ import FormControlLabel from "@mui/material/FormControlLabel"; import IconButton from "@mui/material/IconButton"; import Switch from "@mui/material/Switch"; import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; -import { useFormik } from "formik"; +import { FormikErrors, FormikValues, useFormik } from "formik"; import adjust from "ramda/src/adjust"; import compose from "ramda/src/compose"; import remove from "ramda/src/remove"; @@ -313,7 +313,7 @@ export const ChecklistComponent: React.FC = (props) => { } }, validate: ({ options, ...values }) => { - const errors: Record = {}; + const errors: FormikErrors = {}; if (values.fn && !options?.some((option) => option.data.val)) { errors.fn = "At least one option must set a data value when the checklist has a data field"; diff --git a/editor.planx.uk/src/@planx/components/Question/Editor.tsx b/editor.planx.uk/src/@planx/components/Question/Editor.tsx index 9c027936df..c3160c7238 100644 --- a/editor.planx.uk/src/@planx/components/Question/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Question/Editor.tsx @@ -1,8 +1,7 @@ -import { errors } from "@airbrake/browser/dist/http_req/api"; import FormControlLabel from "@mui/material/FormControlLabel"; import Switch from "@mui/material/Switch"; import { ComponentType as TYPES } from "@opensystemslab/planx-core/types"; -import { useFormik } from "formik"; +import { FormikErrors, FormikValues, useFormik } from "formik"; import React, { useEffect, useRef } from "react"; import { ComponentTagSelect } from "ui/editor/ComponentTagSelect"; import ImgInput from "ui/editor/ImgInput/ImgInput"; @@ -157,12 +156,11 @@ export const Question: React.FC = (props) => { } }, validate: ({ options, ...values }) => { - const errors: Record = {}; + const errors: FormikErrors = {}; if (values.fn && !options.some((option) => option.data.val)) { errors.fn = "At least one option must set a data value when the question has a data field"; } - return errors; }, });