diff --git a/api.planx.uk/modules/gis/service/digitalLand.ts b/api.planx.uk/modules/gis/service/digitalLand.ts index 9298eefd31..96617f7e5a 100644 --- a/api.planx.uk/modules/gis/service/digitalLand.ts +++ b/api.planx.uk/modules/gis/service/digitalLand.ts @@ -28,6 +28,7 @@ export const localAuthorityMetadata: Record = { doncaster: require("./local_authorities/metadata/doncaster"), "epsom-and-ewell": require("./local_authorities/metadata/epsomAndEwell"), gateshead: require("./local_authorities/metadata/gateshead"), + gloucester: require("./local_authorities/metadata/gloucester"), lambeth: require("./local_authorities/metadata/lambeth"), medway: require("./local_authorities/metadata/medway"), newcastle: require("./local_authorities/metadata/newcastle"), diff --git a/api.planx.uk/modules/gis/service/local_authorities/metadata/gloucester.ts b/api.planx.uk/modules/gis/service/local_authorities/metadata/gloucester.ts new file mode 100644 index 0000000000..431ac5a29b --- /dev/null +++ b/api.planx.uk/modules/gis/service/local_authorities/metadata/gloucester.ts @@ -0,0 +1,25 @@ +/* +LAD20CD: E07000081 +LAD20NM: Gloucester +LAD20NMW: +FID: + +https://www.planning.data.gov.uk/entity/?dataset=article-4-direction&dataset=article-4-direction-area&geometry_curie=statistical-geography%3AE07000081&entry_date_day=&entry_date_month=&entry_date_year= +https://docs.google.com/spreadsheets/d/1ALSH4hiupdUlrA7Rq7jhfHnWr0-PcB-IzhsztPLl7FY/edit?gid=0#gid=0 +*/ + +import { LocalAuthorityMetadata } from "../../digitalLand"; + +const planningConstraints: LocalAuthorityMetadata["planningConstraints"] = { + article4: { + // Planx granular values link to Digital Land entity.reference + records: { + "article4.gloucester.southgateStreetConservationArea": + "Southgate Street Conservation Area", + "article4.gloucester.stMichaelsSquare": + "St Michael’s Square Article 4 direction", + }, + }, +}; + +export { planningConstraints }; diff --git a/editor.planx.uk/src/@planx/components/PlanningConstraints/List.tsx b/editor.planx.uk/src/@planx/components/PlanningConstraints/List.tsx index 60e0c59c81..86998af6dc 100644 --- a/editor.planx.uk/src/@planx/components/PlanningConstraints/List.tsx +++ b/editor.planx.uk/src/@planx/components/PlanningConstraints/List.tsx @@ -14,12 +14,16 @@ import type { Metadata, } from "@opensystemslab/planx-core/types"; import groupBy from "lodash/groupBy"; +import { useStore } from "pages/FlowEditor/lib/store"; import React, { ReactNode } from "react"; import ReactHtmlParser from "react-html-parser"; import { FONT_WEIGHT_SEMI_BOLD } from "theme"; import Caret from "ui/icons/Caret"; import ReactMarkdownOrHtml from "ui/shared/ReactMarkdownOrHtml"; +import { SiteAddress } from "../FindProperty/model"; +import { availableDatasets } from "./model"; + const CATEGORY_COLORS: Record = { "General policy": "#99C1DE", "Heritage and conservation": "#EDDCD2", @@ -70,7 +74,7 @@ export default function ConstraintsList({ data, metadata, }: ConstraintsListProps) { - const groupedConstraints = groupBy(data, (constraint: Constraint) => { + const groupedConstraints = groupBy(data, (constraint) => { return constraint.category; }); @@ -84,7 +88,7 @@ export default function ConstraintsList({ disableGutters disableSticky color="primary" - key={category} + key={`${category}-ls`} style={{ padding: 0, backgroundColor: CATEGORY_COLORS[category], @@ -105,10 +109,11 @@ export default function ConstraintsList({ {category} - - {groupedConstraints[category].map((con: any) => ( + + {groupedConstraints[category].map((con) => ( state.computePassport().data?._address, + ) as SiteAddress) || {}; const item = props.metadata?.name.replaceAll(" ", "-"); + const isSourcedFromPlanningData = + props.metadata?.plural !== "Classified roads"; + + // Some constraint categories search for entities amongst many PD datasets, but our `props.metadata.dataset` will only store reference to the last one + // Cross reference with `availableDatasets` in Editor to ensure map URL is filtered to include each possible dataset + const matchingDatasets = availableDatasets.find( + (d) => + props.metadata?.dataset && d.datasets.includes(props.metadata.dataset), + )?.datasets || [props?.metadata?.dataset]; + const encodedMatchingDatasets = matchingDatasets + ?.map((d) => `dataset=${d}`) + .join("&"); + const planningDataMapURL = `https://www.planning.data.gov.uk/map/?${encodedMatchingDatasets}#${latitude},${longitude},17.5z`; return ( - + theme.palette.background.default, }} > - <> + {`This property ${props?.content}`} @@ -169,42 +196,58 @@ function ConstraintListItem({ children, ...props }: ConstraintListItemProps) { sx={{ listStyleType: "disc", pl: 4, pt: 1 }} > {props.data && - props.data.map( - (record: any) => - record.name && ( - - - {record.name}{" "} - {record.name && record["documentation-url"] && ( - - ( - - source - - ) - - )} - - - ), - )} + props.data.map((record: any) => ( + + {isSourcedFromPlanningData ? ( + + + {record.name || + (record["flood-risk-level"] && + `${props.metadata?.name} - Level ${record["flood-risk-level"]}`) || + `Planning Data entity #${record.entity}`} + + + ) : ( + {record.name} + )} + + ))} )} - + + {isSourcedFromPlanningData ? ( + + {`View on the `} + + Planning Data map + + {` (opens in a new tab).`} + + ) : ( + + {`We searched Ordnance Survey MasterMap Highways using the Unique Street Reference Number of your property`} + {usrn && ` (${usrn})`} + + )} + {`How is it defined`} diff --git a/editor.planx.uk/src/components/EditorNavMenu.tsx b/editor.planx.uk/src/components/EditorNavMenu.tsx index 0471ebdc55..ecc8216885 100644 --- a/editor.planx.uk/src/components/EditorNavMenu.tsx +++ b/editor.planx.uk/src/components/EditorNavMenu.tsx @@ -116,18 +116,18 @@ function EditorNavMenu() { route: "/", accessibleBy: ["platformAdmin", "teamEditor", "teamViewer"], }, - { - title: "Admin panel", - Icon: AdminPanelSettingsIcon, - route: "admin-panel", - accessibleBy: ["platformAdmin"], - }, { title: "Global settings", Icon: TuneIcon, route: "global-settings", accessibleBy: ["platformAdmin"], }, + { + title: "Admin panel", + Icon: AdminPanelSettingsIcon, + route: "admin-panel", + accessibleBy: ["platformAdmin"], + }, ]; const teamLayoutRoutes: Route[] = [ @@ -138,9 +138,9 @@ function EditorNavMenu() { accessibleBy: ["platformAdmin", "teamEditor", "teamViewer"], }, { - title: "Team members", - Icon: GroupIcon, - route: `/${teamSlug}/members`, + title: "Settings", + Icon: TuneIcon, + route: `/${teamSlug}/general-settings`, accessibleBy: ["platformAdmin", "teamEditor"], }, { @@ -150,9 +150,9 @@ function EditorNavMenu() { accessibleBy: ["platformAdmin", "teamEditor"], }, { - title: "Settings", - Icon: TuneIcon, - route: `/${teamSlug}/general-settings`, + title: "Team members", + Icon: GroupIcon, + route: `/${teamSlug}/members`, accessibleBy: ["platformAdmin", "teamEditor"], }, ]; diff --git a/editor.planx.uk/src/lib/featureFlags.ts b/editor.planx.uk/src/lib/featureFlags.ts index 31cbfdf23c..90a52dfe3f 100644 --- a/editor.planx.uk/src/lib/featureFlags.ts +++ b/editor.planx.uk/src/lib/featureFlags.ts @@ -1,5 +1,5 @@ // add/edit/remove feature flags in array below -const AVAILABLE_FEATURE_FLAGS = [] as const; +const AVAILABLE_FEATURE_FLAGS = ["SEARCH"] as const; type FeatureFlag = (typeof AVAILABLE_FEATURE_FLAGS)[number]; 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 83d2438261..23527446a7 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 @@ -62,7 +62,7 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { onChange={(event) => { onChangeFn("homepage", event); }} - value={formik.values.homepage} + value={formik.values.homepage ?? ""} errorMessage={formik.errors.homepage} id="homepage" /> @@ -91,7 +91,6 @@ export default function ContactForm({ formikConfig, onSuccess }: FormProps) { { + const isSuccess = await useStore.getState().updateTeamSettings({ + referenceCode: values.referenceCode, + }); + if (isSuccess) { + onSuccess(); + resetForm({ values }); + } + }, + }); + + const onChangeFn = (type: string, event: ChangeEvent) => + formik.setFieldValue(type, event.target.value.toUpperCase()); + + return ( + + + Your local authority reference code is required for submissions. + This is a unique three-letter code per local authority. + + + The reference code can be found from Planning Data at:{" "} + + https://www.planning.data.gov.uk/entity/?dataset=local-authority + + + + } + input={ + <> + + { + onChangeFn("referenceCode", event); + }} + value={formik.values.referenceCode ?? ""} + errorMessage={formik.errors.referenceCode} + id="homepage" + /> + + + } + /> + ); +} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/index.tsx index 71ec6eeca2..1352092514 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/GeneralSettings/index.tsx @@ -10,6 +10,7 @@ import SettingsSection from "ui/editor/SettingsSection"; import BoundaryForm from "./BoundaryForm"; import ContactForm from "./ContactForm"; +import ReferenceCodeForm from "./ReferenceCodeForm"; export interface FormProps { formikConfig: FormikConfig; @@ -62,7 +63,7 @@ const GeneralSettings: React.FC = () => { - General + Settings Important links and settings for how your users connect with you. @@ -72,6 +73,10 @@ const GeneralSettings: React.FC = () => { <> + )} diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search.tsx new file mode 100644 index 0000000000..679377c8cb --- /dev/null +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search.tsx @@ -0,0 +1,134 @@ +import Box from "@mui/material/Box"; +import Container from "@mui/material/Container"; +import Typography from "@mui/material/Typography"; +import { ComponentType } from "@opensystemslab/planx-core/types"; +import { ICONS } from "@planx/components/ui"; +import { debounce } from "lodash"; +import { useStore } from "pages/FlowEditor/lib/store"; +import React, { ChangeEvent, useCallback, useState } from "react"; +import useSWR from "swr"; +import { FONT_WEIGHT_SEMI_BOLD } from "theme"; +import InputLabel from "ui/editor/InputLabel"; +import ChecklistItem from "ui/shared/ChecklistItem"; +import Input from "ui/shared/Input"; + +const mockData: SearchResult[] = [ + { + nodeId: "abc123", + nodeType: ComponentType.Question, + nodeTitle: "Is the property in Lambeth?", + text: "Lambeth example biodiversity text", + path: ["_root", "xyz123", "abc123"], + }, + { + nodeId: "abc456", + nodeType: ComponentType.Notice, + nodeTitle: "It looks like the property is not in Lambeth", + text: "Lambeth example biodiversity text", + path: ["_root", "xyz123", "abc123"], + }, + { + nodeId: "abc789", + nodeType: ComponentType.Question, + nodeTitle: "What are you applying about?", + text: "Lambeth example biodiversity text", + path: ["_root", "xyz123", "abc123"], + }, +]; + +export interface SearchResult { + nodeId: string; + nodeType: ComponentType; + nodeTitle?: string; + text: string; + path: string[]; +} + +const SearchResults: React.FC<{ results: SearchResult[] }> = ({ results }) => { + return ( + + {results.map((result) => ( + + ))} + + ); +}; + +const SearchResultCard: React.FC = ({ + nodeTitle, + text, + nodeType, +}) => { + const Icon = ICONS[nodeType]; + + return ( + ({ + pb: 2, + borderBottom: `1px solid ${theme.palette.border.main}`, + })} + > + + {Icon && } + + Question + {nodeTitle && ` - ${nodeTitle}`} + + + {text} + + ); +}; + +const Search: React.FC = () => { + const [flowId] = useStore((state) => [state.id]); + const [query, setQuery] = useState(""); + const [debouncedQuery, setDebouncedQuery] = useState(query); + + const debounceSearch = useCallback( + debounce((input) => setDebouncedQuery(input), 500), + [], + ); + + const handleChange = (e: ChangeEvent) => { + const input = e.target.value; + setQuery(input); + debounceSearch(input); + }; + + const fetcher = (url: string) => fetch(url).then((r) => r.json()); + const endpoint = `${process.env.REACT_APP_API_URL}/flows/${flowId}/search`; + const { data, error } = useSWR( + debouncedQuery ? `${endpoint}?find=${debouncedQuery}` : null, + fetcher, + ); + + return ( + + + + + {}} + /> + + {error && "Something went wrong"} + {mockData ? : "Loading..."} + + + ); +}; + +export default Search; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx index 1cc8df1652..ed5ed9ab49 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx @@ -19,6 +19,7 @@ import Tabs from "@mui/material/Tabs"; import Tooltip from "@mui/material/Tooltip"; import Typography from "@mui/material/Typography"; import { AxiosError } from "axios"; +import { hasFeatureFlag } from "lib/featureFlags"; import { formatLastPublishMessage } from "pages/FlowEditor/utils"; import React, { useState } from "react"; import { useAsync } from "react-use"; @@ -34,8 +35,9 @@ import { ValidationCheck, ValidationChecks, } from "./PublishDialog"; +import Search from "./Search"; -type SidebarTabs = "PreviewBrowser" | "History"; +type SidebarTabs = "PreviewBrowser" | "History" | "Search"; const Console = styled(Box)(() => ({ overflow: "auto", @@ -449,6 +451,15 @@ const Sidebar: React.FC<{ value="History" label="History" /> + {hasFeatureFlag("SEARCH") && ( + + )} {activeTab === "PreviewBrowser" && ( @@ -463,6 +474,11 @@ const Sidebar: React.FC<{ )} + {activeTab === "Search" && ( + + + + )} {showDebugConsole && } ); diff --git a/editor.planx.uk/src/routes/index.tsx b/editor.planx.uk/src/routes/index.tsx index f2a6bc3449..831a73be98 100644 --- a/editor.planx.uk/src/routes/index.tsx +++ b/editor.planx.uk/src/routes/index.tsx @@ -71,10 +71,10 @@ export default isPreviewOnlyDomain }) : mount({ "/:team/:flow/published": lazy(() => import("./published")), // loads current published flow if exists, or throws Not Found if unpublished - "canterbury/find-out-if-you-need-planning-permission/preview": map( + "/canterbury/find-out-if-you-need-planning-permission/preview": map( async (req) => redirect( - `/canterbury-find-out-if-you-need-planning-permission/published${req?.search}`, + `/canterbury/find-out-if-you-need-planning-permission/published${req?.search}`, ), ), // temporary redirect while Canterbury works with internal IT to update advertised service links "/:team/:flow/preview": lazy(() => import("./preview")), // loads current draft flow and latest published external portals, or throws Not Found if any external portal is unpublished diff --git a/editor.planx.uk/src/ui/shared/Checkbox.tsx b/editor.planx.uk/src/ui/shared/Checkbox.tsx index db2fe034f2..90e816b41b 100644 --- a/editor.planx.uk/src/ui/shared/Checkbox.tsx +++ b/editor.planx.uk/src/ui/shared/Checkbox.tsx @@ -1,9 +1,11 @@ -import Box from "@mui/material/Box"; +import Box, { BoxProps } from "@mui/material/Box"; import { styled } from "@mui/material/styles"; import React from "react"; import { borderedFocusStyle } from "theme"; -const Root = styled(Box)(({ theme }) => ({ +const Root = styled(Box, { + shouldForwardProp: (prop) => !["disabled"].includes(prop.toString()), +})(({ theme, disabled }) => ({ display: "inline-flex", flexShrink: 0, position: "relative", @@ -13,6 +15,10 @@ const Root = styled(Box)(({ theme }) => ({ border: "2px solid", backgroundColor: theme.palette.common.white, "&:focus-within": borderedFocusStyle, + ...(disabled && { + border: `2px solid ${theme.palette.grey[400]}`, + backgroundColor: theme.palette.grey[400], + }), })); const Input = styled("input")(() => ({ @@ -24,11 +30,13 @@ const Input = styled("input")(() => ({ interface IconProps extends React.HTMLAttributes { checked: boolean; + disabled?: boolean; } const Icon = styled("span", { - shouldForwardProp: (prop) => prop !== "checked", -})(({ theme, checked }) => ({ + shouldForwardProp: (prop) => + !["checked", "disabled"].includes(prop.toString()), +})(({ theme, checked, disabled }) => ({ display: checked ? "block" : "none", content: "''", position: "absolute", @@ -41,6 +49,10 @@ const Icon = styled("span", { top: "42%", transform: "translate(-50%, -50%) rotate(45deg)", cursor: "pointer", + ...(disabled && { + borderBottom: `5px solid white`, + borderRight: `5px solid white`, + }), })); export interface Props { @@ -62,7 +74,7 @@ export default function Checkbox({ }; return ( - + - + ); } diff --git a/editor.planx.uk/src/ui/shared/ChecklistItem.tsx b/editor.planx.uk/src/ui/shared/ChecklistItem.tsx index 85f1c90674..b1cc24e8a3 100644 --- a/editor.planx.uk/src/ui/shared/ChecklistItem.tsx +++ b/editor.planx.uk/src/ui/shared/ChecklistItem.tsx @@ -26,6 +26,7 @@ interface Props { label: string; checked: boolean; onChange: (event?: React.MouseEvent) => void; + inputProps?: React.InputHTMLAttributes; } export default function ChecklistItem({ @@ -33,10 +34,16 @@ export default function ChecklistItem({ onChange, checked, id, + inputProps, }: Props): FCReturn { return ( - + diff --git a/hasura.planx.uk/metadata/tables.yaml b/hasura.planx.uk/metadata/tables.yaml index 3118099b7b..0242083d56 100644 --- a/hasura.planx.uk/metadata/tables.yaml +++ b/hasura.planx.uk/metadata/tables.yaml @@ -1283,16 +1283,6 @@ - session_id - created_at filter: {} -- table: - name: project_types - schema: public - select_permissions: - - role: public - permission: - columns: - - description - - value - filter: {} - table: name: published_flows schema: public diff --git a/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/down.sql b/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/down.sql new file mode 100644 index 0000000000..6682b6f158 --- /dev/null +++ b/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/down.sql @@ -0,0 +1,194 @@ +CREATE TABLE "public"."project_types" ( + "description" text NOT NULL, + "value" text NOT NULL, + "id" serial NOT NULL, + PRIMARY KEY ("id") +); +COMMENT ON TABLE "public"."project_types" IS E'A list of things people want to do within the planning system'; +INSERT INTO "public"."project_types" (description, value) VALUES + ('demolition of a building', 'demolish.full'), + ('demolition of part of a building', 'demolish.part'), + ('demolition of an outbuilding', 'demolish.outbuilding'), + ('demolition of an extension', 'demolish.extension'), + ('demolition of a boundary', 'demolish.boundary'), + ('alteration of internal layout', 'internal'), + ('internal alterations', 'alter.internal'), + ('alteration of internal walls', 'alter.internal.walls'), + ('alteration to internal floors', 'alter.internal.floors'), + ('alteration of internal staircases', 'alter.internal.staircases'), + ('alteration of internal doorways', 'alter.internal.doorways'), + ('alteration of internal window openings', 'alter.internal.windows'), + ('alteration of internal finishes', 'alter.internal.finishes'), + ('alteration of internal services', 'alter.internal.services'), + ('installation / replacement of kitchen units', 'alter.internal.kitchen'), + ('installation / replacement of bathroom appliances', 'alter.internal.bathroom'), + ('replacement of internal doors ', 'alter.internal.doors'), + ('alterations to internal decorative features', 'alter.internal.features'), + ('conversion of a roof space into habitable room/s', 'alter.internal.loft'), + ('alteration of internal basements', 'alter.internal.basement'), + ('addition of a mezzanine floor', 'alter.internal.mezzanine'), + ('removal of part of a building', 'alter.remove'), + ('removal of equipment', 'alter.remove.equipment'), + ('removal of a chimney', 'alter.remove.chimney'), + ('removal of a soil pipe', 'alter.remove.soilPipe'), + ('removal of a hard surface', 'alter.remove.surface'), + ('removal of a deck', 'alter.remove.deck'), + ('removal of part of a facade', 'alter.remove.facade'), + ('repairs to windows ', 'alter.repair.windows'), + ('repairs to doors ', 'alter.repair.doors'), + ('replacement of windows with windows', 'alter.replace.windowsToWindows'), + ('replacement of doors with doors', 'alter.replace.doorsToDoors'), + ('replacement of windows with doors', 'alter.replace.windowsToDoors'), + ('replacement of doors with windows', 'alter.replace.doorsToWindows'), + ('changes to door or window openings', 'alter.openings'), + ('addition of window or door openings', 'alter.openings.add'), + ('alteration of window or door openings', 'alter.openings.alter'), + ('alteration of window or door openings to the rear', 'alter.openings.alter.rear'), + ('addition of doorways to the front of the building', 'alter.openings.add.doors.front'), + ('addition of doorways to the side of the building', 'alter.openings.add.doors.side'), + ('addition of doorways to the rear of the building', 'alter.openings.add.doors.rear'), + ('addition of window openings', 'alter.openings.add.windows'), + ('addition of window openings to the front of the building', 'alter.openings.add.windows.front'), + ('addition of window openings to the side of the building', 'alter.openings.add.windows.side'), + ('addition of window openings to the rear of the building', 'alter.openings.add.windows.rear'), + ('addition of high up window', 'alter.openings.add.windows.high'), + ('addition of doors openings to the front of the building', 'alter.openings.alter.doors.front'), + ('addition of doors openings to the side of the building', 'alter.openings.alter.doors.side'), + ('addition of doors openings to the rear of the building', 'alter.openings.alter.doors.rear'), + ('addition of window openings', 'alter.openings.alter.windows'), + ('addition of window openings to the front of the building', 'alter.openings.alter.windows.front'), + ('addition of window openings to the side of the building', 'alter.openings.alter.windows.side'), + ('addition of window openings to the rear of the building', 'alter.openings.alter.windows.rear'), + ('blocking-up of doorways or windows', 'alter.openings.remove'), + ('addition of secondary glazing', 'alter.secondaryGlazing'), + ('addition of one or more skylights', 'alter.rooflight'), + ('alterations to facades', 'alter.facades'), + ('alterations to facades to th rear of the building', 'alter.facades.rear'), + ('painting of facades', 'alter.facades.paint'), + ('cladding of facades', 'alter.facades.reclad'), + ('addition of advert or sign', 'alter.sign'), + ('works to drains', 'alter.drains'), + ('alterations to tree or hedges', 'alter.trees'), + ('alterations to hard surfaces', 'alter.surfaces'), + ('alterations to hard surfaces', 'alter.surfaces.parking'), + ('addition or alteration of a deck', 'alter.decks'), + ('alterations to a boundary', 'alter.boundary'), + ('repairs to a boundary', 'alter.boundary.repair'), + ('repairs to a fence', 'alter.boundary.repair.fence'), + ('repairs to a gate', 'alter.boundary.repair.gate'), + ('repairs to a wall', 'alter.boundary.repair.wall'), + ('replacement of a boundary', 'alter.boundary.replace'), + ('replacement of a fence', 'alter.boundary.replace.fence'), + ('replacement of a gate', 'alter.boundary.replace.gate'), + ('replacement of a walll', 'alter.boundary.replace.wall'), + ('addition of a new boundary', 'alter.boundary.add'), + ('erection of a new fence', 'alter.boundary.add.fence'), + ('addition of a new gate', 'alter.boundary.add.gate'), + ('construction of a new wall', 'alter.boundary.add.wall'), + ('addition of a chimney', 'alter.chimneys'), + ('removal of a chimney', 'alter.remove.chimney'), + ('alterations to the roof', 'alter.roof'), + ('alteration of roof materials', 'alter.roof.materials'), + ('alteration of roof shape', 'alter.roof.shape'), + ('addition of a roof terrace', 'alter.roof.terrace'), + ('alterations to roof parapet', 'alter.roof.parapet'), + ('alterations to a public highway', 'alter.highways'), + ('creation of a point of access to a highway', 'alter.highways.access'), + ('creation of a point of access to an unclassified road', 'alter.highways.access.unclassified'), + ('addition of a dropped kerb', 'alter.highways.droppedKerb.add'), + ('removal of a dropped kerb', 'alter.highways.droppedKerb.remove'), + ('addition or alteration of soil pipes', 'alter.soilPipes'), + ('works to an external staircase', 'alter.staircase'), + ('addition or removal of a bay window', 'alter.bayWindow'), + ('addition of a bay window', 'alter.bayWindow.add'), + ('removal of a bay window', 'alter.bayWindow.remove'), + ('addition of a bay window to the rear', 'alter.bayWindow.rear'), + ('addition of an indoor swimming pool', 'alter.swimmingPool.indoor'), + ('addition of an outdoor swimming pool', 'alter.swimmingPool.outdoor'), + ('addition or removal of a pond', 'alter.landscape.ponds'), + ('addition or removal of a residential lawn or garden', 'alter.landscape.gardens'), + ('installation of equipment', 'alter.equipment'), + ('installation of a barbecue', 'alter.equipment.bbq'), + ('installation of cctv', 'alter.equipment.cctv'), + ('installation of external lighting ', 'alter.equipment.lighting'), + ('installation of wind turbine ', 'alter.equipment.wind'), + ('installation of antennae', 'alter.equipment.antennae'), + ('installation of an aerial', 'alter.equipment.antennae.aerial'), + ('installation of a satellite dish', 'alter.equipment.antennae.dish'), + ('installation of solar panel', 'alter.equipment.solar'), + ('installation of security alarm ', 'alter.equipment.alarm'), + ('installation of tank ', 'alter.equipment.tank'), + ('installation of heat pump (air)', 'alter.equipment.heatPump.air'), + ('installation of heat pump (ground)', 'alter.equipment.heatPump.ground'), + ('installation of heat pump (water)', 'alter.equipment.heatPump.water'), + ('installation of biomass / CHP', 'alter.equipment.biomass'), + ('installation of an electric vehicle charging point', 'alter.equipment.charging'), + ('installation of industrial equipment', 'alter.equipment.industrial'), + ('installation of cables ', 'alter.cables'), + ('installation of pipes', 'alter.pipes'), + ('extension to the rear or side', 'extend.rearSide'), + ('extension to the rear', 'extend.rearSide.rear'), + ('extension to the side', 'extend.rearSide.side'), + ('extension to the front', 'extend.front'), + ('upper storey extension', 'extend.upperStorey'), + ('roof extension', 'extend.roof'), + ('addition of a roof dormer', 'extend.roof.dormer'), + ('addition of a mansard roof', 'extend.roof.mansard'), + ('hip-to-gable roof enlargement', 'extend.roof.hiptogable'), + ('addition of one or more new storeys', 'extend.roof.newstorey'), + ('connection of parts of a roof', 'extend.roof.connect'), + ('alteration of roof shape', 'extend.roof.shape'), + ('addition of a new storey', 'extend.roof.newstorey'), + ('basement extension ', 'extend.basement'), + ('enlargement of a basement', 'extend.basement.extend'), + ('addition of a lightwell', 'extend.basement.lightwell'), + ('addition of an outbuilding', 'extend.outbuilding.garage'), + ('addition of garage', 'extend.outbuilding.garage'), + ('addition of shed', 'extend.outbuilding.shed'), + ('addition of garden office', 'extend.outbuilding.office'), + ('addition of a roof shelter', 'extend.outbuilding.shelter'), + ('additon of sauna', 'extend.outbuilding.sauna'), + ('addition of store', 'extend.outbuilding.store'), + ('addition of gym', 'extend.outbuilding.gym'), + ('addition of summer house', 'extend.outbuilding.summerHouse'), + ('addition of greenhouse', 'extend.outbuilding.greenhouse'), + ('addition of other outbuilding', 'extend.outbuilding.other'), + ('addition of a tank', 'extend.outbuilding.tank'), + ('addition of a porch', 'extend.porch'), + ('addition of a front porch', 'extend.porch.front'), + ('addition of a side porch', 'extend.porch.side'), + ('addition of a rear porch', 'extend.porch.rear'), + ('new home/s', 'new.residential.dwelling'), + ('new flat/s', 'new.residential.dwelling.flat'), + ('new houses/s', 'new.residential.dwelling.house'), + ('new office premises', 'new.office'), + ('new storage or distribution premises', 'new.storage'), + ('new industrial premises', 'new.industrial'), + ('new retail premises', 'new.retail'), + ('new leisure premises', 'new.leisure'), + ('new mixed premises', 'new.mixed'), + ('new agricultural premises', 'new.agriculture'), + ('new agricultural premises', 'new.agriculture.glasshouse'), + ('new agricultural premises', 'new.agriculture.poultry'), + ('new agricultural premises', 'new.agriculture.pigs'), + ('new agricultural premises', 'new.agricultural.mining '), + ('new agricultural premises', 'new.agricultural.fish'), + ('new forestry premises', 'new.forestry'), + ('new other premises', 'new'), + ('change of use', 'changeOfUse.whole'), + ('changing the use of part of the property', 'changeOfUse.part'), + ('permanent change of use', 'changeOfUse.permanent'), + ('temporary change of use', 'changeOfUse.temporary'), + ('temporary change of use - markets', 'changeOfUse.temporary.market'), + ('temporary change of use - motor racing', 'changeOfUse.temporary.motorracing'), + ('conversion of an outbuilding', 'changeOfUse.outbuilding'), + ('convertion of an extension', 'changeOfUse.extension'), + ('working from home', 'changeOfUse.workFromHome'), + ('let a property', 'changeOfUse.let.whole'), + ('let part of a property', 'changeOfUse.let.part'), + ('siting of a caravan', 'changeOfUse.caravans'), + ('land swap', 'changeOfUse.swap'), + ('creation of a residential annexe', 'changeofUse.annexe'), + ('subdivision of a property', 'unit.subdivide'), + ('merge two or more properties', 'unit.merge'), + ('other changes', 'other'); diff --git a/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/up.sql b/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/up.sql new file mode 100644 index 0000000000..4a682ac1da --- /dev/null +++ b/hasura.planx.uk/migrations/1721112734683_drop_table_public_project_types/up.sql @@ -0,0 +1 @@ +DROP table "public"."project_types" CASCADE;