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

Merged
merged 6 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions editor.planx.uk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"classnames": "^2.3.2",
"core-js": "^3.31.0",
"date-fns": "^2.30.0",
"dompurify": "^3.0.6",
"dotenv": "^16.3.1",
"formik": "^2.4.2",
"graphql": "^16.8.1",
Expand Down Expand Up @@ -116,6 +117,7 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/dompurify": "^3.0.5",
"@types/draft-js": "^0.11.12",
"@types/jest": "^27.5.2",
"@types/jest-axe": "^3.5.5",
Expand Down
22 changes: 19 additions & 3 deletions editor.planx.uk/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ const InteractiveFileListItem = (props: FileListItemProps) => {
aria-haspopup="dialog"
size="small"
>
<span>Help</span>
<span>Info</span>
</InfoButton>
)}
<MoreInfo open={open} handleClose={() => setOpen(false)}>
Expand Down
5 changes: 1 addition & 4 deletions editor.planx.uk/src/@planx/components/Notice/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,7 @@ const NoticeComponent: React.FC<Props> = (props) => {
policyRef={props.policyRef}
howMeasured={props.howMeasured}
/>
<Container
customColor={props.color}
mt={{ xs: 9, sm: 10, md: 12, contentWrap: 6 }}
>
<Container customColor={props.color}>
<Content>
<TitleWrap>
<ErrorOutline sx={{ width: 34, height: 34 }} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const contentFlowSpacing = (theme: Theme): React.CSSProperties => ({

const InnerContainer = styled(Box)(({ theme }) => ({
maxWidth: "100%",
position: "relative",
"& > * + *": {
...contentFlowSpacing(theme),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { DESCRIPTION_TEXT } from "../constants";
import MoreInfo from "./MoreInfo";
import MoreInfoSection from "./MoreInfoSection";

const HelpButtonMinWidth = "75px";
const HelpButtonMinWidth = "70px";

interface IQuestionHeader {
title?: string;
Expand All @@ -30,7 +30,7 @@ const Description = styled(Box)(({ theme }) => ({

const TitleWrapper = styled(Box)(({ theme }) => ({
width: theme.breakpoints.values.formWrap,
maxWidth: `calc(100% - ${HelpButtonMinWidth})`,
maxWidth: `calc(100% - (${HelpButtonMinWidth} + 4px))`,
[theme.breakpoints.up("contentWrap")]: {
maxWidth: "100%",
},
Expand All @@ -45,21 +45,20 @@ const HelpButtonWrapper = styled(Box)(({ theme }) => ({
display: "flex",
justifyContent: "stretch",
width: HelpButtonMinWidth,
top: theme.spacing(6),
right: 0,
[theme.breakpoints.up("sm")]: {
top: theme.spacing(6.5),
},
top: "-4px",
right: "-6px",
pointerEvents: "none",
[theme.breakpoints.up("md")]: {
top: theme.spacing(8.5),
width: "110px",
width: "80px",
top: 0,
right: 0,
},
[theme.breakpoints.up("lg")]: {
width: "140px",
width: "100px",
},
"#embedded-browser &": {
top: "-60px",
width: "80px",
top: theme.spacing(13),
},
}));

Expand All @@ -68,20 +67,16 @@ export const HelpButton = styled(Button)(({ theme }) => ({
position: "sticky",
right: 0,
minHeight: "44px",
padding: "0.35em 1em",
padding: "0.35em 0.5em",
alignSelf: "flex-start",
borderRadius: "50px 0 0 50px",
minWidth: "100%",
boxShadow: "none",
backgroundColor: theme.palette.text.primary,
fontSize: "1.125em",
filter: "drop-shadow(0px 2px 2px rgba(0, 0, 0, 0.5))",
[theme.breakpoints.up("md")]: {
padding: "0.35em 1em 0.35em 0.5em",
},
filter: "drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.5))",
pointerEvents: "auto",
[theme.breakpoints.up("lg")]: {
minHeight: "48px",
fontSize: "1.375em",
fontSize: "1.25em",
top: theme.spacing(1),
},
"#embedded-browser &": {
Expand Down Expand Up @@ -112,7 +107,7 @@ const QuestionHeader: React.FC<IQuestionHeader> = ({

return (
<>
<Box mb={1}>
<Box mb={1} sx={{ minHeight: "2em" }}>
{title && (
<TitleWrapper mr={1} pt={0.5}>
<Typography
Expand All @@ -136,6 +131,22 @@ const QuestionHeader: React.FC<IQuestionHeader> = ({
</Typography>
</Description>
)}
{!!(info || policyRef || howMeasured) && (
<HelpButtonWrapper>
<HelpButton
title={`More information`}
aria-label={`See more information about "${title}"`}
onClick={handleHelpClick}
aria-haspopup="dialog"
data-testid="more-info-button"
variant="outlined"
color="primary"
sx={{ width: "100%" }}
>
Help
</HelpButton>
</HelpButtonWrapper>
)}
<MoreInfo open={open} handleClose={() => setOpen(false)}>
{info && info !== emptyContent ? (
<MoreInfoSection title="Why does it matter?">
Expand All @@ -160,21 +171,6 @@ const QuestionHeader: React.FC<IQuestionHeader> = ({
</MoreInfo>
{img && <Image src={img} alt="question" />}
</Box>
{!!(info || policyRef || howMeasured) && (
<HelpButtonWrapper>
<HelpButton
title={`More information`}
aria-label={`See more information about "${title}"`}
onClick={handleHelpClick}
aria-haspopup="dialog"
data-testid="more-info-button"
variant="contained"
sx={{ width: "100%" }}
>
Help
</HelpButton>
</HelpButtonWrapper>
)}
</>
);
};
Expand Down
7 changes: 4 additions & 3 deletions editor.planx.uk/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const Breadcrumbs: React.FC = () => {
)}
{route.data.flow && (
<>
{useStore.getState().canUserEditTeam(route.data.team) ? (
{useStore.getState().canUserEditTeam(team.slug) ? (
<Edit />
) : (
<Visibility />
Expand Down Expand Up @@ -400,9 +400,10 @@ const EditorToolbar: React.FC<{
}> = ({ headerRef, route }) => {
const { navigate } = useNavigation();
const [open, setOpen] = useState(false);
const [togglePreview, user] = useStore((state) => [
const [togglePreview, user, team] = useStore((state) => [
state.togglePreview,
state.getUser(),
state.getTeam(),
]);

const handleClose = () => {
Expand Down Expand Up @@ -506,7 +507,7 @@ const EditorToolbar: React.FC<{
)}

{/* Only show global settings link from top-level admin view */}
{!route.data.flow && !route.data.team && (
{!route.data.flow && !team.slug && (
<MenuItem onClick={() => navigate("/global-settings")}>
Global Settings
</MenuItem>
Expand Down
10 changes: 9 additions & 1 deletion editor.planx.uk/src/pages/Preview/ResumePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ApplicationPath, SendEmailPayload } from "types";
import Input from "ui/Input";
import InputLabel from "ui/InputLabel";
import InputRow from "ui/InputRow";
import { removeSessionIdSearchParamWithoutReloading } from "utils";
import { object, string } from "yup";

import ReconciliationPage from "./ReconciliationPage";
Expand Down Expand Up @@ -215,7 +216,14 @@ const ResumePage: React.FC = () => {
getInitialEmailValue(route.url.query.email),
);
const [paymentRequest, setPaymentRequest] = useState<MinPaymentRequest>();
const sessionId = useCurrentRoute().url.query.sessionId;

// Read the sessionId from the url to validate against
const sessionId = route.url.query.sessionId;

// As the sessionId has been extracted it can now be removed to avoid
// unnecessarily exposing it
removeSessionIdSearchParamWithoutReloading();

const [reconciliationResponse, setReconciliationResponse] =
useState<ReconciliationResponse>();

Expand Down
4 changes: 2 additions & 2 deletions editor.planx.uk/src/pages/Preview/SaveAndReturn.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe("Save and Return component", () => {
expect(results).toHaveNoViolations();
});

it("stores the sessionId as part of the URL once an email has been submitted", async () => {
it("does not store the sessionId as part of the URL once an email has been submitted", async () => {
const children = <Button>Testing 123</Button>;
const { user } = setup(<SaveAndReturn children={children}></SaveAndReturn>);

Expand All @@ -89,7 +89,7 @@ describe("Save and Return component", () => {
expect(screen.getByText("Testing 123")).toBeInTheDocument();
});

expect(window.location.href).toContain(`sessionId=${sessionId}`);
expect(window.location.href).not.toContain(`sessionId=${sessionId}`);
});
});

Expand Down
10 changes: 0 additions & 10 deletions editor.planx.uk/src/pages/Preview/SaveAndReturn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,10 @@ const SaveAndReturn: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const isEmailCaptured = Boolean(useStore((state) => state.saveToEmail));
const sessionId = useStore((state) => state.sessionId);
const isContentPage = useCurrentRoute()?.data?.isContentPage;

// Setting the URL search param "sessionId" will route the user to ApplicationPath.Resume
// Without this the user will need to click the magic link in their email after a refresh
const allowResumeOnBrowserRefresh = () => {
const url = new URL(window.location.href);
url.searchParams.set("sessionId", sessionId);
window.history.pushState({}, document.title, url);
};

const handleSubmit = (email: string) => {
useStore.setState({ saveToEmail: email });
allowResumeOnBrowserRefresh();
};

return (
Expand Down
6 changes: 5 additions & 1 deletion editor.planx.uk/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,13 @@ const getThemeOptions = (primaryColor: string): ThemeOptions => {
},
outlined: {
borderWidth: "2px 2px 3px",
borderColor: "currentcolor",
borderColor: palette.primary.main,
color: palette.text.primary,
backgroundColor: palette.common.white,
"&:hover": {
borderWidth: "2px 2px 3px",
backgroundColor: palette.primary.dark,
color: palette.common.white,
},
},
},
Expand Down
3 changes: 2 additions & 1 deletion editor.planx.uk/src/ui/ReactMarkdownOrHtml.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Box from "@mui/material/Box";
import { styled, Theme } from "@mui/material/styles";
import DOMPurify from "dompurify";
import React from "react";
import ReactMarkdown from "react-markdown";
import { FONT_WEIGHT_SEMI_BOLD, linkStyle } from "theme";
Expand Down Expand Up @@ -56,7 +57,7 @@ export default function ReactMarkdownOrHtml(props: {
return (
<HTMLRoot
color={props.textColor}
dangerouslySetInnerHTML={{ __html: incrementHeaders }}
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(incrementHeaders) }}
id={props.id}
/>
);
Expand Down
6 changes: 6 additions & 0 deletions editor.planx.uk/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,9 @@ export const removeSessionIdSearchParam = () => {
window.history.pushState({}, document.title, currentURL);
window.location.reload();
};

export const removeSessionIdSearchParamWithoutReloading = () => {
const currentURL = new URL(window.location.href);
currentURL.searchParams.delete("sessionId");
window.history.replaceState({}, document.title, currentURL);
};
4 changes: 3 additions & 1 deletion sharedb.planx.uk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
"private": true,
"dependencies": {
"@teamwork/websocket-json-stream": "^2.0.0",
"dompurify": "^3.0.6",
"jsdom": "^23.0.0",
"jsonwebtoken": "^8.5.1",
"pg": "^8.11.3",
"sharedb": "^3.3.1",
"sharedb": "^4.1.1",
"ws": "^8.14.2"
},
"scripts": {
Expand Down
Loading
Loading