Skip to content

Commit

Permalink
Merge branch 'develop' into feature/TMI2-353-mq-start-page
Browse files Browse the repository at this point in the history
  • Loading branch information
ConorFayleAND committed Oct 12, 2023
2 parents 5a06730 + e8342eb commit fb1dd92
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Button, FlexibleQuestionPageLayout } from 'gap-web-ui';
import { GetServerSideProps } from 'next';
import { GetServerSidePropsContext } from 'next';
import CustomLink from '../../../components/custom-link/CustomLink';
import Meta from '../../../components/layout/Meta';
import ExportStatusEnum from '../../../enums/ExportStatus';
Expand All @@ -9,32 +9,24 @@ import {
requestSubmissionsExport,
} from '../../../services/SubmissionsService';
import { getLoggedInUsersDetails } from '../../../services/UserService';
import UserDetails from '../../../types/UserDetails';
import { generateErrorPageRedirect } from '../../../utils/serviceErrorHelpers';
import { getSessionIdFromCookies } from '../../../utils/session';
import { parseBody } from 'next/dist/server/api-utils/node';
import InferProps from '../../../types/InferProps';

export const getServerSideProps: GetServerSideProps = async ({
export const getServerSideProps = async ({
req,
query,
resolvedUrl,
}) => {
}: GetServerSidePropsContext) => {
const sessionCookie = getSessionIdFromCookies(req);
const { schemeId } = query as Record<string, string>;
const { schemeId, requested } = query as Record<string, string>;

let exportStatus: ExportStatusEnum;
let applicationFormsStatus: {
applicationId: string;
submissionCount: number;
}[];
let applicationId: string;
let userDetails: UserDetails = {
firstName: '',
lastName: '',
organisationName: '',
emailAddress: '',
roles: [],
created: '',
};

const errorPageRedirect = generateErrorPageRedirect(
'Something went wrong while trying to export submissions.',
Expand Down Expand Up @@ -63,40 +55,36 @@ export const getServerSideProps: GetServerSideProps = async ({
);
}

exportStatus = await getApplicationExportStatus(sessionCookie, applicationId);

if (exportStatus == ExportStatusEnum.COMPLETE) {
// for now, we just treat COMPLETE the same as NOT_STARTED ie. allow them to trigger another download
// in the future, if an export is complete we should aim to redirect them to the summary table page
// so they can access the most recent export without requiring the email link
exportStatus = ExportStatusEnum.NOT_STARTED;
if (req.method === 'POST') {
const body = await parseBody(req, '1mb');
if ('download-submitted-applications' in body) {
requestSubmissionsExport(sessionCookie, applicationId);
return {
redirect: {
destination: `/scheme/${schemeId}/download-submissions?requested=true`,
statusCode: 302,
},
};
}
}

if (exportStatus == ExportStatusEnum.NOT_STARTED) {
requestSubmissionsExport(sessionCookie, applicationId);
return {
redirect: {
destination: `/scheme/${schemeId}/download-submissions`,
permanent: false,
},
};
}
const exportStatus = await getApplicationExportStatus(
sessionCookie,
applicationId
);

if (
exportStatus == ExportStatusEnum.PROCESSING ||
exportStatus == ExportStatusEnum.REQUESTED
) {
try {
userDetails = await getLoggedInUsersDetails(sessionCookie);
} catch (error) {
return errorPageRedirect;
}
let userDetails;
try {
userDetails = await getLoggedInUsersDetails(sessionCookie);
} catch (error) {
return errorPageRedirect;
}

return {
props: {
backButtonHref: `/scheme/${schemeId}`,
exportStatus,
requested: requested || null,
emailAddress: userDetails.emailAddress,
formAction: resolvedUrl,
csrfToken: (req as any).csrfToken?.() || '',
Expand All @@ -107,16 +95,18 @@ export const getServerSideProps: GetServerSideProps = async ({
const DownloadSubmissions = ({
backButtonHref,
exportStatus,
requested,
emailAddress,
formAction,
csrfToken,
}: DownloadSubmissionsProps) => {
}: InferProps<typeof getServerSideProps>) => {
return (
<>
<Meta
title={`Download applications${
exportStatus == ExportStatusEnum.PROCESSING ||
exportStatus == ExportStatusEnum.REQUESTED
exportStatus == ExportStatusEnum.REQUESTED ||
requested == 'true'
? ' - In progress'
: ''
} - Manage a grant`}
Expand All @@ -127,7 +117,8 @@ const DownloadSubmissions = ({
<div className="govuk-grid-row govuk-!-padding-top-7 govuk-!-margin-bottom-6">
<div className="govuk-grid-column-full">
{(exportStatus == ExportStatusEnum.PROCESSING ||
exportStatus == ExportStatusEnum.REQUESTED) && (
exportStatus == ExportStatusEnum.REQUESTED ||
requested == 'true') && (
<>
<div className="govuk-grid-row">
<div className="govuk-grid-column-two-thirds">
Expand All @@ -151,46 +142,40 @@ const DownloadSubmissions = ({
</>
)}

{exportStatus == ExportStatusEnum.NOT_STARTED && (
<>
<h1 className="govuk-heading-l">View your applications</h1>
<p
className="govuk-body"
data-cy="cy_Download-submissions-page-text-1"
>
To see who has applied for your grant, you need to view and
download your submitted applications.
</p>
<p
className="govuk-body"
data-cy="cy_Download-submissions-page-text-2"
>
Get started by requesting a list of applications.
</p>
<FlexibleQuestionPageLayout
fieldErrors={[]}
formAction={formAction}
csrfToken={csrfToken}
>
<Button
text="Download submitted applications"
addNameAttribute
/>
</FlexibleQuestionPageLayout>
</>
)}
{(exportStatus == ExportStatusEnum.NOT_STARTED ||
exportStatus == ExportStatusEnum.COMPLETE) &&
requested != 'true' && (
<>
<h1 className="govuk-heading-l">View your applications</h1>
<p
className="govuk-body"
data-cy="cy_Download-submissions-page-text-1"
>
To see who has applied for your grant, you need to view and
download your submitted applications.
</p>
<p
className="govuk-body"
data-cy="cy_Download-submissions-page-text-2"
>
Get started by requesting a list of applications.
</p>
<FlexibleQuestionPageLayout
fieldErrors={[]}
formAction={formAction}
csrfToken={csrfToken}
>
<Button
text="Download submitted applications"
addNameAttribute
/>
</FlexibleQuestionPageLayout>
</>
)}
</div>
</div>
</>
);
};

interface DownloadSubmissionsProps {
backButtonHref: string;
exportStatus: ExportStatusEnum;
emailAddress: string;
formAction: string;
csrfToken: string;
}

export default DownloadSubmissions;
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import {
getApplicationExportStatus,
requestSubmissionsExport,
} from '../../../services/SubmissionsService';
import { parseBody } from 'next/dist/server/api-utils/node';

jest.mock('../../../services/SchemeService');
jest.mock('../../../services/ApplicationService');
jest.mock('../../../services/UserService');
jest.mock('../../../services/SubmissionsService');
jest.mock('../../../utils/callServiceMethod');
jest.mock('next/dist/server/api-utils/node', () => ({
parseBody: jest.fn(),
}));

const mockedFindApplicationFormFromScheme =
findApplicationFormFromScheme as jest.Mock;
Expand All @@ -35,6 +39,7 @@ const customProps = {
emailAddress: '',
csrfToken: '',
formAction: '',
requested: null,
};

const component = <DownloadSubmissions {...customProps} />;
Expand Down Expand Up @@ -138,6 +143,7 @@ describe('Download submissions page', () => {
mockedGetApplicationExportStatus.mockResolvedValue(
ExportStatusEnum.PROCESSING
);
(parseBody as jest.Mock).mockResolvedValue({ testBody: true });
});

it('Should NOT return a redirect object if applicationFormsStatus is successfully retrieved', async () => {
Expand Down Expand Up @@ -213,26 +219,6 @@ describe('Download submissions page', () => {
);
});

it('Should redirect to self when NOT_STARTED', async () => {
mockedGetApplicationExportStatus.mockResolvedValue(
ExportStatusEnum.NOT_STARTED
);
mockedRequestSubmissionsExport.mockResolvedValue({});

const response = (await getServerSideProps(
getContext()
)) as NextGetServerSidePropsResponse;

expect(response).toStrictEqual({
redirect: {
permanent: false,
destination: '/scheme/testSchemeId/download-submissions',
},
});
});

it.todo('Placeholder for checking if the export is in progress');

describe('POST method', () => {
beforeEach(() => {
mockedFindApplicationFormFromScheme.mockResolvedValue([
Expand All @@ -250,6 +236,9 @@ describe('Download submissions page', () => {
mockedGetApplicationExportStatus.mockResolvedValue(
ExportStatusEnum.NOT_STARTED
);
(parseBody as jest.Mock).mockResolvedValue({
'download-submitted-applications': true,
});

await getServerSideProps(getPostContext());

Expand Down
5 changes: 4 additions & 1 deletion packages/admin/src/services/UserService.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import axios from 'axios';
import { axiosSessionConfig } from '../utils/session';
import UserDetails from '../types/UserDetails';

const BASE_USERS_URL = process.env.BACKEND_HOST + '/users';

const getLoggedInUsersDetails = async (sessionCookie: string) => {
const getLoggedInUsersDetails = async (
sessionCookie: string
): Promise<UserDetails> => {
const response = await axios.get(
`${BASE_USERS_URL}/loggedInUser`,
axiosSessionConfig(sessionCookie)
Expand Down
6 changes: 3 additions & 3 deletions packages/applicant/src/pages/applications/index.page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ describe('View existing applications', () => {

expect(screen.getByRole('link', { name: 'Application 1' })).toHaveProperty(
'href',
'http://localhost/submissions/subId1/sections'
'http://localhost/apply/applicant/submissions/subId1/sections'
);
expect(screen.getByRole('link', { name: 'Application 2' })).toHaveProperty(
'href',
'http://localhost/submissions/subId2/sections'
'http://localhost/apply/applicant/submissions/subId2/sections'
);
expect(screen.getByRole('link', { name: 'Application 3' })).toHaveProperty(
'href',
'http://localhost/submissions/subId3/sections'
'http://localhost/apply/applicant/submissions/subId3/sections'
);
});
});
Expand Down
25 changes: 12 additions & 13 deletions packages/applicant/src/pages/applications/index.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { getJwtFromCookies } from '../../utils/jwt';
import { routes } from '../../utils/routes';
import getConfig from 'next/config';
import Link from 'next/link';

export const getServerSideProps: GetServerSideProps<ApplicationsPage> = async ({
req,
Expand All @@ -17,7 +16,7 @@ export const getServerSideProps: GetServerSideProps<ApplicationsPage> = async ({
const applicationData = await getApplicationsListById(getJwtFromCookies(req));
return {
props: {
applicationData: applicationData,
applicationData,
},
};
};
Expand Down Expand Up @@ -77,18 +76,18 @@ const ExistingApplications = ({ applicationData }: ApplicationsPage) => {
{application.applicationName}
</p>
) : (
<Link
href={routes.submissions.sections(
application.grantSubmissionId
)}
<a
href={
'/apply/applicant' +
routes.submissions.sections(
application.grantSubmissionId
)
}
className="govuk-link govuk-link--no-visited-state govuk-!-font-weight-regular"
data-cy={`cy-application-link-${application.applicationName}`}
>
<a
className="govuk-link govuk-link--no-visited-state govuk-!-font-weight-regular"
data-cy={`cy-application-link-${application.applicationName}`}
>
{application.applicationName}
</a>
</Link>
{application.applicationName}
</a>
)}
</th>

Expand Down
Loading

0 comments on commit fb1dd92

Please sign in to comment.