diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 56777b787a..f10aa9bc36 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.4", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#134b20d", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d9fc4a0", "@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 22e83f212e..5bba7a65bc 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.4 version: 1.0.0-alpha.4 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#134b20d - version: github.com/theopensystemslab/planx-core/134b20d(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#d9fc4a0 + version: github.com/theopensystemslab/planx-core/d9fc4a0(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -2882,6 +2882,7 @@ packages: strip-ansi-cjs: /strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true /@istanbuljs/load-nyc-config@1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} @@ -3898,6 +3899,7 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} requiresBuild: true + dev: true optional: true /@popperjs/core@2.11.8: @@ -6395,6 +6397,7 @@ packages: /ansi-regex@6.1.0: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} + dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -6415,6 +6418,7 @@ packages: /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + dev: true /anymatch@2.0.0: resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} @@ -6914,6 +6918,7 @@ packages: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 + dev: true /braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -8030,6 +8035,7 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true /editorconfig@1.0.4: resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} @@ -8058,6 +8064,7 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} @@ -8798,6 +8805,17 @@ packages: transitivePeerDependencies: - encoding + /fdir@6.4.2(picomatch@4.0.2): + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + dependencies: + picomatch: 4.0.2 + dev: false + /fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} dev: false @@ -8919,6 +8937,7 @@ packages: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 + dev: true /form-data@2.5.1: resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} @@ -9123,6 +9142,7 @@ packages: minipass: 7.1.2 package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + dev: true /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} @@ -10003,6 +10023,7 @@ packages: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 + dev: true /javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} @@ -10612,20 +10633,20 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - /json-schema-to-typescript@15.0.2: - resolution: {integrity: sha512-+cRBw+bBJ3k783mZroDIgz1pLNPB4hvj6nnbHTWwEVl0dkW8qdZ+M9jWhBb+Y0FAdHvNsXACga3lewGO8lktrw==} + /json-schema-to-typescript@15.0.3: + resolution: {integrity: sha512-iOKdzTUWEVM4nlxpFudFsWyUiu/Jakkga4OZPEt7CGoSEsAsUgdOZqR6pcgx2STBek9Gm4hcarJpXSzIvZ/hKA==} engines: {node: '>=16.0.0'} hasBin: true dependencies: '@apidevtools/json-schema-ref-parser': 11.7.0 '@types/json-schema': 7.0.15 '@types/lodash': 4.17.10 - glob: 10.4.5 is-glob: 4.0.3 js-yaml: 4.1.0 lodash: 4.17.21 minimist: 1.2.8 prettier: 3.3.3 + tinyglobby: 0.2.10 dev: false /json-schema-traverse@0.4.1: @@ -10983,6 +11004,7 @@ packages: /lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + dev: true /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -11456,6 +11478,7 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 + dev: true /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -11463,6 +11486,7 @@ packages: /minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + dev: true /mixin-deep@1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} @@ -11900,6 +11924,7 @@ packages: /package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + dev: true /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -11987,6 +12012,7 @@ packages: dependencies: lru-cache: 10.4.3 minipass: 7.1.2 + dev: true /path-to-regexp@0.1.10: resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} @@ -12029,6 +12055,11 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + dev: false + /pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -13554,6 +13585,7 @@ packages: /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + dev: true /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -13847,6 +13879,7 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 + dev: true /string.prototype.trim@1.2.9: resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} @@ -13901,6 +13934,7 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.1.0 + dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -14161,6 +14195,14 @@ packages: /tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + /tinyglobby@0.2.10: + resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} + engines: {node: '>=12.0.0'} + dependencies: + fdir: 6.4.2(picomatch@4.0.2) + picomatch: 4.0.2 + dev: false + /tinypool@0.8.4: resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} engines: {node: '>=14.0.0'} @@ -14754,8 +14796,8 @@ packages: dev: false optional: true - /uuid@11.0.2: - resolution: {integrity: sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==} + /uuid@11.0.3: + resolution: {integrity: sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==} hasBin: true dev: false @@ -15192,6 +15234,7 @@ packages: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 + dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -15390,9 +15433,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/134b20d(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/134b20d} - id: github.com/theopensystemslab/planx-core/134b20d + github.com/theopensystemslab/planx-core/d9fc4a0(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d9fc4a0} + id: github.com/theopensystemslab/planx-core/d9fc4a0 name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -15412,14 +15455,14 @@ packages: fast-xml-parser: 4.5.0 graphql: 16.9.0 graphql-request: 6.1.0(graphql@16.9.0) - json-schema-to-typescript: 15.0.2 + json-schema-to-typescript: 15.0.3 lodash: 4.17.21 marked: 14.1.3 prettier: 3.3.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) type-fest: 4.26.1 - uuid: 11.0.2 + uuid: 11.0.3 zod: 3.23.8 transitivePeerDependencies: - '@types/react' diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowDescription/FlowDescription.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowDescription/FlowDescription.tsx new file mode 100644 index 0000000000..2c9e4df3a3 --- /dev/null +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowDescription/FlowDescription.tsx @@ -0,0 +1,78 @@ +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { useFormik } from "formik"; +import { useToast } from "hooks/useToast"; +import React from "react"; +import InputLabel from "ui/editor/InputLabel"; +import SettingsSection from "ui/editor/SettingsSection"; +import Input from "ui/shared/Input/Input"; + +import { useStore } from "../../../../lib/store"; +import { SettingsForm } from "../../shared/SettingsForm"; + +const FlowDescription = () => { + const [flowDescription, updateFlowDescription] = useStore((state) => [ + state.flowDescription, + state.updateFlowDescription, + ]); + const toast = useToast(); + + const formik = useFormik<{ description: string }>({ + initialValues: { + description: flowDescription || "", + }, + onSubmit: async (values, { resetForm }) => { + const isSuccess = await updateFlowDescription(values.description); + if (isSuccess) { + toast.success("Description updated successfully"); + resetForm({ values }); + } + if (!isSuccess) { + formik.setFieldError( + "description", + "We are unable to update the service description, check your internet connection and try again", + ); + } + }, + }); + + return ( + + + + Service Information + + + Useful information about this service. + + + + A short blurb on what this service is, how it should be used, and if + there are any dependencies related to this service. + + } + input={ + <> + + { + formik.setFieldValue("description", event.target.value); + }} + value={formik.values.description ?? ""} + errorMessage={formik.errors.description} + id="description" + /> + + + } + /> + + ); +}; + +export default FlowDescription; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/index.tsx index 89fff855f4..404de65fe3 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/index.tsx @@ -1,6 +1,5 @@ import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; -import { formControlLabelClasses } from "@mui/material/FormControlLabel"; import Typography from "@mui/material/Typography"; import type { FlowStatus } from "@opensystemslab/planx-core/types"; import axios from "axios"; @@ -8,7 +7,6 @@ import { useFormik } from "formik"; import { useToast } from "hooks/useToast"; import React from "react"; import { rootFlowPath } from "routes/utils"; -import { FONT_WEIGHT_BOLD } from "theme"; import SettingsDescription from "ui/editor/SettingsDescription"; import SettingsSection from "ui/editor/SettingsSection"; import { Switch } from "ui/shared/Switch"; @@ -92,7 +90,7 @@ const FlowStatus = () => { }; return ( - + Status diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/index.tsx index dde243b1b3..70a630ac02 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/index.tsx @@ -1,6 +1,7 @@ import Container from "@mui/material/Container"; import React from "react"; +import FlowDescription from "./FlowDescription/FlowDescription"; import FlowStatus from "./FlowStatus"; import { FooterLinksAndLegalDisclaimer } from "./FooterLinksAndLegalDisclaimer"; @@ -8,6 +9,7 @@ const ServiceSettings: React.FC = () => ( + ); diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts index 74ef341a0e..874d9cf33b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts @@ -19,6 +19,9 @@ export interface SettingsStore { flowStatus?: FlowStatus; setFlowStatus: (flowStatus: FlowStatus) => void; updateFlowStatus: (newStatus: FlowStatus) => Promise; + flowDescription?: string; + setFlowDescription: (flowDescription: string) => void; + updateFlowDescription: (newDescription: string) => Promise; globalSettings?: GlobalSettings; setGlobalSettings: (globalSettings: GlobalSettings) => void; updateFlowSettings: (newSettings: FlowSettings) => Promise; @@ -51,6 +54,20 @@ export const settingsStore: StateCreator< return Boolean(result?.id); }, + flowDescription: "", + + setFlowDescription: (flowDescription: string) => set({ flowDescription }), + + updateFlowDescription: async (newDescription: string) => { + const { id, $client } = get(); + const result = await $client.flow.setDescription({ + flow: { id }, + description: newDescription, + }); + set({ flowDescription: newDescription }); + return Boolean(result?.id); + }, + globalSettings: undefined, setGlobalSettings: (globalSettings) => { diff --git a/editor.planx.uk/src/routes/serviceSettings.tsx b/editor.planx.uk/src/routes/serviceSettings.tsx index fb8f223999..f22753826d 100644 --- a/editor.planx.uk/src/routes/serviceSettings.tsx +++ b/editor.planx.uk/src/routes/serviceSettings.tsx @@ -13,13 +13,14 @@ interface GetFlowSettings { id: string; settings: FlowSettings; status: FlowStatus; + description: string; }[]; } export const getFlowSettings = async (req: NaviRequest) => { const { data: { - flows: [{ settings, status }], + flows: [{ settings, status, description }], }, } = await client.query({ query: gql` @@ -30,6 +31,7 @@ export const getFlowSettings = async (req: NaviRequest) => { ) { id settings + description status } } @@ -42,6 +44,7 @@ export const getFlowSettings = async (req: NaviRequest) => { useStore.getState().setFlowSettings(settings); useStore.getState().setFlowStatus(status); + useStore.getState().setFlowDescription(description); }; const serviceSettingsRoutes = compose(