-
Notifications
You must be signed in to change notification settings - Fork 76
feat: cancel voting (frontend) #6465
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
base: feat/mg/cancel-voting-backend-6396
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import {CreateVotingRequest} from "store/features/votings/types"; | ||
| import {SERVER_HTTP_URL} from "../config"; | ||
| import { CreateVotingRequest, VotingStatus } from "store/features/votings/types"; | ||
| import { SERVER_HTTP_URL } from "../config"; | ||
|
|
||
| export const VotingAPI = { | ||
| /** | ||
|
|
@@ -23,24 +23,28 @@ export const VotingAPI = { | |
|
|
||
| throw new Error(`create voting request resulted in response with status ${response.status}`); | ||
| } catch (error) { | ||
| throw new Error(`unable to create voting`, {cause: error}); | ||
| throw new Error(`unable to create voting`, { cause: error }); | ||
| } | ||
| }, | ||
|
|
||
| changeVotingStatus: async (board: string, voting: string) => { | ||
| changeVotingStatus: async (board: string, voting: string, status?: VotingStatus) => { | ||
| try { | ||
| const response = await fetch(`${SERVER_HTTP_URL}/boards/${board}/votings/${voting}`, { | ||
| const options: RequestInit = { | ||
|
Member
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. I'd prefer the options inline inside the fetch rather than an extra object, since we do it that way in all other places (not to say this is bad, I just want it to be the same if possible) |
||
| method: "PUT", | ||
| credentials: "include", | ||
| }); | ||
| body: JSON.stringify({ status: status }), | ||
|
Member
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. properties with the same name and value can be shortened like this: |
||
| headers: { "Content-Type": "application/json" }, | ||
| }; | ||
|
|
||
| const response = await fetch(`${SERVER_HTTP_URL}/boards/${board}/votings/${voting}`, options); | ||
|
|
||
| if (response.status === 200) { | ||
| return await response.json(); | ||
| } | ||
|
|
||
| throw new Error(`change voting status request resulted in response with status ${response.status}`); | ||
| } catch (error) { | ||
| throw new Error(`unable to change voting status`, {cause: error}); | ||
| throw new Error(`unable to change voting status`, { cause: error }); | ||
| } | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,18 @@ | ||
| import {useState} from "react"; | ||
| import {useTranslation} from "react-i18next"; | ||
| import {Dialog} from "components/Dialog"; | ||
| import {useNavigate} from "react-router"; | ||
| import {useAppDispatch, useAppSelector} from "store"; | ||
| import {Toggle} from "components/Toggle"; | ||
| import {getNumberFromStorage, saveToStorage, getFromStorage} from "utils/storage"; | ||
| import {CUMULATIVE_VOTING_DEFAULT_STORAGE_KEY, CUSTOM_NUMBER_OF_VOTES_STORAGE_KEY} from "constants/storage"; | ||
| import {PlusIcon, MinusIcon} from "components/Icon"; | ||
| import { useState } from "react"; | ||
| import { useTranslation } from "react-i18next"; | ||
| import { Dialog } from "components/Dialog"; | ||
| import { useNavigate } from "react-router"; | ||
| import { useAppDispatch, useAppSelector } from "store"; | ||
| import { Toggle } from "components/Toggle"; | ||
| import { getNumberFromStorage, saveToStorage, getFromStorage } from "utils/storage"; | ||
| import { CUMULATIVE_VOTING_DEFAULT_STORAGE_KEY, CUSTOM_NUMBER_OF_VOTES_STORAGE_KEY } from "constants/storage"; | ||
| import { PlusIcon, MinusIcon } from "components/Icon"; | ||
| import "./VotingDialog.scss"; | ||
| import {closeVoting, createVoting} from "store/features"; | ||
| import { closeVoting, createVoting, abortVoting } from "store/features"; | ||
|
|
||
| export const VotingDialog = () => { | ||
| const dispatch = useAppDispatch(); | ||
| const {t} = useTranslation(); | ||
| const { t } = useTranslation(); | ||
| const navigate = useNavigate(); | ||
| const isAdmin = useAppSelector((state) => state.participants?.self?.role === "OWNER" || state.participants?.self?.role === "MODERATOR"); | ||
| const voting = useAppSelector((state) => state.votings.open?.id); | ||
|
|
@@ -46,12 +46,23 @@ export const VotingDialog = () => { | |
| navigate(".."); | ||
| }; | ||
|
|
||
| const abort_voting = () => { | ||
|
Member
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. snake case‽ this ain't python |
||
| dispatch(abortVoting(voting!)); | ||
| navigate(".."); | ||
| } | ||
|
|
||
| return ( | ||
| <Dialog className="voting-dialog accent-color__planning-pink" title={t("VoteConfigurationButton.label")} onClose={() => navigate("..")}> | ||
| {voting ? ( | ||
| <button className="voting-dialog__start-button" data-testid="voting-dialog__stop-button" onClick={() => stopVoting()}> | ||
| <label>{t("VoteConfigurationButton.stopVoting")}</label> | ||
| </button> | ||
| <> | ||
| <button className="voting-dialog__start-button" data-testid="voting-dialog__stop-button" onClick={() => stopVoting()}> | ||
| <label>{t("VoteConfigurationButton.stopVoting")}</label> | ||
| </button> | ||
|
|
||
| <button className="voting-dialog__start-button voting-dialog__cancel-button" data-testid="voting-dialog__cancel-button" onClick={() => abort_voting()}> | ||
|
Member
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. should be "abort" instead of "cancel" |
||
| <label>{t("VoteConfigurationButton.cancelVoting")}</label> | ||
| </button> | ||
| </> | ||
| ) : ( | ||
| <> | ||
| <button | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,37 @@ | ||
| import {createAsyncThunk} from "@reduxjs/toolkit"; | ||
| import {API} from "api"; | ||
| import {ApplicationState, retryable} from "store"; | ||
| import {CreateVotingRequest} from "./types"; | ||
| import { createAsyncThunk } from "@reduxjs/toolkit"; | ||
| import { API } from "api"; | ||
| import { ApplicationState, retryable } from "store"; | ||
| import { CreateVotingRequest } from "./types"; | ||
|
|
||
| export const createVoting = createAsyncThunk<void, CreateVotingRequest, {state: ApplicationState}>("votings/createVoting", async (payload, {dispatch, getState}) => { | ||
| export const createVoting = createAsyncThunk<void, CreateVotingRequest, { state: ApplicationState }>("votings/createVoting", async (payload, { dispatch, getState }) => { | ||
| const boardId = getState().board.data!.id; | ||
|
|
||
| await retryable( | ||
| () => API.createVoting(boardId, payload), | ||
| dispatch, | ||
| () => createVoting({...payload}), | ||
| () => createVoting({ ...payload }), | ||
| "createVoting" | ||
| ); | ||
| }); | ||
|
|
||
| export const closeVoting = createAsyncThunk<void, string, {state: ApplicationState}>("votings/closeVoting", async (payload, {dispatch, getState}) => { | ||
| export const closeVoting = createAsyncThunk<void, string, { state: ApplicationState }>("votings/closeVoting", async (payload, { dispatch, getState }) => { | ||
| const boardId = getState().board.data!.id; | ||
|
|
||
| await retryable( | ||
| () => API.changeVotingStatus(boardId, payload), | ||
| () => API.changeVotingStatus(boardId, payload, "CLOSED"), | ||
|
Member
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. should be "ABORT(ED)" here also |
||
| dispatch, | ||
| () => closeVoting(payload), | ||
| "closeVoting" | ||
| ); | ||
| }); | ||
|
|
||
| export const abortVoting = createAsyncThunk<void, string, { state: ApplicationState }>("votings/abortVoting", async (payload, { dispatch, getState }) => { | ||
| const boardId = getState().board.data!.id; | ||
|
|
||
| await retryable( | ||
| () => API.changeVotingStatus(boardId, payload, "ABORTED"), | ||
| dispatch, | ||
| () => abortVoting(payload), | ||
| "abortVoting" | ||
| ); | ||
| }); | ||
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.
statuscan be non-nullable