status page: Specify num new pending votes to load, separate from new total votes

This commit is contained in:
David Ernst
2024-07-17 10:07:26 +03:00
parent 86e56f028c
commit ee0f769958
3 changed files with 32 additions and 22 deletions

View File

@@ -5,9 +5,8 @@ import { firebase } from '../../_services'
import { ReviewLog } from './admin/load-admin'
export default async (req: NextApiRequest, res: NextApiResponse) => {
const { election_id, limitToLast } = req.query
if (limitToLast && +limitToLast < 1) return res.status(200).json([])
const { election_id, num_new_accepted_votes, num_new_pending_votes } = req.query
// console.log({ election_id, num_new_accepted_votes, num_new_pending_votes })
const electionDoc = firebase
.firestore()
@@ -17,10 +16,8 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
// Begin preloading
let votesQuery = electionDoc.collection('votes').orderBy('created_at')
let pendingVotesQuery = electionDoc.collection('votes-pending').orderBy('created_at')
if (typeof limitToLast === 'string') {
votesQuery = votesQuery.limitToLast(+limitToLast)
pendingVotesQuery = votesQuery.limitToLast(+limitToLast)
}
if (num_new_accepted_votes) votesQuery = votesQuery.limitToLast(+num_new_accepted_votes)
if (num_new_pending_votes) pendingVotesQuery = votesQuery.limitToLast(+num_new_pending_votes)
const loadVotes = votesQuery.get()
const loadPendingVotes = pendingVotesQuery.get()

View File

@@ -2,6 +2,12 @@ import { NextApiRequest, NextApiResponse } from 'next'
import { firebase } from '../../_services'
export type NumAcceptedVotes = {
num_invalidated_votes: number
num_pending_votes: number
num_votes: number
}
export default async (req: NextApiRequest, res: NextApiResponse) => {
const { election_id } = req.query
@@ -14,10 +20,9 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
// Is election_id in DB?
if (!electionDoc.exists) return res.status(400).json({ error: 'Unknown Election ID.' })
const { num_invalidated_votes = 0, num_votes } = { ...electionDoc.data() } as {
num_invalidated_votes?: number
num_votes: number
}
const { num_invalidated_votes = 0, num_pending_votes = 0, num_votes = 0 } = { ...electionDoc.data() }
return res.status(200).json(num_votes - num_invalidated_votes)
const response: NumAcceptedVotes = { num_invalidated_votes, num_pending_votes, num_votes }
return res.status(200).json(response)
}

View File

@@ -1,3 +1,4 @@
import { NumAcceptedVotes } from 'api/election/[election_id]/num-votes'
import { useRouter } from 'next/router'
import { Fragment, useEffect, useState } from 'react'
import { CipherStrings } from 'src/crypto/stringify-shuffle'
@@ -26,11 +27,12 @@ export const AcceptedVotes = ({
const [votes, setVotes] = useState<EncryptedVote[]>()
// Exponentially poll for num votes (just a single read)
const { data: numVotes } = useSWRExponentialBackoff(
!election_id ? null : `/api/election/${election_id}/num-accepted-votes`,
const { data } = useSWRExponentialBackoff(
!election_id ? null : `/api/election/${election_id}/num-votes`,
fetcher,
1,
) as { data: number }
) as { data: NumAcceptedVotes }
const { num_pending_votes = 0, num_votes = 0 } = data || {}
// Load all the encrypted votes (heavy, so only on first load)
useEffect(() => {
@@ -42,13 +44,13 @@ export const AcceptedVotes = ({
if (!votes || !ballot_design) return <div>Loading...</div>
const newVotes = numVotes - votes.length
const newTotalVotes = num_votes - votes.length
const { columns } = generateColumnNames({ ballot_design })
return (
<>
<TotalVotesCast {...{ numVotes }} />
<TotalVotesCast numVotes={num_votes} />
<section className="p-4 mb-8 bg-white rounded-lg shadow-[0px_2px_2px_hsl(0_0%_50%_/0.333),0px_4px_4px_hsl(0_0%_50%_/0.333),0px_6px_6px_hsl(0_0%_50%_/0.333)]">
<h3 className="mt-0 mb-1">{title_prefix}All Submitted Votes</h3>
<p className='mt-0 text-sm italic opacity-70"'>
@@ -114,16 +116,22 @@ export const AcceptedVotes = ({
</tbody>
</table>
{!!newVotes && (
{!!newTotalVotes && (
<p
className="inline-block mt-1.5 text-xs text-blue-500 cursor-pointer opacity-70 hover:underline"
onClick={() =>
fetch(`/api/election/${election_id}/accepted-votes?limitToLast=${newVotes}`)
onClick={() => {
const num_loaded_pending_votes = votes.filter(({ auth }) => auth === 'pending').length
const num_new_pending_votes = num_pending_votes - num_loaded_pending_votes
const num_new_accepted_votes = newTotalVotes - num_new_pending_votes
fetch(
`/api/election/${election_id}/accepted-votes?num_new_pending_votes=${num_new_pending_votes}&num_new_accepted_votes=${num_new_accepted_votes}`,
)
.then((r) => r.json())
.then((newVotes) => setVotes(() => [...votes, ...newVotes]))
}
}}
>
+ Load {newVotes} new
+ Load {newTotalVotes} new
</p>
)}