diff --git a/e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts b/e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts
index 691f83a257..991dcd0bc5 100644
--- a/e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts
+++ b/e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts
@@ -62,7 +62,7 @@ test.describe("Flow creation, publish and preview", () => {
await expect(editor.nodeList).toContainText([
"Find property",
"an internal portalEdit Portal",
- "(Flags Filter)ImmuneMissing informationPermission neededPrior approvalNoticePermitted developmentNot development(No Result)",
+ "Filter - Planning permissionImmuneMissing informationPermission neededPrior approvalNoticePermitted developmentNot developmentNo flag result",
"Upload and label",
"Confirm your location plan",
"Planning constraints",
diff --git a/editor.planx.uk/src/@planx/components/Filter/Editor.test.tsx b/editor.planx.uk/src/@planx/components/Filter/Editor.test.tsx
new file mode 100644
index 0000000000..950d00b272
--- /dev/null
+++ b/editor.planx.uk/src/@planx/components/Filter/Editor.test.tsx
@@ -0,0 +1,141 @@
+import {
+ ComponentType as TYPES,
+ DEFAULT_FLAG_CATEGORY,
+ flatFlags,
+} from "@opensystemslab/planx-core/types";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import React from "react";
+import { setup } from "testUtils";
+import { vi } from "vitest";
+
+import Filter from "./Editor";
+
+test("Adding a filter without explicit props uses the default flagset", async () => {
+ const handleSubmit = vi.fn();
+
+ setup();
+
+ expect(screen.getByTestId("flagset-category-select")).toHaveValue(
+ DEFAULT_FLAG_CATEGORY,
+ );
+
+ fireEvent.submit(screen.getByTestId("filter-component-form"));
+
+ await waitFor(() =>
+ expect(handleSubmit).toHaveBeenCalledWith(
+ {
+ type: TYPES.Filter,
+ data: {
+ fn: "flag",
+ category: DEFAULT_FLAG_CATEGORY,
+ },
+ },
+ mockDefaultFlagOptions,
+ ),
+ );
+});
+
+test("Adding a filter and selecting a flagset category", async () => {
+ const handleSubmit = vi.fn();
+
+ setup();
+
+ expect(screen.getByTestId("flagset-category-select")).toHaveValue(
+ DEFAULT_FLAG_CATEGORY,
+ );
+
+ fireEvent.change(screen.getByTestId("flagset-category-select"), {
+ target: { value: "Community infrastructure levy" },
+ });
+
+ fireEvent.submit(screen.getByTestId("filter-component-form"));
+
+ await waitFor(() =>
+ expect(handleSubmit).toHaveBeenCalledWith(
+ {
+ type: TYPES.Filter,
+ data: {
+ fn: "flag",
+ category: "Community infrastructure levy",
+ },
+ },
+ mockCILFlagOptions,
+ ),
+ );
+});
+
+test("Updating an existing filter to another category", async () => {
+ const handleSubmit = vi.fn();
+
+ setup(
+ ,
+ );
+
+ expect(screen.getByTestId("flagset-category-select")).toHaveValue(
+ "Listed building consent",
+ );
+
+ fireEvent.change(screen.getByTestId("flagset-category-select"), {
+ target: { value: "Community infrastructure levy" },
+ });
+
+ fireEvent.submit(screen.getByTestId("filter-component-form"));
+
+ await waitFor(() =>
+ expect(handleSubmit).toHaveBeenCalledWith(
+ {
+ type: TYPES.Filter,
+ data: {
+ fn: "flag",
+ category: "Community infrastructure levy",
+ },
+ },
+ mockCILFlagOptions,
+ ),
+ );
+});
+
+const mockExistingFilterNode = {
+ data: {
+ fn: "flag",
+ category: "Listed building consent",
+ },
+ type: 500,
+ edges: ["flag1", "flag2", "flag3", "flag4", "blankFlag"],
+};
+
+const mockDefaultFlagOptions = [
+ ...flatFlags.filter((flag) => flag.category === DEFAULT_FLAG_CATEGORY),
+ {
+ category: DEFAULT_FLAG_CATEGORY,
+ text: "No flag result",
+ value: "",
+ },
+].map((flag) => ({
+ type: TYPES.Answer,
+ data: {
+ text: flag.text,
+ val: flag.value,
+ },
+}));
+
+const mockCILFlagOptions = [
+ ...flatFlags.filter(
+ (flag) => flag.category === "Community infrastructure levy",
+ ),
+ {
+ category: "Community infrastructure levy",
+ text: "No flag result",
+ value: "",
+ },
+].map((flag) => ({
+ type: TYPES.Answer,
+ data: {
+ text: flag.text,
+ val: flag.value,
+ },
+}));
diff --git a/editor.planx.uk/src/@planx/components/Filter/Editor.tsx b/editor.planx.uk/src/@planx/components/Filter/Editor.tsx
index 5d2f3f2b03..b7b84f8ec3 100644
--- a/editor.planx.uk/src/@planx/components/Filter/Editor.tsx
+++ b/editor.planx.uk/src/@planx/components/Filter/Editor.tsx
@@ -1,52 +1,84 @@
+import Typography from "@mui/material/Typography";
import {
+ ComponentType as TYPES,
DEFAULT_FLAG_CATEGORY,
flatFlags,
} from "@opensystemslab/planx-core/types";
-import { ComponentType as TYPES } from "@opensystemslab/planx-core/types";
import { useFormik } from "formik";
import React from "react";
+import ModalSection from "ui/editor/ModalSection";
+import ModalSectionContent from "ui/editor/ModalSectionContent";
+
+import { ICONS } from "../ui";
export interface Props {
id?: string;
- handleSubmit?: (d: any, c?: any) => void;
+ handleSubmit?: (data: any, children?: any) => void;
node?: any;
}
const Filter: React.FC = (props) => {
const formik = useFormik({
- initialValues: {},
+ initialValues: {
+ fn: "flag",
+ category: props?.node?.data?.category || DEFAULT_FLAG_CATEGORY,
+ },
onSubmit: (newValues) => {
- if (props.handleSubmit) {
- const children = props.id
- ? undefined
- : [
- ...flatFlags,
- {
- category: DEFAULT_FLAG_CATEGORY,
- text: "(No Result)",
- value: "",
- },
- ]
- .filter((f) => f.category === DEFAULT_FLAG_CATEGORY)
- .map((f) => ({
- type: TYPES.Answer,
- data: {
- text: f.text,
- val: f.value,
- },
- }));
+ if (props?.handleSubmit) {
+ const children = [
+ ...flatFlags,
+ {
+ category: formik.values.category,
+ text: "No flag result",
+ value: "",
+ },
+ ]
+ .filter((f) => f.category === formik.values.category)
+ .map((f) => ({
+ type: TYPES.Answer,
+ data: {
+ text: f.text,
+ val: f.value,
+ },
+ }));
- props.handleSubmit(
- { type: TYPES.Filter, data: { newValues, fn: "flag" } },
- children,
- );
+ props.handleSubmit({ type: TYPES.Filter, data: newValues }, children);
}
},
- validate: () => {},
});
+
+ const categories = new Set(flatFlags.map((flag) => flag.category));
+
return (
-
);
};
diff --git a/editor.planx.uk/src/@planx/components/Filter/model.ts b/editor.planx.uk/src/@planx/components/Filter/model.ts
deleted file mode 100644
index 0ca9cf9275..0000000000
--- a/editor.planx.uk/src/@planx/components/Filter/model.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface Filter {
- id?: string;
- handleSubmit?: (d: any, children: any) => void;
- node?: any;
-}
diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx
index 2537272cb3..4a043a42a7 100644
--- a/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx
+++ b/editor.planx.uk/src/pages/FlowEditor/components/Flow/components/Node.tsx
@@ -1,4 +1,7 @@
-import { ComponentType as TYPES } from "@opensystemslab/planx-core/types";
+import {
+ ComponentType as TYPES,
+ DEFAULT_FLAG_CATEGORY,
+} from "@opensystemslab/planx-core/types";
import React from "react";
import { ErrorBoundary } from "react-error-boundary";
import { exhaustiveCheck } from "utils";
@@ -63,7 +66,12 @@ const Node: React.FC = (props) => {
/>
);
case TYPES.Filter:
- return ;
+ return (
+
+ );
case TYPES.FindProperty:
return ;
case TYPES.List: