diff --git a/.github/workflows/pizza-teardown.yml b/.github/workflows/pizza-teardown.yml index 24e3de0de2..5eec564860 100644 --- a/.github/workflows/pizza-teardown.yml +++ b/.github/workflows/pizza-teardown.yml @@ -17,7 +17,7 @@ jobs: action: destroy api_key: ${{ secrets.VULTR_API_KEY }} domain: ${{ env.DOMAIN }} - os_type: ubuntu + os_type: alpine plan: vc2-1c-1gb pull_request_id: ${{ env.PULLREQUEST_ID }} region: lhr diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 8e89d32df7..1511916bc4 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -307,7 +307,7 @@ jobs: action: create api_key: ${{ secrets.VULTR_API_KEY }} domain: ${{ env.DOMAIN }} - os_type: ubuntu + os_type: alpine plan: vc2-1c-1gb pull_request_id: ${{ env.PULLREQUEST_ID }} region: lhr @@ -324,13 +324,19 @@ jobs: password: ${{ steps.create.outputs.default_password }} command_timeout: 20m script: | - apt-get update -y - + apk update + apk add docker + addgroup root docker + rc-update add docker default + service docker start + apk add docker-cli-compose + + apk add git git clone "${{ secrets.AUTHENTICATED_REPO_URL }}" cd planx-new git fetch origin "pull/${{ env.PULLREQUEST_ID }}/head" && git checkout FETCH_HEAD - apt-get install awscli -y + apk add aws-cli export AWS_ACCESS_KEY_ID=${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }} export AWS_SECRET_ACCESS_KEY=${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }} export AWS_REGION=eu-west-2 @@ -352,15 +358,21 @@ jobs: username: root password: ${{ secrets.SSH_PASSWORD }} command_timeout: 10m + # TODO: some of below script might be superfluous for server update (rather than create) script: | - apt-get update -y + apk update + apk add docker + addgroup root docker + rc-update add docker default + service docker start + apk add docker-cli-compose git clone "${{ secrets.AUTHENTICATED_REPO_URL }}" cd planx-new git add . && git stash git fetch origin "pull/${{ env.PULLREQUEST_ID }}/head" && git checkout FETCH_HEAD - apt-get install awscli -y + apk add aws-cli export AWS_ACCESS_KEY_ID=${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }} export AWS_SECRET_ACCESS_KEY=${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }} export AWS_REGION=eu-west-2 diff --git a/.gitignore b/.gitignore index 133d7d8670..d2d8497fb8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ api.planx.uk/tmp/ # Ignore certificate files **/*.chain **/*.cert +**/*.crt **/*.key **/*.pfx **/*.pkcs12 diff --git a/editor.planx.uk/src/@planx/components/List/Public/Context.tsx b/editor.planx.uk/src/@planx/components/List/Public/Context.tsx index 38bb5b1ec4..8d7f033828 100644 --- a/editor.planx.uk/src/@planx/components/List/Public/Context.tsx +++ b/editor.planx.uk/src/@planx/components/List/Public/Context.tsx @@ -129,7 +129,7 @@ export const ListProvider: React.FC = (props) => { if (formik.values.userData.length < schema.min) { return setMinError(true); } - + formik.handleSubmit(); }; diff --git a/editor.planx.uk/src/@planx/components/List/Public/Fields.tsx b/editor.planx.uk/src/@planx/components/List/Public/Fields.tsx index 8fad6c35db..961e219c8c 100644 --- a/editor.planx.uk/src/@planx/components/List/Public/Fields.tsx +++ b/editor.planx.uk/src/@planx/components/List/Public/Fields.tsx @@ -6,6 +6,7 @@ import MenuItem from "@mui/material/MenuItem"; import RadioGroup from "@mui/material/RadioGroup"; import { visuallyHidden } from "@mui/utils"; import { getIn } from "formik"; +import { get } from "lodash"; import React from "react"; import SelectInput from "ui/editor/SelectInput"; import InputLabel from "ui/public/InputLabel"; @@ -23,21 +24,14 @@ import type { TextField, } from "../model"; import { useListContext } from "./Context"; -import { get } from "lodash"; type Props = T & { id: string }; -export const TextFieldInput: React.FC> = ({ - id, - data, -}) => { +export const TextFieldInput: React.FC> = ({ id, data }) => { const { formik, activeIndex } = useListContext(); return ( - + { if (type === "email") return "email"; @@ -48,10 +42,7 @@ export const TextFieldInput: React.FC> = ({ bordered value={formik.values.userData[activeIndex][data.fn]} onChange={formik.handleChange} - errorMessage={get( - formik.errors, - ["userData", activeIndex, data.fn], - )} + errorMessage={get(formik.errors, ["userData", activeIndex, data.fn])} id={id} rows={ data.type && ["long", "extraLong"].includes(data.type) ? 5 : undefined @@ -80,10 +71,7 @@ export const NumberFieldInput: React.FC> = ({ const { formik, activeIndex } = useListContext(); return ( - + > = ({ type="number" value={formik.values.userData[activeIndex][data.fn]} onChange={formik.handleChange} - errorMessage={get( - formik.errors, - ["userData", activeIndex, data.fn], - )} + errorMessage={get(formik.errors, ["userData", activeIndex, data.fn])} inputProps={{ "aria-describedby": [ data.description ? DESCRIPTION_TEXT : "", @@ -161,10 +146,7 @@ export const SelectFieldInput: React.FC> = (props) => { const { id, data } = props; return ( - + { describe("Form validation and error handling", () => { test("form validation is triggered when saving an item", async () => { - const { user, getByRole, getAllByTestId } = setup(); + const { user, getByRole, getAllByTestId } = setup( + , + ); let errorMessages = getAllByTestId(/error-message-input/); - + // Each field has an ErrorWrapper - expect(errorMessages).toHaveLength(mockZooProps.schema.fields.length) + expect(errorMessages).toHaveLength(mockZooProps.schema.fields.length); // All are empty initially - errorMessages.forEach(message => { + errorMessages.forEach((message) => { expect(message).toBeEmptyDOMElement(); }); await user.click(getByRole("button", { name: /Save/ })); - + // Error wrappers persist errorMessages = getAllByTestId(/error-message-input/); - expect(errorMessages).toHaveLength(mockZooProps.schema.fields.length) + expect(errorMessages).toHaveLength(mockZooProps.schema.fields.length); // Each field is in an error state - errorMessages.forEach(message => { + errorMessages.forEach((message) => { expect(message).not.toBeEmptyDOMElement(); - }); + }); }); /** @@ -410,62 +412,95 @@ describe("Form validation and error handling", () => { */ describe("existing validation schemas are correctly referenced", () => { test("text fields", async () => { - const { user, getByRole, getByTestId } = setup(); + const { user, getByRole, getByTestId } = setup( + , + ); const nameInput = screen.getByLabelText(/name/); - await user.type(nameInput, "This is a long string of text over one hundred and twenty characters, which should trigger the 'short' text validation warning"); + await user.type( + nameInput, + "This is a long string of text over one hundred and twenty characters, which should trigger the 'short' text validation warning", + ); await user.click(getByRole("button", { name: /Save/ })); - const nameInputErrorMessage = getByTestId(/error-message-input-text-name/); + const nameInputErrorMessage = getByTestId( + /error-message-input-text-name/, + ); - expect(nameInputErrorMessage).toHaveTextContent(/Your answer must be 120 characters or fewer/); + expect(nameInputErrorMessage).toHaveTextContent( + /Your answer must be 120 characters or fewer/, + ); }); test("number fields", async () => { - const { user, getByRole, getByTestId } = setup(); + const { user, getByRole, getByTestId } = setup( + , + ); const ageInput = screen.getByLabelText(/old/); await user.type(ageInput, "-35"); await user.click(getByRole("button", { name: /Save/ })); - const ageInputErrorMessage = getByTestId(/error-message-input-number-age/); + const ageInputErrorMessage = getByTestId( + /error-message-input-number-age/, + ); expect(ageInputErrorMessage).toHaveTextContent(/Enter a positive number/); }); test("question fields", async () => { - const { user, getByRole, getByTestId } = setup(); + const { user, getByRole, getByTestId } = setup( + , + ); await user.click(getByRole("button", { name: /Save/ })); - const sizeInputErrorMessage = getByTestId(/error-message-input-question-size/); + const sizeInputErrorMessage = getByTestId( + /error-message-input-question-size/, + ); - expect(sizeInputErrorMessage).toHaveTextContent(/Select your answer before continuing/); + expect(sizeInputErrorMessage).toHaveTextContent( + /Select your answer before continuing/, + ); }); test("radio fields", async () => { - const { user, getByRole, getByTestId } = setup(); + const { user, getByRole, getByTestId } = setup( + , + ); await user.click(getByRole("button", { name: /Save/ })); - const cuteInputErrorMessage = getByTestId(/error-message-input-question-cute/); + const cuteInputErrorMessage = getByTestId( + /error-message-input-question-cute/, + ); - expect(cuteInputErrorMessage).toHaveTextContent(/Select your answer before continuing/); + expect(cuteInputErrorMessage).toHaveTextContent( + /Select your answer before continuing/, + ); }); test("checklist fields", async () => { - const { user, getByRole, getByTestId } = setup(); + const { user, getByRole, getByTestId } = setup( + , + ); await user.click(getByRole("button", { name: /Save/ })); - const foodInputErrorMessage = getByTestId(/error-message-input-checklist-food/); + const foodInputErrorMessage = getByTestId( + /error-message-input-checklist-food/, + ); - expect(foodInputErrorMessage).toHaveTextContent(/Select at least one option/); - }) + expect(foodInputErrorMessage).toHaveTextContent( + /Select at least one option/, + ); + }); }); test("an error displays if the minimum number of items is not met", async () => { - const { user, getByRole, getByTestId, getByText } = setup(); + const { user, getByRole, getByTestId, getByText } = setup( + , + ); const minNumberOfItems = mockZooProps.schema.min; expect(minNumberOfItems).toEqual(1); @@ -473,12 +508,16 @@ describe("Form validation and error handling", () => { await user.click(getByRole("button", { name: /Cancel/ })); await user.click(getByTestId("continue-button")); - const minItemsErrorMessage = getByText(`You must provide at least ${minNumberOfItems} response(s)`) + const minItemsErrorMessage = getByText( + `You must provide at least ${minNumberOfItems} response(s)`, + ); expect(minItemsErrorMessage).toBeVisible(); }); test("an error displays if the maximum number of items is exceeded", async () => { - const { user, getAllByTestId, getByTestId, getByText } = setup(); + const { user, getAllByTestId, getByTestId, getByText } = setup( + , + ); const addItemButton = getByTestId(/list-add-button/); const maxNumberOfItems = mockZooProps.schema.max; @@ -497,45 +536,51 @@ describe("Form validation and error handling", () => { // Try to add a fourth await user.click(getByTestId(/list-add-button/)); - const maxItemsErrorMessage = getByText(`You can provide at most ${maxNumberOfItems} response(s)`) + const maxItemsErrorMessage = getByText( + `You can provide at most ${maxNumberOfItems} response(s)`, + ); expect(maxItemsErrorMessage).toBeVisible(); }); - test( - "an error displays if you add a new item, without saving the active item", async () => { - const { user, getByTestId, getByText, getByLabelText } = setup(); - // Start filling out item - const nameInput = getByLabelText(/name/); - await user.type(nameInput, "Richard Parker"); - - const emailInput = getByLabelText(/email/); - await user.type(emailInput, "richard.parker@pi.com"); - - // Try to add a new item - await user.click(getByTestId(/list-add-button/)); - - const activeItemErrorMessage = getByText(/Please save all responses before adding another/) - expect(activeItemErrorMessage).toBeVisible(); - } - ); - - test( - "an error displays if you continue, without saving the active item", async () => { - const { user, getByTestId, getByText, getByLabelText } = setup(); - // Start filling out item - const nameInput = getByLabelText(/name/); - await user.type(nameInput, "Richard Parker"); - - const emailInput = getByLabelText(/email/); - await user.type(emailInput, "richard.parker@pi.com"); - - // Try to continue - await user.click(getByTestId(/continue-button/)); - - const unsavedItemErrorMessage = getByText(/Please save in order to continue/) - expect(unsavedItemErrorMessage).toBeVisible(); - } - ); + test("an error displays if you add a new item, without saving the active item", async () => { + const { user, getByTestId, getByText, getByLabelText } = setup( + , + ); + // Start filling out item + const nameInput = getByLabelText(/name/); + await user.type(nameInput, "Richard Parker"); + + const emailInput = getByLabelText(/email/); + await user.type(emailInput, "richard.parker@pi.com"); + + // Try to add a new item + await user.click(getByTestId(/list-add-button/)); + + const activeItemErrorMessage = getByText( + /Please save all responses before adding another/, + ); + expect(activeItemErrorMessage).toBeVisible(); + }); + + test("an error displays if you continue, without saving the active item", async () => { + const { user, getByTestId, getByText, getByLabelText } = setup( + , + ); + // Start filling out item + const nameInput = getByLabelText(/name/); + await user.type(nameInput, "Richard Parker"); + + const emailInput = getByLabelText(/email/); + await user.type(emailInput, "richard.parker@pi.com"); + + // Try to continue + await user.click(getByTestId(/continue-button/)); + + const unsavedItemErrorMessage = getByText( + /Please save in order to continue/, + ); + expect(unsavedItemErrorMessage).toBeVisible(); + }); }); describe("Payload generation", () => { @@ -559,9 +604,8 @@ describe("Payload generation", () => { it("generates a valid payload with summary stats on submission (Units)", async () => { const handleSubmit = jest.fn(); - const { getByTestId, user, getByRole, getAllByRole, getByLabelText } = setup( - , - ); + const { getByTestId, user, getByRole, getAllByRole, getByLabelText } = + setup(); const addItemButton = getByTestId("list-add-button"); @@ -601,7 +645,7 @@ describe("Payload generation", () => { gardenYesRadio = getAllByRole("radio")[0]; gardenNoRadio = getAllByRole("radio")[1]; unitsNumberInput = getByLabelText(/identical units/); - + await user.click(developmentSelect); await user.click(getByRole("option", { name: /Change of use to a home/ })); await user.click(gardenNoRadio); @@ -611,7 +655,7 @@ describe("Payload generation", () => { await user.click(getByTestId("continue-button")); expect(handleSubmit).toHaveBeenCalled(); - const output = handleSubmit.mock.calls[0][0] + const output = handleSubmit.mock.calls[0][0]; expect(output).toMatchObject(mockUnitsPayload); }); }); diff --git a/editor.planx.uk/src/@planx/components/List/Public/index.tsx b/editor.planx.uk/src/@planx/components/List/Public/index.tsx index c0d3136c29..52ae77b23e 100644 --- a/editor.planx.uk/src/@planx/components/List/Public/index.tsx +++ b/editor.planx.uk/src/@planx/components/List/Public/index.tsx @@ -70,14 +70,14 @@ const ActiveListCard: React.FC<{ }> = ({ index: i }) => { const { schema, saveItem, cancelEditItem, errors, isPageComponent } = useListContext(); - + const ref = useRef(null); useEffect(() => { if (ref.current) { - ref.current.scrollIntoView({ behavior: "smooth" }) + ref.current.scrollIntoView({ behavior: "smooth" }); } }, []); - + return ( = ({ } if ( - destinations.includes(Destination.Idox) && - isReady && + destinations.includes(Destination.Idox) && + isReady && props.handleSubmit ) { props.handleSubmit( - makeData(props, request.value.idox?.event_id, "idoxSendEventId") + makeData(props, request.value.idox?.event_id, "idoxSendEventId"), ); } diff --git a/editor.planx.uk/src/@planx/components/SetValue/Editor.tsx b/editor.planx.uk/src/@planx/components/SetValue/Editor.tsx index f3926067ee..b36c1e37f0 100644 --- a/editor.planx.uk/src/@planx/components/SetValue/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/SetValue/Editor.tsx @@ -106,7 +106,7 @@ function SetValueComponent(props: Props) { /> - {formik.values.operation !== "removeAll" && + {formik.values.operation !== "removeAll" && ( - } + )} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ButtonForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ButtonForm.tsx index 464cf9a215..1a8383e325 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ButtonForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ButtonForm.tsx @@ -61,6 +61,7 @@ export const ButtonForm: React.FC = ({ color={formik.values.actionColour} onChange={(color) => formik.setFieldValue("actionColour", color)} label="Button colour" + errorMessage={formik.errors.actionColour} /> diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/TextLinkForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/TextLinkForm.tsx index 6064cbac15..6f454d6144 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/TextLinkForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/TextLinkForm.tsx @@ -70,6 +70,7 @@ export const TextLinkForm: React.FC = ({ color={formik.values.linkColour} onChange={(color) => formik.setFieldValue("linkColour", color)} label="Text link colour" + errorMessage={formik.errors.linkColour} /> diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ThemeAndLogoForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ThemeAndLogoForm.tsx index 2ab48b447b..3629d5d0c5 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ThemeAndLogoForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/DesignSettings/ThemeAndLogoForm.tsx @@ -86,6 +86,7 @@ export const ThemeAndLogoForm: React.FC = ({ formik.setFieldValue("primaryColour", color) } label="Theme colour" + errorMessage={formik.errors.primaryColour} /> diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/BoundaryForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/BoundaryForm.tsx index a33aa3d16c..f59e2bee97 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/BoundaryForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/BoundaryForm.tsx @@ -3,13 +3,23 @@ import { useStore } from "pages/FlowEditor/lib/store"; import React, { ChangeEvent } from "react"; import InputLabel from "ui/editor/InputLabel"; import Input from "ui/shared/Input"; +import * as Yup from "yup"; import { SettingsForm } from "../shared/SettingsForm"; import { FormProps } from "."; export default function BoundaryForm({ formikConfig, onSuccess }: FormProps) { + const formSchema = Yup.object().shape({ + boundaryUrl: Yup.string() + .url( + "Enter a boundary URL in the correct format, https://www.planning.data.gov.uk/", + ) + .required("Enter a boundary URL"), + }); + const formik = useFormik({ ...formikConfig, + validationSchema: formSchema, onSubmit: async (values, { resetForm }) => { const isSuccess = await useStore.getState().updateTeamSettings({ boundaryUrl: values.boundaryUrl, @@ -49,6 +59,7 @@ export default function BoundaryForm({ formikConfig, onSuccess }: FormProps) { ) => { formik.setFieldValue("boundaryUrl", ev.target.value); }} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/ContactForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/ContactForm.tsx index 906ab6531d..7924634a00 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/ContactForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/ContactForm.tsx @@ -11,12 +11,16 @@ import { FormProps } from "."; export default function ContactForm({ formikConfig, onSuccess }: FormProps) { const formSchema = Yup.object().shape({ helpEmail: Yup.string() - .email("Please enter valid email") - .required("Help Email is required"), - helpPhone: Yup.string().required("Help Phone is required"), - helpOpeningHours: Yup.string().required(), + .email( + "Enter an email address in the correct format, like example@email.com", + ) + .required("Enter a help email address"), + helpPhone: Yup.string().required("Enter a help phone number"), + helpOpeningHours: Yup.string().required("Enter your opening hours"), homepage: Yup.string() - .url("Please enter a valid URL for the homepage") + .url( + "Enter a homepage URL in the correct format, like https://www.localauthority.gov.uk/", + ) .required("Enter a homepage"), }); @@ -59,6 +63,7 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { onChangeFn("homepage", event); }} value={formik.values.homepage} + errorMessage={formik.errors.homepage} id="homepage" /> @@ -66,6 +71,7 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { { onChangeFn("helpEmail", event); }} @@ -76,6 +82,7 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { { onChangeFn("helpPhone", event); }} @@ -87,6 +94,7 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { multiline name="helpOpeningHours" value={formik.values.helpOpeningHours} + errorMessage={formik.errors.helpOpeningHours} onChange={(event) => { onChangeFn("helpOpeningHours", event); }} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/shared/SettingsForm.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/shared/SettingsForm.tsx index 61b67c6f6c..10cf9fefee 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/shared/SettingsForm.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/shared/SettingsForm.tsx @@ -40,27 +40,21 @@ export const SettingsForm = ({ {preview} )} - - - - - - - + + + + ); diff --git a/editor.planx.uk/src/ui/editor/ColorPicker.tsx b/editor.planx.uk/src/ui/editor/ColorPicker.tsx index d855547bc1..3f56a4e996 100644 --- a/editor.planx.uk/src/ui/editor/ColorPicker.tsx +++ b/editor.planx.uk/src/ui/editor/ColorPicker.tsx @@ -2,13 +2,16 @@ import Box, { BoxProps } from "@mui/material/Box"; import ButtonBase, { ButtonBaseProps } from "@mui/material/ButtonBase"; import { styled } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; +import { ErrorMessage } from "formik"; import React, { useState } from "react"; import { ChromePicker, ColorChangeHandler } from "react-color"; +import ErrorWrapper from "ui/shared/ErrorWrapper"; export interface Props { label?: string; inline?: boolean; color?: string; + errorMessage?: string; onChange?: (newColor: string) => void; } @@ -93,28 +96,33 @@ export default function ColorPicker(props: Props): FCReturn { }; return ( - - - {props.label || "Background colour"}:{" "} - - - - {props.color} - - {show ? ( - - - - - ) : null} - + + + + {props.label || "Background colour"}:{" "} + + + + {props.color} + + {show ? ( + + + + + ) : null} + + ); } diff --git a/editor.planx.uk/src/ui/shared/Checkbox.tsx b/editor.planx.uk/src/ui/shared/Checkbox.tsx index 37969b1e90..db2fe034f2 100644 --- a/editor.planx.uk/src/ui/shared/Checkbox.tsx +++ b/editor.planx.uk/src/ui/shared/Checkbox.tsx @@ -57,9 +57,9 @@ export default function Checkbox({ inputProps, }: Props): FCReturn { const handleChange = (e: React.MouseEvent) => { - e.preventDefault() + e.preventDefault(); onChange && onChange(); - } + }; return ( diff --git a/hasura.planx.uk/metadata/tables.yaml b/hasura.planx.uk/metadata/tables.yaml index 1bab36f613..31b922cac7 100644 --- a/hasura.planx.uk/metadata/tables.yaml +++ b/hasura.planx.uk/metadata/tables.yaml @@ -157,7 +157,7 @@ definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 30 num_retries: 1 @@ -171,7 +171,7 @@ query_params: type: bops-submission template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/send-slack-notification" + url: '{{$base_url}}/webhooks/hasura/send-slack-notification' version: 2 - table: name: document_template @@ -225,7 +225,7 @@ definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 30 num_retries: 1 @@ -239,7 +239,7 @@ query_params: type: email-submission template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/send-slack-notification" + url: '{{$base_url}}/webhooks/hasura/send-slack-notification' version: 2 - table: name: feedback @@ -451,9 +451,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http - role: platformAdmin permission: @@ -475,9 +475,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http - role: teamEditor permission: @@ -506,9 +506,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http select_permissions: - role: api @@ -609,9 +609,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http - role: platformAdmin permission: @@ -629,9 +629,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http - role: teamEditor permission: @@ -656,9 +656,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http delete_permissions: - role: platformAdmin @@ -689,9 +689,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http select_permissions: - role: platformAdmin @@ -724,9 +724,9 @@ forward_client_headers: false headers: - name: authorization - value: "{{HASURA_PLANX_API_KEY}}" + value: '{{HASURA_PLANX_API_KEY}}' timeout: 10 - url: "{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html" + url: '{{HASURA_PLANX_API_URL}}/webhooks/hasura/validate-input/jsonb/clean-html' type: http - table: name: lowcal_sessions @@ -873,7 +873,7 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/send-email/confirmation" + url: '{{$base_url}}/send-email/confirmation' version: 2 - name: setup_lowcal_expiry_events definition: @@ -903,7 +903,7 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-expiry-event" + url: '{{$base_url}}/webhooks/hasura/create-expiry-event' version: 2 - name: setup_lowcal_reminder_events definition: @@ -933,7 +933,7 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-reminder-event" + url: '{{$base_url}}/webhooks/hasura/create-reminder-event' version: 2 - table: name: operations @@ -1110,7 +1110,7 @@ definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 10 num_retries: 3 @@ -1132,13 +1132,13 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-payment-expiry-events" + url: '{{$base_url}}/webhooks/hasura/create-payment-expiry-events' version: 2 - name: setup_payment_invitation_events definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 10 num_retries: 3 @@ -1160,13 +1160,13 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-payment-invitation-events" + url: '{{$base_url}}/webhooks/hasura/create-payment-invitation-events' version: 2 - name: setup_payment_reminder_events definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 10 num_retries: 3 @@ -1188,7 +1188,7 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-payment-reminder-events" + url: '{{$base_url}}/webhooks/hasura/create-payment-reminder-events' version: 2 - name: setup_payment_send_events definition: @@ -1217,7 +1217,7 @@ method: POST query_params: {} template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/create-payment-send-events" + url: '{{$base_url}}/webhooks/hasura/create-payment-send-events' version: 2 - table: name: payment_status @@ -1662,7 +1662,7 @@ columns: - id - team_id - - boundary_json + - boundary_bbox - boundary_url - email_reply_to_id - external_planning_site_name @@ -1679,7 +1679,7 @@ columns: - id - team_id - - boundary_json + - boundary_bbox - boundary_url - email_reply_to_id - external_planning_site_name @@ -1694,7 +1694,7 @@ - role: public permission: columns: - - boundary_json + - boundary_bbox - boundary_url - email_reply_to_id - external_planning_site_name @@ -1713,7 +1713,7 @@ columns: - id - team_id - - boundary_json + - boundary_bbox - boundary_url - email_reply_to_id - external_planning_site_name @@ -2064,7 +2064,7 @@ definition: enable_manual: false insert: - columns: "*" + columns: '*' retry_conf: interval_sec: 30 num_retries: 1 @@ -2078,7 +2078,7 @@ query_params: type: uniform-submission template_engine: Kriti - url: "{{$base_url}}/webhooks/hasura/send-slack-notification" + url: '{{$base_url}}/webhooks/hasura/send-slack-notification' version: 2 - table: name: user_roles diff --git a/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/down.sql b/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/down.sql new file mode 100644 index 0000000000..91c81c2392 --- /dev/null +++ b/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/down.sql @@ -0,0 +1 @@ +alter table "public"."team_settings" rename column "boundary_bbox" to "boundary_json"; diff --git a/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/up.sql b/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/up.sql new file mode 100644 index 0000000000..6379f408d1 --- /dev/null +++ b/hasura.planx.uk/migrations/1720175441656_alter_table_public_team_settings_alter_column_boundary_json/up.sql @@ -0,0 +1 @@ +alter table "public"."team_settings" rename column "boundary_json" to "boundary_bbox"; diff --git a/infrastructure/application/Pulumi.production.yaml b/infrastructure/application/Pulumi.production.yaml index 199fd0a32d..2065d18a51 100644 --- a/infrastructure/application/Pulumi.production.yaml +++ b/infrastructure/application/Pulumi.production.yaml @@ -57,6 +57,10 @@ config: secure: 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 application:ssl-doncaster-key: secure: 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 + application:ssl-epsom-and-ewell-cert: + secure: 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 + application:ssl-epsom-and-ewell-key: + secure: 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 application:ssl-gateshead-cert: secure: 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 application:ssl-gateshead-chain: diff --git a/infrastructure/application/index.ts b/infrastructure/application/index.ts index 26deceb602..a5817ffe67 100644 --- a/infrastructure/application/index.ts +++ b/infrastructure/application/index.ts @@ -76,6 +76,10 @@ const CUSTOM_DOMAINS: CustomDomains = domain: "planningservices.gloucester.gov.uk", name: "gloucester", }, + { + domain: "planningservices.epsom-ewell.gov.uk", + name: "epsom-and-ewell", + }, ] : []; diff --git a/scripts/pullrequest/create.sh b/scripts/pullrequest/create.sh index c8fc91cadf..6f0f9394f5 100755 --- a/scripts/pullrequest/create.sh +++ b/scripts/pullrequest/create.sh @@ -10,15 +10,6 @@ echo "root:$SSH_PASSWORD" | chpasswd # https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-22-04 swapon --show -# install docker -apt-get install apt-transport-https ca-certificates curl gnupg lsb-release -y -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --batch --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -echo \ - "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null -apt-get update -y -apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y - # set env for this shell set -o allexport source .env.pizza diff --git a/scripts/seed-database/write/team_settings.sql b/scripts/seed-database/write/team_settings.sql index 1278dac0aa..ad7d7ac281 100644 --- a/scripts/seed-database/write/team_settings.sql +++ b/scripts/seed-database/write/team_settings.sql @@ -11,7 +11,7 @@ CREATE TEMPORARY TABLE sync_team_settings ( external_planning_site_url text, external_planning_site_name text, boundary_url text, - boundary_json jsonb + boundary_bbox jsonb ); \copy sync_team_settings FROM '/tmp/team_settings.csv' WITH (FORMAT csv, DELIMITER ';'); @@ -29,7 +29,7 @@ INSERT INTO external_planning_site_url, external_planning_site_name, boundary_url, - boundary_json + boundary_bbox ) SELECT id, @@ -43,7 +43,7 @@ SELECT external_planning_site_url, external_planning_site_name, boundary_url, - boundary_json + boundary_bbox FROM sync_team_settings ON CONFLICT (id) DO UPDATE @@ -58,7 +58,7 @@ SET external_planning_site_url = EXCLUDED.external_planning_site_url, external_planning_site_name = EXCLUDED.external_planning_site_name, boundary_url = EXCLUDED.boundary_url, - boundary_json = EXCLUDED.boundary_json; + boundary_bbox = EXCLUDED.boundary_bbox; SELECT setval('team_settings_id_seq', max(id)) FROM