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

feat: verify email before downloading application #4000

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
40c1f2d
Redirect download link to basic verify email page
jamdelion Nov 21, 2024
766abcc
try to download application file on email submit - no verification
jamdelion Nov 21, 2024
56f08cc
Merge branch 'main' into jh/verify-email-page
jamdelion Nov 25, 2024
aff54ca
Fix global import problem
jamdelion Nov 25, 2024
e660026
Works with permission error
jamdelion Nov 25, 2024
99a447c
Use existing endpoint to check email address
jamdelion Nov 25, 2024
1c07974
Move helper to utils file
jamdelion Nov 25, 2024
08e62da
Use react query
jamdelion Nov 25, 2024
e39f856
Lint fix
jamdelion Nov 25, 2024
2ad7978
Tidy up
jamdelion Nov 25, 2024
139c1d9
Add test todos
jamdelion Nov 26, 2024
5de9aa2
Fix typing
jamdelion Nov 26, 2024
03454a3
Display errors nicely
jamdelion Nov 27, 2024
4260930
Fix error wrapper type issue
jamdelion Nov 28, 2024
725ea12
Revert moving urlWithParams
jamdelion Dec 2, 2024
fbcca1f
Update wording to be more appropriate
jamdelion Dec 2, 2024
db050b0
Rename files to verifySubmissionEmail
jamdelion Dec 2, 2024
795497a
Rename url to download-application
jamdelion Dec 2, 2024
e7c5171
Merge branch 'main' into jh/verify-email-page
jamdelion Dec 3, 2024
ce3b34a
Replace react-query with axios
jamdelion Dec 3, 2024
810c7e4
Readd loading state
jamdelion Dec 3, 2024
6c183e4
Add application summary
jamdelion Dec 3, 2024
ea18fcf
Add one more test.todo
jamdelion Dec 3, 2024
2147de4
Remove react query
jamdelion Dec 3, 2024
a0e28f8
Remove queryProvider
jamdelion Dec 3, 2024
c58ef33
Remove rq lint plugin
jamdelion Dec 3, 2024
570df3d
Remove rq from test utils
jamdelion Dec 3, 2024
868c820
Use correct zip filename
jamdelion Dec 4, 2024
2b8c421
Move application summary and capitalise team name
jamdelion Dec 10, 2024
60cd604
Wrap verifySubmissionPage in PlanX headers
jamdelion Dec 10, 2024
d35c7da
Revert error typing
jamdelion Dec 10, 2024
9d9e967
Merge branch 'main' into jh/verify-email-page
jamdelion Jan 6, 2025
8aa35df
Merge branch 'main' into jh/verify-email-page
jamdelion Jan 8, 2025
88f1252
Merge branch 'main' into jh/verify-email-page
jamdelion Jan 13, 2025
cc6b34c
Account for recent changes to searchParams
jamdelion Jan 13, 2025
e577c01
lint
jamdelion Jan 13, 2025
bc746c0
Merge branch 'main' into jh/verify-email-page
jamdelion Feb 3, 2025
7df63e7
test: verify email component (#4019)
jamdelion Feb 7, 2025
cf098d9
Merge branch 'main' into jh/verify-email-page
jamdelion Feb 10, 2025
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
3 changes: 2 additions & 1 deletion api.planx.uk/modules/send/email/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ export const sendToEmail: SendIntegrationController = async (
// Get the applicant email and flow slug associated with the session
const { email, flow } = await getSessionEmailDetailsById(sessionId);
const flowName = flow.name;
const serviceURL = `${process.env.EDITOR_URL_EXT}/${localAuthority}/${flow.slug}/${sessionId}`;

// Prepare email template
const config: EmailSubmissionNotifyConfig = {
personalisation: {
serviceName: flowName,
sessionId,
applicantEmail: email,
downloadLink: `${process.env.API_URL_EXT}/download-application-files/${sessionId}?email=${teamSettings.submissionEmail}&localAuthority=${localAuthority}`,
downloadLink: `${serviceURL}/verify-email`, // redirect to verify email before download
...teamSettings,
},
};
Expand Down
4 changes: 2 additions & 2 deletions api.planx.uk/modules/send/email/service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { gql } from "graphql-request";
import { $api } from "../../../client/index.js";
import type {
Session,
TeamContactSettings,
} from "@opensystemslab/planx-core/types";
import { gql } from "graphql-request";
import { $api } from "../../../client/index.js";
import type { EmailSubmissionNotifyConfig } from "../../../types.js";

interface GetTeamEmailSettings {
Expand Down
2 changes: 2 additions & 0 deletions editor.planx.uk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@mui/utils": "^5.15.11",
"@opensystemslab/map": "1.0.0-alpha.4",
"@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#ccf9ac3",
"@tanstack/react-query": "^5.61.3",
jamdelion marked this conversation as resolved.
Show resolved Hide resolved
"@tiptap/core": "^2.4.0",
"@tiptap/extension-bold": "^2.0.3",
"@tiptap/extension-bubble-menu": "^2.1.13",
Expand Down Expand Up @@ -117,6 +118,7 @@
"@storybook/react-vite": "^8.3.1",
"@storybook/test": "^8.3.1",
"@storybook/theming": "^8.3.1",
"@tanstack/eslint-plugin-query": "^5.61.3",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.4.3",
Expand Down
108 changes: 108 additions & 0 deletions editor.planx.uk/pnpm-lock.yaml

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

37 changes: 21 additions & 16 deletions editor.planx.uk/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ApolloProvider } from "@apollo/client";
import CssBaseline from "@mui/material/CssBaseline";
import { StyledEngineProvider, ThemeProvider } from "@mui/material/styles";
import { MyMap } from "@opensystemslab/map";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ToastContextProvider } from "contexts/ToastContext";
import { getCookie, setCookie } from "lib/cookie";
import ErrorPage from "pages/ErrorPage";
Expand All @@ -22,6 +23,8 @@ import { client } from "./lib/graphql";
import navigation from "./lib/navigation";
import { defaultTheme } from "./theme";

const queryClient = new QueryClient();

if (import.meta.env.VITE_APP_ENV !== "production") {
console.log(`ENV: ${import.meta.env.VITE_APP_ENV}`);
}
Expand Down Expand Up @@ -95,20 +98,22 @@ const Layout: React.FC<{

root.render(
<ToastContextProvider>
<ApolloProvider client={client}>
<AnalyticsProvider>
<Router context={{ currentUser: hasJWT() }} navigation={navigation}>
<HelmetProvider>
<Layout>
<CssBaseline />
<Suspense fallback={null}>
<View />
</Suspense>
</Layout>
</HelmetProvider>
</Router>
</AnalyticsProvider>
</ApolloProvider>
<ToastContainer icon={false} theme="colored" />
</ToastContextProvider>,
<QueryClientProvider client={queryClient}>
<ApolloProvider client={client}>
jamdelion marked this conversation as resolved.
Show resolved Hide resolved
<AnalyticsProvider>
<Router context={{ currentUser: hasJWT() }} navigation={navigation}>
<HelmetProvider>
<Layout>
<CssBaseline />
<Suspense fallback={null}>
<View />
</Suspense>
</Layout>
</HelmetProvider>
</Router>
</AnalyticsProvider>
</ApolloProvider>
<ToastContainer icon={false} theme="colored" />
</QueryClientProvider>
</ToastContextProvider>
);
8 changes: 1 addition & 7 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ import axios from "axios";
import { client } from "lib/graphql";
import navigation from "lib/navigation";
import debounce from "lodash/debounce";
import isEmpty from "lodash/isEmpty";
import omitBy from "lodash/omitBy";
import { customAlphabet } from "nanoid-good";
import en from "nanoid-good/locale/en";
import { type } from "ot-json0";
import { urlWithParams } from "utils";
import type { StateCreator } from "zustand";
import { persist } from "zustand/middleware";

Expand Down Expand Up @@ -507,11 +506,6 @@ export const editorStore: StateCreator<
async publishFlow(flowId: string, summary?: string) {
const token = get().jwt;

const urlWithParams = (url: string, params: any) =>
jamdelion marked this conversation as resolved.
Show resolved Hide resolved
[url, new URLSearchParams(omitBy(params, isEmpty))]
.filter(Boolean)
.join("?");

const { data } = await axios.post<PublishFlowResponse>(
urlWithParams(
`${import.meta.env.VITE_APP_API_URL}/flows/${flowId}/publish`,
Expand Down
8 changes: 4 additions & 4 deletions editor.planx.uk/src/pages/Preview/SaveAndReturn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const ConfirmEmail: React.FC<{
<CardHeader
title="Enter your email address"
description="We will use this to save your application so you can come back to it later. We will also email you updates about your application."
></CardHeader>
/>
<InputRow>
<InputLabel label={"Email address"} htmlFor={"email"}>
<Input
Expand All @@ -54,7 +54,7 @@ export const ConfirmEmail: React.FC<{
onChange={formik.handleChange}
type="email"
value={formik.values.email}
></Input>
/>
</InputLabel>
</InputRow>
<InputRow>
Expand All @@ -72,7 +72,7 @@ export const ConfirmEmail: React.FC<{
onChange={formik.handleChange}
type="email"
value={formik.values.confirmEmail}
></Input>
/>
</InputLabel>
</InputRow>
</Card>
Expand Down Expand Up @@ -105,7 +105,7 @@ const SaveAndReturn: React.FC<{ children: React.ReactNode }> = ({
{isEmailCaptured || isContentPage ? (
children
) : (
<ConfirmEmail handleSubmit={handleSubmit}></ConfirmEmail>
<ConfirmEmail handleSubmit={handleSubmit} />
)}
</>
);
Expand Down
17 changes: 17 additions & 0 deletions editor.planx.uk/src/pages/VerifyEmail/VerifyEmail.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Meta, StoryObj } from "@storybook/react";
import React from "react";

import { VerifyEmail } from "./VerifyEmail";

const meta = {
title: "Design System/Pages/VerifyEmail",
component: VerifyEmail,
} satisfies Meta<typeof VerifyEmail>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Basic = {
render: () => <VerifyEmail params={{ sessionId: "1" }} />,
};
Loading
Loading