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

Election form refactor final #128

Open
wants to merge 15 commits into
base: main-v2
Choose a base branch
from
1,189 changes: 1,037 additions & 152 deletions admin-ui/package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@mui/lab": "^5.0.0-alpha.55",
"@mui/material": "^5.0.4",
"@mui/styles": "^5.0.1",
"@mui/x-date-pickers": "^6.0.4",
"axios": "^0.23.0",
"date-fns": "^2.25.0",
"html-loader": "^4.2.0",
Expand All @@ -37,4 +38,4 @@
"eslint-config-next": "11.1.2",
"typescript": "4.4.4"
}
}
}
7 changes: 5 additions & 2 deletions admin-ui/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import type { AppProps } from "next/app";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from "@mui/material/styles";

import AdapterDateFns from "@mui/lab/AdapterDateFns";
import LocalizationProvider from "@mui/lab/LocalizationProvider";
// import AdapterDateFns from "@mui/lab/AdapterDateFns";
// import LocalizationProvider from "@mui/lab/LocalizationProvider";

import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'

import UserContext, { UserContextType } from "context/UserContext";
import { useEffect, useState } from "react";
Expand Down
31 changes: 31 additions & 0 deletions admin-ui/pages/elections/[id]/[step].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { NextPage } from "next";

import { useRouter } from "next/router";
import { ElectionViewQueryParam, StepsRoutes } from "types";
import ElectionPageLayout from "layout/ElectionPageLayout";
import { ElectionProvider } from "context/ElectionContext";
import ElectionFormContainer from "component/ElectionFormContainer";
import { useEffect } from "react";

const EditElectionName: NextPage = () => {
// const [election, setElection] = useState<Maybe<Election>>(null);
const router = useRouter();
const { query } = router;
const { id, step } = query;

const electionId = Array.isArray(id) ? id[0] : id || '';
const stepName = Array.isArray(step) ? step[0] : step || '';
const viewOnly:boolean = query.hasOwnProperty(ElectionViewQueryParam);
const activeStepIndex = stepName ? Object.values(StepsRoutes).indexOf(stepName as StepsRoutes) : 0;
const pageTitle = viewOnly ? 'View Election' : 'Update ELection';

return (
<ElectionPageLayout title={pageTitle} step={activeStepIndex} electionId={electionId} >
<ElectionProvider electionId={electionId}>
<ElectionFormContainer stepName={stepName} viewOnly={viewOnly} />
</ElectionProvider>
</ElectionPageLayout>
);
};

export default EditElectionName;
2 changes: 1 addition & 1 deletion admin-ui/pages/elections/[id]/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ const NewElection: NextPage = () => {
);
};

export default NewElection;
export default NewElection;
231 changes: 155 additions & 76 deletions admin-ui/pages/elections/[id]/open-test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Grid, Slider, SliderThumb, Typography } from "@mui/material";
import { Alert, Button, Grid, Slider, SliderThumb, Typography } from "@mui/material";
import LoggedInLayout from "layout/LoggedInLayout";
import type { NextPage } from "next";
import { useRouter } from "next/router";
Expand All @@ -15,8 +15,9 @@ import {
import GC from "component/GC";
import GI from "component/GI";
import Loading from "component/Loading";
import ElectionCard from "component/ElectionCard";
import { useNavigate } from "react-router-dom";
import useCurrentElection from "hooks/useCurrentElection";
import LoadingButton from "component/LoadingButton";

interface ThumbProps {
children: ReactNode;
Expand All @@ -40,13 +41,18 @@ const TestElection: NextPage = () => {
const { id } = query;

const electionId = Array.isArray(id) ? id[0] : id;

const [currentElection, reloadCurrentElection, loadingCurrentElection] = useCurrentElection();
const [election, setElection] = useState<Maybe<Election>>(null);

const shouldShowSetCurrentBtn = !loadingCurrentElection && currentElection && currentElection?.electionId != electionId;
const [alertText, setAlertText] = useState<string>("");
const [maliciousRequest, setMaliciousRequest] = useState<boolean>(false);

const loadElection = async () => {
if (electionId) {
const resp = await getElection(electionId);
setElection(resp);

}
};

Expand All @@ -56,13 +62,38 @@ const TestElection: NextPage = () => {
}
}, [electionId]);

useEffect(() => {
const modesNotAllowedForTest = [ElectionStatus.archived, ElectionStatus.closed, ElectionStatus.open];
if (election && modesNotAllowedForTest.includes(election.electionStatus)) {
// setAlertText(`${resp?.electionName} is ${resp.electionStatus} and so cannot be set to test mode.`)
setMaliciousRequest(true);
}
}, [election]);

const testElection = async () => {
if (electionId) {
await setCurrentElection(electionId);
await openElectionTest(electionId);
router.push("/dashboard");
try {
await openElectionTest(electionId);
router.push("/dashboard");
} catch (e: any) {
console.error(e);
setAlertText(e?.data?.error_description);
}
// await setCurrentElection(electionId);
}
// loadElection();
};

const runSetCurrentElection = async () => {
if (electionId) {
try {
await setCurrentElection(electionId);
reloadCurrentElection();
} catch (e: any) {
console.error(e);
setAlertText(`${currentElection?.electionJurisdictionName} ${currentElection?.electionName} ${e?.data?.error_description}`);
}
}
loadElection();
};

const navigate = useNavigate();
Expand All @@ -71,83 +102,131 @@ const TestElection: NextPage = () => {
navigate(-1);
};

return (
<LoggedInLayout title="Test Election">
{!election && <Loading />}
{election &&
election.latMode ==
1 /*election?.electionStatus === ElectionStatus.test */ && (
<GC direction="column" spacing={2}>
const InTestMode = () => {
return (
<GC direction="column" spacing={2}>
<GI>
<Typography variant="h2">You are now in Testing Mode!</Typography>
</GI>
<Typography sx={{ fontSize: "3em", margin: "2em 0" }}>
You are now in testing mode! Please test your election with your
team, then come back to finish editing and launch your election!
</Typography>
<GI>
<GC justifyContent="space-between">
<GI>
<Typography variant="h2">You are now in Testing Mode!</Typography>
<Button
onClick={() =>
router.push(`/elections/${election.electionId}/test`)
}
>
View Test Status
</Button>
</GI>
<Typography sx={{ fontSize: "3em", margin: "2em 0" }}>
You are now in testing mode! Please test your election with your
team, then come back to finish editing and launch your election!
</Typography>
<GI>
<GC justifyContent="space-between">
<GI>
<Button
onClick={() =>
router.push(`/elections/${election.electionId}/test`)
}
>
View Test Status
</Button>
</GI>
<GI>
<Button onClick={() => router.push("/dashboard")}>
Go to Dashboard
</Button>
</GI>
</GC>
<Button onClick={() => router.push("/dashboard")}>
Go to Dashboard
</Button>
</GI>
</GC>
)}
{election && !election?.latMode && (
// This should be latMode 0; but some elections don't have that?
//== 0 /*election?.electionStatus !== ElectionStatus.test */ && (
<>
<Typography variant="h2">Please confirm to continue.</Typography>
<Typography sx={{ fontSize: "3em", margin: "2em 0" }}>
Please confirm that you would like to enter testing mode for{" "}
{election?.electionName}.
</Typography>
<Grid container spacing={4}>
<Grid item xs={3}>
</GI>
</GC>
)
}

const NeedCurrentMode = () => {
return (
<GC direction="column" spacing={2}>
<GI>
<Typography variant="h2">Prerequisites not met for test mode!</Typography>
</GI>
<Typography sx={{ fontSize: "3em", margin: "2em 0" }}>
Election for {election?.electionJurisdictionName} {election?.electionName} is not the current election and so cannot be set to test mode.
</Typography>
<GI>
<GC justifyContent="space-between">
<GI item xs={3}>
<Button onClick={goBack}>Back</Button>
</Grid>
<Grid item xs={2}>
&nbsp;
</Grid>
<Grid item xs={6}>
<Slider
onChangeCommitted={(_event, newValue) => {
if (newValue === 100) {
testElection();
}
}}
components={{
Thumb: ThumbComponent,
}}
step={null}
marks={[
{
value: 0,
label: "",
},
{
value: 100,
label: "",
},
]}
defaultValue={0}
/>
</Grid>
</GI>
{!alertText ?
<GI item xs={3}>
<LoadingButton onClick={runSetCurrentElection}>
Set Current
</LoadingButton>
</GI>
: false
}
</GC>
</GI>
</GC>
)
}

const SetTestMode = () => {
return (
<>
<Typography variant="h2">Please confirm to continue.</Typography>
<Typography sx={{ fontSize: "3em", margin: "2em 0" }}>
Please confirm that you would like to enter testing mode for{" "}
{election?.electionName}.
</Typography>
<Grid container spacing={4}>
<Grid item xs={3}>
<Button onClick={goBack}>Back</Button>
</Grid>
<Grid item xs={2}>
&nbsp;
</Grid>
<Grid item xs={6}>
<Slider
onChangeCommitted={(_event, newValue) => {
if (newValue === 100) {
testElection();
}
}}
components={{
Thumb: ThumbComponent,
}}
step={null}
marks={[
{
value: 0,
label: "",
},
{
value: 100,
label: "",
},
]}
defaultValue={0}
/>
</Grid>
</Grid>
</>
)
}

return (
<LoggedInLayout title="Test Election">
{(!election || loadingCurrentElection) && <Loading />}
{maliciousRequest ?
<Alert severity="error">{election?.electionName} is {election?.electionStatus} and so cannot be set to test mode.</Alert>
:
<>
{!loadingCurrentElection && election &&
election.latMode == 1 /*election?.electionStatus === ElectionStatus.test */ &&
<InTestMode />
}
{!loadingCurrentElection && election && !election?.latMode && (
// This should be latMode 0; but some elections don't have that?
//== 0 /*election?.electionStatus !== ElectionStatus.test */ && (
shouldShowSetCurrentBtn ? <NeedCurrentMode /> : <SetTestMode />
)}
<Grid xs={12}>
{alertText && <Alert severity="error">{alertText}</Alert>}
</Grid>
</>
)}
}
</LoggedInLayout>
);
};
Expand Down
Loading