diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 8e5efc1c1c..c88562c7d1 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#5781880", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#0ade7fa", "@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 acbdfdfc0c..c49a588d06 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#5781880 - version: github.com/theopensystemslab/planx-core/5781880(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#0ade7fa + version: github.com/theopensystemslab/planx-core/0ade7fa(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -8423,6 +8423,7 @@ packages: /eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -15352,9 +15353,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - 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 + github.com/theopensystemslab/planx-core/0ade7fa(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/0ade7fa} + id: github.com/theopensystemslab/planx-core/0ade7fa name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts index ad940f461e..2ae767d087 100644 --- a/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts +++ b/editor.planx.uk/src/@planx/components/FileUploadAndLabel/schema.ts @@ -33,7 +33,7 @@ const moreInformationSchema: SchemaOf = object({ }); const baseNodeDataSchema: SchemaOf = object({ - tags: array(mixed().oneOf(NODE_TAGS)), + tags: array(mixed().oneOf([...NODE_TAGS])), }).concat(moreInformationSchema); const valFnSchema = mixed().when("condition", { diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Tag.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Tag.tsx index 7dbca109bb..c411ce2852 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Tag.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Tag.tsx @@ -1,35 +1,60 @@ import Box from "@mui/material/Box"; -import { visuallyHidden } from "@mui/utils"; +import { Palette, useTheme } from "@mui/material/styles"; import { NodeTag } from "@opensystemslab/planx-core/types"; +import { useStore } from "pages/FlowEditor/lib/store"; import React from "react"; +import { getContrastTextColor } from "styleUtils"; import { FONT_WEIGHT_SEMI_BOLD } from "theme"; export const TAG_DISPLAY_VALUES: Record< NodeTag, - { color: string; displayName: string } + { color: keyof Palette["nodeTag"]; displayName: string } > = { placeholder: { - color: "#FAE1B7", + color: "blocking", displayName: "Placeholder", }, + toReview: { + color: "nonBlocking", + displayName: "To review", + }, + sensitiveData: { + color: "information", + displayName: "Sensitive data", + }, + analytics: { + color: "information", + displayName: "Analytics", + }, + automation: { + color: "information", + displayName: "Automation", + }, } as const; -export const Tag: React.FC<{ tag: NodeTag }> = ({ tag }) => ( - -); +export const Tag: React.FC<{ tag: NodeTag }> = ({ tag }) => { + const theme = useTheme(); + + const showTags = useStore((state) => state.showTags); + if (!showTags) return null; + + const tagBgColor = theme.palette.nodeTag[TAG_DISPLAY_VALUES[tag].color]; + + return ( + ({ + bgcolor: tagBgColor, + borderColor: theme.palette.common.black, + borderWidth: "0 1px 1px 1px", + borderStyle: "solid", + width: "100%", + p: 0.5, + textAlign: "center", + fontWeight: FONT_WEIGHT_SEMI_BOLD, + color: getContrastTextColor(tagBgColor, "#FFF"), + })} + > + {TAG_DISPLAY_VALUES[tag].displayName} + + ); +}; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/FlowEditor/ToggleTagsButton.tsx b/editor.planx.uk/src/pages/FlowEditor/components/FlowEditor/ToggleTagsButton.tsx new file mode 100644 index 0000000000..93e5bf4991 --- /dev/null +++ b/editor.planx.uk/src/pages/FlowEditor/components/FlowEditor/ToggleTagsButton.tsx @@ -0,0 +1,61 @@ +import LabelIcon from "@mui/icons-material/Label"; +import LabelOffIcon from "@mui/icons-material/LabelOff"; +import Box from "@mui/material/Box"; +import IconButton from "@mui/material/IconButton"; +import { styled } from "@mui/material/styles"; +import Tooltip, { tooltipClasses, TooltipProps } from "@mui/material/Tooltip"; +import { useStore } from "pages/FlowEditor/lib/store"; +import React from "react"; +import { FONT_WEIGHT_SEMI_BOLD } from "theme"; + +const TooltipWrap = styled(({ className, ...props }: TooltipProps) => ( + +))(() => ({ + [`& .${tooltipClasses.arrow}`]: { + color: "#2c2c2c", + }, + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: "#2c2c2c", + left: "-5px", + fontSize: "0.8em", + borderRadius: 0, + fontWeight: FONT_WEIGHT_SEMI_BOLD, + }, +})); + +export const ToggleTagsButton: React.FC = () => { + const [showTags, toggleShowTags] = useStore((state) => [ + state.showTags, + state.toggleShowTags, + ]); + + return ( + ({ + position: "fixed", + bottom: theme.spacing(2), + left: theme.spacing(7), + zIndex: theme.zIndex.appBar, + border: `1px solid ${theme.palette.border.main}`, + borderRadius: "3px", + background: theme.palette.background.paper, + })} + > + + ({ + padding: theme.spacing(1), + color: showTags + ? theme.palette.text.primary + : theme.palette.text.disabled, + })} + > + {showTags ? : } + + + + ); +}; diff --git a/editor.planx.uk/src/pages/FlowEditor/index.tsx b/editor.planx.uk/src/pages/FlowEditor/index.tsx index b5130f0f24..167b517006 100644 --- a/editor.planx.uk/src/pages/FlowEditor/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/index.tsx @@ -7,6 +7,7 @@ import React, { useRef } from "react"; import { useCurrentRoute } from "react-navi"; import Flow from "./components/Flow"; +import { ToggleTagsButton } from "./components/FlowEditor/ToggleTagsButton"; import Sidebar from "./components/Sidebar"; import { useStore } from "./lib/store"; import useScrollControlsAndRememberPosition from "./lib/useScrollControlsAndRememberPosition"; @@ -49,6 +50,7 @@ const FlowEditor = () => { > + 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 d46f351c3c..e44a33e504 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts @@ -26,7 +26,7 @@ import { customAlphabet } from "nanoid-good"; import en from "nanoid-good/locale/en"; import { type } from "ot-json0"; import type { StateCreator } from "zustand"; -import { persist } from 'zustand/middleware' +import { persist } from "zustand/middleware"; import { FlowLayout } from "../../components/Flow"; import { connectToDB, getConnection } from "./../sharedb"; @@ -49,6 +49,8 @@ export interface EditorUIStore { toggleSidebar: () => void; isTestEnvBannerVisible: boolean; hideTestEnvBanner: () => void; + showTags: boolean; + toggleShowTags: () => void; } export const editorUIStore: StateCreator< @@ -69,11 +71,18 @@ export const editorUIStore: StateCreator< isTestEnvBannerVisible: !window.location.href.includes(".uk"), hideTestEnvBanner: () => set({ isTestEnvBannerVisible: false }), + + showTags: false, + + toggleShowTags: () => set({ showTags: !get().showTags }), }), { name: "editorUIStore", - partialize: (state) => ({ showSidebar: state.showSidebar }), - } + partialize: (state) => ({ + showSidebar: state.showSidebar, + showTags: state.showTags, + }), + }, ); interface PublishFlowResponse { diff --git a/editor.planx.uk/src/theme.ts b/editor.planx.uk/src/theme.ts index 088d927808..84932b2d4a 100644 --- a/editor.planx.uk/src/theme.ts +++ b/editor.planx.uk/src/theme.ts @@ -76,6 +76,12 @@ const DEFAULT_PALETTE: Partial = { input: "#0B0C0C", light: "#E0E0E0", }, + nodeTag: { + error: "#FFA8A1", + blocking: "#FAE1B7", + nonBlocking: "#FFFDB0", + information: "#B7FAD7", + }, tonalOffset: DEFAULT_TONAL_OFFSET, }; diff --git a/editor.planx.uk/src/themeOverrides.d.ts b/editor.planx.uk/src/themeOverrides.d.ts index 7dc5f5b35c..bc4802fb65 100644 --- a/editor.planx.uk/src/themeOverrides.d.ts +++ b/editor.planx.uk/src/themeOverrides.d.ts @@ -32,6 +32,12 @@ declare module "@mui/material/styles/createPalette" { border: { main: string; input: string; light: string }; link: { main: string }; prompt: { main: string; contrastText: string; light: string; dark: string }; + nodeTag: { + error: string; + nonBlocking: string; + blocking: string; + information: string; + }; } interface PaletteOptions { @@ -43,6 +49,12 @@ declare module "@mui/material/styles/createPalette" { light: string; dark: string; }; + nodeTag?: { + error: string; + nonBlocking: string; + blocking: string; + information: string; + }; } interface TypeText { diff --git a/editor.planx.uk/src/ui/editor/ComponentTagSelect.tsx b/editor.planx.uk/src/ui/editor/ComponentTagSelect.tsx index d47440a766..d055481444 100644 --- a/editor.planx.uk/src/ui/editor/ComponentTagSelect.tsx +++ b/editor.planx.uk/src/ui/editor/ComponentTagSelect.tsx @@ -1,9 +1,11 @@ import BookmarksIcon from "@mui/icons-material/Bookmarks"; import { AutocompleteProps } from "@mui/material/Autocomplete"; +import Chip from "@mui/material/Chip"; import ListItem from "@mui/material/ListItem"; import { NODE_TAGS, NodeTag } from "@opensystemslab/planx-core/types"; import { TAG_DISPLAY_VALUES } from "pages/FlowEditor/components/Flow/components/Tag"; import React from "react"; +import { getContrastTextColor } from "styleUtils"; import ModalSection from "ui/editor/ModalSection"; import ModalSectionContent from "ui/editor/ModalSectionContent"; import InputRow from "ui/shared/InputRow"; @@ -12,7 +14,7 @@ import { CustomCheckbox, SelectMultiple } from "ui/shared/SelectMultiple"; interface Props { value?: NodeTag[]; onChange: (values: NodeTag[]) => void; -}; +} const renderOption: AutocompleteProps< NodeTag, @@ -23,10 +25,32 @@ const renderOption: AutocompleteProps< >["renderOption"] = (props, tag, { selected }) => ( ); +const renderTags: AutocompleteProps< + NodeTag, + true, + true, + false, + "div" +>["renderTags"] = (value, getTagProps) => + value.map((tag, index) => ( + ({ + backgroundColor: theme.palette.nodeTag[TAG_DISPLAY_VALUES[tag].color], + color: getContrastTextColor( + theme.palette.nodeTag[TAG_DISPLAY_VALUES[tag].color], + "#FFF", + ), + })} + /> + )); + export const ComponentTagSelect: React.FC = ({ value, onChange }) => { return ( @@ -39,9 +63,10 @@ export const ComponentTagSelect: React.FC = ({ value, onChange }) => { onChange={(_e, value) => onChange(value)} value={value} renderOption={renderOption} + renderTags={renderTags} /> - ) -} \ No newline at end of file + ); +};