diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json
index b77fbb1..df36e49 100644
--- a/packages/concordia-app/public/locales/en/translation.json
+++ b/packages/concordia-app/public/locales/en/translation.json
@@ -90,6 +90,7 @@
"topic.poll.invalid.data.header": "This topic has a poll but the data are untrusted!",
"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.vote": "Vote",
"topic.poll.tab.results.votes": "Votes",
"topic.poll.tab.results.user.vote": "You voted: ",
"topic.poll.tab.vote.no.changes": "This poll does not allow vote changes.",
diff --git a/packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx b/packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx
index 313a3e8..c5ca9d7 100644
--- a/packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx
+++ b/packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { CHART_TYPE_BAR } from '../../../../constants/polls/PollGraph';
const PollChartBar = (props) => {
- const { pollOptions, voteCounts } = props;
+ const { pollOptions, voteCounts, voterNames } = props;
const chartOptions = useMemo(() => ({
chart: {
@@ -30,9 +30,20 @@ const PollChartBar = (props) => {
},
},
tooltip: {
- enabled: false,
+ enabled: true,
+ x: {
+ show: false,
+ },
+ y: {
+ formatter(value, { seriesIndex }) {
+ return `
${voterNames[seriesIndex].join('
')}
`;
+ },
+ title: {
+ formatter: () => null,
+ },
+ },
},
- }), [pollOptions]);
+ }), [pollOptions, voterNames]);
const chartSeries = useMemo(() => [{
name: 'Votes',
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 03acf4f..3d0644c 100644
--- a/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx
+++ b/packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { CHART_TYPE_DONUT } from '../../../../constants/polls/PollGraph';
const PollChartDonut = (props) => {
- const { pollOptions, voteCounts } = props;
+ const { pollOptions, voteCounts, voterNames } = props;
const chartOptions = useMemo(() => ({
chart: {
@@ -30,12 +30,21 @@ const PollChartDonut = (props) => {
},
labels: pollOptions,
tooltip: {
- enabled: false,
+ enabled: true,
+ fillSeriesColor: false,
+ y: {
+ formatter(value, { seriesIndex }) {
+ return `${voterNames[seriesIndex].join('
')}
`;
+ },
+ title: {
+ formatter: () => null,
+ },
+ },
},
legend: {
position: 'bottom',
},
- }), [pollOptions]);
+ }), [pollOptions, voterNames]);
return (
{
- const { pollOptions, voteCounts, userVoteIndex } = props;
+ const { pollOptions, userVoteIndex, voteCounts, voterNames } = props;
+ const [totalVotes, setTotalVotes] = useState(voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0));
const { t } = useTranslation();
+ useEffect(() => {
+ setTotalVotes(voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0));
+ }, [voteCounts]);
+
const footer = useMemo(() => (
<>
- {voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0)}
+ { totalVotes }
- {t('topic.poll.tab.results.votes')}
+
+ { totalVotes !== 1 ? t('topic.poll.tab.results.votes') : t('topic.poll.tab.results.vote') }
+
{userVoteIndex !== -1
&& (
@@ -26,7 +33,7 @@ const PollGraph = (props) => {
)}
>
- ), [pollOptions, t, userVoteIndex, voteCounts]);
+ ), [pollOptions, t, totalVotes, userVoteIndex]);
const panes = useMemo(() => {
const chartBarPane = (
@@ -38,6 +45,7 @@ const PollGraph = (props) => {
@@ -59,6 +67,7 @@ const PollGraph = (props) => {
@@ -76,7 +85,7 @@ const PollGraph = (props) => {
{ menuItem: { key: 'chart-bar', icon: 'chart bar' }, render: () => chartBarPane },
{ menuItem: { key: 'chart-donut', icon: 'chart pie' }, render: () => chartDonutPane },
]);
- }, [footer, pollOptions, voteCounts]);
+ }, [footer, pollOptions, voteCounts, voterNames]);
return (
{
const [pollOptions, setPollOptions] = useState([]);
const [voteCounts, setVoteCounts] = useState([]);
const [voters, setVoters] = useState([]);
+ const [voterNames, setVoterNames] = useState([]);
const [pollHashValid, setPollHashValid] = useState(true);
const [pollQuestion, setPollQuestion] = useState('');
const [chainDataLoading, setChainDataLoading] = useState(true);
@@ -84,6 +85,11 @@ const PollView = (props) => {
.slice(index > 0 ? cumulativeSum[index - 1] : 0,
subArrayEnd)));
+ setVoterNames(cumulativeSum
+ .map((subArrayEnd, index) => pollResults.value[6]
+ .slice(index > 0 ? cumulativeSum[index - 1] : 0,
+ subArrayEnd)));
+
setChainDataLoading(false);
}
}, [getPollCallHash, getPollResults]);
@@ -148,10 +154,11 @@ const PollView = (props) => {
pollOptions={pollOptions}
voteCounts={voteCounts}
userVoteIndex={userVoteIndex}
+ voterNames={voterNames}
/>
)
: null
- ), [chainDataLoading, orbitDataLoading, pollOptions, userVoteIndex, voteCounts]);
+ ), [chainDataLoading, orbitDataLoading, pollOptions, userVoteIndex, voteCounts, voterNames]);
const panes = useMemo(() => {
const pollVotePane = (
diff --git a/packages/concordia-contracts/contracts/Forum.sol b/packages/concordia-contracts/contracts/Forum.sol
index dca35fc..66ccd64 100644
--- a/packages/concordia-contracts/contracts/Forum.sol
+++ b/packages/concordia-contracts/contracts/Forum.sol
@@ -3,6 +3,7 @@ pragma solidity 0.8.1;
contract Forum {
// Error messages for require()
+ string public constant USER_HAS_SIGNED_UP = "User has already signed up.";
string public constant USER_HAS_NOT_SIGNED_UP = "User hasn't signed up yet.";
string public constant USERNAME_TAKEN = "Username is already taken.";
string public constant TOPIC_DOES_NOT_EXIST = "Topic doesn't exist.";
@@ -28,7 +29,7 @@ contract Forum {
event UsernameUpdated(string newName, string oldName, address userAddress);
function signUp(string memory username) public returns (bool) {
- require(!hasUserSignedUp(msg.sender), USER_HAS_NOT_SIGNED_UP);
+ require(!hasUserSignedUp(msg.sender), USER_HAS_SIGNED_UP);
require(!isUserNameTaken(username), USERNAME_TAKEN);
users[msg.sender] = User(username, new uint[](0), new uint[](0), block.timestamp, true);
usernameAddresses[username] = msg.sender;
@@ -118,6 +119,16 @@ contract Forum {
return userAddresses;
}
+ function getUsernames(address[] memory userAddressesArray) public view returns (string[] memory) {
+ string[] memory usernamesArray = new string[](userAddressesArray.length);
+
+ for (uint i = 0; i < userAddressesArray.length; i++) {
+ usernamesArray[i] = getUsername(userAddressesArray[i]);
+ }
+
+ return usernamesArray;
+ }
+
//----------------------------------------POSTING----------------------------------------
struct Topic {
uint topicID;
diff --git a/packages/concordia-contracts/contracts/Voting.sol b/packages/concordia-contracts/contracts/Voting.sol
index b11d9b1..03eb04c 100644
--- a/packages/concordia-contracts/contracts/Voting.sol
+++ b/packages/concordia-contracts/contracts/Voting.sol
@@ -68,26 +68,29 @@ contract Voting {
);
}
- function getPoll(uint topicID) public view returns (uint, string memory, bool, uint, uint[] memory, address[] memory, uint) {
+ function getPoll(uint topicID) public view
+ returns (uint, string memory, bool, uint, uint[] memory, address[] memory, string[] memory) {
require(pollExists(topicID), POLL_DOES_NOT_EXIST);
- uint totalVotes = getTotalVotes(topicID);
uint[] memory voteCounts = getVoteCounts(topicID);
- address[] memory voters = getSerializedVoters(topicID, voteCounts, totalVotes);
+ address[] memory voters = getSerializedVoters(topicID, voteCounts);
+ string[] memory voterNames = forum.getUsernames(voters);
+
+ Poll storage poll = polls[topicID];
return (
- polls[topicID].numOptions,
- polls[topicID].dataHash,
- polls[topicID].enableVoteChanges,
- polls[topicID].timestamp,
- voteCounts,
- voters,
- totalVotes
+ poll.numOptions,
+ poll.dataHash,
+ poll.enableVoteChanges,
+ poll.timestamp,
+ voteCounts,
+ voters,
+ voterNames
);
}
- function getSerializedVoters(uint topicID, uint[] memory voteCounts, uint totalVotes) private view returns (address[] memory) {
-
+ function getSerializedVoters(uint topicID, uint[] memory voteCounts) private view returns (address[] memory) {
+ uint totalVotes = getTotalVotes(topicID);
address[] memory voters = new address[](totalVotes);
uint serializationIndex = 0;
@@ -99,7 +102,7 @@ contract Voting {
}
}
- return (voters);
+ return voters;
}
function isOptionValid(uint topicID, uint option) private view returns (bool) {