Skip to content

Commit

Permalink
Add confirmation dialog on new election page, add loaders on button
Browse files Browse the repository at this point in the history
  • Loading branch information
Renu authored and Renu committed Mar 17, 2023
1 parent cf84015 commit c0d8876
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 33 deletions.
62 changes: 62 additions & 0 deletions admin-ui/src/component/ConfirmationDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { ReactNode, useState } from "react";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import { styled } from "@mui/material/styles";
import LoadingButton from "./LoadingButton";


interface ConfirmationDialogProps {
title?: string;
open: boolean;
children: ReactNode;
btnCancelText?: string;
btnConfirmText?: string;
onClose: (confirmed: boolean) => void;
}

export default function ConfirmationDialog({
title,
children,
open,
btnCancelText = 'Cancel',
btnConfirmText = 'Confirm',
onClose,
}: ConfirmationDialogProps) {

const handleConfirm = async () => {
await onClose(true);
};

const handleCancel = async () => {
onClose(false);
};

const ActionButton = styled(LoadingButton) `
width: auto;
border-radius: 5px;
margin: 0 5px 10px 5px;
`

return (
<Dialog maxWidth="md" open={open} onClose={handleCancel} >
<DialogTitle variant="h3">
{title}
</DialogTitle>
<DialogContent>
{children}
</DialogContent>
<DialogActions>
<ActionButton onClick={handleCancel} variant="outlined">
{btnCancelText}
</ActionButton>
<ActionButton onClick={handleConfirm} autoFocus>
{btnConfirmText}
</ActionButton>
</DialogActions>
</Dialog>
);
};
109 changes: 79 additions & 30 deletions admin-ui/src/component/ElectionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Alert,
Link,
} from "@mui/material";
import CircularProgress from '@mui/material/CircularProgress';
import {
Election,
ElectionConfiguration,
Expand Down Expand Up @@ -60,6 +61,9 @@ import Loading from "./Loading";
import { dateToYMD, formatTimeStamp } from "dsl/date";
import InputEnumSelect from "./InputEnumSelect";
import { eachHourOfInterval } from "date-fns";
import ConfirmationDialog from "./ConfirmationDialog";
import LoadingButton from "./LoadingButton";
import useCurrentElection from "hooks/useCurrentElection";

interface ElectionFormProps {
election: Maybe<Election>;
Expand All @@ -74,8 +78,9 @@ export default function ElectionForm({
}: ElectionFormProps) {
const [step, setStepData] = useState<number>(0);
const [data, setData] = useState<Maybe<Election | ElectionCreate>>(election);
const [currentElection, setReferenceCurrentElection] =
useState<Maybe<Election>>();
const [currentElection, reloadCurrentElection, loadingCurrentElection] = useCurrentElection();
// const [currentElection, setReferenceCurrentElection] =
// useState<Maybe<Election>>();
const [alertText, setAlertText] = useState<string>("");

const setStep = (step: number): void => {
Expand Down Expand Up @@ -120,6 +125,8 @@ export default function ElectionForm({
election?.testVotersFile ? { status: "started" } : {}
);

const [currentElectionDialogOpen, setCurrentElectionDialogOpen] = useState(false);

const router = useRouter();

const steps = [
Expand Down Expand Up @@ -199,13 +206,50 @@ export default function ElectionForm({
handleDataChange(name, formattedDate);
};

const handleSetCurrentElection = async () => {
if (currentElection) {
setCurrentElectionDialogOpen(true);
} else {
await saveAsCurrentElection();
}
};

const handleCurrentElectionDialogClose = async (confirmed: boolean) => {

if (confirmed) {
await saveAsCurrentElection();
} else {
setCurrentElectionDialogOpen(false);
}

};

const saveAsCurrentElection = async () => {
if (election) {
try {
await setCurrentElection(election.electionId);
} catch (e) {
console.log("setCurrentElection error");
console.log(e);
messageError(e);
} finally {
await reloadElectionData();
reloadCurrentElection();
setCurrentElectionDialogOpen(false);
}
}
}



const reloadElectionData = async () => {
if (election?.electionId) {
const updatedElection = await getElection(election?.electionId);
setData(updatedElection);
onUpdateElection(updatedElection);
}
const currentElection = await adminGetCurrentElection();
setReferenceCurrentElection(currentElection);
// const currentElection = await adminGetCurrentElection();
// setReferenceCurrentElection(currentElection);
};

const save = async () => {
Expand Down Expand Up @@ -939,7 +983,7 @@ export default function ElectionForm({
</Grid>
</Grid>
);

let formContents: ReactNode = null;
if (step === 0) {
formContents = electionNameFields;
Expand All @@ -956,21 +1000,22 @@ export default function ElectionForm({
} else if (step === 6) {
formContents = reviewFields;
}


const actions = (
<Grid container justifyContent="space-between" spacing={2}>
<Grid container justifyContent="space-between" spacing={2} alignItems="flex-end">
<Grid item xs={4} sm={4} md={3}>
{step > 0 && (
<Button startIcon={<NavigateBeforeIcon />} onClick={saveBack}>
<LoadingButton startIcon={<NavigateBeforeIcon />} onClick={saveBack}>
Prev
</Button>
</LoadingButton>
)}
</Grid>
<Grid item xs={4} sm={4} md={3}>
{step < steps.length - 1 && step !== 5 && (
<Button endIcon={<NavigateNextIcon />} onClick={saveNext}>
<LoadingButton endIcon={<NavigateNextIcon />} onClick={saveNext}>
Next
</Button>
</LoadingButton>
)}
</Grid>
{step === 4 &&
Expand All @@ -990,14 +1035,16 @@ export default function ElectionForm({
}}
>
{(election?.testCount ?? 0) >= 1 ? "Continue" : "Begin"} Testing

</Button>

</Grid>
) : (
step === 4 && (
<Grid>
<Grid item xs={4} sm={4} md={3}>
{step === 4 &&
election &&
currentElection &&
!loadingCurrentElection && currentElection &&
currentElection?.electionId !== election.electionId && (
<p>
This election is not the current election and so cannot be set
Expand All @@ -1010,28 +1057,30 @@ export default function ElectionForm({
(!election.electionStatus ||
election.electionStatus === ElectionStatus.draft) &&
(!currentElection ||
(currentElection &&
(!loadingCurrentElection && currentElection &&
currentElection?.electionId !== election?.electionId &&
currentElection?.latMode !== 1 &&
currentElection?.electionStatus !== ElectionStatus.open)) && (
<Button
<>
<LoadingButton
disabled={
election?.electionId === currentElection?.electionId
}
onClick={async () => {
try {
await setCurrentElection(election.electionId);
} catch (e) {
console.log("setCurrentElection error");
console.log(e);
messageError(e);
} finally {
reloadElectionData();
}
}}
onClick={handleSetCurrentElection}
>
Set Current
</Button>
</LoadingButton>
<ConfirmationDialog
open={currentElectionDialogOpen}
title="Set as Current Election?"
onClose={handleCurrentElectionDialogClose}
btnConfirmText="Yes, set current"
>
<Typography sx={{ fontSize: "1.1em"}}>
It will archive the election for <em>{currentElection?.electionJurisdictionName} {currentElection?.electionName}.</em>
</Typography>
</ConfirmationDialog>
</>
)}
</Grid>
)
Expand All @@ -1043,15 +1092,15 @@ export default function ElectionForm({
currentElection?.electionId === election.electionId &&
(election?.testCount ?? 0) >= 1 &&
!election?.testComplete && (
<Button
<LoadingButton
//endIcon={<ConstructionIcon />}
onClick={() => {
setElectionTestComplete((data as Election)?.electionId);
onClick={async () => {
await setElectionTestComplete((data as Election)?.electionId);
router.push("/dashboard");
}}
>
Finalize Testing
</Button>
</LoadingButton>
)}
{step === steps.length - 1 && (
<Button
Expand Down
42 changes: 42 additions & 0 deletions admin-ui/src/component/LoadingButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Button, { ButtonProps } from "@mui/material/Button";
import CircularProgress from "@mui/material/CircularProgress";
import React, { ReactNode, useEffect, useState } from "react";


interface LoadingButtonProps extends ButtonProps {
onClick: () => Promise<void>;
children: ReactNode;
}

export default function LoadingButton ({ onClick, children, ...props }: LoadingButtonProps) {
const [isLoading, setIsLoading] = useState(false);

const handleClick = async () => {
setIsLoading(true);
await onClick();
setIsLoading(false);
};

useEffect(() => {
return () => {
setIsLoading(false)
}
}, [])

return (
<div>
<Button onClick={handleClick} {...props} disabled={isLoading}>
{children}
{isLoading && (
<CircularProgress
size={30}
color="primary"
style={{ position: "absolute" }}
/>
)}
</Button>

</div>
);
};

1 change: 1 addition & 0 deletions admin-ui/src/hooks/useCurrentElection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function useCurrentElection(): [
const [election, setElection] = useState<Maybe<Election>>(null);

const loadElection = async () => {
setLoading(true);
let e = await adminGetCurrentElection();

//CTW shouldn't be doing it this way now
Expand Down
Binary file modified examples/edf-validation/.DS_Store
Binary file not shown.
4 changes: 2 additions & 2 deletions local-env-osx.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Parameters": {
"DEV_ENVIRONMENT": "OSX",
"UPLOAD_BUCKET": "abc-uploads-development-vadminui",
"ELECTIONS_DOCUMENT_BUCKET": "abc-documents-development-vadminui"
"UPLOAD_BUCKET": "abc-uploads-development-radmin",
"ELECTIONS_DOCUMENT_BUCKET": "abc-documents-development-radmin"
}
}
3 changes: 2 additions & 1 deletion template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Parameters:
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 15
Timeout: 300
Handler: app.lambdaHandler
Runtime: nodejs18.x
Environment:
Expand Down Expand Up @@ -941,6 +941,7 @@ Resources:
CodeUri: endpoints/setElectionVoters/
Layers:
- !Ref LibLayer
MemorySize: 512
Events:
AbcBackendApiGateway:
Type: Api
Expand Down

0 comments on commit c0d8876

Please sign in to comment.