Skip to content

Commit

Permalink
implements voting weight selector dropdown shown only to whales (from…
Browse files Browse the repository at this point in the history
… 91-adjustable-vote-weight)
  • Loading branch information
valzav committed Aug 10, 2016
1 parent f5884bf commit 901fcdd
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 33 deletions.
90 changes: 74 additions & 16 deletions app/components/elements/Voting.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import transaction from 'app/redux/Transaction';
// import ReactTooltip from 'react-tooltip';
import Slider from 'react-rangeslider';
import Icon from 'app/components/elements/Icon';
import Tooltip from 'app/components/elements/Tooltip';
import Follow from 'app/components/elements/Follow';
Expand All @@ -11,9 +11,17 @@ import pluralize from 'pluralize';
import {formatDecimal, parsePayoutAmount} from 'app/utils/ParsersAndFormatters';
import DropdownMenu from 'app/components/elements/DropdownMenu';
import TimeAgoWrapper from 'app/components/elements/TimeAgoWrapper';
import {Dropdown} from 'react-foundation-components/lib/global/dropdown';

const ABOUT_FLAG = 'Flagging a post can remove rewards and make this material less visible. You can still unflag or upvote later if you change your mind.'
const MAX_VOTES_DISPLAY = 20;
const VOTE_WEIGHT_DROPDOWN_THRESHOLD = 1000.0 * 1000.0 * 1000.0;

function findParent(el, class_name) {
if (el.className && el.className.indexOf && el.className.indexOf(class_name) !== -1) return el;
if (el.parentElement) return findParent(el.parentElement, class_name);
return null;
}

class Voting extends React.Component {

Expand All @@ -33,6 +41,7 @@ class Voting extends React.Component {
pending_payout: React.PropTypes.string,
total_payout: React.PropTypes.string,
cashout_time: React.PropTypes.string,
vesting_shares: React.PropTypes.number,
showList: React.PropTypes.bool,
voting: React.PropTypes.bool,
};
Expand All @@ -42,18 +51,26 @@ class Voting extends React.Component {
flag: false
};

constructor() {
super()
this.state = {}
constructor(props) {
super(props);
const saved_weight_value = (process.env.BROWSER && localStorage.getItem('vote_weight'));
this.state = {
showWeight: false,
weight: saved_weight_value ? parseInt(saved_weight_value, 10) : 10000
}
this.voteUp = e => {
e.preventDefault();
if(this.props.voting) return
this.setState({votingUp: true, votingDown: false})
const {author, permlink, username, myVote} = this.props
// already voted Up, remove the vote
const weight = myVote > 0 ? 0 : 10000
if (this.state.weight !== 10000) {
localStorage.setItem('vote_weight', this.state.weight);
}
const weight = myVote > 0 ? 0 : this.state.weight
if (this.state.showWeight) this.setState({showWeight: false})
this.props.vote(weight, {author, permlink, username, myVote})
}
};
this.voteDown = e => {
e.preventDefault();
if(this.props.voting) return
Expand All @@ -62,13 +79,37 @@ class Voting extends React.Component {
// already vote Down, remove vote
const weight = myVote < 0 ? 0 : -10000
this.props.vote(weight, {author, permlink, username, myVote})
}
};
this.handleWeightChange = weight => {
this.setState({weight: weight + 100})
};
this.toggleWeight = e => {
e.preventDefault();
this.setState({showWeight: !this.state.showWeight})
};
this.closeWeightDropdownOnOutsideClick = e => {
const inside_dropdown = findParent(e.target, 'Voting__adjust_weight');
const inside_upvote_button = findParent(e.target, 'Voting__button-up');
if (!inside_dropdown && !inside_upvote_button) this.setState({showWeight: false});
};
this.shouldComponentUpdate = shouldComponentUpdate(this, 'Voting')
}

componentDidUpdate(prevProps, prevState) {
const showWeight = this.state.showWeight;
if (showWeight !== prevState.showWeight) {
if (showWeight) document.body.addEventListener('click', this.closeWeightDropdownOnOutsideClick);
else document.body.removeEventListener('click', this.closeWeightDropdownOnOutsideClick);
}
}

componentWillUnmount() {
document.body.removeEventListener('click', this.closeWeightDropdownOnOutsideClick);
}

render() {
const {myVote, active_votes, showList, voting, flag} = this.props;
const {votingUp, votingDown} = this.state;
const {myVote, active_votes, showList, voting, flag, vesting_shares} = this.props;
const {votingUp, votingDown, showWeight, weight} = this.state;
// console.log('-- Voting.render -->', myVote, votingUp, votingDown);
if(!active_votes) return <span></span>
// if( payout[0] == '-' ) payout = "0.000 SBD";
Expand Down Expand Up @@ -133,20 +174,35 @@ class Voting extends React.Component {
if (showList) {
voters_list = <DropdownMenu selected={pluralize('votes', count, true)} className="Voting__voters_list" items={voters} el="div" />;
}

let voteUpClick = this.voteUp;
let dropdown = null;
if (vesting_shares > VOTE_WEIGHT_DROPDOWN_THRESHOLD) {
voteUpClick = this.toggleWeight;
if (showWeight) {
dropdown = <Dropdown>
<div className="Voting__adjust_weight">
<Slider min={100} max={10000} step={100} value={weight} orientation="vertical" onChange={this.handleWeightChange} />
<div className="weight-display">{weight / 100}%</div>
<a href="#" onClick={this.voteUp} className="button">Vote</a>
</div>
</Dropdown>;
}
}
return (
<span className="Voting">
<span className="Voting__inner">
<span className={classUp}>
{votingUpActive ? up : <a href="#" onClick={this.voteUp} title={myVote > 0 ? 'Remove Vote' : 'Upvote'}>{up}</a>}
{votingUpActive ? up : <a href="#" onClick={voteUpClick} title={myVote > 0 ? 'Remove Vote' : 'Upvote'}>{up}</a>}
{dropdown}
</span>
</span>
<span className="Voting__inner">
{payoutEl}
{/*<span className={classDown}>
{votingDownActive ? down : <a href="#" onClick={this.voteDown} title="Downvote">{down}</a>}
</span>*/}
</span>
{voters_list}
</span>
);
);
}
}

Expand All @@ -159,7 +215,9 @@ export default connect(
const permlink = post.get('permlink')
const last_payout = post.get('last_payout')
const active_votes = post.get('active_votes')
const username = state.user.getIn(['current', 'username'])
const current_account = state.user.get('current')
const username = current_account ? current_account.get('username') : null;
const vesting_shares = current_account ? current_account.get('vesting_shares') : 0.0;
const voting = state.global.get(`transaction_vote_active_${author}_${permlink}`)
let myVote = null;
if (username && active_votes) {
Expand All @@ -169,7 +227,7 @@ export default connect(
}
return {
...ownProps,
myVote, author, permlink, username, active_votes,
myVote, author, permlink, username, active_votes, vesting_shares,
loggedin: username != null,
voting
}
Expand Down
82 changes: 79 additions & 3 deletions app/components/elements/Voting.scss
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,83 @@
}

.Voting__inner {
border-right: 1px solid $medium-gray;
padding-right: 0.5rem;
margin-right: 1rem;
// padding-right: 0.5rem;
position: relative;
.cancel {
font-size: 80%;
padding: 0 0.4em;
margin-left: 0.5rem;
margin-right: 2px;
background-color: #f8f8f8;
border-radius: 50%;
border: 1px solid #dadada;
color: #8a8a8a;
}
}

.Voting__adjust_weight {
padding: 10px;
padding-bottom: 0;
.weight-display {
text-align: center;
color: $dark-gray;
}
}

.Voting__adjust_weight {
.rangeslider {
position: relative;
background: #e6e6e6;
.rangeslider__fill, .rangeslider__handle {
position: absolute;
}
&, .rangeslider__fill {
display: block;
box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);
border-radius: 10px;
}
.rangeslider__handle {
background: #fff;
border: 1px solid #ccc;
cursor: pointer;
display: inline-block;
position: absolute;
&:active {
background: #999;
}
}
}
.rangeslider-vertical {
margin: 0 auto;
height: 150px;
max-width: 10px;
background: none;
.rangeslider__fill {
width: 100%;
background: #4ba2f2;
box-shadow: none;
bottom: 0;
}
.rangeslider__handle {
width: 30px;
height: 30px;
border-radius: 50%;
left: -10px;
&:active {
box-shadow: none;
}
}
}

.button {
color: #fff;
&:hover {
text-decoration: none;
}
}
}

.Voting__button-up {
display: inline-block;
position: relative;
}
2 changes: 2 additions & 0 deletions app/redux/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ export default createModule({
private_keys: object,
login_owner_pubkey: string,
previous_owner_authority: object,
vesting_shares: string,
// pending_private_key: object,
},
reducer: (state, {payload}) => {
// console.log('SET_USER')
if (payload.vesting_shares) payload.vesting_shares = parseFloat(payload.vesting_shares);
return state.mergeDeep({ current: payload, show_login_modal: false, loginBroadcastOperation: undefined, loginDefault: undefined, logged_out: undefined })
}
},
Expand Down
7 changes: 5 additions & 2 deletions app/redux/UserSaga.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,13 @@ function* usernamePasswordLogin2({payload: {username, password, saveLogin,
private_keys = private_keys.remove('memo_private')

// If user is signing operation by operaion and has no saved login, don't save to RAM
if(!operationType || saveLogin)
if(!operationType || saveLogin) {
// Keep the posting key in RAM but only when not signing an operation.
// No operation or the user has checked: Keep me logged in...
yield put(user.actions.setUser({username, private_keys, login_owner_pubkey}))
yield put(user.actions.setUser({username, private_keys, login_owner_pubkey, vesting_shares: account.get('vesting_shares')}))
} else {
yield put(user.actions.setUser({username, vesting_shares: account.get('vesting_shares')}))
}

if (!autopost && saveLogin)
yield put(user.actions.saveLogin());
Expand Down
17 changes: 5 additions & 12 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"react-overlays": "0.6.4",
"react-prop-types": "^0.3.0",
"react-qr": "0.0.2",
"react-rangeslider": "^1.0.3",
"react-redux": "^4.4.0",
"react-router": "^2.4.0",
"react-router-redux": "^4.0.0",
Expand Down

0 comments on commit 901fcdd

Please sign in to comment.