From 22e027d519bb290ec221226cd32df1798e79075f Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Thu, 4 Jul 2024 18:07:19 +0200 Subject: [PATCH 1/6] wip --- .../modules/flows/validate/service.ts | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index 6b4dc388c4..cd4f18972e 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -55,7 +55,8 @@ const validateAndDiffFlow = async ( const validationChecks = []; const sections = validateSections(flattenedFlow); const inviteToPay = validateInviteToPay(flattenedFlow); - validationChecks.push(sections, inviteToPay); + const fileTypes = validateFileTypes(flattenedFlow); + validationChecks.push(sections, inviteToPay, fileTypes); // Sort validation checks by status: Fail, Pass, Not applicable const applicableChecks = validationChecks @@ -206,4 +207,46 @@ const inviteToPayEnabled = (flowGraph: FlowGraph): boolean => { ); }; +const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { + const allFileFns = [ + ...getFileUploadNodeFns(flowGraph), + ...getFileUploadAndLabelNodeFns(flowGraph), + ]; + // todo: get schema file types via planx-core method, compare arrays + + if (allFileFns.length < 1) { + return { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }; + } + + return { + title: "File types", + status: "Pass", + message: + "Files collected via FileUpload or UploadAndLabel are all supported by the ODP Schema", + }; +}; + +const getFileUploadNodeFns = (flowGraph: FlowGraph): string[] => { + const fileUploadNodes = Object.entries(flowGraph).filter( + (entry): entry is [string, Node] => + isComponentType(entry, ComponentType.FileUpload), + ); + return fileUploadNodes.map(([_nodeId, node]) => node.data?.fn as string); +}; + +const getFileUploadAndLabelNodeFns = (flowGraph: FlowGraph): string[] => { + const uploadAndLabelNodes = Object.entries(flowGraph).filter( + (entry): entry is [string, Node] => + isComponentType(entry, ComponentType.FileUploadAndLabel), + ); + const uploadAndLabelFileTypes = uploadAndLabelNodes + .map(([_nodeId, node]) => node.data?.fileTypes) + .flat(); + return uploadAndLabelFileTypes?.map((file: any) => file?.fn as string); +}; + export { validateAndDiffFlow }; From 510c8797fff11feba5d4ae4b526e376cb4d9b129 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Fri, 5 Jul 2024 10:16:26 +0200 Subject: [PATCH 2/6] working validation warning --- .../modules/flows/validate/service.ts | 35 ++++-- .../modules/flows/validate/validate.test.ts | 116 ++++++++++++++++++ api.planx.uk/package.json | 2 +- api.planx.uk/pnpm-lock.yaml | 8 +- e2e/tests/api-driven/package.json | 2 +- e2e/tests/api-driven/pnpm-lock.yaml | 8 +- e2e/tests/ui-driven/package.json | 2 +- e2e/tests/ui-driven/pnpm-lock.yaml | 8 +- editor.planx.uk/package.json | 2 +- editor.planx.uk/pnpm-lock.yaml | 11 +- .../components/Sidebar/PublishDialog.tsx | 4 +- 11 files changed, 168 insertions(+), 30 deletions(-) diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index cd4f18972e..65a24e4468 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -1,3 +1,4 @@ +import { getValidSchemaValues } from "@opensystemslab/planx-core"; import { ComponentType, Edges, @@ -23,7 +24,7 @@ type AlteredNode = { type ValidationResponse = { title: string; - status: "Pass" | "Fail" | "Not applicable"; + status: "Pass" | "Fail" | "Warn" | "Not applicable"; message: string; }; @@ -58,14 +59,17 @@ const validateAndDiffFlow = async ( const fileTypes = validateFileTypes(flattenedFlow); validationChecks.push(sections, inviteToPay, fileTypes); - // Sort validation checks by status: Fail, Pass, Not applicable - const applicableChecks = validationChecks - .filter((v) => v.status !== "Not applicable") - .sort((a, b) => a.status.localeCompare(b.status)); + // Arrange list of validation checks in order of status: Fail, Warn, Pass, Not applicable + const failingChecks = validationChecks.filter((v) => v.status == "Fail"); + const warningChecks = validationChecks.filter((v) => v.status === "Warn"); + const passingChecks = validationChecks.filter((v) => v.status === "Pass"); const notApplicableChecks = validationChecks.filter( (v) => v.status === "Not applicable", ); - const sortedValidationChecks = applicableChecks.concat(notApplicableChecks); + const sortedValidationChecks = failingChecks + .concat(warningChecks) + .concat(passingChecks) + .concat(notApplicableChecks); return { alteredNodes, @@ -208,12 +212,11 @@ const inviteToPayEnabled = (flowGraph: FlowGraph): boolean => { }; const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { + // Get all passport variables set by FileUpload and/or FileUploadAndLabel const allFileFns = [ ...getFileUploadNodeFns(flowGraph), ...getFileUploadAndLabelNodeFns(flowGraph), ]; - // todo: get schema file types via planx-core method, compare arrays - if (allFileFns.length < 1) { return { title: "File types", @@ -222,6 +225,22 @@ const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { }; } + // Get all file types supported by current release of ODP Schema & compare + const validFileTypes = getValidSchemaValues("FileType"); + const invalidFileFns: string[] = []; + allFileFns.forEach((fn) => { + if (!validFileTypes?.includes(fn)) { + invalidFileFns.push(fn); + } + }); + if (invalidFileFns.length > 0) { + return { + title: "File types", + status: "Warn", + message: `Your FileUpload or UploadAndLabel are setting data fields that are not supported by the ODP Schema: ${invalidFileFns.join(", ")}`, + }; + } + return { title: "File types", status: "Pass", diff --git a/api.planx.uk/modules/flows/validate/validate.test.ts b/api.planx.uk/modules/flows/validate/validate.test.ts index f17a73052d..e595900f27 100644 --- a/api.planx.uk/modules/flows/validate/validate.test.ts +++ b/api.planx.uk/modules/flows/validate/validate.test.ts @@ -120,6 +120,11 @@ describe("sections validation on diff", () => { status: "Not applicable", message: "Your flow is not using Invite to Pay", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -168,6 +173,11 @@ describe("sections validation on diff", () => { status: "Not applicable", message: "Your flow is not using Invite to Pay", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -207,6 +217,11 @@ describe("invite to pay validation on diff", () => { status: "Not applicable", message: "Your flow is not using Sections", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -256,6 +271,11 @@ describe("invite to pay validation on diff", () => { status: "Not applicable", message: "Your flow is not using Sections", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -301,6 +321,11 @@ describe("invite to pay validation on diff", () => { status: "Not applicable", message: "Your flow is not using Sections", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -348,6 +373,11 @@ describe("invite to pay validation on diff", () => { status: "Not applicable", message: "Your flow is not using Sections", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, ]); }); }); @@ -397,6 +427,92 @@ describe("invite to pay validation on diff", () => { status: "Not applicable", message: "Your flow is not using Sections", }, + { + title: "File types", + status: "Not applicable", + message: "Your flow is not using FileUpload or UploadAndLabel", + }, + ]); + }); + }); +}); + +describe("ODP Schema file type validation on diff", () => { + it("warns if any file data fields aren't supported by the ODP Schema", async () => { + const alteredFlow = { + ...mockFlowData, + fileUpload: { + type: 140, + data: { + color: "#EFEFEF", + fn: "roofPlan.existing", + title: "Roof plans", + }, + }, + fileUploadAndLabel: { + type: 145, + data: { + title: "Upload and label", + fileTypes: [ + { + name: "Site plans", + fn: "sitePlanTypo", + rule: { + condition: "AlwaysRequired", + }, + }, + { + name: "Heritage statement", + fn: "heritageStatement", + rule: { + condition: "AlwaysRequired", + }, + }, + ], + hideDropZone: false, + }, + }, + }; + + queryMock.mockQuery({ + name: "GetFlowData", + matchOnVariables: false, + data: { + flow: { + data: alteredFlow, + slug: "altered-flow-name", + team_id: 1, + team: { + slug: "testing", + }, + publishedFlows: [{ data: alteredFlow }], + }, + }, + }); + + await supertest(app) + .post("/flows/1/diff") + .set(auth) + .expect(200) + .then((res) => { + expect(res.body.message).toEqual("Changes queued to publish"); + expect(res.body.validationChecks).toEqual([ + { + title: "File types", + status: "Warn", + message: + "Your FileUpload or UploadAndLabel are setting data fields that are not supported by the ODP Schema: sitePlanTypo", + }, + { + title: "Sections", + status: "Pass", + message: "Your flow has valid Sections", + }, + { + title: "Invite to Pay", + status: "Not applicable", + message: "Your flow is not using Invite to Pay", + }, ]); }); }); diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index 09c750cf4c..ff04ff18dc 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -5,7 +5,7 @@ "packageManager": "pnpm@8.6.6", "dependencies": { "@airbrake/node": "^2.1.8", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#60158b2", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", "@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 a4251b7ad7..0eac243d38 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#60158b2 - version: github.com/theopensystemslab/planx-core/60158b2 + specifier: git+https://github.com/theopensystemslab/planx-core#d398f2c + version: github.com/theopensystemslab/planx-core/d398f2c '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -8202,8 +8202,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/60158b2: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/60158b2} + github.com/theopensystemslab/planx-core/d398f2c: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} 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 3d7bb5de3d..fd66fdf3cd 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#60158b2", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", "axios": "^1.6.8", "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 5852716546..7683932248 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#60158b2 - version: github.com/theopensystemslab/planx-core/60158b2 + specifier: git+https://github.com/theopensystemslab/planx-core#d398f2c + version: github.com/theopensystemslab/planx-core/d398f2c axios: specifier: ^1.6.8 version: 1.6.8 @@ -3053,8 +3053,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/60158b2: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/60158b2} + github.com/theopensystemslab/planx-core/d398f2c: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} 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 920b91f9c2..ae39976954 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#60158b2", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", "axios": "^1.6.8", "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 6a74c3ec0b..4e8cd838cd 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#60158b2 - version: github.com/theopensystemslab/planx-core/60158b2 + specifier: git+https://github.com/theopensystemslab/planx-core#d398f2c + version: github.com/theopensystemslab/planx-core/d398f2c axios: specifier: ^1.6.8 version: 1.6.8 @@ -2780,8 +2780,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/60158b2: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/60158b2} + github.com/theopensystemslab/planx-core/d398f2c: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index bc7dc36125..bb0a7c5ee0 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -13,7 +13,7 @@ "@mui/material": "^5.15.2", "@mui/utils": "^5.15.2", "@opensystemslab/map": "^0.8.3", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#60158b2", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", "@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 dcd836ee57..962a11e506 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -42,8 +42,8 @@ dependencies: specifier: ^0.8.3 version: 0.8.3 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#60158b2 - version: github.com/theopensystemslab/planx-core/60158b2(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#d398f2c + version: github.com/theopensystemslab/planx-core/d398f2c(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -14758,6 +14758,7 @@ packages: /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true dependencies: argparse: 1.0.10 esprima: 4.0.1 @@ -21521,9 +21522,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/60158b2(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/60158b2} - id: github.com/theopensystemslab/planx-core/60158b2 + github.com/theopensystemslab/planx-core/d398f2c(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} + id: github.com/theopensystemslab/planx-core/d398f2c name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx index cb33d3ba3c..446cfafedd 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx @@ -18,6 +18,7 @@ import { useAsync } from "react-use"; import Caret from "ui/icons/Caret"; import { useStore } from "../../lib/store"; +import Warning from "@mui/icons-material/Warning"; export interface AlteredNode { id: string; @@ -231,7 +232,7 @@ export const AlteredNodesSummaryContent = (props: { export interface ValidationCheck { title: string; - status: "Pass" | "Fail" | "Not applicable"; + status: "Pass" | "Fail" | "Warn" | "Not applicable"; message: string; } @@ -243,6 +244,7 @@ export const ValidationChecks = (props: { const Icon: Record = { Pass: , Fail: , + Warn: , "Not applicable": , }; From 126b7eb5be36225ade8d9d2ad008eb10192ddbc0 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Fri, 5 Jul 2024 12:02:35 +0200 Subject: [PATCH 3/6] only validate UploadAndLabel when dropzone is active --- .../modules/flows/validate/service.ts | 4 +- .../modules/flows/validate/validate.test.ts | 72 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index 65a24e4468..4c02c7ae92 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -258,9 +258,11 @@ const getFileUploadNodeFns = (flowGraph: FlowGraph): string[] => { }; const getFileUploadAndLabelNodeFns = (flowGraph: FlowGraph): string[] => { + // Exclude Upload & Label nodes used in "info-only" mode with a hidden dropzone const uploadAndLabelNodes = Object.entries(flowGraph).filter( (entry): entry is [string, Node] => - isComponentType(entry, ComponentType.FileUploadAndLabel), + isComponentType(entry, ComponentType.FileUploadAndLabel) && + entry[1].data?.hideDropZone !== true, ); const uploadAndLabelFileTypes = uploadAndLabelNodes .map(([_nodeId, node]) => node.data?.fileTypes) diff --git a/api.planx.uk/modules/flows/validate/validate.test.ts b/api.planx.uk/modules/flows/validate/validate.test.ts index e595900f27..8e5b43f3cc 100644 --- a/api.planx.uk/modules/flows/validate/validate.test.ts +++ b/api.planx.uk/modules/flows/validate/validate.test.ts @@ -516,4 +516,76 @@ describe("ODP Schema file type validation on diff", () => { ]); }); }); + + it("skips validation checks for UploadAndLabel components used in info-only mode with hidden dropzone", async () => { + const alteredFlow = { + ...mockFlowData, + fileUpload: { + type: 140, + data: { + color: "#EFEFEF", + fn: "roofPlan.existing", + title: "Roof plans", + }, + }, + fileUploadAndLabelInfoOnly: { + type: 145, + data: { + title: "Prepare these documents", + fileTypes: [ + { + name: "Design and access statement", + fn: "designAndAccessTypo", + rule: { + condition: "AlwaysRequired", + }, + }, + ], + hideDropZone: true, + }, + }, + }; + + queryMock.mockQuery({ + name: "GetFlowData", + matchOnVariables: false, + data: { + flow: { + data: alteredFlow, + slug: "altered-flow-name", + team_id: 1, + team: { + slug: "testing", + }, + publishedFlows: [{ data: alteredFlow }], + }, + }, + }); + + await supertest(app) + .post("/flows/1/diff") + .set(auth) + .expect(200) + .then((res) => { + expect(res.body.message).toEqual("Changes queued to publish"); + expect(res.body.validationChecks).toEqual([ + { + title: "Sections", + status: "Pass", + message: "Your flow has valid Sections", + }, + { + title: "File types", + status: "Pass", + message: + "Files collected via FileUpload or UploadAndLabel are all supported by the ODP Schema", + }, + { + title: "Invite to Pay", + status: "Not applicable", + message: "Your flow is not using Invite to Pay", + }, + ]); + }); + }); }); From bea485c752e6983a9cb9e1b1756eb077f1cef064 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Sun, 7 Jul 2024 19:55:21 +0200 Subject: [PATCH 4/6] planx-core bump plus design feedback --- api.planx.uk/modules/flows/validate/service.ts | 9 ++++++++- api.planx.uk/modules/flows/validate/validate.test.ts | 2 +- api.planx.uk/package.json | 2 +- api.planx.uk/pnpm-lock.yaml | 9 +++++---- e2e/tests/api-driven/package.json | 2 +- e2e/tests/api-driven/pnpm-lock.yaml | 8 ++++---- e2e/tests/ui-driven/package.json | 2 +- e2e/tests/ui-driven/pnpm-lock.yaml | 8 ++++---- editor.planx.uk/package.json | 2 +- editor.planx.uk/pnpm-lock.yaml | 11 ++++++----- 10 files changed, 32 insertions(+), 23 deletions(-) diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index 4c02c7ae92..bda0e7cb4a 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -7,6 +7,7 @@ import { } from "@opensystemslab/planx-core/types"; import * as jsondiffpatch from "jsondiffpatch"; import intersection from "lodash/intersection"; +import countBy from "lodash/countBy"; import { dataMerged, getMostRecentPublishedFlow } from "../../../helpers"; import { @@ -234,10 +235,16 @@ const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { } }); if (invalidFileFns.length > 0) { + // Get unique fns with count of occurances + const countInvalidFileFns = countBy(invalidFileFns); + let summarisedInvalidFileFns: string[] = []; + Object.entries(countInvalidFileFns).map(([k, v]: [string, number]) => { + summarisedInvalidFileFns.push(`${k} (${v})`); + }); return { title: "File types", status: "Warn", - message: `Your FileUpload or UploadAndLabel are setting data fields that are not supported by the ODP Schema: ${invalidFileFns.join(", ")}`, + message: `Your FileUpload or UploadAndLabel are setting data fields that are not supported by the current release of the ODP Schema: ${summarisedInvalidFileFns.join(", ")}`, }; } diff --git a/api.planx.uk/modules/flows/validate/validate.test.ts b/api.planx.uk/modules/flows/validate/validate.test.ts index 8e5b43f3cc..dce4af082e 100644 --- a/api.planx.uk/modules/flows/validate/validate.test.ts +++ b/api.planx.uk/modules/flows/validate/validate.test.ts @@ -501,7 +501,7 @@ describe("ODP Schema file type validation on diff", () => { title: "File types", status: "Warn", message: - "Your FileUpload or UploadAndLabel are setting data fields that are not supported by the ODP Schema: sitePlanTypo", + "Your FileUpload or UploadAndLabel are setting data fields that are not supported by the current release of the ODP Schema: sitePlanTypo (1)", }, { title: "Sections", diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index ff04ff18dc..3ae697df3f 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -5,7 +5,7 @@ "packageManager": "pnpm@8.6.6", "dependencies": { "@airbrake/node": "^2.1.8", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#ed7c187", "@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 0eac243d38..c28fa8d50e 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#d398f2c - version: github.com/theopensystemslab/planx-core/d398f2c + specifier: git+https://github.com/theopensystemslab/planx-core#ed7c187 + version: github.com/theopensystemslab/planx-core/ed7c187 '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -5528,6 +5528,7 @@ packages: /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true dependencies: argparse: 1.0.10 esprima: 4.0.1 @@ -8202,8 +8203,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/d398f2c: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} + github.com/theopensystemslab/planx-core/ed7c187: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/ed7c187} 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 fd66fdf3cd..f0542e3572 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#d398f2c", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#ed7c187", "axios": "^1.6.8", "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 7683932248..d193c924e6 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#d398f2c - version: github.com/theopensystemslab/planx-core/d398f2c + specifier: git+https://github.com/theopensystemslab/planx-core#ed7c187 + version: github.com/theopensystemslab/planx-core/ed7c187 axios: specifier: ^1.6.8 version: 1.6.8 @@ -3053,8 +3053,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/d398f2c: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} + github.com/theopensystemslab/planx-core/ed7c187: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/ed7c187} 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 ae39976954..8838e01c2e 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#d398f2c", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#ed7c187", "axios": "^1.6.8", "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 4e8cd838cd..f055a392b8 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#d398f2c - version: github.com/theopensystemslab/planx-core/d398f2c + specifier: git+https://github.com/theopensystemslab/planx-core#ed7c187 + version: github.com/theopensystemslab/planx-core/ed7c187 axios: specifier: ^1.6.8 version: 1.6.8 @@ -2780,8 +2780,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/d398f2c: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} + github.com/theopensystemslab/planx-core/ed7c187: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/ed7c187} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index bb0a7c5ee0..3fe13db76c 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -13,7 +13,7 @@ "@mui/material": "^5.15.2", "@mui/utils": "^5.15.2", "@opensystemslab/map": "^0.8.3", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#d398f2c", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#ed7c187", "@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 962a11e506..a9111c6554 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -42,8 +42,8 @@ dependencies: specifier: ^0.8.3 version: 0.8.3 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#d398f2c - version: github.com/theopensystemslab/planx-core/d398f2c(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#ed7c187 + version: github.com/theopensystemslab/planx-core/ed7c187(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -13022,6 +13022,7 @@ packages: /glob@10.4.2: resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} engines: {node: '>=16 || 14 >=14.18'} + hasBin: true dependencies: foreground-child: 3.2.1 jackspeak: 3.4.0 @@ -21522,9 +21523,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/d398f2c(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d398f2c} - id: github.com/theopensystemslab/planx-core/d398f2c + github.com/theopensystemslab/planx-core/ed7c187(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/ed7c187} + id: github.com/theopensystemslab/planx-core/ed7c187 name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true From f0a1e4fc6e8fb1abc203d12c4b9a19f672109e35 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Sun, 7 Jul 2024 19:58:42 +0200 Subject: [PATCH 5/6] run prettier --- api.planx.uk/modules/flows/validate/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index bda0e7cb4a..231e001687 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -237,7 +237,7 @@ const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { if (invalidFileFns.length > 0) { // Get unique fns with count of occurances const countInvalidFileFns = countBy(invalidFileFns); - let summarisedInvalidFileFns: string[] = []; + const summarisedInvalidFileFns: string[] = []; Object.entries(countInvalidFileFns).map(([k, v]: [string, number]) => { summarisedInvalidFileFns.push(`${k} (${v})`); }); From a64b9fd33a91d764742441bcd3cd2cac6e8b7ac2 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Mon, 8 Jul 2024 12:25:34 +0200 Subject: [PATCH 6/6] update swagger, tidy types --- api.planx.uk/modules/flows/docs.yaml | 32 +++++++++++++++---- .../modules/flows/validate/service.ts | 14 ++++---- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/api.planx.uk/modules/flows/docs.yaml b/api.planx.uk/modules/flows/docs.yaml index 389ebf4075..d02b1290db 100644 --- a/api.planx.uk/modules/flows/docs.yaml +++ b/api.planx.uk/modules/flows/docs.yaml @@ -56,6 +56,25 @@ components: type: array items: type: string + ValidationCheck: + type: object + properties: + title: + type: string + example: File types + required: true + status: + type: string + enum: + - Pass + - Fail + - Warn + - Not applicable + example: Pass + message: + type: string + example: Your flow has valid file types + required: true responses: CopyFlow: content: @@ -124,19 +143,20 @@ components: properties: message: type: string - required: false - description: - type: string - required: false + required: true alteredNodes: oneOf: - type: array items: $ref: "#/components/schemas/Node" - type: "null" - updatedFlow: - $ref: "#/components/schemas/FlowData" + validationChecks: required: false + oneOf: + - type: array + items: + $ref: "#/components/schemas/ValidationCheck" + - type: "null" FlattenData: content: application/json: diff --git a/api.planx.uk/modules/flows/validate/service.ts b/api.planx.uk/modules/flows/validate/service.ts index 231e001687..802f8f5c9e 100644 --- a/api.planx.uk/modules/flows/validate/service.ts +++ b/api.planx.uk/modules/flows/validate/service.ts @@ -199,9 +199,8 @@ const validateInviteToPay = (flowGraph: FlowGraph): ValidationResponse => { }; const inviteToPayEnabled = (flowGraph: FlowGraph): boolean => { - const payNodes = Object.entries(flowGraph).filter( - (entry): entry is [string, Node] => - isComponentType(entry, ComponentType.Pay), + const payNodes = Object.entries(flowGraph).filter((entry) => + isComponentType(entry, ComponentType.Pay), ); const payNodeStatuses = payNodes.map( ([_nodeId, node]) => node?.data?.allowInviteToPay, @@ -257,9 +256,8 @@ const validateFileTypes = (flowGraph: FlowGraph): ValidationResponse => { }; const getFileUploadNodeFns = (flowGraph: FlowGraph): string[] => { - const fileUploadNodes = Object.entries(flowGraph).filter( - (entry): entry is [string, Node] => - isComponentType(entry, ComponentType.FileUpload), + const fileUploadNodes = Object.entries(flowGraph).filter((entry) => + isComponentType(entry, ComponentType.FileUpload), ); return fileUploadNodes.map(([_nodeId, node]) => node.data?.fn as string); }; @@ -267,12 +265,12 @@ const getFileUploadNodeFns = (flowGraph: FlowGraph): string[] => { const getFileUploadAndLabelNodeFns = (flowGraph: FlowGraph): string[] => { // Exclude Upload & Label nodes used in "info-only" mode with a hidden dropzone const uploadAndLabelNodes = Object.entries(flowGraph).filter( - (entry): entry is [string, Node] => + (entry) => isComponentType(entry, ComponentType.FileUploadAndLabel) && entry[1].data?.hideDropZone !== true, ); const uploadAndLabelFileTypes = uploadAndLabelNodes - .map(([_nodeId, node]) => node.data?.fileTypes) + .map(([_nodeId, node]: [string, Node]) => node.data?.fileTypes) .flat(); return uploadAndLabelFileTypes?.map((file: any) => file?.fn as string); };