Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Production deploy #3802

Merged
merged 6 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ We'd love to hear what you're building on Planx, don't hesitate to get in touch

The root of the project has several scripts set up to help you manage your docker containers:

- `pnpm run up` alias for `pnpm recreate && pnpm add-data`
- `pnpm run up` alias for `pnpm recreate && pnpm sync-data`
- `pnpm run down` alias for `pnpm destroy`
- `pnpm run restart` alias for `pnpm stop && pnpm start`
- `pnpm start` will (re)create docker containers without rebuilding them
- `pnpm stop` will stop your docker containers without destroying them
- `pnpm recreate` will build and (re)start your docker containers from scratch.
- `pnpm destroy` will remove volumes (i.e. database data) and can be a useful hard reset when necessary.
- `pnpm add-data` will sync production records with modified data in your database
- `pnpm sync-data` will sync production records with modified data in your database
- `pnpm clean-data` will sync production records and reset any modified data
- `pnpm tests` will recreate your docker containers and include test services
- `pnpm analytics` will recreate your docker containers and include [Metabase](https://www.metabase.com/)
Expand Down
8 changes: 0 additions & 8 deletions api.planx.uk/modules/auth/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ export const failedLogin: RequestHandler = (_req, _res, next) =>
message: "User failed to authenticate",
});

export const logout: RequestHandler = (req, res) => {
// TODO: implement dual purpose as Microsoft frontend logout channel
req.logout(() => {
// do nothing
});
res.redirect(process.env.EDITOR_URL_EXT!);
};

export const handleSuccess = (req: Request, res: Response) => {
if (!req.user) {
return res.json({
Expand Down
23 changes: 16 additions & 7 deletions api.planx.uk/modules/auth/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ tags:
- name: auth
description: Authentication related requests
paths:
/logout:
get:
summary: Logout from the PlanX service
tags: ["auth"]
responses:
"302":
description: Redirect to PlanX Editor
/auth/login/failed:
get:
summary: Failed login
Expand Down Expand Up @@ -44,3 +37,19 @@ paths:
responses:
"200":
description: OK
/auth/microsoft:
get:
summary: Authenticate via Microsoft SSO
description: The first step in Microsoft authentication will involve redirecting the user to login.microsoftonline.com
tags: ["auth"]
responses:
"200":
description: OK
/auth/microsoft/callback:
get:
summary: Generate a JWT for an authenticated user
description: After authentication, Microsoft will redirect the user back to this route which generates a JWT for the user
tags: ["auth"]
responses:
"200":
description: OK
2 changes: 0 additions & 2 deletions api.planx.uk/modules/auth/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import * as Controller from "./controller.js";
export default (passport: Authenticator): Router => {
const router = Router();

router.get("/logout", Controller.logout);
// router.get("/auth/frontchannel-logout", Controller.frontChannelLogout)
router.get("/auth/login/failed", Controller.failedLogin);
router.get("/auth/google", Middleware.getGoogleAuthHandler(passport));
router.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
141 changes: 141 additions & 0 deletions editor.planx.uk/src/@planx/components/Filter/Editor.test.tsx
Original file line number Diff line number Diff line change
@@ -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(<Filter handleSubmit={handleSubmit} />);

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(<Filter handleSubmit={handleSubmit} />);

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(
<Filter
id="filterNodeId"
node={mockExistingFilterNode}
handleSubmit={handleSubmit}
/>,
);

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,
},
}));
90 changes: 61 additions & 29 deletions editor.planx.uk/src/@planx/components/Filter/Editor.tsx
Original file line number Diff line number Diff line change
@@ -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> = (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 (
<form onSubmit={formik.handleSubmit} id="modal">
<h1>Filter Component</h1>
<form
onSubmit={formik.handleSubmit}
id="modal"
data-testid="filter-component-form"
>
<ModalSection>
<ModalSectionContent title="Filter" Icon={ICONS[TYPES.Filter]}>
<Typography variant="body2">
Filters automatically sort based on collected flags. Flags within a
category are ordered heirarchically and the filter will route
through the left-most matching flag option only.
</Typography>
</ModalSectionContent>
<ModalSectionContent title="Pick a flagset category (coming soon)">
<select
data-testid="flagset-category-select"
name="category"
value={formik.values.category}
onChange={formik.handleChange}
disabled
>
{Array.from(categories).map((category) => (
<option key={category} value={category}>
{category}
</option>
))}
</select>
</ModalSectionContent>
</ModalSection>
</form>
);
};
Expand Down
5 changes: 0 additions & 5 deletions editor.planx.uk/src/@planx/components/Filter/model.ts

This file was deleted.

Loading