-
Notifications
You must be signed in to change notification settings - Fork 7
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
Polish CVR import and export UIs #4047
Changes from all commits
814ab01
0f56604
c5462b8
e926d13
35fff0c
e3020c0
ef63b3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,14 +34,14 @@ export function ConfirmRemovingFileModal({ | |
let singleFileRemoval = true; | ||
switch (fileType) { | ||
case ResultsFileType.CastVoteRecord: { | ||
fileTypeName = 'CVRs'; | ||
const fileList = castVoteRecordFilesQuery.data; | ||
singleFileRemoval = fileList.length <= 1; | ||
fileTypeName = 'CVR Files'; | ||
mainContent = ( | ||
<React.Fragment> | ||
<P> | ||
Do you want to remove the {fileList.length} loaded CVR{' '} | ||
{pluralize('files', fileList.length)}? | ||
{pluralize('export', fileList.length)}? | ||
</P> | ||
<P>All reports will be unavailable without CVR data.</P> | ||
</React.Fragment> | ||
|
@@ -56,7 +56,7 @@ export function ConfirmRemovingFileModal({ | |
<React.Fragment> | ||
<P> | ||
Do you want to remove the {fileList.length} loaded CVR{' '} | ||
{pluralize('files', fileList.length)} | ||
{pluralize('export', fileList.length)} | ||
{hasManualData && ' and the manually entered data'}? | ||
</P> | ||
<P>All reports will be unavailable without CVR data.</P> | ||
|
@@ -70,7 +70,7 @@ export function ConfirmRemovingFileModal({ | |
|
||
return ( | ||
<Modal | ||
centerContent | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like we more often left-align our modals than center-align them, so I've made that consistent for CVR modals. |
||
title={`Remove ${fileTypeName}`} | ||
content={mainContent} | ||
actions={ | ||
<React.Fragment> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,11 +252,11 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
if (currentState.state === 'duplicate') { | ||
return ( | ||
<Modal | ||
title="Duplicate File" | ||
title="Duplicate Export" | ||
content={ | ||
<P> | ||
The selected file was ignored as a duplicate of a previously loaded | ||
file. | ||
The selected export was ignored as a duplicate of a previously | ||
loaded export. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because exports are now (and have for a while been) directories instead of single files, I've moved away from "file" as the descriptor for a CVR export and shifted to "export" |
||
</P> | ||
} | ||
onOverlayClick={onClose} | ||
|
@@ -266,25 +266,31 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
} | ||
|
||
if (currentState.state === 'success') { | ||
const { alreadyPresent, newlyAdded } = currentState.result; | ||
const total = alreadyPresent + newlyAdded; | ||
const content = (() => { | ||
if (alreadyPresent > 0) { | ||
if (total === 1) { | ||
return <P>The 1 CVR in the selected export was previously loaded.</P>; | ||
} | ||
return ( | ||
<P> | ||
Of the {format.count(total)} total CVRs in the selected export,{' '} | ||
{format.count(alreadyPresent)}{' '} | ||
{alreadyPresent === 1 ? 'was' : 'were'} previously loaded. | ||
</P> | ||
); | ||
} | ||
return <P>The CVRs in the selected export were successfully loaded.</P>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
})(); | ||
return ( | ||
<Modal | ||
title={`${format.count( | ||
currentState.result.newlyAdded | ||
)} new CVRs Loaded`} | ||
content={ | ||
currentState.result.alreadyPresent > 0 && ( | ||
<P> | ||
Of the{' '} | ||
{format.count( | ||
currentState.result.newlyAdded + | ||
currentState.result.alreadyPresent | ||
)}{' '} | ||
total CVRs in this file,{' '} | ||
{format.count(currentState.result.alreadyPresent)} were previously | ||
loaded. | ||
</P> | ||
) | ||
title={ | ||
newlyAdded === 1 | ||
? '1 New CVR Loaded' | ||
: `${format.count(newlyAdded)} New CVRs Loaded` | ||
} | ||
content={content} | ||
onOverlayClick={onClose} | ||
actions={<Button onPress={onClose}>Close</Button>} | ||
/> | ||
|
@@ -294,8 +300,7 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
if ( | ||
!castVoteRecordFilesQuery.isSuccess || | ||
!castVoteRecordFileModeQuery.isSuccess || | ||
!cvrFilesOnUsbQuery.isSuccess || | ||
currentState.state === 'loading' | ||
!cvrFilesOnUsbQuery.isSuccess | ||
) { | ||
return ( | ||
<Modal | ||
|
@@ -310,6 +315,10 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
); | ||
} | ||
|
||
if (currentState.state === 'loading') { | ||
return <Modal content={<Loading>Loading CVRs</Loading>} />; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that I'm intentionally not specifying an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great. |
||
} | ||
|
||
if ( | ||
usbDriveStatus.status === 'no_drive' || | ||
usbDriveStatus.status === 'ejected' || | ||
|
@@ -321,8 +330,7 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
content={ | ||
<P> | ||
<UsbImage src="/assets/usb-drive.svg" alt="Insert USB Image" /> | ||
Please insert a USB drive in order to load CVR files from the | ||
scanner. | ||
Please insert a USB drive in order to load CVRs from a scanner. | ||
</P> | ||
} | ||
onOverlayClick={onClose} | ||
|
@@ -332,8 +340,9 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
<FileInputButton | ||
data-testid="manual-input" | ||
onChange={processCastVoteRecordFileFromFilePicker} | ||
accept=".json" | ||
> | ||
Select Files… | ||
Select Export Manually… | ||
</FileInputButton> | ||
)} | ||
<Button onPress={onClose}>Cancel</Button> | ||
|
@@ -367,7 +376,7 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
<tr key={name} data-testid="table-row"> | ||
<td>{moment(exportTimestamp).format(TIME_FORMAT)}</td> | ||
<td>{scannerIds.join(', ')}</td> | ||
<td data-testid="cvr-count">{cvrCount}</td> | ||
<td data-testid="cvr-count">{format.count(cvrCount)}</td> | ||
{!fileModeLocked && ( | ||
<td> | ||
<LabelText> | ||
|
@@ -410,29 +419,33 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
if (numberOfNewFiles === 0) { | ||
instructionalText = fileModeLocked ? ( | ||
<React.Fragment> | ||
There were no new {headerModeText} CVR files automatically found on | ||
this USB drive. Save CVR files to this USB drive from the scanner. | ||
Optionally, you may manually select files to load. | ||
No new {headerModeText.toLowerCase()} CVR exports were automatically | ||
found on this USB drive. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Erring on the side of more concise text since I know longer text often isn't read |
||
</React.Fragment> | ||
) : ( | ||
'There were no new CVR files automatically found on this USB drive. Save CVR files to this USB drive from the scanner. Optionally, you may manually select files to load.' | ||
<React.Fragment> | ||
No new CVR exports were automatically found on this USB drive. | ||
</React.Fragment> | ||
); | ||
} else if (fileModeLocked) { | ||
instructionalText = ( | ||
<React.Fragment> | ||
The following {headerModeText} CVR files were automatically found on | ||
this USB drive. Previously loaded CVR entries will be ignored. | ||
The following {headerModeText.toLowerCase()} CVR exports were | ||
automatically found on this USB drive. | ||
</React.Fragment> | ||
); | ||
} else { | ||
instructionalText = | ||
'The following CVR files were automatically found on this USB drive. Previously loaded CVR entries will be ignored.'; | ||
instructionalText = ( | ||
<React.Fragment> | ||
The following CVR exports were automatically found on this USB drive. | ||
</React.Fragment> | ||
); | ||
} | ||
|
||
return ( | ||
<Modal | ||
modalWidth={ModalWidth.Wide} | ||
title={`Load ${headerModeText} CVR Files`} | ||
title={`Load ${headerModeText} CVRs`} | ||
content={ | ||
<Content> | ||
<P>{instructionalText}</P> | ||
|
@@ -462,7 +475,7 @@ export function ImportCvrFilesModal({ onClose }: Props): JSX.Element | null { | |
onChange={processCastVoteRecordFileFromFilePicker} | ||
accept=".json" | ||
> | ||
Select File Manually… | ||
Select Export Manually… | ||
</FileInputButton> | ||
<Button onPress={onClose}>Cancel</Button> | ||
</React.Fragment> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closing the loop on #3956 (comment)!
Whereas you could previously select the top-level
cast-vote-record-report.json
, you can now select the top-levelmetadata.json
. I couldn't find an easy way to support directory selection. Though non-ideal, we really only use this feature in dev. If an election official were to have to use it, I'd imagine it be in a context where we were guiding them.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏