Browse Source

feat: add ability to remove vote

develop
Ezerous 4 years ago
parent
commit
da1d9727d6
  1. 3
      packages/concordia-app/public/locales/en/translation.json
  2. 7
      packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx
  3. 40
      packages/concordia-app/src/components/PollView/PollGraph/index.jsx
  4. 4
      packages/concordia-app/src/components/PollView/PollGraph/styles.css
  5. 67
      packages/concordia-app/src/components/PollView/PollVote/index.jsx
  6. 3
      packages/concordia-app/src/components/PollView/index.jsx

3
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",

7
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 (

40
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(() => (
<>
{' '}
<Header as="h4">
{t('topic.poll.tab.results.votes.count', {
totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0),
})}
</Header>
{userVoteIndex !== -1
&& (
<Header as="h4">
{t('topic.poll.tab.results.user.vote', {
userVote: pollOptions[userVoteIndex],
})}
</Header>
)}
</>
), [pollOptions, t, userVoteIndex, voteCounts]);
const panes = useMemo(() => {
const chartBarPane = (
<Tab.Pane attached={false}>
@ -26,11 +45,7 @@ const PollGraph = (props) => {
</Grid.Row>
<Grid.Row>
<Grid.Column textAlign="center">
<Header as="h4">
{t('topic.poll.tab.results.votes.count', {
totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0),
})}
</Header>
{footer}
</Grid.Column>
</Grid.Row>
</Grid>
@ -49,7 +64,11 @@ const PollGraph = (props) => {
</Grid.Column>
<Grid.Column />
</Grid.Row>
<Grid.Row />
<Grid.Row>
<Grid.Column textAlign="center">
{footer}
</Grid.Column>
</Grid.Row>
</Grid>
</Tab.Pane>
);
@ -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 (
<Tab
@ -68,9 +87,14 @@ const PollGraph = (props) => {
);
};
PollGraph.defaultProps = {
userVoteIndex: -1,
};
PollGraph.propTypes = {
pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired,
voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
userVoteIndex: PropTypes.number,
};
export default PollGraph;

4
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;
}

67
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 (
<>
<Header as="h4">
{t('topic.poll.tab.results.user.vote', {
userVote: pollOptions[userVoteIndex],
})}
</Header>
<div>
{t('topic.poll.tab.vote.no.changes')}
</div>
</>
);
}
return (
<Form onSubmit={onCastVote}>
<Form.Group grouped>
@ -34,17 +74,28 @@ const PollVote = (props) => {
label={pollOption}
value={index}
checked={index === selectedOptionIndex}
disabled={hasUserVoted && !enableVoteChanges && index !== selectedOptionIndex}
disabled={voting}
onChange={onOptionSelected}
/>
))}
</Form.Group>
<Form.Button
<Button
type="submit"
disabled={voting || (hasUserVoted && !enableVoteChanges) || (selectedOptionIndex === userVoteIndex)}
className="primary-button"
disabled={voting || (selectedOptionIndex === userVoteIndex)}
>
{t('topic.poll.tab.vote.form.button.submit')}
</Form.Button>
</Button>
{hasUserVoted && enableVoteChanges
&& (
<Button
type="submit"
disabled={voting}
onClick={onUnvote}
>
{t('topic.poll.tab.vote.form.button.unvote')}
</Button>
)}
</Form>
);
};

3
packages/concordia-app/src/components/PollView/index.jsx

@ -147,10 +147,11 @@ const PollView = (props) => {
<PollGraph
pollOptions={pollOptions}
voteCounts={voteCounts}
userVoteIndex={userVoteIndex}
/>
)
: null
), [chainDataLoading, orbitDataLoading, pollOptions, voteCounts]);
), [chainDataLoading, orbitDataLoading, pollOptions, userVoteIndex, voteCounts]);
const panes = useMemo(() => {
const pollVotePane = (

Loading…
Cancel
Save