Skip to content

Commit

Permalink
Merge pull request #13 from datasektionen/admin-vote-count
Browse files Browse the repository at this point in the history
Add counter for the amount of votes that has been submitted in an election
  • Loading branch information
Herkarl authored Nov 30, 2023
2 parents a583343 + ff464d9 commit 6ee68fe
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 4 deletions.
13 changes: 12 additions & 1 deletion client/src/components/AdminElectionView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from "react";
import { Candidate, NullTime } from "../util/ElectionTypes";
import { CandidateList } from "./CandidateList";
import { DateTimeInput } from "./DateTime";
import Loading from "./Loading";

export interface ElectionFormValues {
title: string,
Expand Down Expand Up @@ -35,7 +36,8 @@ export interface AdminElectionViewProps {
userInputError: string | false,
openTimeDefault?: NullTime,
closeTimeDefault?: NullTime,
submitDisabled?: boolean
submitDisabled?: boolean,
submittedVotes?: number | null,
}

const useStyles = createStyles((theme) => {
Expand All @@ -51,6 +53,7 @@ export const AdminElectionView: React.FC<AdminElectionViewProps> = ({
onCloseTimeChanged, onOpenTimeChanged, userInputError,
candidates, onCandidateAdded, onCandidateRemoved, onCandidateChanged,
openTimeDefault = null, closeTimeDefault = null, submitDisabled = false,
submittedVotes
}) => {
const { classes } = useStyles();

Expand Down Expand Up @@ -115,7 +118,15 @@ export const AdminElectionView: React.FC<AdminElectionViewProps> = ({
{...electionForm.getInputProps("extraMandates")}
min={0}
/>
</div>

<div>
<Text size="lg" fw={700} align="center">
Submitted votes
</Text>
<Text align="center">
{submittedVotes ?? "-"}
</Text>
</div>
</Grid.Col>

Expand Down
10 changes: 7 additions & 3 deletions client/src/views/admin/EditElection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import { Container, createStyles, Center, Button, Modal, Text, Grid } from "@man
import { useForm } from "@mantine/form";
import { useDisclosure, useListState } from "@mantine/hooks";

import { Candidate, CandidateSchema, Election, ElectionResultResponse, ElectionResultResponseSchema, ElectionSchema, NullTime, parseElectionResponse } from "../../util/ElectionTypes";
import { Candidate, Election, ElectionResultResponse, ElectionResultResponseSchema, ElectionSchema, NullTime, parseElectionResponse } from "../../util/ElectionTypes";
import useAuthorization from "../../hooks/useAuthorization";
import { useNavigate, useParams } from "react-router-dom";
import { useAPIData } from "../../hooks/useAxios";
import { AdminElectionView, ElectionFormValues } from "../../components/AdminElectionView";
import Loading, { Error } from "../../components/Loading";
import { ClassNames } from "@emotion/react";
import { DisplaySchultzeResult } from "../../components/DisplayResult";
import { string, z } from "zod";
import { z } from "zod";

const useStyles = createStyles((theme) => ({
failed: {
Expand Down Expand Up @@ -46,6 +45,10 @@ const EditElection: React.FC = () => {
closeTime: null as NullTime,
}
});
const [voteCount, loadingVotes, errorVotes] = useAPIData<number>(
`/api/election/${electionId}/vote-count`,
(data) => z.number().parseAsync(data)
);

const [finalizeModalOpen, {
open: openFinalizeModal,
Expand Down Expand Up @@ -259,6 +262,7 @@ const EditElection: React.FC = () => {
userInputError={userInputError}
openTimeDefault={electionData.openTime}
closeTimeDefault={electionData.closeTime}
submittedVotes={voteCount}
/>

<Modal opened={finalizeModalOpen} onClose={closeFinalizeModal} centered my={"md"}
Expand Down
21 changes: 21 additions & 0 deletions server/actions/votes.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,27 @@ func GetVotes(c *gin.Context) {
c.JSON(http.StatusOK, response)
}

func GetVoteCount(c *gin.Context) {
electionId, err := uuid.FromString(c.Param("id"))
if err != nil {
fmt.Println(err)
c.String(http.StatusBadRequest, util.BadUUIDMessage)
return
}

db := database.GetDB()
defer database.ReleaseDB()

var count int64
if err := db.Model(database.Vote{}).Where("election_id = ?", electionId).Count(&count).Error; err != nil {
fmt.Println(err)
c.String(http.StatusInternalServerError, util.RequestFailedMessage)
return
}

c.JSON(http.StatusOK, count)
}

// CountVotes calculates the winner of an election using the "Alternativsomröstning" algorithm,
// as described in https://styrdokument.datasektionen.se/reglemente (§3.12.7 Urnval)
// Expects there to be token candidates for a vacant spot and a blank vote, which it
Expand Down
1 change: 1 addition & 0 deletions server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func InitRoutes(r *gin.RouterGroup) {
auth.GET("/election/:id/has-voted", actions.HasVoted)
read.GET("/election/:id/votes", actions.GetVotes)
read.GET("/election/:id/count", actions.CountVotesSchultze)
write.GET("/election/:id/vote-count", actions.GetVoteCount)
// read.GET("/election/:id/countOld", actions.CountVotes)
vote.GET("/election/hashes", actions.GetHashes)

Expand Down

0 comments on commit 6ee68fe

Please sign in to comment.