From da1d9727d6b8b9301febc742ae8ea2aa4e9d79d3 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 6 Apr 2021 21:06:15 +0300 Subject: [PATCH] feat: add ability to remove vote --- .../public/locales/en/translation.json | 3 + .../PollGraph/PollChartDonut/index.jsx | 7 +- .../components/PollView/PollGraph/index.jsx | 40 ++++++++--- .../components/PollView/PollGraph/styles.css | 4 ++ .../components/PollView/PollVote/index.jsx | 67 ++++++++++++++++--- .../src/components/PollView/index.jsx | 3 +- 6 files changed, 103 insertions(+), 21 deletions(-) diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json index 3eb7a2d..6994476 100644 --- a/packages/concordia-app/public/locales/en/translation.json +++ b/packages/concordia-app/public/locales/en/translation.json @@ -91,7 +91,10 @@ "topic.poll.invalid.data.sub.header": "The poll data downloaded from the poster have been tampered with.", "topic.poll.tab.graph.title": "Results", "topic.poll.tab.results.votes.count": "Total votes: {{totalVotes}}", + "topic.poll.tab.results.user.vote": "You voted: {{userVote}}", + "topic.poll.tab.vote.no.changes": "This poll does not allow vote changes.", "topic.poll.tab.vote.form.button.submit": "Submit", + "topic.poll.tab.vote.form.button.unvote": "Remove Vote", "topic.poll.tab.vote.form.radio.label": "Select one of the options:", "topic.poll.tab.vote.title": "Vote", "username.selector.error.username.empty.message": "Username is required", diff --git a/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx b/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx index e592d74..2f7ddbe 100644 --- a/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx +++ b/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx @@ -18,10 +18,6 @@ const PollChartDonut = (props) => { donut: { labels: { show: true, - total: { - show: true, - label: 'Total Votes', - }, }, }, }, @@ -30,6 +26,9 @@ const PollChartDonut = (props) => { tooltip: { enabled: false, }, + legend: { + position: 'bottom', + }, }), [pollOptions]); return ( diff --git a/packages/concordia-app/src/components/PollView/PollGraph/index.jsx b/packages/concordia-app/src/components/PollView/PollGraph/index.jsx index 770a844..7b77ec5 100644 --- a/packages/concordia-app/src/components/PollView/PollGraph/index.jsx +++ b/packages/concordia-app/src/components/PollView/PollGraph/index.jsx @@ -7,9 +7,28 @@ import PollChartDonut from './PollChartDonut'; import './styles.css'; const PollGraph = (props) => { - const { pollOptions, voteCounts } = props; + const { pollOptions, voteCounts, userVoteIndex } = props; const { t } = useTranslation(); + const footer = useMemo(() => ( + <> + {' '} +
+ {t('topic.poll.tab.results.votes.count', { + totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0), + })} +
+ {userVoteIndex !== -1 + && ( +
+ {t('topic.poll.tab.results.user.vote', { + userVote: pollOptions[userVoteIndex], + })} +
+ )} + + ), [pollOptions, t, userVoteIndex, voteCounts]); + const panes = useMemo(() => { const chartBarPane = ( @@ -26,11 +45,7 @@ const PollGraph = (props) => { -
- {t('topic.poll.tab.results.votes.count', { - totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0), - })} -
+ {footer}
@@ -49,7 +64,11 @@ const PollGraph = (props) => { - + + + {footer} + +
); @@ -58,7 +77,7 @@ const PollGraph = (props) => { { menuItem: { key: 'chart-bar', icon: 'chart bar' }, render: () => chartBarPane }, { menuItem: { key: 'chart-donut', icon: 'chart pie' }, render: () => chartDonutPane }, ]); - }, [pollOptions, t, voteCounts]); + }, [footer, pollOptions, voteCounts]); return ( { ); }; +PollGraph.defaultProps = { + userVoteIndex: -1, +}; + PollGraph.propTypes = { pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired, voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired, + userVoteIndex: PropTypes.number, }; export default PollGraph; diff --git a/packages/concordia-app/src/components/PollView/PollGraph/styles.css b/packages/concordia-app/src/components/PollView/PollGraph/styles.css index a2c3d42..3e86acd 100644 --- a/packages/concordia-app/src/components/PollView/PollGraph/styles.css +++ b/packages/concordia-app/src/components/PollView/PollGraph/styles.css @@ -2,3 +2,7 @@ box-shadow: none; border: none; } + +#topic-poll-container h4 { + margin-top: 0.5rem; +} diff --git a/packages/concordia-app/src/components/PollView/PollVote/index.jsx b/packages/concordia-app/src/components/PollView/PollVote/index.jsx index 836e45e..b1ac786 100644 --- a/packages/concordia-app/src/components/PollView/PollVote/index.jsx +++ b/packages/concordia-app/src/components/PollView/PollVote/index.jsx @@ -1,9 +1,11 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { Form } from 'semantic-ui-react'; +import { useSelector } from 'react-redux'; +import { Button, Form, Header } from 'semantic-ui-react'; import { useTranslation } from 'react-i18next'; import { VOTING_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; import { drizzle } from '../../../redux/store'; +import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/TransactionStatus'; const { contracts: { [VOTING_CONTRACT]: { methods: { vote } } } } = drizzle; @@ -11,19 +13,57 @@ const PollVote = (props) => { const { topicId, account, pollOptions, enableVoteChanges, hasUserVoted, userVoteIndex, } = props; + const transactionStack = useSelector((state) => state.transactionStack); + const transactions = useSelector((state) => state.transactions); + const [voteCacheSendStackId, setVoteCacheSendStackId] = useState(''); const [selectedOptionIndex, setSelectedOptionIndex] = useState(userVoteIndex); - const [voting, setVoting] = useState(''); + const [voting, setVoting] = useState(false); const { t } = useTranslation(); const onOptionSelected = (e, { value }) => { setSelectedOptionIndex(value); }; + useEffect(() => { + setSelectedOptionIndex(userVoteIndex); + }, [userVoteIndex]); + const onCastVote = () => { setVoting(true); - vote.cacheSend(...[topicId, selectedOptionIndex + 1], { from: account }); + setVoteCacheSendStackId(vote.cacheSend(...[topicId, selectedOptionIndex + 1], { from: account })); + }; + + const onUnvote = (e) => { + e.preventDefault(); + setVoting(true); + setVoteCacheSendStackId(vote.cacheSend(...[topicId, 0], { from: account })); }; + useEffect(() => { + if (voting && transactionStack && transactionStack[voteCacheSendStackId] + && transactions[transactionStack[voteCacheSendStackId]]) { + if (transactions[transactionStack[voteCacheSendStackId]].status === TRANSACTION_ERROR + || transactions[transactionStack[voteCacheSendStackId]].status === TRANSACTION_SUCCESS) { + setVoting(false); + } + } + }, [transactionStack, transactions, voteCacheSendStackId, voting]); + + if (hasUserVoted && !enableVoteChanges) { + return ( + <> +
+ {t('topic.poll.tab.results.user.vote', { + userVote: pollOptions[userVoteIndex], + })} +
+
+ {t('topic.poll.tab.vote.no.changes')} +
+ + ); + } + return (
@@ -34,17 +74,28 @@ const PollVote = (props) => { label={pollOption} value={index} checked={index === selectedOptionIndex} - disabled={hasUserVoted && !enableVoteChanges && index !== selectedOptionIndex} + disabled={voting} onChange={onOptionSelected} /> ))} - {t('topic.poll.tab.vote.form.button.submit')} - + + {hasUserVoted && enableVoteChanges + && ( + + )}
); }; diff --git a/packages/concordia-app/src/components/PollView/index.jsx b/packages/concordia-app/src/components/PollView/index.jsx index a7c2445..955d2f8 100644 --- a/packages/concordia-app/src/components/PollView/index.jsx +++ b/packages/concordia-app/src/components/PollView/index.jsx @@ -147,10 +147,11 @@ const PollView = (props) => { ) : null - ), [chainDataLoading, orbitDataLoading, pollOptions, voteCounts]); + ), [chainDataLoading, orbitDataLoading, pollOptions, userVoteIndex, voteCounts]); const panes = useMemo(() => { const pollVotePane = (