From f446f0bc1eff9d989721165c10e51fa3ef90bcf6 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:49:37 +0000 Subject: [PATCH] refactor: create baseOptionsEditor and delete duplicates (#4041) --- .../components/Checklist/Editor/Options.tsx | 6 +- .../Checklist/Editor/OptionsEditor.tsx | 132 +++++------------- .../Checklist/Public/tests/Public.test.tsx | 16 +-- .../src/@planx/components/Checklist/types.ts | 9 -- .../src/@planx/components/Question/Editor.tsx | 99 +------------ .../components/Question/OptionsEditor.tsx | 23 +++ .../components/shared/BaseOptionsEditor.tsx | 109 +++++++++++++++ 7 files changed, 182 insertions(+), 212 deletions(-) create mode 100644 editor.planx.uk/src/@planx/components/Question/OptionsEditor.tsx create mode 100644 editor.planx.uk/src/@planx/components/shared/BaseOptionsEditor.tsx diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx index 0080d90a92..388c021dac 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx @@ -14,7 +14,7 @@ import InputRow from "ui/shared/InputRow"; import { Option } from "../../shared"; import type { Group } from "../model"; -import { OptionEditor } from "./OptionsEditor"; +import ChecklistOptionsEditor from "./OptionsEditor"; export const Options: React.FC<{ formik: FormikHookReturn }> = ({ formik }) => { return ( @@ -70,7 +70,7 @@ export const Options: React.FC<{ formik: FormikHookReturn }> = ({ formik }) => { }) as Option } newValueLabel="add new option" - Editor={OptionEditor} + Editor={ChecklistOptionsEditor} editorExtraProps={{ groupIndex, showValueField: !!formik.values.fn, @@ -142,7 +142,7 @@ export const Options: React.FC<{ formik: FormikHookReturn }> = ({ formik }) => { }, }) as Option } - Editor={OptionEditor} + Editor={ChecklistOptionsEditor} editorExtraProps={{ showValueField: !!formik.values.fn }} /> )} diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor/OptionsEditor.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor/OptionsEditor.tsx index 67bff66212..bb4dfb6e41 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/OptionsEditor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/OptionsEditor.tsx @@ -1,104 +1,46 @@ +import { + BaseOptionsEditor, + BaseOptionsEditorProps, +} from "@planx/components/shared/BaseOptionsEditor"; import React from "react"; -import ImgInput from "ui/editor/ImgInput/ImgInput"; import SimpleMenu from "ui/editor/SimpleMenu"; -import Input from "ui/shared/Input/Input"; -import InputRow from "ui/shared/InputRow"; -import InputRowItem from "ui/shared/InputRowItem"; -import { FlagsSelect } from "../../shared/FlagsSelect"; -import { OptionEditorProps } from "../types"; +export type ChecklistOptionsEditorProps = BaseOptionsEditorProps & { + index: number; + groupIndex?: number; + groups?: Array; + onMoveToGroup?: (itemIndex: number, groupIndex: number) => void; + showValueField?: boolean; +}; -export const OptionEditor: React.FC = (props) => { +const ChecklistOptionsEditor: React.FC = ({ + value, + onChange, + showValueField = false, + groups, + onMoveToGroup, + index, +}) => { return ( -
- - {props.value.id ? ( - - ) : null} - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - text: ev.target.value, - }, - }); - }} - placeholder="Option" - /> - - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - img, - }, - }); - }} + + {typeof index !== "undefined" && groups && onMoveToGroup && ( + ({ + label: `Move to ${group || `group ${groupIndex}`}`, + onClick: () => { + if (onMoveToGroup && typeof index === "number") + onMoveToGroup(index, groupIndex); + }, + disabled: groupIndex === groupIndex, + }))} /> - - {typeof props.index !== "undefined" && - props.groups && - props.onMoveToGroup && ( - ({ - label: `Move to ${group || `group ${groupIndex}`}`, - onClick: () => { - props.onMoveToGroup && - typeof props.index === "number" && - props.onMoveToGroup(props.index, groupIndex); - }, - disabled: groupIndex === props.groupIndex, - }))} - /> - )} - - - {props.showValueField && ( - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - val: ev.target.value, - }, - }); - }} - /> - )} - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - flag: ev, - }, - }); - }} - /> -
+ ); }; + +export default ChecklistOptionsEditor; diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx index f77d90ae1b..c7a6804537 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx @@ -22,7 +22,7 @@ describe("Checklist Component - Grouped Layout", () => { text="home type?" handleSubmit={handleSubmit} groupedOptions={groupedOptions} - />, + /> ); await user.click(screen.getByText("Section 1")); @@ -46,7 +46,7 @@ describe("Checklist Component - Grouped Layout", () => { handleSubmit={handleSubmit} previouslySubmittedData={{ answers: ["S1_Option1", "S3_Option1"] }} groupedOptions={groupedOptions} - />, + /> ); expect(screen.getByTestId("group-0-expanded")).toBeTruthy(); @@ -67,7 +67,7 @@ describe("Checklist Component - Grouped Layout", () => { description="" text="home type?" groupedOptions={groupedOptions} - />, + /> ); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -83,7 +83,7 @@ describe("Checklist Component - Grouped Layout", () => { text="home type?" handleSubmit={handleSubmit} groupedOptions={groupedOptions} - />, + /> ); const [section1Button, section2Button, section3Button] = screen.getAllByRole("button"); @@ -140,7 +140,7 @@ describe("Checklist Component - Basic & Images Layout", () => { text="home type?" handleSubmit={handleSubmit} options={options[type]} - />, + /> ); expect(screen.getByRole("heading")).toHaveTextContent("home type?"); @@ -177,7 +177,7 @@ describe("Checklist Component - Basic & Images Layout", () => { handleSubmit={handleSubmit} previouslySubmittedData={{ answers: ["flat_id", "house_id"] }} options={options[type]} - />, + /> ); await user.click(screen.getByTestId("continue-button")); @@ -194,7 +194,7 @@ describe("Checklist Component - Basic & Images Layout", () => { description="" text="home type?" options={options[type]} - />, + /> ); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -210,7 +210,7 @@ describe("Checklist Component - Basic & Images Layout", () => { text="home type?" handleSubmit={handleSubmit} options={options[type]} - />, + /> ); await user.tab(); diff --git a/editor.planx.uk/src/@planx/components/Checklist/types.ts b/editor.planx.uk/src/@planx/components/Checklist/types.ts index cdebd204ad..76ef9d47bd 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/types.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/types.ts @@ -17,14 +17,5 @@ export interface ChecklistProps extends Checklist { } & BaseNodeData; }; } -export interface OptionEditorProps { - index: number; - value: Option; - onChange: (newVal: Option) => void; - groupIndex?: number; - groups?: Array; - onMoveToGroup?: (itemIndex: number, groupIndex: number) => void; - showValueField?: boolean; -} export type Props = PublicProps; diff --git a/editor.planx.uk/src/@planx/components/Question/Editor.tsx b/editor.planx.uk/src/@planx/components/Question/Editor.tsx index e60f851311..bf61ce94ed 100644 --- a/editor.planx.uk/src/@planx/components/Question/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Question/Editor.tsx @@ -10,14 +10,13 @@ import ModalSectionContent from "ui/editor/ModalSectionContent"; import RichTextInput from "ui/editor/RichTextInput/RichTextInput"; import Input from "ui/shared/Input/Input"; import InputRow from "ui/shared/InputRow"; -import InputRowItem from "ui/shared/InputRowItem"; import { Switch } from "ui/shared/Switch"; import { InternalNotes } from "../../../ui/editor/InternalNotes"; import { MoreInformation } from "../../../ui/editor/MoreInformation/MoreInformation"; import { BaseNodeData, Option, parseBaseNodeData } from "../shared"; -import { FlagsSelect } from "../shared/FlagsSelect"; import { ICONS } from "../shared/icons"; +import QuestionOptionsEditor from "./OptionsEditor"; interface Props { node: { @@ -34,100 +33,6 @@ interface Props { handleSubmit?: Function; } -const OptionEditor: React.FC<{ - value: Option; - onChange: (newVal: Option) => void; - showValueField?: boolean; -}> = (props) => ( -
- - {props.value.id && ( - - )} - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - text: ev.target.value, - }, - }); - }} - placeholder="Option" - /> - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - img, - }, - }); - }} - /> - - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - description: ev.target.value, - }, - }); - }} - /> - - {props.showValueField && ( - - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - val: ev.target.value, - }, - }); - }} - /> - - )} - { - props.onChange({ - ...props.value, - data: { - ...props.value.data, - flag: ev, - }, - }); - }} - /> -
-); - export const Question: React.FC = (props) => { const type = TYPES.Question; @@ -246,7 +151,7 @@ export const Question: React.FC = (props) => { }, }) as Option } - Editor={OptionEditor} + Editor={QuestionOptionsEditor} editorExtraProps={{ showValueField: !!formik.values.fn }} /> diff --git a/editor.planx.uk/src/@planx/components/Question/OptionsEditor.tsx b/editor.planx.uk/src/@planx/components/Question/OptionsEditor.tsx new file mode 100644 index 0000000000..d9e0c4792b --- /dev/null +++ b/editor.planx.uk/src/@planx/components/Question/OptionsEditor.tsx @@ -0,0 +1,23 @@ +import React from "react"; + +import { + BaseOptionsEditor, + BaseOptionsEditorProps, +} from "../shared/BaseOptionsEditor"; + +const QuestionOptionsEditor: React.FC = ({ + value, + onChange, + showValueField = false, +}) => { + return ( + + ); +}; + +export default QuestionOptionsEditor; diff --git a/editor.planx.uk/src/@planx/components/shared/BaseOptionsEditor.tsx b/editor.planx.uk/src/@planx/components/shared/BaseOptionsEditor.tsx new file mode 100644 index 0000000000..702c843868 --- /dev/null +++ b/editor.planx.uk/src/@planx/components/shared/BaseOptionsEditor.tsx @@ -0,0 +1,109 @@ +import React, { ReactNode } from "react"; +import ImgInput from "ui/editor/ImgInput/ImgInput"; +import Input from "ui/shared/Input/Input"; +import InputRow from "ui/shared/InputRow"; +import InputRowItem from "ui/shared/InputRowItem"; + +import { Option } from "."; +import { FlagsSelect } from "./FlagsSelect"; + +export interface BaseOptionsEditorProps { + value: Option; + showValueField?: boolean; + showDescriptionField?: boolean; + onChange: (newVal: Option) => void; + children?: ReactNode; +} + +export const BaseOptionsEditor: React.FC = (props) => ( +
+ + {props.value.id && ( + + )} + + { + props.onChange({ + ...props.value, + data: { + ...props.value.data, + text: ev.target.value, + }, + }); + }} + placeholder="Option" + /> + + { + props.onChange({ + ...props.value, + data: { + ...props.value.data, + img, + }, + }); + }} + /> + {props.children} + + {props.showDescriptionField && ( + + + props.onChange({ + ...props.value, + data: { + ...props.value.data, + description: ev.target.value, + }, + }) + } + /> + + )} + {props.showValueField && ( + + { + props.onChange({ + ...props.value, + data: { + ...props.value.data, + val: ev.target.value, + }, + }); + }} + /> + + )} + { + props.onChange({ + ...props.value, + data: { + ...props.value.data, + flag: ev, + }, + }); + }} + /> +
+);