diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index 4170c74a61..fa3db980a1 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@airbrake/node": "^2.1.8", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7712ff7", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#5781880", "@types/isomorphic-fetch": "^0.0.36", "adm-zip": "^0.5.10", "aws-sdk": "^2.1467.0", diff --git a/api.planx.uk/pnpm-lock.yaml b/api.planx.uk/pnpm-lock.yaml index 0e86074f8c..56943aa62a 100644 --- a/api.planx.uk/pnpm-lock.yaml +++ b/api.planx.uk/pnpm-lock.yaml @@ -14,8 +14,8 @@ dependencies: specifier: ^2.1.8 version: 2.1.8 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#7712ff7 - version: github.com/theopensystemslab/planx-core/7712ff7 + specifier: git+https://github.com/theopensystemslab/planx-core#5781880 + version: github.com/theopensystemslab/planx-core/5781880 '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -6244,8 +6244,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/7712ff7: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7712ff7} + github.com/theopensystemslab/planx-core/5781880: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/5781880} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/e2e/tests/api-driven/package.json b/e2e/tests/api-driven/package.json index 6d82e8573c..86f5ef5c22 100644 --- a/e2e/tests/api-driven/package.json +++ b/e2e/tests/api-driven/package.json @@ -7,7 +7,7 @@ "packageManager": "pnpm@8.6.6", "dependencies": { "@cucumber/cucumber": "^9.3.0", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7712ff7", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#5781880", "axios": "^1.7.4", "dotenv": "^16.3.1", "dotenv-expand": "^10.0.0", diff --git a/e2e/tests/api-driven/pnpm-lock.yaml b/e2e/tests/api-driven/pnpm-lock.yaml index 1c973deb2d..d5ca2161e4 100644 --- a/e2e/tests/api-driven/pnpm-lock.yaml +++ b/e2e/tests/api-driven/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#7712ff7 - version: github.com/theopensystemslab/planx-core/7712ff7 + specifier: git+https://github.com/theopensystemslab/planx-core#5781880 + version: github.com/theopensystemslab/planx-core/5781880 axios: specifier: ^1.7.4 version: 1.7.4 @@ -2932,8 +2932,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/7712ff7: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7712ff7} + github.com/theopensystemslab/planx-core/5781880: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/5781880} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/e2e/tests/ui-driven/package.json b/e2e/tests/ui-driven/package.json index 5d1669c5de..6dd1a3d6e9 100644 --- a/e2e/tests/ui-driven/package.json +++ b/e2e/tests/ui-driven/package.json @@ -8,7 +8,7 @@ "postinstall": "./install-dependencies.sh" }, "dependencies": { - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7712ff7", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#5781880", "axios": "^1.7.4", "dotenv": "^16.3.1", "eslint": "^8.56.0", diff --git a/e2e/tests/ui-driven/pnpm-lock.yaml b/e2e/tests/ui-driven/pnpm-lock.yaml index 01c29f0a60..5f3e56a391 100644 --- a/e2e/tests/ui-driven/pnpm-lock.yaml +++ b/e2e/tests/ui-driven/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#7712ff7 - version: github.com/theopensystemslab/planx-core/7712ff7 + specifier: git+https://github.com/theopensystemslab/planx-core#5781880 + version: github.com/theopensystemslab/planx-core/5781880 axios: specifier: ^1.7.4 version: 1.7.4 @@ -2686,8 +2686,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/7712ff7: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7712ff7} + github.com/theopensystemslab/planx-core/5781880: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/5781880} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/docs/adding-a-new-component.md b/editor.planx.uk/docs/adding-a-new-component.md index 173f2731d2..3ec886133e 100644 --- a/editor.planx.uk/docs/adding-a-new-component.md +++ b/editor.planx.uk/docs/adding-a-new-component.md @@ -17,9 +17,9 @@ SetValue = 380, 3. `model.ts` ```typescript -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface SetValue extends MoreInformation { +export interface SetValue extends BaseNodeData { fn: string; } @@ -27,7 +27,7 @@ export const parseContent = ( data: Record | undefined, ): SetValue => ({ fn: data?.fn || "", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); ``` diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index fc5ebaf274..8e5efc1c1c 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -15,7 +15,7 @@ "@mui/material": "^5.15.10", "@mui/utils": "^5.15.11", "@opensystemslab/map": "1.0.0-alpha.3", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7712ff7", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#5781880", "@tiptap/core": "^2.4.0", "@tiptap/extension-bold": "^2.0.3", "@tiptap/extension-bubble-menu": "^2.1.13", diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index 65a5392a54..acbdfdfc0c 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -47,8 +47,8 @@ dependencies: specifier: 1.0.0-alpha.3 version: 1.0.0-alpha.3 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#7712ff7 - version: github.com/theopensystemslab/planx-core/7712ff7(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#5781880 + version: github.com/theopensystemslab/planx-core/5781880(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -15352,9 +15352,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/7712ff7(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7712ff7} - id: github.com/theopensystemslab/planx-core/7712ff7 + github.com/theopensystemslab/planx-core/5781880(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/5781880} + id: github.com/theopensystemslab/planx-core/5781880 name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/src/@planx/components/AddressInput/model.ts b/editor.planx.uk/src/@planx/components/AddressInput/model.ts index 51b51bb51c..c04c6350bb 100644 --- a/editor.planx.uk/src/@planx/components/AddressInput/model.ts +++ b/editor.planx.uk/src/@planx/components/AddressInput/model.ts @@ -1,7 +1,7 @@ import type { SchemaOf } from "yup"; import { object, string } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export type Address = { line1: string; @@ -21,7 +21,7 @@ export const userDataSchema: SchemaOf
= object({ country: string(), }); -export interface AddressInput extends MoreInformation { +export interface AddressInput extends BaseNodeData { title: string; description?: string; fn?: string; @@ -33,5 +33,5 @@ export const parseAddressInput = ( title: data?.title || "", description: data?.description, fn: data?.fn || "", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/Calculate/model.ts b/editor.planx.uk/src/@planx/components/Calculate/model.ts index 4dacba6216..4278f75cab 100644 --- a/editor.planx.uk/src/@planx/components/Calculate/model.ts +++ b/editor.planx.uk/src/@planx/components/Calculate/model.ts @@ -1,8 +1,8 @@ import * as math from "mathjs"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface Calculate extends MoreInformation { +export interface Calculate extends BaseNodeData { title?: string; output: string; defaults: Record; @@ -19,7 +19,7 @@ export interface Input { export const parseCalculate = ( data: Record | undefined, ): Calculate => ({ - ...parseMoreInformation(data), + ...parseBaseNodeData(data), output: data?.output || "", defaults: data?.defaults || {}, formula: data?.formula || "", diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx index 1f075141e6..29bfe2b3ff 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor.tsx @@ -22,7 +22,7 @@ import Input from "ui/shared/Input"; import InputRow from "ui/shared/InputRow"; import InputRowItem from "ui/shared/InputRowItem"; -import { Option, parseMoreInformation } from "../shared"; +import { BaseNodeData, Option, parseBaseNodeData } from "../shared"; import PermissionSelect from "../shared/PermissionSelect"; import { ICONS, InternalNotes, MoreInformation } from "../ui"; import type { Category, Checklist, Group } from "./model"; @@ -35,16 +35,11 @@ export interface ChecklistProps extends Checklist { data?: { allRequired?: boolean; categories?: Array; - definitionImg?: string; description?: string; fn?: string; - howMeasured?: string; img?: string; - info?: string; - notes?: string; - policyRef?: string; text: string; - }; + } & BaseNodeData; }; } @@ -295,7 +290,7 @@ export const ChecklistComponent: React.FC = (props) => { img: props.node?.data?.img || "", options: props.options, text: props.node?.data?.text || "", - ...parseMoreInformation(props.node?.data), + ...parseBaseNodeData(props.node?.data), }, onSubmit: ({ options, groupedOptions, ...values }) => { const sourceOptions = options?.length diff --git a/editor.planx.uk/src/@planx/components/Checklist/model.ts b/editor.planx.uk/src/@planx/components/Checklist/model.ts index 623cd57172..1275873d0a 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/model.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/model.ts @@ -1,6 +1,6 @@ import { array } from "yup"; -import { MoreInformation, Option } from "../shared"; +import { BaseNodeData, Option } from "../shared"; import { ChecklistLayout } from "./Public"; export interface Group { @@ -13,7 +13,7 @@ export interface Category { count: number; } -export interface Checklist extends MoreInformation { +export interface Checklist extends BaseNodeData { fn?: string; description?: string; text?: string; diff --git a/editor.planx.uk/src/@planx/components/Confirmation/model.ts b/editor.planx.uk/src/@planx/components/Confirmation/model.ts index 3622f1f23b..c5ebca945d 100644 --- a/editor.planx.uk/src/@planx/components/Confirmation/model.ts +++ b/editor.planx.uk/src/@planx/components/Confirmation/model.ts @@ -1,9 +1,11 @@ +import { BaseNodeData } from "../shared"; + export interface Step { title: string; description: string; } -export interface Confirmation { +export interface Confirmation extends BaseNodeData { heading?: string; description?: string; color?: { text: string; background: string }; diff --git a/editor.planx.uk/src/@planx/components/ContactInput/model.ts b/editor.planx.uk/src/@planx/components/ContactInput/model.ts index 73701a44ea..6d3d0191cb 100644 --- a/editor.planx.uk/src/@planx/components/ContactInput/model.ts +++ b/editor.planx.uk/src/@planx/components/ContactInput/model.ts @@ -1,7 +1,7 @@ import type { SchemaOf } from "yup"; import { object, string } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export type Contact = { title?: string; @@ -41,7 +41,7 @@ export const userDataSchema: SchemaOf = object({ }, }); -export interface ContactInput extends MoreInformation { +export interface ContactInput extends BaseNodeData { title: string; description?: string; fn?: string; @@ -53,5 +53,5 @@ export const parseContactInput = ( title: data?.title || "", description: data?.description, fn: data?.fn || "", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/Content/model.ts b/editor.planx.uk/src/@planx/components/Content/model.ts index 0c447bcff6..be1ad1c9ea 100644 --- a/editor.planx.uk/src/@planx/components/Content/model.ts +++ b/editor.planx.uk/src/@planx/components/Content/model.ts @@ -1,6 +1,6 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface Content extends MoreInformation { +export interface Content extends BaseNodeData { content: string; color?: string; } @@ -10,5 +10,5 @@ export const parseContent = ( ): Content => ({ content: data?.content || "", color: data?.color, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/DateInput/model.ts b/editor.planx.uk/src/@planx/components/DateInput/model.ts index d8075f6ba3..7f05c712ea 100644 --- a/editor.planx.uk/src/@planx/components/DateInput/model.ts +++ b/editor.planx.uk/src/@planx/components/DateInput/model.ts @@ -1,12 +1,12 @@ import { isValid, parseISO } from "date-fns"; import { object, SchemaOf, string } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; // Expected format: YYYY-MM-DD export type UserData = string; -export interface DateInput extends MoreInformation { +export interface DateInput extends BaseNodeData { title: string; description?: string; fn?: string; @@ -129,7 +129,7 @@ export const parseDateInput = ( fn: data?.fn, min: data?.min, max: data?.max, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); export const editorValidationSchema = () => diff --git a/editor.planx.uk/src/@planx/components/DrawBoundary/model.ts b/editor.planx.uk/src/@planx/components/DrawBoundary/model.ts index 34d10d398b..14e7098779 100644 --- a/editor.planx.uk/src/@planx/components/DrawBoundary/model.ts +++ b/editor.planx.uk/src/@planx/components/DrawBoundary/model.ts @@ -1,4 +1,4 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export enum DrawBoundaryUserAction { Accept = "Accepted the title boundary", @@ -7,7 +7,7 @@ export enum DrawBoundaryUserAction { Upload = "Uploaded a location plan", } -export interface DrawBoundary extends MoreInformation { +export interface DrawBoundary extends BaseNodeData { title: string; description: string; titleForUploading: string; @@ -15,16 +15,12 @@ export interface DrawBoundary extends MoreInformation { hideFileUpload?: boolean; dataFieldBoundary: string; dataFieldArea: string; - info?: string; - policyRef?: string; - howMeasured?: string; - definitionImg?: string; } export const parseDrawBoundary = ( data: Record | undefined, ): DrawBoundary => ({ - ...parseMoreInformation(data), + ...parseBaseNodeData(data), title: data?.title || defaultContent?.["title"], description: data?.description || defaultContent?.["description"], titleForUploading: diff --git a/editor.planx.uk/src/@planx/components/FileUpload/model.tsx b/editor.planx.uk/src/@planx/components/FileUpload/model.tsx index 09f5df769f..50ddeec6c7 100644 --- a/editor.planx.uk/src/@planx/components/FileUpload/model.tsx +++ b/editor.planx.uk/src/@planx/components/FileUpload/model.tsx @@ -1,10 +1,10 @@ -import { MoreInformation } from "@planx/components/shared"; +import { BaseNodeData } from "@planx/components/shared"; import { Store } from "pages/FlowEditor/lib/store"; import type { HandleSubmit } from "pages/Preview/Node"; import { FileWithPath } from "react-dropzone"; import { array } from "yup"; -export interface FileUpload extends MoreInformation { +export interface FileUpload extends BaseNodeData { id?: string; title?: string; fn: string; diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/Modal.tsx b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/Modal.tsx index 1b91833b3e..f9a4fdb0a3 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/Modal.tsx +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/Modal.tsx @@ -12,7 +12,7 @@ import { FileUploadSlot } from "../FileUpload/model"; import { UploadedFileCard } from "../shared/PrivateFileUpload/UploadedFileCard"; import { FileList } from "./model"; import { fileLabelSchema, formatFileLabelSchemaErrors } from "./schema"; -import { SelectMultiple } from "./SelectMultiple"; +import { SelectMultipleFileTypes } from "./SelectMultipleFileTypes"; interface FileTaggingModalProps { uploadedFiles: FileUploadSlot[]; @@ -83,7 +83,7 @@ export const FileTaggingModal = ({ key={slot.id} removeFile={() => removeFile(slot)} /> - , -)(({ theme }) => ({ - marginTop: theme.spacing(2), - // Prevent label from overlapping expand icon - "& > div > label": { - paddingRight: theme.spacing(3), - }, - // Vertically center "large" size caret icon - [`& .${autocompleteClasses.endAdornment}`]: { - top: "unset", - }, - "&:focus-within": { - "& svg": { - color: "black", - }, - }, -})); - -const StyledTextField = styled(TextField)(({ theme }) => ({ - "&:focus-within": { - ...borderedFocusStyle, - [`& .${outlinedInputClasses.notchedOutline}`]: { - border: "1px solid transparent !important", - }, - }, - [`& .${outlinedInputClasses.notchedOutline}`]: { - borderRadius: 0, - border: `1px solid${theme.palette.border.main} !important`, - }, - "& fieldset": { - borderColor: theme.palette.border.main, - }, - backgroundColor: theme.palette.background.paper, - [`& .${outlinedInputClasses.root}, input`]: { - cursor: "pointer", - }, - [`& .${inputLabelClasses.root}`]: { - textDecoration: "underline", - color: theme.palette.primary.main, - "&[data-shrink=true]": { - textDecoration: "none", - color: theme.palette.text.primary, - paddingY: 0, - transform: "translate(0px, -22px) scale(0.85)", - }, - }, -})); - -const CustomCheckbox = styled("span")(({ theme }) => ({ - display: "inline-flex", - flexShrink: 0, - position: "relative", - width: 40, - height: 40, - borderColor: theme.palette.text.primary, - border: "2px solid", - background: "transparent", - marginRight: theme.spacing(1.5), - "&.selected::after": { - content: "''", - position: "absolute", - height: 24, - width: 12, - borderColor: theme.palette.text.primary, - borderBottom: "5px solid", - borderRight: "5px solid", - left: "50%", - top: "42%", - transform: "translate(-50%, -50%) rotate(45deg)", - cursor: "pointer", - }, -})); - -/** - * Function which returns the Input component used by Autocomplete - */ -const renderInput: AutocompleteProps< - Option, - true, - true, - false, - "div" ->["renderInput"] = (params) => ( - -); - /** * Function which returns the groups (ul elements) used by Autocomplete */ @@ -180,8 +79,6 @@ const renderOption: AutocompleteProps< ); -const PopupIcon = ; - /** * Custom Listbox component * Used to wrap options within the autocomplete and append a custom element above the option list @@ -199,7 +96,7 @@ const ListboxComponent = forwardRef( ), ); -export const SelectMultiple = (props: SelectMultipleProps) => { +export const SelectMultipleFileTypes = (props: SelectMultipleProps) => { const { uploadedFile, fileList, setFileList } = props; const initialTags = getTagsForSlot(uploadedFile.id, fileList); @@ -224,7 +121,7 @@ export const SelectMultiple = (props: SelectMultipleProps) => { const value: Option[] = useMemo( () => initialTags.flatMap((tag) => options.filter(({ name }) => name === tag)), - [initialTags], + [initialTags, options], ); /** @@ -266,46 +163,19 @@ export const SelectMultiple = (props: SelectMultipleProps) => { }; return ( - + getOptionLabel={(option) => option.name} + groupBy={(option) => option.category} + id={`select-multiple-file-tags-${uploadedFile.id}`} + isOptionEqualToValue={(option, value) => option.name === value.name} key={`form-${uploadedFile.id}`} - sx={{ display: "flex", flexDirection: "column" }} - > - option.name} - groupBy={(option) => option.category} - id={`select-multiple-file-tags-${uploadedFile.id}`} - isOptionEqualToValue={(option, value) => option.name === value.name} - ListboxComponent={ListboxComponent} - multiple - onChange={handleChange} - options={options} - popupIcon={PopupIcon} - renderGroup={renderGroup} - renderInput={renderInput} - renderOption={renderOption} - value={value} - ChipProps={{ - variant: "uploadedFileTag", - size: "small", - sx: { pointerEvents: "none" }, - onDelete: undefined, - }} - componentsProps={{ - popupIndicator: { - disableRipple: true, - }, - popper: { - sx: { - boxShadow: 10, - }, - }, - }} - /> - + label="What does this file show? (select all that apply)" + ListboxComponent={ListboxComponent} + onChange={handleChange} + options={options} + renderGroup={renderGroup} + renderOption={renderOption} + value={value} + /> ); }; diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts index a5bd2b14b4..706619b3fe 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/model.ts @@ -5,7 +5,7 @@ import { Store, useStore } from "pages/FlowEditor/lib/store"; import { FileWithPath } from "react-dropzone"; import { FileUploadSlot } from "../FileUpload/model"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, MoreInformation, parseBaseNodeData } from "../shared"; export const PASSPORT_REQUESTED_FILES_KEY = "_requestedFiles" as const; @@ -67,7 +67,7 @@ export interface FileType { moreInformation?: MoreInformation; } -export interface FileUploadAndLabel extends MoreInformation { +export interface FileUploadAndLabel extends BaseNodeData { title: string; description?: string; fn?: string; @@ -83,7 +83,7 @@ export const parseContent = ( fn: data?.fn || "", fileTypes: cloneDeep(data?.fileTypes) || [newFileType()], hideDropZone: data?.hideDropZone || false, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); const DEFAULT_TITLE = "Upload and label"; diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts index 05c14af45d..ad940f461e 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts @@ -1,3 +1,4 @@ +import { NODE_TAGS } from "@opensystemslab/planx-core/types"; import { array, boolean, @@ -10,7 +11,7 @@ import { } from "yup"; import { FileUploadSlot } from "../FileUpload/model"; -import { MoreInformation } from "../shared"; +import { BaseNodeData, MoreInformation } from "../shared"; import { checkIfConditionalRule, Condition, @@ -31,6 +32,10 @@ const moreInformationSchema: SchemaOf = object({ definitionImg: string(), }); +const baseNodeDataSchema: SchemaOf = object({ + tags: array(mixed().oneOf(NODE_TAGS)), +}).concat(moreInformationSchema); + const valFnSchema = mixed().when("condition", { is: checkIfConditionalRule, then: (schema) => schema.required(), @@ -63,7 +68,7 @@ export const fileUploadAndLabelSchema: SchemaOf = object({ fn: string(), fileTypes: array().of(fileTypeSchema).required().min(1), hideDropZone: boolean(), -}).concat(moreInformationSchema); +}).concat(baseNodeDataSchema); interface SlotsSchemaTestContext extends TestContext { fileList: FileList; diff --git a/editor.planx.uk/src/@planx/components/FindProperty/model.ts b/editor.planx.uk/src/@planx/components/FindProperty/model.ts index e455051575..0d3dbc982c 100644 --- a/editor.planx.uk/src/@planx/components/FindProperty/model.ts +++ b/editor.planx.uk/src/@planx/components/FindProperty/model.ts @@ -1,4 +1,4 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export enum FindPropertyUserAction { Existing = "Selected an existing address", @@ -7,7 +7,7 @@ export enum FindPropertyUserAction { export const PASSPORT_COMPONENT_ACTION_KEY = "findProperty.action"; -export interface FindProperty extends MoreInformation { +export interface FindProperty extends BaseNodeData { title: string; description: string; allowNewAddresses?: boolean; @@ -27,7 +27,7 @@ export const parseFindProperty = ( data?.newAddressDescription || DEFAULT_NEW_ADDRESS_DESCRIPTION, newAddressDescriptionLabel: data?.newAddressDescriptionLabel || DEFAULT_NEW_ADDRESS_LABEL, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); // Addresses can come from two sources: diff --git a/editor.planx.uk/src/@planx/components/List/model.ts b/editor.planx.uk/src/@planx/components/List/model.ts index 49be4253fe..610f92ecf2 100644 --- a/editor.planx.uk/src/@planx/components/List/model.ts +++ b/editor.planx.uk/src/@planx/components/List/model.ts @@ -1,11 +1,11 @@ import { cloneDeep } from "lodash"; import { number, object } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; import { Schema } from "../shared/Schema/model"; import { SCHEMAS } from "./Editor"; -export interface List extends MoreInformation { +export interface List extends BaseNodeData { fn: string; title: string; description?: string; @@ -19,11 +19,16 @@ export const parseContent = (data: Record | undefined): List => ({ description: data?.description, schemaName: data?.schemaName || SCHEMAS[0].name, schema: cloneDeep(data?.schema) || SCHEMAS[0].schema, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); export const validationSchema = object({ schema: object({ - max: number().optional().min(2, "The maximum must be greater than 1 - a Page component should be used when max is equal to 1"), + max: number() + .optional() + .min( + 2, + "The maximum must be greater than 1 - a Page component should be used when max is equal to 1", + ), }), -}); \ No newline at end of file +}); diff --git a/editor.planx.uk/src/@planx/components/MapAndLabel/model.ts b/editor.planx.uk/src/@planx/components/MapAndLabel/model.ts index 3f2877f91c..00d2bc605b 100644 --- a/editor.planx.uk/src/@planx/components/MapAndLabel/model.ts +++ b/editor.planx.uk/src/@planx/components/MapAndLabel/model.ts @@ -1,10 +1,10 @@ import cloneDeep from "lodash/cloneDeep"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; import { Schema } from "../shared/Schema/model"; import { SCHEMAS } from "./Editor"; -export interface MapAndLabel extends MoreInformation { +export interface MapAndLabel extends BaseNodeData { fn: string; title: string; description?: string; @@ -26,5 +26,5 @@ export const parseContent = ( drawType: data?.drawType || "Polygon", schemaName: data?.schemaName || SCHEMAS[0].name, schema: cloneDeep(data?.schema) || SCHEMAS[0].schema, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/NextSteps/model.ts b/editor.planx.uk/src/@planx/components/NextSteps/model.ts index 7693b4f4e1..9b8720e52d 100644 --- a/editor.planx.uk/src/@planx/components/NextSteps/model.ts +++ b/editor.planx.uk/src/@planx/components/NextSteps/model.ts @@ -1,6 +1,6 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface NextSteps extends MoreInformation { +export interface NextSteps extends BaseNodeData { title: string; description: string; steps: Array; @@ -18,7 +18,7 @@ export const parseNextSteps = ( steps: data?.steps || [], title: data?.title || DEFAULT_TITLE, description: data?.description || "", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); const DEFAULT_TITLE = "What would you like to do next?"; diff --git a/editor.planx.uk/src/@planx/components/Notice/model.ts b/editor.planx.uk/src/@planx/components/Notice/model.ts index f76bc32d7b..a0ee5475de 100644 --- a/editor.planx.uk/src/@planx/components/Notice/model.ts +++ b/editor.planx.uk/src/@planx/components/Notice/model.ts @@ -1,10 +1,9 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface Notice extends MoreInformation { +export interface Notice extends BaseNodeData { title: string; description: string; color: string; - notes?: string; resetButton?: boolean; } @@ -13,5 +12,5 @@ export const parseNotice = (data: Record | undefined) => ({ description: data?.description || "", color: data?.color || "#EFEFEF", resetButton: data?.resetButton || false, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/NumberInput/model.ts b/editor.planx.uk/src/@planx/components/NumberInput/model.ts index c0e78b9614..0c98f276d8 100644 --- a/editor.planx.uk/src/@planx/components/NumberInput/model.ts +++ b/editor.planx.uk/src/@planx/components/NumberInput/model.ts @@ -1,8 +1,8 @@ import { object, string } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface NumberInput extends MoreInformation { +export interface NumberInput extends BaseNodeData { title: string; description?: string; fn?: string; @@ -28,7 +28,7 @@ export const parseNumberInput = ( fn: data?.fn || "", units: data?.units, allowNegatives: data?.allowNegatives || false, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); export const numberInputValidationSchema = (input: NumberInput) => diff --git a/editor.planx.uk/src/@planx/components/Page/model.ts b/editor.planx.uk/src/@planx/components/Page/model.ts index 6f43aa971d..79cfe86878 100644 --- a/editor.planx.uk/src/@planx/components/Page/model.ts +++ b/editor.planx.uk/src/@planx/components/Page/model.ts @@ -1,6 +1,6 @@ import { cloneDeep } from "lodash"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; import { Schema } from "../shared/Schema/model"; import { PAGE_SCHEMAS } from "./Editor"; @@ -9,7 +9,7 @@ export interface PageSchema extends Schema { max: 1; } -export interface Page extends MoreInformation { +export interface Page extends BaseNodeData { fn: string; title: string; description?: string; @@ -23,5 +23,5 @@ export const parsePage = (data: Record | undefined): Page => ({ description: data?.description, schemaName: data?.schemaName || PAGE_SCHEMAS[0].name, schema: cloneDeep(data?.schema) || PAGE_SCHEMAS[0].schema, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/Pay/Editor.tsx b/editor.planx.uk/src/@planx/components/Pay/Editor.tsx index f85e8e96dc..417ef34b18 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Pay/Editor.tsx @@ -13,7 +13,7 @@ import { REQUIRED_GOVPAY_METADATA, validationSchema, } from "@planx/components/Pay/model"; -import { parseMoreInformation } from "@planx/components/shared"; +import { parseBaseNodeData } from "@planx/components/shared"; import { EditorProps, ICONS, @@ -180,7 +180,7 @@ const Component: React.FC = (props: Props) => { value: "@paidViaInviteToPay", }, ], - ...parseMoreInformation(props.node?.data), + ...parseBaseNodeData(props.node?.data), }; const onSubmit = (newValues: Pay) => { diff --git a/editor.planx.uk/src/@planx/components/Pay/model.ts b/editor.planx.uk/src/@planx/components/Pay/model.ts index ad8db9bb74..bc63edf279 100644 --- a/editor.planx.uk/src/@planx/components/Pay/model.ts +++ b/editor.planx.uk/src/@planx/components/Pay/model.ts @@ -8,9 +8,9 @@ import { useStore } from "pages/FlowEditor/lib/store"; import { ApplicationPath, Passport } from "types"; import { array, boolean, object, string } from "yup"; -import type { MoreInformation } from "../shared"; +import type { BaseNodeData } from "../shared"; -export interface Pay extends MoreInformation { +export interface Pay extends BaseNodeData { title: string; bannerTitle?: string; description?: string; diff --git a/editor.planx.uk/src/@planx/components/PlanningConstraints/model.ts b/editor.planx.uk/src/@planx/components/PlanningConstraints/model.ts index 92e236d0f7..820491ea7c 100644 --- a/editor.planx.uk/src/@planx/components/PlanningConstraints/model.ts +++ b/editor.planx.uk/src/@planx/components/PlanningConstraints/model.ts @@ -1,6 +1,6 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface PlanningConstraints extends MoreInformation { +export interface PlanningConstraints extends BaseNodeData { title: string; description: string; fn: string; @@ -16,7 +16,7 @@ export const parseContent = ( "Planning constraints might limit how you can develop or use the property", fn: data?.fn || DEFAULT_FN, disclaimer: data?.disclaimer || DEFAULT_PLANNING_CONDITIONS_DISCLAIMER, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); export type IntersectingConstraints = Record; diff --git a/editor.planx.uk/src/@planx/components/PropertyInformation/model.ts b/editor.planx.uk/src/@planx/components/PropertyInformation/model.ts index 29e2ee5634..1d4fc94794 100644 --- a/editor.planx.uk/src/@planx/components/PropertyInformation/model.ts +++ b/editor.planx.uk/src/@planx/components/PropertyInformation/model.ts @@ -1,6 +1,6 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface PropertyInformation extends MoreInformation { +export interface PropertyInformation extends BaseNodeData { title: string; description: string; showPropertyTypeOverride?: boolean; @@ -14,5 +14,5 @@ export const parseContent = ( data?.description || "This is the information we currently have about the property, including its title boundary shown in blue from the Land Registry", showPropertyTypeOverride: data?.showPropertyTypeOverride || false, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/Question/Editor.tsx b/editor.planx.uk/src/@planx/components/Question/Editor.tsx index 9b5da4ad30..b108ef2a51 100644 --- a/editor.planx.uk/src/@planx/components/Question/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Question/Editor.tsx @@ -11,24 +11,19 @@ import Input from "ui/shared/Input"; import InputRow from "ui/shared/InputRow"; import InputRowItem from "ui/shared/InputRowItem"; -import { Option, parseMoreInformation } from "../shared"; +import { BaseNodeData, Option, parseBaseNodeData } from "../shared"; import PermissionSelect from "../shared/PermissionSelect"; import { ICONS, InternalNotes, MoreInformation } from "../ui"; interface Props { node: { data?: { - definitionImg?: string; description?: string; fn?: string; - howMeasured?: string; img?: string; - info?: string; - notes?: string; - policyRef?: string; text: string; type?: string; - }; + } & BaseNodeData; }; options?: Option[]; handleSubmit?: Function; @@ -135,7 +130,7 @@ export const Question: React.FC = (props) => { img: props.node?.data?.img || "", options: props.options || [], text: props.node?.data?.text || "", - ...parseMoreInformation(props.node?.data), + ...parseBaseNodeData(props.node?.data), }, onSubmit: ({ options, ...values }) => { const children = options diff --git a/editor.planx.uk/src/@planx/components/Question/model.ts b/editor.planx.uk/src/@planx/components/Question/model.ts index 52c70525a3..908b5bc2bb 100644 --- a/editor.planx.uk/src/@planx/components/Question/model.ts +++ b/editor.planx.uk/src/@planx/components/Question/model.ts @@ -1,14 +1,12 @@ import { Store } from "pages/FlowEditor/lib/store"; import { HandleSubmit } from "pages/Preview/Node"; -export interface Question { +import { BaseNodeData } from "../shared"; + +export interface Question extends BaseNodeData { id?: string; text?: string; description?: string; - info?: string; - policyRef?: string; - howMeasured?: string; - definitionImg?: string; img?: string; responses: { id?: string; diff --git a/editor.planx.uk/src/@planx/components/Result/model.ts b/editor.planx.uk/src/@planx/components/Result/model.ts index 94b37e16ce..01a2708696 100644 --- a/editor.planx.uk/src/@planx/components/Result/model.ts +++ b/editor.planx.uk/src/@planx/components/Result/model.ts @@ -4,12 +4,14 @@ import { Response } from "pages/FlowEditor/lib/store/preview"; import type { HandleSubmit } from "pages/Preview/Node"; import type { TextContent } from "types"; +import { BaseNodeData } from "../shared"; + export interface FlagDisplayText { heading?: string; description?: string; } -export interface Result { +export interface Result extends BaseNodeData { flagSet: FlagSet; overrides?: { [flagId: string]: FlagDisplayText }; } diff --git a/editor.planx.uk/src/@planx/components/Review/model.ts b/editor.planx.uk/src/@planx/components/Review/model.ts index 7dece94873..842da0ad45 100644 --- a/editor.planx.uk/src/@planx/components/Review/model.ts +++ b/editor.planx.uk/src/@planx/components/Review/model.ts @@ -1,7 +1,8 @@ -export interface Review { +import { BaseNodeData } from "../shared"; + +export interface Review extends BaseNodeData { title: string; description: string; - notes: string; } export const parseContent = ( diff --git a/editor.planx.uk/src/@planx/components/Section/model.ts b/editor.planx.uk/src/@planx/components/Section/model.ts index bedfeb8711..2b59273cdf 100644 --- a/editor.planx.uk/src/@planx/components/Section/model.ts +++ b/editor.planx.uk/src/@planx/components/Section/model.ts @@ -1,9 +1,9 @@ import type { Store } from "pages/FlowEditor/lib/store"; import { SectionNode, SectionStatus } from "types"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface Section extends MoreInformation { +export interface Section extends BaseNodeData { title: string; description?: string; } @@ -13,7 +13,7 @@ export const parseSection = ( ): Section => ({ title: data?.title || "", description: data?.description, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); export function computeSectionStatuses({ diff --git a/editor.planx.uk/src/@planx/components/Send/model.ts b/editor.planx.uk/src/@planx/components/Send/model.ts index 61153fbb93..31929e0808 100644 --- a/editor.planx.uk/src/@planx/components/Send/model.ts +++ b/editor.planx.uk/src/@planx/components/Send/model.ts @@ -1,5 +1,5 @@ import type { Store } from "../../../pages/FlowEditor/lib/store"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export enum Destination { BOPS = "bops", @@ -16,7 +16,7 @@ interface EventPayload { }; } -export interface Send extends MoreInformation { +export interface Send extends BaseNodeData { title: string; destinations: Destination[]; } @@ -25,7 +25,7 @@ export const DEFAULT_TITLE = "Send"; export const DEFAULT_DESTINATION = Destination.Email; export const parseContent = (data: Record | undefined): Send => ({ - ...parseMoreInformation(data), + ...parseBaseNodeData(data), title: data?.title || DEFAULT_TITLE, destinations: data?.destinations || [DEFAULT_DESTINATION], }); diff --git a/editor.planx.uk/src/@planx/components/SetValue/model.ts b/editor.planx.uk/src/@planx/components/SetValue/model.ts index 70b7575e1d..ee6850889c 100644 --- a/editor.planx.uk/src/@planx/components/SetValue/model.ts +++ b/editor.planx.uk/src/@planx/components/SetValue/model.ts @@ -1,6 +1,6 @@ -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; -export interface BaseSetValue extends MoreInformation { +export interface BaseSetValue extends BaseNodeData { fn: string; } @@ -22,5 +22,5 @@ export const parseSetValue = ( fn: data?.fn || "", val: data?.val || "", operation: data?.operation || "replace", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/TaskList/model.ts b/editor.planx.uk/src/@planx/components/TaskList/model.ts index be5e80c910..9e7752b4b8 100644 --- a/editor.planx.uk/src/@planx/components/TaskList/model.ts +++ b/editor.planx.uk/src/@planx/components/TaskList/model.ts @@ -1,7 +1,7 @@ -import type { MoreInformation } from "../shared"; -import { parseMoreInformation } from "../shared"; +import type { BaseNodeData } from "../shared"; +import { parseBaseNodeData } from "../shared"; -export interface TaskList extends MoreInformation { +export interface TaskList extends BaseNodeData { title: string; description?: string; tasks: Array; @@ -24,5 +24,5 @@ export const parseTaskList = ( tasks: data?.taskList?.tasks || data?.tasks || [], title: data?.title || "", description: data?.description || "", - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/TextInput/model.ts b/editor.planx.uk/src/@planx/components/TextInput/model.ts index f378c22fd6..3a96c2f2e0 100644 --- a/editor.planx.uk/src/@planx/components/TextInput/model.ts +++ b/editor.planx.uk/src/@planx/components/TextInput/model.ts @@ -1,6 +1,6 @@ import { SchemaOf, string } from "yup"; -import { MoreInformation, parseMoreInformation } from "../shared"; +import { BaseNodeData, parseBaseNodeData } from "../shared"; export type UserData = string; @@ -64,7 +64,7 @@ export const userDataSchema = ({ type }: TextInput): SchemaOf => }, }); -export interface TextInput extends MoreInformation { +export interface TextInput extends BaseNodeData { title: string; description?: string; fn?: string; @@ -78,5 +78,5 @@ export const parseTextInput = ( description: data?.description, fn: data?.fn, type: data?.type, - ...parseMoreInformation(data), + ...parseBaseNodeData(data), }); diff --git a/editor.planx.uk/src/@planx/components/shared/index.ts b/editor.planx.uk/src/@planx/components/shared/index.ts index 364bc753bd..0d1a5756f8 100644 --- a/editor.planx.uk/src/@planx/components/shared/index.ts +++ b/editor.planx.uk/src/@planx/components/shared/index.ts @@ -1,4 +1,9 @@ +import { NodeTags } from "@opensystemslab/planx-core/types"; import trim from "lodash/trim"; +import { Store } from "pages/FlowEditor/lib/store"; + +/** Shared properties across all node types */ +export type BaseNodeData = NodeTags & MoreInformation; export interface MoreInformation { howMeasured?: string; @@ -8,14 +13,15 @@ export interface MoreInformation { definitionImg?: string; } -export const parseMoreInformation = ( - data: Record | undefined, -): MoreInformation => ({ +export const parseBaseNodeData = ( + data: Store.Node["data"] | undefined, +): BaseNodeData => ({ notes: data?.notes, definitionImg: data?.definitionImg, howMeasured: data?.howMeasured, policyRef: data?.policyRef, info: data?.info, + tags: data?.tags, }); export interface Option { diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/EventsLog.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/EventsLog.tsx index ff21f5325a..069b00572b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/EventsLog.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/EventsLog.tsx @@ -112,6 +112,7 @@ const CollapsibleRow: React.FC = (submission) => { const showDownloadButton = canUserEditTeam(teamSlug) && submission.status === "Success" && + submission.eventType !== "Pay" && submissionEmail && isBefore(new Date(), submissionDataExpirationDate); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/index.tsx index 73d1e4c247..f8b2dd6e02 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/Submissions/index.tsx @@ -78,7 +78,9 @@ const Submissions: React.FC = () => { Submissions - Feed of payment and submission events for this service + Feed of payment and submission events for this service. Successful + submission events within the last 28 days are availabe to download to + team editors. diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/SearchHeader.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/SearchHeader.tsx index be98cd8baa..cbefedd4a4 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/SearchHeader.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/SearchHeader.tsx @@ -8,6 +8,7 @@ import ChecklistItem from "ui/shared/ChecklistItem"; import Input from "ui/shared/Input"; import { Context, Data } from "."; +import { ALL_FACETS, DATA_FACETS } from "./facets"; export const SearchHeader: Components["Header"] = ({ context, @@ -23,6 +24,15 @@ export const SearchHeader: Components["Header"] = ({ } }, [formik.values.pattern, lastPattern, setIsSearching]); + // Use "data.title" as proxy for all facets + const isCurrentlyDataOnlySearch = () => + !formik.values.facets.includes("data.title"); + + const toggleDataOnly = () => + isCurrentlyDataOnlySearch() + ? formik.setFieldValue("facets", ALL_FACETS) + : formik.setFieldValue("facets", DATA_FACETS); + return ( ["Header"] = ({ /> )} - {}} - variant="compact" - /> + {hasFeatureFlag("DATA_ONLY_SEARCH") ? ( + + ) : ( + + )} {formik.values.pattern && ( {context?.results.length === 0 && "No matches found"} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/facets.ts b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/facets.ts index e58e82460a..219a378177 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/facets.ts +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/facets.ts @@ -1,7 +1,7 @@ -import { IndexedNode } from "@opensystemslab/planx-core/types"; +import { flatFlags, IndexedNode } from "@opensystemslab/planx-core/types"; import { FuseOptionKey } from "fuse.js"; -type SearchFacets = Array>; +export type SearchFacets = Array>; const generalData: SearchFacets = ["data.fn", "data.val"]; @@ -26,10 +26,109 @@ const drawBoundaryData: SearchFacets = [ ]; /** Data fields used across PlanX components */ -export const DATA_FACETS = [ +export const DATA_FACETS: SearchFacets = [ ...generalData, ...fileUploadAndLabelData, ...calculateData, ...listData, ...drawBoundaryData, ]; + +const basicFields: SearchFacets = [ + "data.text", + "data.title", + "data.description", +]; + +const moreInformation: SearchFacets = [ + "data.notes", + "data.howMeasured", + "data.policyRef", + "data.info", +]; + +const checklist: SearchFacets = ["data.categories.title"]; + +const nextSteps: SearchFacets = [ + "data.steps.title", + "data.steps.description", + "data.steps.url", +]; + +const fileUploadAndLabel: SearchFacets = [ + "data.fileTypes.name", + "data.fileTypes.notes", + "data.fileTypes.howMeasured", + "data.fileTypes.policyRef", + "data.fileTypes.info", +]; + +/** List, Page, and MapAndLabel components share this structure */ +const schemaComponents: SearchFacets = [ + "data.schema.fields.data.title", + "data.schema.fields.data.description", + "data.schema.fields.data.options.description", + "data.schema.fields.data.options.text", +]; + +const taskList: SearchFacets = ["data.tasks.title", "data.tasks.description"]; + +const result: SearchFacets = [ + ...flatFlags.flatMap(({ value }) => [ + `data.overrides.${value}.heading`, + `data.overrides.${value}.description`, + ]), +]; + +const content: SearchFacets = ["data.content"]; + +const confirmation: SearchFacets = [ + "data.heading", + "data.moreInfo", + "data.contactInfo", + "data.nextSteps.title", + "data.nextSteps.description", +]; + +const findProperty: SearchFacets = [ + "data.newAddressTitle", + "data.newAddressDescription", + "data.newAddressDescriptionLabel", +]; + +const drawBoundary: SearchFacets = [ + "data.titleForUploading", + "data.descriptionForUploading", +]; + +const planningConstraints: SearchFacets = ["data.disclaimer"]; + +const pay: SearchFacets = [ + "data.bannerTitle", + "data.instructionsTitle", + "data.instructionsDescription", + "data.secondaryPageTitle", + "data.nomineeTitle", + "data.nomineeDescription", + "data.yourDetailsTitle", + "data.yourDetailsDescription", + "data.yourDetailsLabel", +]; + +export const ALL_FACETS: SearchFacets = [ + ...basicFields, + ...moreInformation, + ...checklist, + ...nextSteps, + ...fileUploadAndLabel, + ...schemaComponents, + ...taskList, + ...result, + ...content, + ...confirmation, + ...findProperty, + ...drawBoundary, + ...planningConstraints, + ...pay, + ...DATA_FACETS, +]; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/index.tsx index d9cfd8b2dc..9b64008d3d 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/index.tsx @@ -13,7 +13,7 @@ import React, { useEffect, useMemo, useState } from "react"; import { Components, Virtuoso } from "react-virtuoso"; import { ExternalPortalList } from "./ExternalPortalList"; -import { DATA_FACETS } from "./facets"; +import { ALL_FACETS, SearchFacets } from "./facets"; import { SearchHeader } from "./SearchHeader"; import { SearchResultCard } from "./SearchResultCard"; @@ -21,7 +21,7 @@ const DEBOUNCE_MS = 500; interface SearchNodes { pattern: string; - facets: typeof DATA_FACETS; + facets: SearchFacets; } // Types for Virtuoso @@ -64,7 +64,7 @@ const Search: React.FC = () => { // Set up search input form const formik = useFormik({ - initialValues: { pattern: "", facets: DATA_FACETS }, + initialValues: { pattern: "", facets: ALL_FACETS }, onSubmit: ({ pattern }) => { debouncedSearch(pattern); }, diff --git a/editor.planx.uk/src/ui/shared/SelectMultiple.tsx b/editor.planx.uk/src/ui/shared/SelectMultiple.tsx new file mode 100644 index 0000000000..8d3624b86e --- /dev/null +++ b/editor.planx.uk/src/ui/shared/SelectMultiple.tsx @@ -0,0 +1,146 @@ +import ArrowIcon from "@mui/icons-material/KeyboardArrowDown"; +import Autocomplete, { + autocompleteClasses, + AutocompleteProps, +} from "@mui/material/Autocomplete"; +import FormControl from "@mui/material/FormControl"; +import { inputLabelClasses } from "@mui/material/InputLabel"; +import { outlinedInputClasses } from "@mui/material/OutlinedInput"; +import { styled } from "@mui/material/styles"; +import TextField from "@mui/material/TextField"; +import React from "react"; +import { borderedFocusStyle } from "theme"; + +const PopupIcon = ( + ({ color: theme.palette.primary.main })} + fontSize="large" + /> +); + +type RequiredAutocompleteProps = Pick< + AutocompleteProps, + "options" | "onChange" +>; + +type OptionalAutocompleteProps = Partial< + Omit, "multiple"> +>; + +type Props = { + label: string; +} & RequiredAutocompleteProps & + OptionalAutocompleteProps; + +const StyledAutocomplete = styled(Autocomplete)(({ theme }) => ({ + marginTop: theme.spacing(2), + "& > div > label": { + paddingRight: theme.spacing(3), + }, + [`& .${autocompleteClasses.endAdornment}`]: { + top: "unset", + }, + "&:focus-within": { + "& svg": { + color: "black", + }, + }, +})) as typeof Autocomplete; + +const StyledTextField = styled(TextField)(({ theme }) => ({ + "&:focus-within": { + ...borderedFocusStyle, + [`& .${outlinedInputClasses.notchedOutline}`]: { + border: "1px solid transparent !important", + }, + }, + [`& .${outlinedInputClasses.notchedOutline}`]: { + borderRadius: 0, + border: `1px solid${theme.palette.border.main} !important`, + }, + "& fieldset": { + borderColor: theme.palette.border.main, + }, + backgroundColor: theme.palette.background.paper, + [`& .${outlinedInputClasses.root}, input`]: { + cursor: "pointer", + }, + [`& .${inputLabelClasses.root}`]: { + textDecoration: "underline", + color: theme.palette.primary.main, + "&[data-shrink=true]": { + textDecoration: "none", + color: theme.palette.text.primary, + paddingY: 0, + transform: "translate(0px, -22px) scale(0.85)", + }, + }, +})); + +export const CustomCheckbox = styled("span")(({ theme }) => ({ + display: "inline-flex", + flexShrink: 0, + position: "relative", + width: 40, + height: 40, + borderColor: theme.palette.text.primary, + border: "2px solid", + background: "transparent", + marginRight: theme.spacing(1.5), + "&.selected::after": { + content: "''", + position: "absolute", + height: 24, + width: 12, + borderColor: theme.palette.text.primary, + borderBottom: "5px solid", + borderRight: "5px solid", + left: "50%", + top: "42%", + transform: "translate(-50%, -50%) rotate(45deg)", + cursor: "pointer", + }, +})); + +export function SelectMultiple(props: Props) { + return ( + + + role="status" + aria-atomic={true} + aria-live="polite" + disableClearable + disableCloseOnSelect + multiple + popupIcon={PopupIcon} + renderInput={(params) => ( + + )} + ChipProps={{ + variant: "uploadedFileTag", + size: "small", + sx: { pointerEvents: "none" }, + onDelete: undefined, + }} + componentsProps={{ + popupIndicator: { + disableRipple: true, + }, + popper: { + sx: { + boxShadow: 10, + }, + }, + }} + {...props} + /> + + ); +}