Accept and reject curator from bounty list (#4295)

* Add Accept Curator functionality to bounty list

* Extract Bounties Action Button

* Add unassign curator functionality

* Change curator reject icon and button labels

* Apply review suggestions

* Revert "Apply review suggestions"

This reverts commit 93d637bb3d4593555ce4cc6d5a0654263eb7b4d2.

* Apply review suggestions

* Apply requested changes
This commit is contained in:
Ewa Kowalska 2020-12-29 20:14:38 +01:00 committed by GitHub
parent 8e1ae30016
commit 8490d76bc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 14 deletions

View File

@ -1,4 +1,5 @@
{
"Accept": "Accept",
"Account does not have enough funds.": "Account does not have enough funds.",
"Add Bounty": "Add Bounty",
"Allocation value is smaller than the minimum bounty value.": "Allocation value is smaller than the minimum bounty value.",
@ -6,7 +7,7 @@
"Bond is estimated based on bountyDepositBase and dataDepositPerByte constants.": "Bond is estimated based on bountyDepositBase and dataDepositPerByte constants.",
"Bounties": "Bounties",
"Calculated bond for bounty": "Calculated bond for bounty",
"Claim Bounty": "Claim Bounty",
"Claim": "Claim",
"Claimable": "Claimable",
"Curators deposit": "Curators deposit",
"Curators fee": "Curators fee",
@ -15,6 +16,7 @@
"No open bounties": "No open bounties",
"Proposer": "Proposer",
"Proposer bond depends on bounty title length.": "Proposer bond depends on bounty title length.",
"Reject": "Reject",
"Select the account you wish to propose the bounty from.": "Select the account you wish to propose the bounty from.",
"The description of this bounty": "The description of this bounty",
"The total payment amount of this bounty, curators fee included.": "The total payment amount of this bounty, curators fee included.",

View File

@ -11,7 +11,7 @@ import { AddressSmall, Icon, LinkExternal } from '@polkadot/react-components';
import { BlockToTime, FormatBalance } from '@polkadot/react-query';
import { formatNumber } from '@polkadot/util';
import BountyClaim from './BountyClaim';
import { BountyActions } from './BountyActions';
import { getBountyStatus } from './helpers';
import { useTranslation } from './translate';
@ -58,13 +58,11 @@ function Bounty ({ bestNumber, bounty, className = '', description, index }: Pro
<td>{beneficiary ? <AddressSmall value={beneficiary} /> : EMPTY_CELL}</td>
<td><DueBlocks dueBlocks={blocksUntilPayout} /></td>
<td>
{beneficiary && blocksUntilPayout && (
<BountyClaim
beneficiaryId={beneficiary}
index={index}
payoutDue={blocksUntilPayout}
/>
)}
<BountyActions
bestNumber={bestNumber}
index={index}
status={status}
/>
</td>
<td className='table-column-icon'>
<LinkExternal

View File

@ -0,0 +1,40 @@
// Copyright 2017-2020 @polkadot/app-bounties authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BlockNumber, BountyStatus } from '@polkadot/types/interfaces';
import React, { useCallback, useMemo } from 'react';
import BountyClaimAction from './BountyClaimAction';
import BountyCuratorProposedActions from './BountyCuratorProposedActions';
import { getBountyStatus } from './helpers';
interface Props {
bestNumber: BlockNumber;
index: number;
status: BountyStatus;
}
export function BountyActions ({ bestNumber, index, status }: Props): JSX.Element {
const updateStatus = useCallback(() => getBountyStatus(status), [status]);
const { beneficiary, curator, unlockAt } = updateStatus();
const blocksUntilPayout = useMemo(() => unlockAt?.sub(bestNumber), [bestNumber, unlockAt]);
return (
<>
{status.isCuratorProposed && curator &&
<BountyCuratorProposedActions
curatorId={curator}
index={index}
/>}
{status.isPendingPayout && beneficiary && blocksUntilPayout &&
<BountyClaimAction
beneficiaryId={beneficiary}
index={index}
payoutDue={blocksUntilPayout}
/>}
</>
);
}

View File

@ -18,22 +18,22 @@ interface Props {
payoutDue: BN;
}
function BountyClaim ({ beneficiaryId, index, payoutDue }: Props) {
function BountyClaimAction ({ beneficiaryId, index, payoutDue }: Props) {
const { t } = useTranslation();
const { api } = useApi();
const { allAccounts, hasAccounts } = useAccounts();
const { allAccounts } = useAccounts();
const isBountyClaimable = useMemo(
() => isClaimable(allAccounts, beneficiaryId, payoutDue),
[allAccounts, beneficiaryId, payoutDue]
);
return hasAccounts && isBountyClaimable
return isBountyClaimable
? (
<TxButton
accountId={beneficiaryId}
icon='plus'
label={t<string>('Claim Bounty')}
label={t<string>('Claim')}
params={[index]}
tx={(api.tx.bounties || api.tx.treasury).claimBounty}
/>
@ -41,4 +41,4 @@ function BountyClaim ({ beneficiaryId, index, payoutDue }: Props) {
: null;
}
export default React.memo(BountyClaim);
export default React.memo(BountyClaimAction);

View File

@ -0,0 +1,47 @@
// Copyright 2017-2020 @polkadot/app-bounties authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AccountId } from '@polkadot/types/interfaces';
import React, { useMemo } from 'react';
import { TxButton } from '@polkadot/react-components';
import { useAccounts, useApi } from '@polkadot/react-hooks';
import { useTranslation } from './translate';
interface Props {
curatorId: AccountId;
index: number;
}
function BountyCuratorProposedActions ({ curatorId, index }: Props) {
const { t } = useTranslation();
const { api } = useApi();
const { allAccounts } = useAccounts();
const isCurator = useMemo(() => allAccounts.includes(curatorId.toString()), [allAccounts, curatorId]);
return isCurator
? (
<>
<TxButton
accountId={curatorId}
icon='check'
label={t<string>('Accept')}
params={[index]}
tx={(api.tx.bounties || api.tx.treasury).acceptCurator}
/>
<TxButton
accountId={curatorId}
icon='times'
label={t<string>('Reject')}
params={[index]}
tx={(api.tx.bounties || api.tx.treasury).unassignCurator}
/>
</>
)
: null;
}
export default React.memo(BountyCuratorProposedActions);