import React, { Fragment, Component, PureComponent } from 'react'; import { toString } from 'lodash'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import CardActions from '@material-ui/core/CardActions'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import Slide from '@material-ui/core/Slide'; import Typography from '@material-ui/core/Typography'; import Slider from '@material-ui/lab/Slider'; import PollManager from 'Embark/contracts/PollManager'; import IconButton from '@material-ui/core/IconButton'; import CloseIcon from '@material-ui/icons/Close'; import web3 from "Embark/web3" import CircularProgress from '@material-ui/core/CircularProgress'; import { withStyles } from '@material-ui/core/styles'; import { VotingContext } from '../../context'; import rlp from 'rlp'; const styles = { card: { display: 'flex', flexDirection: 'column', alignItems: 'center', }, thumb: { width: '24px', height: '24px' }, appBar: { position: 'relative', }, flex: { flex: 1, }, }; function Transition(props) { return ; }; const getIdeaFromStr = str => { const match = str.match(/\(([^)]+)\)/) if (match) return match[1].toLowerCase(); return match; } const sortingFn = { MOST_VOTES: (a, b) => b._qvResults - a._qvResults, MOST_VOTERS: (a, b) => b._voters - a._voters, NEWEST_ADDED: (a, b) => b._startBlock - a._startBlock, ENDING_SOONEST: (a, b) => a._endBlock - b._endBlock }; class Poll extends PureComponent { constructor(props){ super(props); this.state = { t: 0, value: props.votes, originalVotes: {}, // TODO: props.votes balance: 0, isSubmitting: false, open: false, votes: { } }; } updateVotes = i => numVotes => { const votes = this.state.votes; votes[i] = numVotes; this.setState({votes, t: new Date()}); } handleClickOpen = () => { this.setState({ open: true }); }; handleClose = () => { this.setState({ open: false }); }; handleClick = (event) => { event.preventDefault(); this.setState({isSubmitting: true}); const { vote, poll, unvote } = PollManager.methods; const { updatePoll, idPoll } = this.props; const { votes } = this.state; const { toWei } = web3.utils; const ballots = Object.values(votes).map(el => el * el); const balance4Voting = ballots.reduce((prev, curr) => prev + curr, 0); const toSend = balance4Voting == 0 ? unvote(idPoll) : vote(idPoll, ballots); toSend.estimateGas() .then(gasEstimated => { console.log("voting gas estimated: " + gasEstimated); return toSend.send({gas: gasEstimated + 100000}); }) .then(res => { console.log('sucess:', res); this.setState({ isSubmitting: false, originalVotes: Object.assign({}, votes)}); return updatePoll(idPoll); }) .catch(res => { console.log('fail:', res, res.messsage); this.setState({ error: res.message }) }) .finally(() => { this.setState({isSubmitting: false}); }); } render(){ const { _description, _voters, _qvResults, _results, _canVote, balance, classes, ideaSites, _numBallots, } = this.props; const { originalVotes, isSubmitting, error, votes } = this.state; const cantVote = balance == 0 || !_canVote; const disableVote = cantVote || isSubmitting; const originalVotesQty = Object.values(originalVotes).reduce((x,y) => x+y, 0); const votesQty = Object.values(votes).reduce((x,y) => x+y, 0); const buttonText = originalVotesQty != 0 && originalVotesQty != votesQty ? 'Change Vote' : 'Vote'; // Extracting description const decodedDesc = rlp.decode(_description); const title = decodedDesc[0].toString(); const ballots = decodedDesc[1]; const idea = getIdeaFromStr(title); const ideaSite = ideaSites && ideaSites.filter(site => site.includes(idea)); // Calculating votes availables const maxVotes = Math.floor(Math.sqrt(balance)); const maxValuesForBallots = {}; let votedSNT = 0; for(let i = 0; i < ballots.length; i++){ if(votes[i] == undefined){ votes[i] = 0; maxValuesForBallots[i] = 0; } else { votedSNT += votes[i]*votes[i]; } } for(let i = 0; i < ballots.length; i++){ maxValuesForBallots[i] = Math.floor(Math.sqrt(balance - votedSNT + votes[i]*votes[i])); // votes[i] // Math.floor(Math.sqrt(balance - (votedSNT*votedSNT) + (votes[i]*votes[i]))); } return ( {title} Total: {_voters} voters. {_qvResults} votes ({(_results)} SNT) SNT available for voting: {(balance - votedSNT).toFixed(2)} of {(parseFloat(balance).toFixed(2))} SNT { _numBallots > 0 && ballots.map((opt, i) => { return
{opt.toString()} {!cantVote }
}) } {cantVote && {balance == 0 && Voting disabled for proposals made when there was no SNT in the account} {balance != 0 && !_canVote && You can not vote on this poll} } {error && {error}} {ideaSite && ideaSite.length > 0 && {ideaSite}} {ideaSite && close
}
{!cantVote && {isSubmitting ? : } }
) } } const PollsList = ({ classes }) => ( {({ updatePoll, rawPolls, pollOrder, appendToPoll, ideaSites }) => {rawPolls .sort(sortingFn[pollOrder]) .map((poll, i) => )} } ) class BallotSlider extends Component { constructor(props){ super(props); this.state = { value: props.votes || 0 } } handleChange = (event, value) => { if(value > this.props.maxVotesAvailable){ value = this.props.maxVotesAvailable; } this.setState({value}); this.props.updateVotes(value); }; render(){ const {maxVotes, maxVotesAvailable, classes} = this.props; const {value} = this.state; const nextVote = value + 1; return Votes: {value} ({value * value} SNT) { nextVote <= maxVotesAvailable ? - Additional vote will cost {nextVote*nextVote - value*value} SNT : - Not enough balance available to buy additional votes } } } export default withStyles(styles)(PollsList);