Browse Source

feat: add popup to post votes

develop
Ezerous 4 years ago
parent
commit
0a0c5a4496
  1. 71
      packages/concordia-app/src/components/PostList/PostVoting/index.jsx
  2. 10
      packages/concordia-app/src/components/PostList/PostVoting/styles.css
  3. 6
      packages/concordia-contracts/contracts/PostVoting.sol

71
packages/concordia-app/src/components/PostList/PostVoting/index.jsx

@ -1,13 +1,14 @@
import React, { import React, {
memo, useCallback, useEffect, useMemo, useState, memo, useCallback, useEffect, useMemo, useState,
} from 'react'; } from 'react';
import { Button } from 'semantic-ui-react'; import { Button, Popup } from 'semantic-ui-react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './styles.css';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { POST_VOTING_CONTRACT } from '../../../constants/contracts/ContractNames'; import { POST_VOTING_CONTRACT } from '../../../constants/contracts/ContractNames';
import { drizzle } from '../../../redux/store'; import { drizzle } from '../../../redux/store';
import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/TransactionStatus'; import { TRANSACTION_ERROR, TRANSACTION_SUCCESS } from '../../../constants/TransactionStatus';
import './styles.css';
const CHOICE_DEFAULT = '0'; const CHOICE_DEFAULT = '0';
const CHOICE_UP = '1'; const CHOICE_UP = '1';
@ -18,7 +19,8 @@ const {
[POST_VOTING_CONTRACT]: { [POST_VOTING_CONTRACT]: {
methods: { methods: {
getVote: { cacheCall: getVoteChainData }, getVote: { cacheCall: getVoteChainData },
getTotalVoteCount: { cacheCall: getTotalVoteCountChainData }, getUpvoteCount: { cacheCall: getUpvoteCountChainData },
getDownvoteCount: { cacheCall: getDownvoteCountChainData },
upvote, downvote, unvote, upvote, downvote, unvote,
}, },
}, },
@ -33,12 +35,17 @@ const PostVoting = (props) => {
const userAccount = useSelector((state) => state.accounts[0]); const userAccount = useSelector((state) => state.accounts[0]);
// Current votes // Current votes
const getVoteResults = useSelector((state) => state.contracts[POST_VOTING_CONTRACT].getVote); const getVoteResult = useSelector((state) => state.contracts[POST_VOTING_CONTRACT].getVote);
const getTotalVoteCountResult = useSelector((state) => state.contracts[POST_VOTING_CONTRACT].getTotalVoteCount); const getUpvoteCountResult = useSelector((state) => state.contracts[POST_VOTING_CONTRACT].getUpvoteCount);
const getDownvoteCountResult = useSelector((state) => state.contracts[POST_VOTING_CONTRACT].getDownvoteCount);
const [getVoteCallHash, setGetVoteCallHash] = useState([]); const [getVoteCallHash, setGetVoteCallHash] = useState([]);
const [getTotalVoteCountCallHash, setGetTotalVoteCountCallHash] = useState([]); const [getUpvoteCountCallHash, setGetUpvoteCountCallHash] = useState([]);
const [getDownvoteCountCallHash, setGetDownvoteCountCallHash] = useState([]);
const [ownVote, setOwnVote] = useState(null); const [ownVote, setOwnVote] = useState(null);
const [totalVoteCount, setTotalVoteCount] = useState(null); const [upvoteCount, setUpvoteCount] = useState(null);
const [downvoteCount, setDownvoteCount] = useState(null);
// Voting // Voting
const transactionStack = useSelector((state) => state.transactionStack); const transactionStack = useSelector((state) => state.transactionStack);
@ -48,12 +55,12 @@ const PostVoting = (props) => {
// Current votes // Current votes
useEffect(() => { useEffect(() => {
const shouldGetTotalVoteCountDataFromChain = totalVoteCount === null; if (drizzleInitialized && !drizzleInitializationFailed && postId !== null) {
if (upvoteCount === null) setGetUpvoteCountCallHash(getUpvoteCountChainData(postId));
if (drizzleInitialized && !drizzleInitializationFailed && shouldGetTotalVoteCountDataFromChain && postId !== null) { if (downvoteCount === null) setGetDownvoteCountCallHash(getDownvoteCountChainData(postId));
setGetTotalVoteCountCallHash(getTotalVoteCountChainData(postId));
} }
}, [drizzleInitializationFailed, drizzleInitialized, postId, totalVoteCount]); }, [downvoteCount, drizzleInitializationFailed, drizzleInitialized, postId, upvoteCount, userAccount]);
useEffect(() => { useEffect(() => {
const shouldGetOwnVoteFromChain = ownVote === null; const shouldGetOwnVoteFromChain = ownVote === null;
@ -65,16 +72,22 @@ const PostVoting = (props) => {
}, [drizzleInitializationFailed, drizzleInitialized, ownVote, postId, userAccount]); }, [drizzleInitializationFailed, drizzleInitialized, ownVote, postId, userAccount]);
useEffect(() => { useEffect(() => {
if (getVoteCallHash && getVoteResults && getVoteResults[getVoteCallHash]) { if (getVoteCallHash && getVoteResult && getVoteResult[getVoteCallHash]) {
setOwnVote(getVoteResults[getVoteCallHash].value); setOwnVote(getVoteResult[getVoteCallHash].value);
}
}, [getVoteCallHash, getVoteResult]);
useEffect(() => {
if (getUpvoteCountCallHash && getUpvoteCountResult && getUpvoteCountResult[getUpvoteCountCallHash]) {
setUpvoteCount(getUpvoteCountResult[getUpvoteCountCallHash].value);
} }
}, [getVoteCallHash, getVoteResults]); }, [getUpvoteCountCallHash, getUpvoteCountResult]);
useEffect(() => { useEffect(() => {
if (getTotalVoteCountCallHash && getTotalVoteCountResult && getTotalVoteCountResult[getTotalVoteCountCallHash]) { if (getDownvoteCountCallHash && getDownvoteCountResult && getDownvoteCountResult[getDownvoteCountCallHash]) {
setTotalVoteCount(getTotalVoteCountResult[getTotalVoteCountCallHash].value); setDownvoteCount(getDownvoteCountResult[getDownvoteCountCallHash].value);
} }
}, [getTotalVoteCountCallHash, getTotalVoteCountResult]); }, [getDownvoteCountCallHash, getDownvoteCountResult]);
// Voting // Voting
useEffect(() => { useEffect(() => {
@ -96,6 +109,7 @@ const PostVoting = (props) => {
}, [ownVote, postId, userAccount, voting]); }, [ownVote, postId, userAccount, voting]);
const disableVoting = userAccount === null || !hasSignedUp || postAuthorAddress === null || userAccount === postAuthorAddress; const disableVoting = userAccount === null || !hasSignedUp || postAuthorAddress === null || userAccount === postAuthorAddress;
const totalVoteCount = (upvoteCount !== null && downvoteCount !== null) ? upvoteCount - downvoteCount : null;
return useMemo(() => ( return useMemo(() => (
<div className="post-voting"> <div className="post-voting">
<Button <Button
@ -106,11 +120,32 @@ const PostVoting = (props) => {
disabled={disableVoting} disabled={disableVoting}
onClick={() => vote(CHOICE_DOWN)} onClick={() => vote(CHOICE_DOWN)}
/> />
<Popup
trigger={(
<span className="unselectable"> <span className="unselectable">
&nbsp;&nbsp; &nbsp;&nbsp;
{totalVoteCount || 0} {totalVoteCount || 0}
&nbsp;&nbsp; &nbsp;&nbsp;
</span> </span>
)}
disabled={(upvoteCount === null && downvoteCount === null) || (upvoteCount === '0' && downvoteCount === '0')}
position="bottom center"
>
{upvoteCount !== '0' ? (
<span className="upvote-count">
+
{upvoteCount}
&nbsp;&nbsp;
</span>
) : null}
{downvoteCount !== '0' ? (
<span className="downvote-count">
-
{downvoteCount}
</span>
) : null}
</Popup>
<Button <Button
compact compact
size="mini" size="mini"
@ -120,7 +155,7 @@ const PostVoting = (props) => {
onClick={() => vote(CHOICE_UP)} onClick={() => vote(CHOICE_UP)}
/> />
</div> </div>
), [disableVoting, ownVote, totalVoteCount, vote]); ), [disableVoting, downvoteCount, ownVote, totalVoteCount, upvoteCount, vote]);
}; };
PostVoting.propTypes = { PostVoting.propTypes = {

10
packages/concordia-app/src/components/PostList/PostVoting/styles.css

@ -3,10 +3,18 @@
margin-top: 1.2rem; margin-top: 1.2rem;
} }
.post-voting > button{ .post-voting > button {
margin: 0 !important; margin: 0 !important;
} }
.post-voting > span{ .post-voting > span{
vertical-align: middle; vertical-align: middle;
} }
.upvote-count {
color: #21ba45;
}
.downvote-count {
color: #db2828;
}

6
packages/concordia-contracts/contracts/PostVoting.sol

@ -40,12 +40,6 @@ contract PostVoting {
return (getVoteCount(postID, Option.DOWN)); return (getVoteCount(postID, Option.DOWN));
} }
function getTotalVoteCount(uint postID) public view returns (int) {
int upvoteCount = int(getUpvoteCount(postID));
int downvoteCount = int(getDownvoteCount(postID));
return upvoteCount - downvoteCount;
}
// Gets voters for a specific option (Option.UP/ Option.DOWN) // Gets voters for a specific option (Option.UP/ Option.DOWN)
function getVoters(uint postID, Option option) private view returns (address[] memory) { function getVoters(uint postID, Option option) private view returns (address[] memory) {
require(forum.postExists(postID), forum.POST_DOES_NOT_EXIST()); require(forum.postExists(postID), forum.POST_DOES_NOT_EXIST());

Loading…
Cancel
Save