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 #3503

Merged
merged 7 commits into from
Aug 9, 2024
3 changes: 3 additions & 0 deletions api.planx.uk/.env.test.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ EDITOR_URL_EXT=example.com
HASURA_GRAPHQL_URL=http://hasura:8080/v1/graphql
HASURA_PLANX_API_KEY=👻

# Minio object storage server port
MINIO_PORT=1234

# Integrations
BOPS_API_TOKEN=👻
BOPS_API_TOKEN=👻
Expand Down
5 changes: 4 additions & 1 deletion api.planx.uk/jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import dotenv from "dotenv";
import { queryMock } from "./tests/graphqlQueryMock";

dotenv.config({ path: "./.env.test" });
dotenv.config({
path: "./.env.test",
override: true,
});

beforeEach(() => {
queryMock.setup(process.env.HASURA_GRAPHQL_URL);
Expand Down
2 changes: 1 addition & 1 deletion api.planx.uk/modules/file/service/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe("s3 Factory", () => {
});

it("returns Minio config for local development", () => {
expect(s3Factory()).toHaveProperty("endpoint.host", "minio");
expect(s3Factory()).toHaveProperty("endpoint.host", "minio:1234");
});

["pizza", "staging", "production"].forEach((env) => {
Expand Down
7 changes: 4 additions & 3 deletions api.planx.uk/modules/gis/service/digitalLand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
} from "@opensystemslab/planx-core/types";
import { gql } from "graphql-request";
import fetch from "isomorphic-fetch";
import { addDesignatedVariable, omitGeometry } from "./helpers";
import { addDesignatedVariable } from "./helpers";
import { baseSchema } from "./local_authorities/metadata/base";
import { $api } from "../../../client";

Expand Down Expand Up @@ -68,6 +68,7 @@
entries: "current",
geometry: geom,
geometry_relation: "intersects",
exclude_field: "geometry,point",
limit: "100", // TODO handle pagination in future for large polygons & many datasets, but should be well within this limit now
};
// 'dataset' param is not array[string] per docs, instead re-specify param name per unique dataset
Expand All @@ -78,8 +79,8 @@
options,
)}${datasets}`;
const res = await fetch(url)
.then((response: { json: () => any }) => response.json())

Check warning on line 82 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 82 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 82 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type
.catch((error: any) => console.log(error));

Check warning on line 83 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 83 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 83 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

// if analytics are "on", store an audit record of the raw response
if (extras?.analytics !== "false") {
Expand Down Expand Up @@ -113,21 +114,21 @@
// check for & add any 'positive' constraints to the formattedResult
let formattedResult: Record<string, Constraint> = {};
if (res && res.count > 0 && res.entities) {
res.entities.forEach((entity: { dataset: any }) => {

Check warning on line 117 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 117 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type

Check warning on line 117 in api.planx.uk/modules/gis/service/digitalLand.ts

View workflow job for this annotation

GitHub Actions / Run API Tests

Unexpected any. Specify a different type
// get the planx variable that corresponds to this entity's 'dataset', should never be null because our initial request is filtered on 'dataset'
const key = Object.keys(baseSchema).find((key) =>
baseSchema[key]["digital-land-datasets"]?.includes(entity.dataset),
);
// because there can be many digital land datasets per planx variable, check if this key is already in our result
if (key && Object.keys(formattedResult).includes(key)) {
formattedResult[key]["data"]?.push(omitGeometry(entity));
formattedResult[key]["data"]?.push(entity);
} else {
if (key) {
formattedResult[key] = {
fn: key,
value: true,
text: baseSchema[key].pos,
data: [omitGeometry(entity)],
data: [entity],
category: baseSchema[key].category,
};
}
Expand Down
11 changes: 0 additions & 11 deletions api.planx.uk/modules/gis/service/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,6 @@ const getA4Subvariables = (features, articleFours, a4Key) => {
return result;
};

// Filter a Digital Land entity response object, omitting the "geometry" & "point" keys if exists
const omitGeometry = (entity) => {
return Object.keys(entity)
.filter((key) => !["geometry", "point"].includes(key))
.reduce((obj, key) => {
obj[key] = entity[key];
return obj;
}, {});
};

export {
setEsriGeometryType,
setEsriGeometry,
Expand All @@ -219,6 +209,5 @@ export {
squashResultLayers,
rollupResultLayers,
getA4Subvariables,
omitGeometry,
addDesignatedVariable,
};

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions e2e/tests/ui-driven/src/pay.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, expect } from "@playwright/test";

Check failure on line 1 in e2e/tests/ui-driven/src/pay.spec.ts

View workflow job for this annotation

GitHub Actions / E2E tests

[chromium] › pay.spec.ts:53:7 › Gov Pay integration @regression › a successful payment

1) [chromium] › pay.spec.ts:53:7 › Gov Pay integration @regression › a successful payment ──────── Test timeout of 45000ms exceeded.
import {
cards,
fillGovUkCardDetails,
Expand Down Expand Up @@ -313,10 +313,16 @@
await expect(page.getByText("Application sent")).toBeVisible();
await expect(page.getByText(actualPaymentId)).toBeVisible();

// try going back to the payment page
// Try going back to the GovPay payment page
await page.goBack();
// Unable to make another payment - just get a status page...
await expect(
page.locator("h1").getByText("Your payment session has expired"),
page.locator("h1").getByText("Your payment was successful"),
).toBeVisible();
// ...with a link back to PlanX
await page.locator("a").getByText("View your payment summary").click();
await expect(
page.locator("h1").getByText("Application sent"),
).toBeVisible();
});
});
Expand Down
108 changes: 89 additions & 19 deletions editor.planx.uk/src/@planx/components/MapAndLabel/Public.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,112 @@
import { alpha } from "@mui/material/styles";
import Typography from "@mui/material/Typography";
import { Feature } from "geojson";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";
import React, { useEffect, useState } from "react";
import { FONT_WEIGHT_SEMI_BOLD } from "theme";
import ErrorWrapper from "ui/shared/ErrorWrapper";

import Card from "../shared/Preview/Card";
import CardHeader from "../shared/Preview/CardHeader";
import { MapContainer } from "../shared/Preview/MapContainer";
import { MapContainer, MapFooter } from "../shared/Preview/MapContainer";
import { PublicProps } from "../ui";
import { MapAndLabel } from "./model";

type Props = PublicProps<MapAndLabel>;

type Boundary = Feature | undefined;

function MapAndLabelComponent(props: Props) {
const teamSettings = useStore.getState().teamSettings;
const [boundary, setBoundary] = useState<Boundary>();
const [area, setArea] = useState<number | undefined>(0);
const [objectArray, setObjectArray] = useState<any>([]);
const [mapValidationError, setMapValidationError] = useState<string>();

let count = 0;

useEffect(() => {
const areaChangeHandler = ({ detail }: { detail: string }) => {
const numberString = detail.split(" ")[0];
const area = Number(numberString);
setArea(area);
};

const geojsonChangeHandler = ({ detail: geojson }: any) => {
if (geojson["EPSG:3857"]?.features) {
count++;

// only a single polygon can be drawn, so get first feature in geojson "FeatureCollection"
setBoundary(geojson["EPSG:3857"].features[0]);
setObjectArray([
...objectArray,
{ number: count, feature: geojson["EPSG:3857"].features[0] },
]);
} else {
// if the user clicks 'reset' to erase the drawing, geojson will be empty object, so set boundary to undefined
setBoundary(undefined);
}
};

const map: any = document.getElementById("draw-boundary-map");

map?.addEventListener("areaChange", areaChangeHandler);
map?.addEventListener("geojsonChange", geojsonChangeHandler);

return function cleanup() {
map?.removeEventListener("areaChange", areaChangeHandler);
map?.removeEventListener("geojsonChange", geojsonChangeHandler);
};
}, [objectArray, boundary]);

useEffect(() => {
if (!boundary && objectArray.length < 1) {
setMapValidationError("Add a boundary to the map");
}
}, [boundary]);

return (
<Card handleSubmit={props.handleSubmit} isValid>
<Card handleSubmit={props.handleSubmit} isValid={!mapValidationError}>
<CardHeader
title={props.title}
description={props.description}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
/>
<MapContainer environment="standalone">
{/* @ts-ignore */}
<my-map
drawMode
drawPointer="crosshair"
zoom={16}
drawFillColor={alpha(props.drawColor, 0.1)}
drawColor={props.drawColor}
drawPointColor={props.drawColor}
drawType={props.drawType}
clipGeojsonData={
teamSettings?.boundaryBBox &&
JSON.stringify(teamSettings?.boundaryBBox)
}
/>
</MapContainer>
<ErrorWrapper error={mapValidationError} id="draw-boundary-map">
<MapContainer environment="standalone">
{/* @ts-ignore */}
<my-map
id="draw-boundary-map"
drawMode
drawPointer="crosshair"
drawGeojsonData={JSON.stringify(boundary)}
zoom={16}
drawFillColor={alpha(props.drawColor, 0.1)}
drawColor={props.drawColor}
drawPointColor={props.drawColor}
drawType={props.drawType}
clipGeojsonData={
teamSettings?.boundaryBBox &&
JSON.stringify(teamSettings?.boundaryBBox)
}
/>

<MapFooter>
<Typography variant="body1">
The property boundary you have drawn is{" "}
<Typography
component="span"
noWrap
sx={{ fontWeight: FONT_WEIGHT_SEMI_BOLD }}
>
{area?.toLocaleString("en-GB") ?? 0} m²
</Typography>
</Typography>
</MapFooter>
</MapContainer>
</ErrorWrapper>
</Card>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import Chip from "@mui/material/Chip";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import React from "react";

import { StyledAvatar, StyledTableRow } from "./styles";
import { TeamMember } from "./types";

export const MembersTable: React.FC<{ members: TeamMember[] }> = ({
members,
}) => {
const roleLabels: Record<string, string> = {
platformAdmin: "Admin",
teamEditor: "Editor",
teamViewer: "Viewer",
};

const getRoleLabel = (role: string) => {
return roleLabels[role] || role;
};

if (members.length === 0) {
return (
<Table>
<TableHead>
<TableRow>
<TableCell>
<strong>No members found</strong>
</TableCell>
</TableRow>
</TableHead>
</Table>
);
}

return (
<TableContainer>
<Table>
<TableHead>
<StyledTableRow>
<TableCell sx={{ width: 300 }}>
<strong>User</strong>
</TableCell>
<TableCell sx={{ width: 200 }}>
<strong>Role</strong>
</TableCell>
<TableCell>
<strong>Email</strong>
</TableCell>
</StyledTableRow>
</TableHead>
<TableBody>
{members.map((member) => (
<StyledTableRow key={member.id}>
<TableCell
sx={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
<StyledAvatar>
{member.firstName[0]}
{member.lastName[0]}
</StyledAvatar>
{member.firstName} {member.lastName}
</TableCell>
<TableCell>
<Chip
label={getRoleLabel(member.role)}
size="small"
sx={{ background: "#ddd" }}
/>
</TableCell>
<TableCell>{member.email}</TableCell>
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
Loading
Loading