diff --git a/app/components/cards/Comment.jsx b/app/components/cards/Comment.jsx index 171c140c0..b9f7f146e 100644 --- a/app/components/cards/Comment.jsx +++ b/app/components/cards/Comment.jsx @@ -35,8 +35,6 @@ class CommentImpl extends PureComponent { rootComment: PropTypes.string, anchorLink: PropTypes.string.isRequired, deletePost: PropTypes.func.isRequired, - ignoreList: PropTypes.any, - negativeCommenters: PropTypes.any }; static defaultProps = { @@ -58,7 +56,7 @@ class CommentImpl extends PureComponent { const content = this.props.cont.get(this.props.content); if (content) { - this._checkHide(content, this.props.negativeCommenters); + this._checkHide(content) } } @@ -79,7 +77,7 @@ class CommentImpl extends PureComponent { const content = np.cont.get(np.content); if (content) { - this._checkHide(content, np.negativeCommenters); + this._checkHide(content) } } @@ -88,16 +86,14 @@ class CommentImpl extends PureComponent { * - `hideBody` is true when comment rshares OR author rep is negative. * it hides the comment body (but not the header) until the "reveal comment" link is clicked. */ - _checkHide(content, negativeCommenters) { + _checkHide(content) { let hide = hideSubtree(this.props.cont, this.props.content) - if (content) { - const comment = content.toJS() - if (negativeCommenters.has(comment.author)) { - hide = true - } - } + // console.log('CON', content.toJS()) + if (content.get('bad')) { + hide = true + } if (hide) { const { onHide } = this.props; @@ -134,19 +130,14 @@ class CommentImpl extends PureComponent { depth, anchorLink, showNegativeComments, - ignoreList, - negativeCommenters, sortOrder, username, - blocked } = this.props; const post = comment.author + '/' + comment.permlink; const { showReply, showEdit, hide, hideBody } = this.state; - const ignore = ignoreList && ignoreList.has(comment.author); - - if (!showNegativeComments && (hide || ignore)) { + if (!showNegativeComments && hide) { return null; } @@ -210,8 +201,6 @@ class CommentImpl extends PureComponent { rootComment={this._getRootComment(comment)} showNegativeComments={showNegativeComments} onHide={this.props.onHide} - ignoreList={ignoreList} - negativeCommenters={negativeCommenters} /> )); } @@ -231,10 +220,6 @@ class CommentImpl extends PureComponent { ); } - if (negativeCommenters && negativeCommenters.has(username)) { - renderedEditor =
{tt('g.blocked_from_blog')}
- } - return (
@@ -427,20 +412,13 @@ class CommentImpl extends PureComponent { const Comment = connect( (state, props) => { - const { cont, content, negativeCommenters } = props; + const { cont, content, } = props; const username = state.user.getIn(['current', 'username']); const dis = cont.get(content); - let blocked = false - - if (dis) { - const comment = dis.toJS() - blocked = negativeCommenters.has(comment.author) - } return { ...props, - blocked, // Using a hash here is not standard but intentional; see issue #124 for details anchorLink: '#@' + content, username, diff --git a/app/components/cards/PostFull.jsx b/app/components/cards/PostFull.jsx index 53971149a..0dfff70f7 100644 --- a/app/components/cards/PostFull.jsx +++ b/app/components/cards/PostFull.jsx @@ -193,7 +193,7 @@ class PostFull extends React.Component { const p = extractContent(immutableAccessor, postContent); const content = postContent.toJS(); - const { author, permlink, parent_author, parent_permlink } = content; + const { author, permlink, parent_author, parent_permlink, root_author } = content; const jsonMetadata = showReply ? null : p.json_metadata; let link = `/@${content.author}/${content.permlink}`; @@ -212,6 +212,7 @@ class PostFull extends React.Component { permlink, parent_author, parent_permlink, + root_author, category, title, body, @@ -326,12 +327,6 @@ class PostFull extends React.Component { } _renderReplyEditor(replyParams, jsonMetadata, isEdit) { - const { ignoring, username } = this.props; - - if (ignoring && ignoring.has(username)) { - return
{tt('g.blocked_from_blog')}
- } - return ( { const username = state.user.getIn(['current', 'username']) - const curr_blog_author = props.cont.get(props.post).get('author') - const key = ['follow', 'getFollowingAsync', curr_blog_author, 'ignore_result'] - const ignoring = state.global.getIn(key) let prevPosts = state.global.get('prev_posts') prevPosts = prevPosts ? prevPosts.toJS() : [] return { ...props, username, - ignoring, prevPosts } }, diff --git a/app/components/cards/PostsList.jsx b/app/components/cards/PostsList.jsx index fa8da3278..8907b5474 100644 --- a/app/components/cards/PostsList.jsx +++ b/app/components/cards/PostsList.jsx @@ -28,7 +28,6 @@ class PostsList extends PureComponent { showSpam: PropTypes.bool, fetchState: PropTypes.func.isRequired, pathname: PropTypes.string, - ignoreResult: PropTypes.any, }; static defaultProps = { @@ -200,7 +199,6 @@ class PostsList extends PureComponent { loading, category, content, - ignoreResult, account, pathname, } = this.props; @@ -220,11 +218,10 @@ class PostsList extends PureComponent { console.error('PostsList --> Missing cont key', item); return; } - const ignore = ignoreResult && ignoreResult.has(cont.get('author')); const hide = cont.getIn(['stats', 'hide']); - if (!(ignore || hide) || showSpam) { - postsInfo.push({ item, ignore }); + if (!hide || showSpam) { + postsInfo.push({ item, ignore: false }); } }); @@ -313,12 +310,6 @@ export default connect( username, content: state.global.get('content'), next_from: state.global.get('next_from'), - ignoreResult: state.global.getIn([ - 'follow', - 'getFollowingAsync', - username, - 'ignore_result', - ]), pathname: state.app.get('location').pathname, }; }, diff --git a/app/components/cards/TransferHistoryRow.jsx b/app/components/cards/TransferHistoryRow.jsx index cacb36d46..dcb4d7a23 100644 --- a/app/components/cards/TransferHistoryRow.jsx +++ b/app/components/cards/TransferHistoryRow.jsx @@ -32,25 +32,7 @@ class TransferHistoryRow extends React.Component { let target_hint = ""; let data_memo = data.memo; - if (type === 'claim') { - if( data.to === context ) { - if( data.from === context ) { - description_start += tt('g.receive') + data.amount + tt('transferhistoryrow_jsx.with_claim'); - } - else { - description_start += tt('g.receive') + data.amount + tt('transferhistoryrow_jsx.with_claim') + tt('transferhistoryrow_jsx.from'); - link = data.from - } - } else { - description_start += tt('transferhistoryrow_jsx.transfer') + data.amount + tt('transferhistoryrow_jsx.with_claim') + tt('g.to'); - link = data.to - } - if (data.to_vesting) { - description_end += tt('transferhistoryrow_jsx.to_golos_power'); - } - } - - else if(/^transfer$|^transfer_to_savings$|^transfer_from_savings$/.test(type)) { + if (/^transfer$|^transfer_to_savings$|^transfer_from_savings$/.test(type)) { const fromWhere = type === 'transfer_to_savings' ? tt('transferhistoryrow_jsx.to_savings') : type === 'transfer_from_savings' ? tt('transferhistoryrow_jsx.from_savings') : @@ -247,6 +229,40 @@ class TransferHistoryRow extends React.Component { link = data.worker_request_author + "/" + data.worker_request_permlink; } + else if (type === 'account_freeze' && !data.frozen) { + description_start += tt('transferhistoryrow_jsx.claimed') + data.unfreeze_fee + tt('transferhistoryrow_jsx.account_unfreeze'); + } + + else if (type === 'unwanted_cost') { + if (data.blocker === this.props.context) { + description_start += tt('transferhistoryrow_jsx.received') + data.amount + tt('transferhistoryrow_jsx.from') + link = data.blocking + description_end += tt('transferhistoryrow_jsx.for_unwanted') + } else { + description_start += tt('transferhistoryrow_jsx.transfer') + data.amount + tt('g.to') + link = data.blocker + description_end += tt('transferhistoryrow_jsx.for_unwanted') + } + } + + else if (type === 'unlimit_cost') { + description_start += tt('transferhistoryrow_jsx.claimed') + data.amount + tt('transferhistoryrow_jsx.from_tip') + tt('transferhistoryrow_jsx.for') + if (data.target_type === 'comment') { + link = data.id1 + '/' + data.id2 + linkTitle = tt('transferhistoryrow_jsx.comment') + } else if (data.target_type === 'vote') { + link = data.id1 + '/' + (data.id2 || '') + linkTitle = tt('transferhistoryrow_jsx.vote') + } else { + description_start += tt('transferhistoryrow_jsx.action') + } + if (data.limit_type === 'negrep') { + description_end += tt('transferhistoryrow_jsx.with_negrep') + } else { + description_end += tt('transferhistoryrow_jsx.with_unlimit') + } + } + else { code_key = JSON.stringify({type, ...data}, null, 2); } diff --git a/app/components/elements/DoNotBother.jsx b/app/components/elements/DoNotBother.jsx new file mode 100644 index 000000000..05965bd8e --- /dev/null +++ b/app/components/elements/DoNotBother.jsx @@ -0,0 +1,79 @@ +import React from 'react' +import { connect } from 'react-redux' +import tt from 'counterpart' + +import transaction from 'app/redux/Transaction' +import LoadingIndicator from 'app/components/elements/LoadingIndicator' + +class DoNotBother extends React.Component { + state = { + checked: false, + submitting: false + } + + componentDidMount() { + const { account } = this.props + if (account) + this.setState({ + checked: account.do_not_bother + }) + } + + onChange = (e) => { + this.setState({ submitting: true }) + + const checked = e.target.checked + const { account, updateBlock } = this.props + updateBlock(account.name, checked, () => { + this.setState({ submitting: false, checked }) + }, (err) => { + console.error(err) + alert(err.message || err) + this.setState({ submitting: false }) + }) + } + + render() { + const { account } = this.props + const { checked, submitting } = this.state + return
+
+

+ {submitting ? + : +
+

{tt('do_not_bother.title')}

+ +
} +
+
+ } +} + +export default DoNotBother + +module.exports = connect( + (state, ownProps) => ({ + }), + dispatch => ({ + updateBlock: (blocker, do_not_bother, done, errorCallback) => { + dispatch(transaction.actions.broadcastOperation({ + type: 'account_setup', + operation: { + account: blocker, + settings: [ + [1, { + do_not_bother + }] + ], + extensions: [] + }, + successCallback: done, + errorCallback, + })) + }, + }) +)(DoNotBother); diff --git a/app/components/elements/Follow.jsx b/app/components/elements/Follow.jsx index 0c337cd51..d920038fa 100644 --- a/app/components/elements/Follow.jsx +++ b/app/components/elements/Follow.jsx @@ -40,7 +40,7 @@ export default class Follow extends React.Component { } initEvents(props) { - const {updateFollow, follower, following} = props; + const {updateFollow, updateBlock, follower, following} = props; /** @param {string} [msg] Confirmation message. */ const upd = (type, msg) => { @@ -51,11 +51,32 @@ export default class Follow extends React.Component { this.setState({busy: true}); const done = () => {this.setState({busy: false})}; - updateFollow(follower, following, type, done) + + const { isFollowing, isBlocking } = this.props + + if (type === 'blog') { + const follow = () => { + updateFollow(follower, following, type, done) + } + if (isBlocking) { + updateBlock(follower, following, false, follow) + } else { + follow() + } + } else if (type === 'block') { + updateBlock(follower, following, true, done) + } else { + if (isFollowing) { + updateFollow(follower, following, null, done) + } + if (isBlocking) { + updateBlock(follower, following, false, done) + } + } }; this.follow = upd.bind(null, 'blog', '' /*tt('g.confirm_follow')*/) this.unfollow = upd.bind(null, null, tt('g.confirm_unfollow')) - this.ignore = upd.bind(null, 'ignore', tt('g.confirm_ignore')) + this.ignore = upd.bind(null, 'block', tt('g.confirm_ignore')) this.unignore = upd.bind(null, null, '' /*tt('g.confirm_unignore')*/) } @@ -123,9 +144,9 @@ export default class Follow extends React.Component { ; // Can't follow or ignore self - if(follower === following) return + if(follower === following && !this.props.showMuteInNew) return - const {followingWhat} = this.props; // redux + const {isFollowing, isBlocking} = this.props; // redux const {showFollow, showMute, showMuteInNew, donateUrl, children} = this.props; // html const {busy} = this.state; @@ -134,16 +155,16 @@ export default class Follow extends React.Component { const cnDonate = 'button slim alert ' + cnBusy; const cnMessage = 'button slim ' + cnBusy; return - {showFollow && followingWhat !== 'blog' && + {showFollow && !isFollowing && } - {showFollow && followingWhat === 'blog' && + {showFollow && isFollowing && } - {showMute && followingWhat !== 'ignore' && + {showMute && !isBlocking && } - {showMute && followingWhat === 'ignore' && + {showMute && isBlocking && } {showMuteInNew && @@ -174,21 +195,40 @@ module.exports = connect( const {following} = ownProps; const f = state.global.getIn(['follow', 'getFollowingAsync', follower], emptyMap); - const loading = f.get('blog_loading', false) || f.get('ignore_loading', false); - const followingWhat = - f.get('blog_result', emptySet).contains(following) ? 'blog' : - f.get('ignore_result', emptySet).contains(following) ? 'ignore' : - null; + const loading = f.get('blog_loading', false) + const isFollowing = + f.get('blog_result', emptySet).contains(following) + + const b = state.global.getIn(['block', 'blocking', follower], emptyMap); + const isBlocking = b.get('result', emptySet).contains(following) return { follower, following, - followingWhat, + isFollowing, + isBlocking, loading, metaData, }; }, dispatch => ({ + updateBlock: (blocker, blocking, block, done) => { + dispatch(transaction.actions.broadcastOperation({ + type: 'account_setup', + operation: { + account: blocker, + settings: [ + [0, { + account: blocking, + block + }] + ], + extensions: [] + }, + successCallback: done, + errorCallback: done, + })) + }, updateFollow: (follower, following, action, done) => { const what = action ? [action] : []; const json = ['follow', {follower, following, what}]; diff --git a/app/components/elements/Voting.jsx b/app/components/elements/Voting.jsx index 567e213dc..aae775c59 100644 --- a/app/components/elements/Voting.jsx +++ b/app/components/elements/Voting.jsx @@ -9,6 +9,7 @@ import CloseButton from 'react-foundation-components/lib/global/close-button' import tt from 'counterpart' import { Asset } from 'golos-lib-js/lib/utils' +import { checkAllowed, AllowTypes } from 'app/utils/Allowance' import Icon from 'app/components/elements/Icon'; import shouldComponentUpdate from 'app/utils/shouldComponentUpdate'; import DropdownMenu from 'app/components/elements/DropdownMenu'; @@ -35,8 +36,6 @@ class Voting extends React.Component { active_votes: PropTypes.object, loggedin: PropTypes.bool, post_obj: PropTypes.object, - net_vesting_shares: PropTypes.number, - vesting_shares: PropTypes.number, voting: PropTypes.bool, }; @@ -54,6 +53,12 @@ class Voting extends React.Component { voteListPage: 0, }; + this.getAllowType = () => { + const { post_obj } = this.props + const cashoutTime = post_obj.get('cashout_time') + return (!cashoutTime || cashoutTime.startsWith('19')) ? + AllowTypes.voteArchived : AllowTypes.vote + } this.voteUp = e => { e.preventDefault() const { myVote } = this.state @@ -61,8 +66,9 @@ class Voting extends React.Component { this.props.showLogin() return } - const { author, permlink } = this.props - this.props.showDonate(author, permlink, this.props.is_comment, myVote) + const { author, permlink, } = this.props + this.props.showDonate(author, permlink, this.props.is_comment, myVote, + this.getAllowType()) } this.voteDown = e => { e.preventDefault(); @@ -73,7 +79,7 @@ class Voting extends React.Component { if(this.props.voting) return; this.setState({votingUp: up, votingDown: !up}); const {myVote} = this.state; - const {author, permlink, username, is_comment} = this.props; + const {author, permlink, username, is_comment } = this.props; if (myVote <= 0 && !up) { localStorage.removeItem('vote_weight'); // deprecated localStorage.setItem('voteWeightDown-'+username+(is_comment ? '-comment' : ''), @@ -81,7 +87,11 @@ class Voting extends React.Component { } // already voted Up, remove the vote const weight = up ? (myVote > 0 ? 0 : this.state.weight) : (myVote < 0 ? 0 : -1 * this.state.weight); - this.props.vote(weight, {author, permlink, username, myVote}) + this.props.vote(weight, { + author, permlink, + username, myVote, + allowType: this.getAllowType() + }) }; this.handleWeightChange = weight => { @@ -133,7 +143,7 @@ class Voting extends React.Component { } render() { - const {active_votes, showList, voting, flag, net_vesting_shares, is_comment, post_obj} = this.props; + const {active_votes, showList, voting, flag, is_comment, post_obj} = this.props; const {username} = this.props; const {votingUp, votingDown, showWeightDown, weight, myVote, voteListPage} = this.state; if(flag && !username) return null @@ -280,16 +290,6 @@ export default connect( const username = current_account ? current_account.get('username') : null; - const vesting_shares = current_account - ? current_account.get('vesting_shares') - : 0.0; - const delegated_vesting_shares = current_account - ? current_account.get('delegated_vesting_shares') - : 0.0; - const received_vesting_shares = current_account - ? current_account.get('received_vesting_shares') - : 0.0; - const net_vesting_shares = vesting_shares - delegated_vesting_shares + received_vesting_shares; const voting = state.global.get(`transaction_vote_active_${author}_${permlink}`) return { @@ -300,8 +300,6 @@ export default connect( permlink, username, active_votes, - net_vesting_shares, - vesting_shares, is_comment, post_obj: post, loggedin: username != null, @@ -313,8 +311,21 @@ export default connect( showLogin: () => { dispatch(user.actions.showLogin()) }, - vote: (weight, {author, permlink, username, myVote}) => { + vote: async (weight, {author, permlink, username, myVote, allowType}) => { + const blocking = await checkAllowed(username, [], + null, allowType) + if (blocking.error) { + dispatch({ + type: 'ADD_NOTIFICATION', + payload: { + message: blocking.error, + dismissAfter: 5000, + }, + }) + return + } const confirm = () => { + if (blocking.confirm) return blocking.confirm if(myVote == null) return const t = tt('voting_jsx.we_will_reset_curation_rewards_for_this_post') if(weight === 0) return tt('voting_jsx.removing_your_vote') + t @@ -331,7 +342,7 @@ export default connect( successCallback: () => dispatch(user.actions.getAccount()) })) }, - showDonate(author, permlink, is_comment, myVote) { + showDonate(author, permlink, is_comment, myVote, voteAllowType) { const sym = LIQUID_TICKER dispatch(user.actions.setDonateDefaults({ permlink, @@ -339,7 +350,8 @@ export default connect( to: author, sym, precision: 3, - myVote: myVote ? Math.round(myVote / 100) : myVote, + myVote: myVote ? Math.max(Math.round(myVote / 100), 0) : myVote, + voteAllowType })) dispatch(user.actions.showDonate()) }, diff --git a/app/components/modules/CommentForm/CommentForm.jsx b/app/components/modules/CommentForm/CommentForm.jsx index 1ee915197..3e493fc45 100644 --- a/app/components/modules/CommentForm/CommentForm.jsx +++ b/app/components/modules/CommentForm/CommentForm.jsx @@ -14,6 +14,7 @@ import MarkdownViewer, { getRemarkable, } from 'app/components/cards/MarkdownViewer'; import { checkPostHtml } from 'app/utils/validator'; +import { checkAllowed, AllowTypes } from 'app/utils/Allowance' import './CommentForm.scss'; const DRAFT_KEY = 'golos.comment.draft'; @@ -270,10 +271,12 @@ class CommentForm extends React.Component { if (editMode) { data.permlink = params.permlink; + data.root_author = params.root_author data.parent_author = params.parent_author; data.parent_permlink = params.parent_permlink; data.__config.originalBody = params.body; } else { + data.root_author = params.root_author data.parent_author = params.author; data.parent_permlink = params.permlink; data.__config.comment_options = {}; @@ -283,6 +286,7 @@ class CommentForm extends React.Component { this.props.onPost( data, + editMode, () => { try { localStorage.removeItem(DRAFT_KEY); @@ -292,7 +296,7 @@ class CommentForm extends React.Component { this.setState({ disabled: false }); }, err => { - this.refs.footer.showPostError(err.toString().trim()); + if (err) this.refs.footer.showPostError(err.toString().trim()); this.setState({ disabled: false }); } ); @@ -357,11 +361,20 @@ export default connect( author: state.user.getIn(['current', 'username']), }), dispatch => ({ - onPost(payload, onSuccess, onError) { + async onPost(payload, editMode, onSuccess, onError) { + let blocking = await checkAllowed(payload.author, + [payload.parent_author, payload.root_author], + null, editMode ? AllowTypes.commentEdit : AllowTypes.comment) + if (blocking.error) { + onError(blocking.error) + return + } + const confirm = blocking.confirm dispatch( transaction.actions.broadcastOperation({ type: 'comment', operation: payload, + confirm, hideErrors: true, errorCallback: onError, successCallback: onSuccess, diff --git a/app/components/modules/CurationRewards.jsx b/app/components/modules/CurationRewards.jsx index 49532c2f5..ded2ed158 100644 --- a/app/components/modules/CurationRewards.jsx +++ b/app/components/modules/CurationRewards.jsx @@ -38,7 +38,9 @@ class CurationRewards extends React.Component { effectiveVestingShares(account, gprops) { const vesting_steem = this.vestsToSteem(account.vesting_shares, gprops); const received_vesting_shares = this.vestsToSteem(account.received_vesting_shares, gprops); + + this.vestsToSteem(account.emission_received_vesting_shares, gprops) const delegated_vesting_shares = this.vestsToSteem(account.delegated_vesting_shares, gprops); + + this.vestsToSteem(account.emission_delegated_vesting_shares, gprops); return Asset(vesting_steem + received_vesting_shares - delegated_vesting_shares, 3, 'GOLOS'); diff --git a/app/components/modules/DelegateVestingShares.jsx b/app/components/modules/DelegateVestingShares.jsx index f0f2b42da..666f0bf48 100644 --- a/app/components/modules/DelegateVestingShares.jsx +++ b/app/components/modules/DelegateVestingShares.jsx @@ -43,7 +43,7 @@ class DelegateVestingShares extends React.Component { } initForm(props) { - const fields = [ 'to', 'amount', 'interestRate' ] + const fields = [ 'to', 'amount', 'emissionInterest:checked', 'interestRate' ] const insufficientFunds = (amount) => { const { gprops, currentAccount } = this.props @@ -78,6 +78,7 @@ class DelegateVestingShares extends React.Component { interestLimit(values.interestRate) ? tt('delegatevestingshares_jsx.too_large_percent') : null, + emissionInterest: null, }) }) } @@ -119,12 +120,16 @@ class DelegateVestingShares extends React.Component { console.error('getVestingDelegationsAsync', error); } if (delegations && delegations[0] && delegations[0].delegatee === value) { - let amount = delegations[0].vesting_shares; + const vdo = delegations[0] + + let amount = vdo.vesting_shares amount = vestsToSteem(amount, gprops); this.state.amount.props.onChange(amount); - let interestRate = delegations[0].interest_rate / 100; - this.state.interestRate.props.onChange(interestRate.toString()); + let interestRate = vdo.interest_rate / 100; + this.state.interestRate.props.onChange(vdo.is_emission ? '0' : interestRate.toString()); + + this.state.emissionInterest.props.onChange(vdo.is_emission) this.setState({ vdoLoading: false, @@ -159,6 +164,11 @@ class DelegateVestingShares extends React.Component { this.state.interestRate.props.onChange(value); }; + onChangeEmissionInterest = (e) => { + this.state.interestRate.props.onChange('0'); + this.state.emissionInterest.props.onChange(e.target.checked) + } + onClickRevoke = (e) => { e.preventDefault(); const { dispatchSubmit, gprops, currentAccount, } = this.props; @@ -167,13 +177,14 @@ class DelegateVestingShares extends React.Component { to: this.state.to.props.value, amount: '0', interestRate: this.state.interestRate.props.value, + emissionInterest: this.state.emissionInterest.props.checked, errorCallback: this.errorCallback, successCallback: this.successCallback, gprops, currentAccount }) }; render() { const { gprops, cprops, currentAccount, dispatchSubmit, } = this.props; - const { to, amount, interestRate, loading, trxError, vdoLoading, vdoExists, } = this.state; + const { to, amount, interestRate, emissionInterest, loading, trxError, vdoLoading, vdoExists, } = this.state; const { submitting, valid, handleSubmit, } = this.state.delegate_vesting; const VESTING_TOKEN2 = tt('token_names.VESTING_TOKEN2') @@ -276,6 +287,25 @@ class DelegateVestingShares extends React.Component {
} + {!vdoLoading &&
+
+
+ +
+ {emissionInterest.touched && emissionInterest.blur && emissionInterest.error && +
{emissionInterest.error} 
+ } +
+
} + {!vdoLoading &&
{tt('delegatevestingshares_jsx.interest')} @@ -294,7 +324,7 @@ class DelegateVestingShares extends React.Component { autoCorrect='off' autoCapitalize='off' spellCheck='false' - disabled={loading || vdoExists} + disabled={loading || vdoExists || emissionInterest.props.checked} />
{interestRate.touched && interestRate.blur && interestRate.error &&
{interestRate.error} 
} @@ -338,7 +368,7 @@ export default connect( let interestRate = calcDefaultInterest(cprops); - const initialValues = { to: null, interestRate, } + const initialValues = { to: null, interestRate, emissionInterest: false } return { ...ownProps, @@ -350,7 +380,7 @@ export default connect( }, dispatch => ({ - dispatchSubmit: ({ to, amount, interestRate, errorCallback, successCallback, gprops, currentAccount }) => { + dispatchSubmit: ({ to, amount, interestRate, emissionInterest, errorCallback, successCallback, gprops, currentAccount }) => { const delegator = currentAccount.get('name'); const delegatee = to; const vestingShares = `${steemToVests(amount, gprops)} GESTS`; @@ -370,6 +400,15 @@ export default connect( __config = { title: tt('delegate_vesting_shares_info_jsx.confirm_title', { VESTING_TOKENS: tt('token_names.VESTING_TOKENS') }), }; } + let extensions =[] + if (emissionInterest) { + extensions.push([0, + { + is_emission: true + }]) + interestRate = 100 + } + dispatch(transaction.actions.broadcastOperation({ type: 'delegate_vesting_shares_with_interest', operation: { @@ -377,6 +416,7 @@ export default connect( delegatee, vesting_shares: vestingShares, interest_rate: Math.trunc(interestRate * 100), + extensions, __config, }, confirm, diff --git a/app/components/modules/DelegateVestingSharesInfo.jsx b/app/components/modules/DelegateVestingSharesInfo.jsx index fef876903..4c6afd3e7 100644 --- a/app/components/modules/DelegateVestingSharesInfo.jsx +++ b/app/components/modules/DelegateVestingSharesInfo.jsx @@ -63,7 +63,7 @@ class DelegateVestingSharesInfo extends React.Component { {vestingShares_str} - {interestRate}% + {c.is_emission ? tt('delegatevestingshares_jsx.no_interest_emission') : interestRate + '%'} {type === 'delegated' && isMyAccount && ( diff --git a/app/components/modules/Donate.jsx b/app/components/modules/Donate.jsx index 345b0ffdb..7187464ac 100644 --- a/app/components/modules/Donate.jsx +++ b/app/components/modules/Donate.jsx @@ -17,6 +17,7 @@ import TipAssetList from 'app/components/elements/donate/TipAssetList' import VoteSlider from 'app/components/elements/donate/VoteSlider' import { checkMemo } from 'app/utils/ParsersAndFormatters'; import { accuEmissionPerDay } from 'app/utils/StateFunctions' +import { checkAllowed, AllowTypes } from 'app/utils/Allowance' class Donate extends React.Component { constructor(props) { @@ -86,18 +87,24 @@ class Donate extends React.Component { this.props.setDonateDefaults(donateDefs) } - _onSubmit = (values, actions) => { + _onSubmit = async (values, actions) => { const { currentUser, opts, dispatchSubmit } = this.props const { to, permlink, is_comment } = opts const { isMemoEncrypted } = this.state const vote = { percent: values.sliderPercent * 100 } - dispatchSubmit({ + await dispatchSubmit({ to, amount: values.amount.asset, memo: values.memo, isMemoEncrypted, - permlink, is_comment, vote, myVote: opts.myVote * 100, currentUser, + permlink, is_comment, + vote, + myVote: opts.myVote * 100, + voteAllowType: opts.voteAllowType, + currentUser, errorCallback: (err) => { - actions.setErrors({ memo: err.message || err }) + if (err) { + actions.setErrors({ memo: err.message || err }) + } actions.setSubmitting(false) } }) @@ -254,9 +261,9 @@ export default connect( setDonateDefaults: (donateDefaults) => { dispatch(user.actions.setDonateDefaults(donateDefaults)) }, - dispatchSubmit: ({ + dispatchSubmit: async ({ to, amount, memo, isMemoEncrypted, - permlink, is_comment, vote, myVote, currentUser, errorCallback + permlink, is_comment, vote, myVote, voteAllowType, currentUser, errorCallback }) => { const username = currentUser.get('username') @@ -277,13 +284,20 @@ export default connect( let trx = [ ['donate', operation] ] + let aTypes = [ + AllowTypes.transfer + ] if (vote && vote.percent !== myVote) { const voteOp = { voter: username, author: to, permlink, weight: vote.percent } - if (amount.amount <= 0) trx = [] + if (amount.amount <= 0) { + trx = [] + aTypes = [] + } trx.push(['vote', voteOp]) + aTypes.push(voteAllowType) if (!myVote) { localStorage.removeItem('vote_weight'); // deprecated @@ -303,8 +317,17 @@ export default connect( dispatch(user.actions.hideDonate()) } + let confirm + const tipAmount = Asset(operation.amount) + const blocking = await checkAllowed(operation.from, [operation.to], tipAmount, aTypes) + if (blocking.error) { + errorCallback(blocking.error) + return + } + confirm = blocking.confirm + dispatch(transaction.actions.broadcastOperation({ - type: 'donate', username, trx, successCallback, errorCallback + type: 'donate', username, trx, confirm, successCallback, errorCallback })) } }) diff --git a/app/components/modules/Header.jsx b/app/components/modules/Header.jsx index 281a5a3ca..df752da03 100644 --- a/app/components/modules/Header.jsx +++ b/app/components/modules/Header.jsx @@ -198,7 +198,7 @@ class Header extends React.Component {
  • - {APP_NAME_UP}blockchain + {APP_NAME_UP}blogs platform
  • {selected_sort_order && } diff --git a/app/components/modules/LoginForm.jsx b/app/components/modules/LoginForm.jsx index 5dba254be..ca2962912 100644 --- a/app/components/modules/LoginForm.jsx +++ b/app/components/modules/LoginForm.jsx @@ -13,7 +13,7 @@ import reactForm from 'app/utils/ReactForm' import tt from 'counterpart'; import { APP_DOMAIN } from 'app/client_config'; import { translateError } from 'app/utils/ParsersAndFormatters'; -import { authRegisterUrl, } from 'app/utils/AuthApiClient'; +import { authUrl, authRegisterUrl, } from 'app/utils/AuthApiClient'; class LoginForm extends Component { @@ -158,7 +158,15 @@ class LoginForm extends Component { const submitLabel = loginBroadcastOperation ? tt('g.sign_in') : tt('g.login'); const cancelIsRegister = loginDefault && loginDefault.get('cancelIsRegister'); let error = password.touched && password.error ? password.error : this.props.login_error; - if (error === 'owner_login_blocked') { + if (error === 'account_frozen') { + error = + {tt('loginform_jsx.account_frozen')} +   + + {tt('g.more_hint')} + + + } else if (error === 'owner_login_blocked') { error = {tt('loginform_jsx.this_password_is_bound_to_your_account_owner_key')}   diff --git a/app/components/modules/PostForm/PostForm.jsx b/app/components/modules/PostForm/PostForm.jsx index 1d734d295..7f7821c82 100644 --- a/app/components/modules/PostForm/PostForm.jsx +++ b/app/components/modules/PostForm/PostForm.jsx @@ -28,6 +28,7 @@ import { updateFavoriteTags, } from 'app/utils/tags'; import { DRAFT_KEY, EDIT_KEY } from 'app/utils/postForm'; +import { checkAllowed, AllowTypes } from 'app/utils/Allowance' const EDITORS_TYPES = { MARKDOWN: 1, @@ -665,6 +666,7 @@ class PostForm extends React.Component { this.props.onPost( data, + editMode, () => { try { if (editMode) { @@ -692,7 +694,7 @@ class PostForm extends React.Component { isPosting: false, }); - this.refs.footer.showPostError(err.toString().trim()); + if (err) this.refs.footer.showPostError(err.toString().trim()); } } ); @@ -801,11 +803,20 @@ export default connect( categories: state.global.get('tag_idx'), }), dispatch => ({ - onPost(payload, onSuccess, onError) { + async onPost(payload, editMode, onSuccess, onError) { + let blocking = await checkAllowed(payload.author, + [], + null, editMode ? AllowTypes.postEdit : AllowTypes.post) + if (blocking.error) { + onError(blocking.error) + return + } + const confirm = blocking.confirm dispatch( transaction.actions.broadcastOperation({ type: 'comment', operation: payload, + confirm, hideErrors: true, errorCallback: onError, successCallback: onSuccess, diff --git a/app/components/modules/Settings.jsx b/app/components/modules/Settings.jsx index 4f93e838d..951637be3 100644 --- a/app/components/modules/Settings.jsx +++ b/app/components/modules/Settings.jsx @@ -6,6 +6,7 @@ import tt from 'counterpart'; import throttle from 'lodash/throttle' import transaction from 'app/redux/Transaction' import { getMetadataReliably } from 'app/utils/NormalizeProfile'; +import DoNotBother from 'app/components/elements/DoNotBother'; import Icon from 'app/components/elements/Icon'; import LoadingIndicator from 'app/components/elements/LoadingIndicator' import Userpic from 'app/components/elements/Userpic'; @@ -303,9 +304,9 @@ class Settings extends React.Component { const {profile_image, cover_image, name, about, gender, location, website, donatePresets, emissionDonatePct, notifyPresets, notifyPresetsTouched} = this.state - const {follow, account, isOwnAccount} = this.props + const {follow, block, account, isOwnAccount} = this.props const following = follow && follow.getIn(['getFollowingAsync', account.name]); - const ignores = isOwnAccount && following && following.get('ignore_result'); + const ignores = isOwnAccount && block && block.getIn(['blocking', account.name, 'result']) const mutedInNew = isOwnAccount && props.mutedInNew; let mutedUIA = []; if (process.env.BROWSER) { @@ -542,6 +543,8 @@ class Settings extends React.Component {
    } + + {ignores && ignores.size > 0 &&
    @@ -580,6 +583,7 @@ export default connect( isOwnAccount: username == accountname, profile, mutedInNew, + block: state.global.get('block'), follow: state.global.get('follow'), ...ownProps } diff --git a/app/components/modules/Transfer.jsx b/app/components/modules/Transfer.jsx index 98ed972f6..e8bee8b79 100644 --- a/app/components/modules/Transfer.jsx +++ b/app/components/modules/Transfer.jsx @@ -1,8 +1,11 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types' import ReactDOM from 'react-dom'; -import reactForm from 'app/utils/ReactForm'; import {Map} from 'immutable'; +import tt from 'counterpart'; +import { Asset } from 'golos-lib-js/lib/utils' + +import reactForm from 'app/utils/ReactForm'; import transaction from 'app/redux/Transaction'; import user from 'app/redux/User'; import g from 'app/redux/GlobalReducer'; @@ -11,9 +14,9 @@ import runTests, {browserTests} from 'app/utils/BrowserTests'; import {validate_account_name} from 'app/utils/ChainValidation'; import { saveMemo, loadMemo, clearOldMemos, } from 'app/utils/UIA'; import {countDecimals, formatAmount, checkMemo} from 'app/utils/ParsersAndFormatters'; -import tt from 'counterpart'; import { LIQUID_TICKER, DEBT_TICKER , VESTING_TOKEN2 } from 'app/client_config'; import VerifiedExchangeList from 'app/utils/VerifiedExchangeList'; +import { checkAllowed } from 'app/utils/Allowance' import DropdownMenu from 'app/components/elements/DropdownMenu'; import Icon from 'app/components/elements/Icon'; @@ -103,13 +106,12 @@ class TransferForm extends Component { const {toVesting, uia} = props const isWithdraw = transferType && transferType === 'Savings Withdraw' const isTIP = transferType && transferType.startsWith('TIP to') - const isClaim = transferType && transferType === 'Claim' const isIssueUIA = (transferType === 'Issue UIA') const insufficientFunds = (asset, amount) => { const {currentAccount, uia} = this.props const balanceValue = !asset || asset === 'GOLOS' ? - isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : (isClaim ? currentAccount.get('accumulative_balance') : currentAccount.get('balance'))) : + isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : currentAccount.get('balance')) : asset === 'GBG' ? isWithdraw ? currentAccount.get('savings_sbd_balance') : currentAccount.get('sbd_balance') : isIssueUIA ? uia.get('can_issue') : @@ -121,7 +123,7 @@ class TransferForm extends Component { return parseFloat(amount) > parseFloat(balance) } const fields = toVesting ? ['to', 'amount'] : ['to', 'amount', 'asset'] - if(!toVesting && transferType !== 'Transfer to Savings' && transferType !== 'Savings Withdraw' && transferType !== 'Claim') + if(!toVesting && transferType !== 'Transfer to Savings' && transferType !== 'Savings Withdraw') fields.push('memo') reactForm({ @@ -131,7 +133,7 @@ class TransferForm extends Component { validation: values => { return { to: ! values.to ? tt('g.required') : - (VerifiedExchangeList.includes(values.to) && (isTIP || isClaim)) ? tt('transfer_jsx.verified_exchange_liquid_only') : + (VerifiedExchangeList.includes(values.to) && isTIP) ? tt('transfer_jsx.verified_exchange_liquid_only') : (VerifiedExchangeList.includes(values.to) && values.memo === '') ? tt('transfer_jsx.verified_exchange_no_memo') : validate_account_name(values.to), amount: @@ -157,9 +159,8 @@ class TransferForm extends Component { const {transferType} = this.props.initialValues const {currentAccount} = this.props const isWithdraw = transferType && transferType === 'Savings Withdraw' - const isClaim = transferType && transferType === 'Claim' const isTIP = transferType && transferType.startsWith('TIP to') - return isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : (isClaim ? currentAccount.get('accumulative_balance') : currentAccount.get('balance'))) + return isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : currentAccount.get('balance')) } balanceValue() { @@ -168,11 +169,10 @@ class TransferForm extends Component { const {asset} = this.state const isWithdraw = transferType && transferType === 'Savings Withdraw' const isTIP = transferType && transferType.startsWith('TIP to') - const isClaim = transferType && transferType === 'Claim' const isIssueUIA = (transferType === 'Issue UIA') return !asset || asset.value === 'GOLOS' ? - isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : (isClaim ? currentAccount.get('accumulative_balance') : currentAccount.get('balance'))) : + isWithdraw ? currentAccount.get('savings_balance') : (isTIP ? currentAccount.get('tip_balance') : currentAccount.get('balance')) : asset.value === 'GBG' ? isWithdraw ? currentAccount.get('savings_sbd_balance') : currentAccount.get('sbd_balance') : isIssueUIA ? @@ -408,8 +408,8 @@ class TransferForm extends Component { const amountLabel = tt('g.amount') const columns = this._getColumnSizes() const form = ( -
    { - dispatchSubmit({...data, isUIA, precision, errorCallback: this.errorCallback, currentUser, toVesting, transferType, + { + await dispatchSubmit({...data, isUIA, precision, errorCallback: this.errorCallback, currentUser, toVesting, transferType, withdrawalWay, isMemoPrivate, }) })} onChange={this.clearError} @@ -484,7 +484,7 @@ class TransferForm extends Component {
    this.onChangeAmount(e)}/> - {asset && !isUIA && transferType !== 'Claim' && !transferType.startsWith('TIP to') && !transferType.endsWith('to TIP') && + {asset && !isUIA && !transferType.startsWith('TIP to') && !transferType.endsWith('to TIP') &&