Skip to content

Commit

Permalink
fix: ensure questions that set a data field with no option data value…
Browse files Browse the repository at this point in the history
…s are not automated (#3903)
  • Loading branch information
jessicamcinchak authored Nov 4, 2024
1 parent cc6fa05 commit bdf40be
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
13 changes: 11 additions & 2 deletions editor.planx.uk/src/@planx/components/Checklist/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -312,7 +312,14 @@ export const ChecklistComponent: React.FC<ChecklistProps> = (props) => {
alert(JSON.stringify({ type, ...values, options }, null, 2));
}
},
validate: () => {},
validate: ({ options, ...values }) => {
const errors: FormikErrors<FormikValues> = {};
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<HTMLInputElement | null>(null);
Expand Down Expand Up @@ -365,6 +372,8 @@ export const ChecklistComponent: React.FC<ChecklistProps> = (props) => {
value={formik.values.fn}
placeholder="Data Field"
onChange={formik.handleChange}
error={Boolean(formik.errors?.fn)}
errorMessage={formik.errors?.fn}
/>
</InputRow>
<InputRow>
Expand Down
20 changes: 16 additions & 4 deletions editor.planx.uk/src/@planx/components/Question/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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";
Expand Down Expand Up @@ -109,7 +109,11 @@ const OptionEditor: React.FC<{
</InputRow>
)}
<FlagsSelect
value={Array.isArray(props.value.data.flag) ? props.value.data.flag : [props.value.data.flag]}
value={
Array.isArray(props.value.data.flag)
? props.value.data.flag
: [props.value.data.flag]
}
onChange={(ev) => {
props.onChange({
...props.value,
Expand Down Expand Up @@ -151,7 +155,14 @@ export const Question: React.FC<Props> = (props) => {
alert(JSON.stringify({ type, ...values, children }, null, 2));
}
},
validate: () => { },
validate: ({ options, ...values }) => {
const errors: FormikErrors<FormikValues> = {};
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<HTMLInputElement | null>(null);
Expand Down Expand Up @@ -201,6 +212,8 @@ export const Question: React.FC<Props> = (props) => {
value={formik.values.fn}
placeholder="Data Field"
onChange={formik.handleChange}
error={Boolean(formik.errors?.fn)}
errorMessage={formik.errors?.fn}
/>
</InputRow>
<InputRow>
Expand All @@ -221,7 +234,6 @@ export const Question: React.FC<Props> = (props) => {
</InputRow>
</InputGroup>
</ModalSectionContent>

<ModalSectionContent subtitle="Options">
<ListManager
values={formik.values.options}
Expand Down
7 changes: 4 additions & 3 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,12 @@ 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) return;
if (!visitedFns.length) return;

// Get all options (aka edges or Answer nodes) for this node
const options: Array<Store.Node> = edges.map((edgeId) => ({
Expand Down

0 comments on commit bdf40be

Please sign in to comment.