<commit_before>import React from 'react';
import { connect } from 'react-redux';
import transaction from 'app/redux/Transaction';
import Slider from 'react-rangeslider';
import Icon from 'app/components/elements/Icon';
import Follow from 'app/components/elements/Follow';
import FormattedAsset from 'app/components/elements/FormattedAsset';
import shouldComponentUpdate from 'app/utils/shouldComponentUpdate';
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 FoundationDropdown from 'app/components/elements/FoundationDropdown';
import CloseButton from 'react-foundation-components/lib/global/close-button';

const ABOUT_FLAG = <div>
    <p>Flagging a post can remove rewards and make this material less visible.  The flag should be used for the following:</p>
    <ul>
        <li>Fraud or Plagiarism</li>
        <li>Hate Speech or Internet Trolling</li>
        <li>Intentional miss-categorized content or Spam</li>
    </ul>
</div>

const MAX_VOTES_DISPLAY = 20;
const VOTE_WEIGHT_DROPDOWN_THRESHOLD = 1.0 * 1000.0 * 1000.0;

class Voting extends React.Component {

    static propTypes = {
        // HTML properties
        post: React.PropTypes.string.isRequired,
        flag: React.PropTypes.bool,

        // Redux connect properties
        vote: React.PropTypes.func.isRequired,
        author: React.PropTypes.string, // post was deleted
        permlink: React.PropTypes.string,
        username: React.PropTypes.string,
        is_comment: React.PropTypes.bool,
        myVote: React.PropTypes.number,
        active_votes: React.PropTypes.object,
        loggedin: React.PropTypes.bool,
        pending_payout: React.PropTypes.number,
        promoted: React.PropTypes.number,
        total_author_payout: React.PropTypes.number,
        total_curator_payout: React.PropTypes.number,
        cashout_time: React.PropTypes.string,
        vesting_shares: React.PropTypes.number,
        showList: React.PropTypes.bool,
        voting: React.PropTypes.bool,
    };

    static defaultProps = {
        showList: true,
        flag: false
    };

    constructor(props) {
        super(props);
        this.state = {
            showWeight: false,
            weight: 10000
        }

        this.voteUp = e => {
            e.preventDefault();
            this.voteUpOrDown(true)
        }
        this.voteDown = e => {
            e.preventDefault();
            this.voteUpOrDown(false)
        }
        this.voteUpOrDown = (up) => {
            if(this.props.voting) return
            this.setState({votingUp: up, votingDown: !up})
            const {author, permlink, username, myVote, is_comment} = this.props
            if (this.props.vesting_shares > VOTE_WEIGHT_DROPDOWN_THRESHOLD) {
                localStorage.setItem('voteWeight' + (up ? '' : 'Down') + '-'+username+(is_comment ? '-comment' : ''),
                    this.state.weight);
            }
            // already voted Up, remove the vote
            const weight = up ? (myVote > 0 ? 0 : this.state.weight) : (myVote < 0 ? 0 : -1 * this.state.weight)
            if (this.state.showWeight) this.setState({showWeight: false})
            this.props.vote(weight, {author, permlink, username, myVote})
        };

        this.handleWeightChange = weight => {
            this.setState({weight})
        };

        this.toggleWeightUp = e => {
            e.preventDefault();
            this.toggleWeightUpOrDown(true)
        }
        this.toggleWeightDown = e => {
            e.preventDefault();
            this.toggleWeightUpOrDown(false)
        }
        this.toggleWeightUpOrDown = up => {
            const {username, is_comment} = this.props
            // Upon opening dialog, read last used weight (this works accross tabs)
            if(! this.state.showWeight) {
                localStorage.removeItem('vote_weight'); // deprecated. remove this line after 8/31
                const saved_weight = localStorage.getItem('voteWeight' + (up ? '' : 'Down') + '-'+username+(is_comment ? '-comment' : ''));
                this.setState({weight: saved_weight ? parseInt(saved_weight, 10) : 10000});
            }
            this.setState({showWeight: !this.state.showWeight})
        };
        this.shouldComponentUpdate = shouldComponentUpdate(this, 'Voting')
    }

    render() {
        const {myVote, active_votes, showList, voting, flag, vesting_shares} = this.props;
        const {username} = this.props;
        const {votingUp, votingDown, showWeight, weight} = this.state;
        // console.log('-- Voting.render -->', myVote, votingUp, votingDown);
        if(!active_votes) return <span></span>
        if(flag && !username) return null
        // if( payout[0] == '-' ) payout = "0.000 SBD";
        const votingUpActive = voting && votingUp
        const votingDownActive = voting && votingDown

        const down = <Icon name={votingDownActive ? 'empty' : (myVote < 0 ? 'flag2' : 'flag1')} />;
        const classDown = 'Voting__button Voting__button-down' + (myVote < 0 ? ' Voting__button--downvoted' : '') + (votingDownActive ? ' votingDown' : '');

        if (flag) {
            // myVote === current vote
            const dropdown = <FoundationDropdown show={showWeight} className="Voting__adjust_weight_down">
                {(myVote == null || myVote === 0) && vesting_shares > VOTE_WEIGHT_DROPDOWN_THRESHOLD &&
                    <div>
                        <div className="weight-display">- {weight / 100}%</div>
                        <Slider min={100} max={10000} step={100} value={weight} onChange={this.handleWeightChange} />
                    </div>
                }
                <CloseButton onClick={() => this.setState({showWeight: false})} />
                <div className="clear Voting__about-flag">
                    <p>{ABOUT_FLAG}</p>
                    <a href="#" onClick={this.voteDown} className="confirm_weight button outline" title="Flag">Flag</a>
                </div>
            </FoundationDropdown>

            // ? Remove negative votes unless full power -1000 (we had downvoting spam)
            const down_votes = active_votes.filter( v => v.get('percent') < 0 /*=== -1000*/).size
            const flagClickAction = myVote === null || myVote === 0 ? this.toggleWeightDown : this.voteDown
            return <span className="Voting">
                <span className={classDown}>
                    {down_votes > 0 && <span className="Voting__button-downvotes">{down_votes}</span>}
                    {votingDownActive ? down : <a href="#" onClick={flagClickAction} title="Flag">{down}</a>}
                    {dropdown}
                </span>
            </span>
        }

        const {pending_payout, total_author_payout, total_curator_payout, cashout_time, promoted} = this.props;
        let payout = pending_payout + total_author_payout + total_curator_payout;
        if (payout < 0.0) payout = 0.0;

        const up = <Icon name={votingUpActive ? 'empty' : 'chevron-up-circle'} />;
        const classUp = 'Voting__button Voting__button-up' + (myVote > 0 ? ' Voting__button--upvoted' : '') + (votingUpActive ? ' votingUp' : '');

        const payoutItems = [
            {value: 'Potential Payout $' + formatDecimal(pending_payout).join('')},
            {value: 'Boost Payments $' + formatDecimal(promoted).join('')}
        ];
        if (cashout_time && cashout_time.indexOf('1969') !== 0 && cashout_time.indexOf('1970') !== 0) {
            payoutItems.push({value: <TimeAgoWrapper date={cashout_time} />});
        }
        if(total_author_payout > 0) {
            payoutItems.push({value: 'Past Payouts $' + formatDecimal(total_author_payout + total_curator_payout).join('')});
            payoutItems.push({value: ' - Author: $' + formatDecimal(total_author_payout).join('')});
            payoutItems.push({value: ' - Curators: $' + formatDecimal(total_curator_payout).join('')});<commit_msg>promoted formatDecimal error<commit_after>import React from 'react';
import { connect } from 'react-redux';
import transaction from 'app/redux/Transaction';
import Slider from 'react-rangeslider';
import Icon from 'app/components/elements/Icon';
import Follow from 'app/components/elements/Follow';
import FormattedAsset from 'app/components/elements/FormattedAsset';
import shouldComponentUpdate from 'app/utils/shouldComponentUpdate';
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 FoundationDropdown from 'app/components/elements/FoundationDropdown';
import CloseButton from 'react-foundation-components/lib/global/close-button';

const ABOUT_FLAG = <div>
    <p>Flagging a post can remove rewards and make this material less visible.  The flag should be used for the following:</p>
    <ul>
        <li>Fraud or Plagiarism</li>
        <li>Hate Speech or Internet Trolling</li>
        <li>Intentional miss-categorized content or Spam</li>
    </ul>
</div>

const MAX_VOTES_DISPLAY = 20;
const VOTE_WEIGHT_DROPDOWN_THRESHOLD = 1.0 * 1000.0 * 1000.0;

class Voting extends React.Component {

    static propTypes = {
        // HTML properties
        post: React.PropTypes.string.isRequired,
        flag: React.PropTypes.bool,

        // Redux connect properties
        vote: React.PropTypes.func.isRequired,
        author: React.PropTypes.string, // post was deleted
        permlink: React.PropTypes.string,
        username: React.PropTypes.string,
        is_comment: React.PropTypes.bool,
        myVote: React.PropTypes.number,
        active_votes: React.PropTypes.object,
        loggedin: React.PropTypes.bool,
        pending_payout: React.PropTypes.number,
        promoted: React.PropTypes.number,
        total_author_payout: React.PropTypes.number,
        total_curator_payout: React.PropTypes.number,
        cashout_time: React.PropTypes.string,
        vesting_shares: React.PropTypes.number,
        showList: React.PropTypes.bool,
        voting: React.PropTypes.bool,
    };

    static defaultProps = {
        showList: true,
        flag: false
    };

    constructor(props) {
        super(props);
        this.state = {
            showWeight: false,
            weight: 10000
        }

        this.voteUp = e => {
            e.preventDefault();
            this.voteUpOrDown(true)
        }
        this.voteDown = e => {
            e.preventDefault();
            this.voteUpOrDown(false)
        }
        this.voteUpOrDown = (up) => {
            if(this.props.voting) return
            this.setState({votingUp: up, votingDown: !up})
            const {author, permlink, username, myVote, is_comment} = this.props
            if (this.props.vesting_shares > VOTE_WEIGHT_DROPDOWN_THRESHOLD) {
                localStorage.setItem('voteWeight' + (up ? '' : 'Down') + '-'+username+(is_comment ? '-comment' : ''),
                    this.state.weight);
            }
            // already voted Up, remove the vote
            const weight = up ? (myVote > 0 ? 0 : this.state.weight) : (myVote < 0 ? 0 : -1 * this.state.weight)
            if (this.state.showWeight) this.setState({showWeight: false})
            this.props.vote(weight, {author, permlink, username, myVote})
        };

        this.handleWeightChange = weight => {
            this.setState({weight})
        };

        this.toggleWeightUp = e => {
            e.preventDefault();
            this.toggleWeightUpOrDown(true)
        }
        this.toggleWeightDown = e => {
            e.preventDefault();
            this.toggleWeightUpOrDown(false)
        }
        this.toggleWeightUpOrDown = up => {
            const {username, is_comment} = this.props
            // Upon opening dialog, read last used weight (this works accross tabs)
            if(! this.state.showWeight) {
                localStorage.removeItem('vote_weight'); // deprecated. remove this line after 8/31
                const saved_weight = localStorage.getItem('voteWeight' + (up ? '' : 'Down') + '-'+username+(is_comment ? '-comment' : ''));
                this.setState({weight: saved_weight ? parseInt(saved_weight, 10) : 10000});
            }
            this.setState({showWeight: !this.state.showWeight})
        };
        this.shouldComponentUpdate = shouldComponentUpdate(this, 'Voting')
    }

    render() {
        const {myVote, active_votes, showList, voting, flag, vesting_shares} = this.props;
        const {username} = this.props;
        const {votingUp, votingDown, showWeight, weight} = this.state;
        // console.log('-- Voting.render -->', myVote, votingUp, votingDown);
        if(!active_votes) return <span></span>
        if(flag && !username) return null
        // if( payout[0] == '-' ) payout = "0.000 SBD";
        const votingUpActive = voting && votingUp
        const votingDownActive = voting && votingDown

        const down = <Icon name={votingDownActive ? 'empty' : (myVote < 0 ? 'flag2' : 'flag1')} />;
        const classDown = 'Voting__button Voting__button-down' + (myVote < 0 ? ' Voting__button--downvoted' : '') + (votingDownActive ? ' votingDown' : '');

        if (flag) {
            // myVote === current vote
            const dropdown = <FoundationDropdown show={showWeight} className="Voting__adjust_weight_down">
                {(myVote == null || myVote === 0) && vesting_shares > VOTE_WEIGHT_DROPDOWN_THRESHOLD &&
                    <div>
                        <div className="weight-display">- {weight / 100}%</div>
                        <Slider min={100} max={10000} step={100} value={weight} onChange={this.handleWeightChange} />
                    </div>
                }
                <CloseButton onClick={() => this.setState({showWeight: false})} />
                <div className="clear Voting__about-flag">
                    <p>{ABOUT_FLAG}</p>
                    <a href="#" onClick={this.voteDown} className="confirm_weight button outline" title="Flag">Flag</a>
                </div>
            </FoundationDropdown>

            // ? Remove negative votes unless full power -1000 (we had downvoting spam)
            const down_votes = active_votes.filter( v => v.get('percent') < 0 /*=== -1000*/).size
            const flagClickAction = myVote === null || myVote === 0 ? this.toggleWeightDown : this.voteDown
            return <span className="Voting">
                <span className={classDown}>
                    {down_votes > 0 && <span className="Voting__button-downvotes">{down_votes}</span>}
                    {votingDownActive ? down : <a href="#" onClick={flagClickAction} title="Flag">{down}</a>}
                    {dropdown}
                </span>
            </span>
        }

        const {pending_payout, total_author_payout, total_curator_payout, cashout_time, promoted} = this.props;
        let payout = pending_payout + total_author_payout + total_curator_payout;
        if (payout < 0.0) payout = 0.0;

        const up = <Icon name={votingUpActive ? 'empty' : 'chevron-up-circle'} />;
        const classUp = 'Voting__button Voting__button-up' + (myVote > 0 ? ' Voting__button--upvoted' : '') + (votingUpActive ? ' votingUp' : '');

        const payoutItems = [
            {value: 'Potential Payout $' + formatDecimal(pending_payout).join('')},
            {value: 'Boost Payments $' + formatDecimal(promoted || 0).join('')}
        ];
        if (cashout_time && cashout_time.indexOf('1969') !== 0 && cashout_time.indexOf('1970') !== 0) {
            payoutItems.push({value: <TimeAgoWrapper date={cashout_time} />});
        }
        if(total_author_payout > 0) {
            payoutItems.push({value: 'Past Payouts $' + formatDecimal(total_author_payout + total_curator_payout).join('')});
            payoutItems.push({value: ' - Author: $' + formatDecimal(total_author_payout).join('')});
            payoutItems.push({value: ' - Curators: $' + formatDecimal(total_curator_payout).join('')});
{'fraction_non_alphanumeric': 0.12852741836105977, 'fraction_numerical': 0.010536044362292052, 'mean_word_length': 2.436586915096337, 'pattern_counts': {'":': 0, '<': 91, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '107827', 'n_tokens_mistral': 4888, 'n_tokens_neox': 4692, 'n_words': 990}