Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
423 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright 2017-2020 @polkadot/app-treasury authors & contributors | ||
// This software may be modified and distributed under the terms | ||
// of the Apache-2.0 license. See the LICENSE file for details. | ||
|
||
import { OpenTip } from '@polkadot/types/interfaces'; | ||
|
||
import React from 'react'; | ||
import { AddressSmall, AddressMini, Expander } from '@polkadot/react-components'; | ||
import { useApi, useCall } from '@polkadot/react-hooks'; | ||
import { FormatBalance } from '@polkadot/react-query'; | ||
import { Option } from '@polkadot/types'; | ||
|
||
import { useTranslation } from '../translate'; | ||
import TipEndorse from './TipEndorse'; | ||
import TipReason from './TipReason'; | ||
|
||
interface Props { | ||
className?: string; | ||
hash: string; | ||
isMember: boolean; | ||
members: string[]; | ||
} | ||
|
||
function Tip ({ className, hash, isMember, members }: Props): React.ReactElement<Props> | null { | ||
const { t } = useTranslation(); | ||
const { api } = useApi(); | ||
const tip = useCall<OpenTip | null>(api.query.treasury.tips, [hash], { | ||
transform: (optTip: Option<OpenTip>) => optTip.unwrapOr(null) | ||
}); | ||
|
||
if (!tip) { | ||
return null; | ||
} | ||
|
||
const { finder, reason, tips, who } = tip; | ||
const finderInfo = finder.unwrapOr(null); | ||
|
||
return ( | ||
<tr className={className}> | ||
<td className='address'> | ||
<AddressSmall value={who} /> | ||
</td> | ||
<td className='address'> | ||
{finderInfo && ( | ||
<AddressMini value={finderInfo[0]} /> | ||
)} | ||
</td> | ||
<td className='number'> | ||
{finderInfo && ( | ||
<FormatBalance value={finderInfo[1]} /> | ||
)} | ||
</td> | ||
<TipReason hash={reason} /> | ||
<td className='start all'> | ||
{tips.length !== 0 && ( | ||
<Expander summary={t('Endorsements ({{count}})', { replace: { count: tips.length } })}> | ||
{tips.map(([tipper, balance]) => ( | ||
<AddressMini | ||
balance={balance} | ||
key={tipper.toString()} | ||
value={tipper} | ||
withBalance | ||
/> | ||
))} | ||
</Expander> | ||
)} | ||
</td> | ||
<td className='button'> | ||
<TipEndorse | ||
hash={hash} | ||
isMember={isMember} | ||
members={members} | ||
/> | ||
</td> | ||
</tr> | ||
); | ||
} | ||
|
||
export default React.memo(Tip); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright 2017-2020 @polkadot/app-treasury authors & contributors | ||
// This software may be modified and distributed under the terms | ||
// of the Apache-2.0 license. See the LICENSE file for details. | ||
|
||
import BN from 'bn.js'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { Button, Input, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components'; | ||
import { useToggle } from '@polkadot/react-hooks'; | ||
|
||
import { useTranslation } from '../translate'; | ||
|
||
interface Props { | ||
members: string[]; | ||
refresh: () => void; | ||
} | ||
|
||
const MAX_REASON_LEN = 128; | ||
const MIN_REASON_LEN = 5; | ||
|
||
function TipCreate ({ members, refresh }: Props): React.ReactElement<Props> { | ||
const { t } = useTranslation(); | ||
const [isOpen, toggleOpen] = useToggle(); | ||
const [accountId, setAccountId] = useState<string | null>(null); | ||
const [beneficiary, setBeneficiary] = useState<string | null>(null); | ||
const [isMember, setIsMember] = useState(false); | ||
const [reason, setReason] = useState(''); | ||
const [value, setValue] = useState<BN | undefined>(); | ||
const hasValue = value?.gtn(0); | ||
const hasReason = reason?.length >= MIN_REASON_LEN && reason?.length <= MAX_REASON_LEN; | ||
|
||
useEffect((): void => { | ||
setIsMember( | ||
accountId | ||
? members.includes(accountId) | ||
: false | ||
); | ||
}, [accountId, members]); | ||
|
||
return ( | ||
<> | ||
<Button | ||
icon='plus' | ||
label={t('Tip')} | ||
onClick={toggleOpen} | ||
/> | ||
{isOpen && ( | ||
<Modal | ||
header={t('Submit tip request')} | ||
size='small' | ||
> | ||
<Modal.Content> | ||
<InputAddress | ||
help={t('Select the account you wish to submit the tip from.')} | ||
label={t('submit with account')} | ||
onChange={setAccountId} | ||
type='account' | ||
withLabel | ||
/> | ||
<InputAddress | ||
help={t('The account to which the tip will be transferred if approved')} | ||
label={t('beneficiary')} | ||
onChange={setBeneficiary} | ||
type='allPlus' | ||
/> | ||
<Input | ||
autoFocus | ||
help={t('The reason why this tip should be paid.')} | ||
isError={!hasReason} | ||
label={t('tip reason')} | ||
onChange={setReason} | ||
/> | ||
{isMember && ( | ||
<InputBalance | ||
help={t('The suggested value for this tip')} | ||
isError={!hasValue} | ||
label={t('tip value')} | ||
onChange={setValue} | ||
/> | ||
)} | ||
</Modal.Content> | ||
<Modal.Actions onCancel={toggleOpen}> | ||
<TxButton | ||
accountId={accountId} | ||
icon='add' | ||
isDisabled={!accountId || (isMember ? !hasValue : false) || !hasReason} | ||
isPrimary | ||
label={t('Propose tip')} | ||
onStart={toggleOpen} | ||
onSuccess={refresh} | ||
params={ | ||
isMember | ||
? [reason, beneficiary, value] | ||
: [reason, beneficiary] | ||
} | ||
tx={ | ||
isMember | ||
? 'treasury.tipNew' | ||
: 'treasury.reportAwesome' | ||
} | ||
/> | ||
</Modal.Actions> | ||
</Modal> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
export default React.memo(TipCreate); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2017-2020 @polkadot/app-treasury authors & contributors | ||
// This software may be modified and distributed under the terms | ||
// of the Apache-2.0 license. See the LICENSE file for details. | ||
|
||
import BN from 'bn.js'; | ||
import React, { useState } from 'react'; | ||
import { Button, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components'; | ||
import { useToggle } from '@polkadot/react-hooks'; | ||
|
||
import { useTranslation } from '../translate'; | ||
|
||
interface Props { | ||
hash: string; | ||
isMember: boolean; | ||
members: string[]; | ||
} | ||
|
||
function TipEndorse ({ hash, isMember, members }: Props): React.ReactElement<Props> { | ||
const { t } = useTranslation(); | ||
const [isOpen, toggleOpen] = useToggle(); | ||
const [accountId, setAccountId] = useState<string | null>(null); | ||
const [value, setValue] = useState<BN | undefined>(); | ||
const hasValue = value?.gtn(0); | ||
|
||
return ( | ||
<> | ||
<Button | ||
icon='check' | ||
isDisabled={!isMember} | ||
label={t('Endorse')} | ||
onClick={toggleOpen} | ||
/> | ||
{isOpen && ( | ||
<Modal | ||
header={t('Submit tip endorsement')} | ||
size='small' | ||
> | ||
<Modal.Content> | ||
<InputAddress | ||
filter={members} | ||
help={t('Select the account you wish to submit the tip from.')} | ||
label={t('submit with account')} | ||
onChange={setAccountId} | ||
type='account' | ||
withLabel | ||
/> | ||
<InputBalance | ||
help={t('The tip amount that should be allocated')} | ||
isError={!hasValue} | ||
label={t('value')} | ||
onChange={setValue} | ||
/> | ||
</Modal.Content> | ||
<Modal.Actions onCancel={toggleOpen}> | ||
<TxButton | ||
accountId={accountId} | ||
icon='add' | ||
isDisabled={!accountId || !hasValue } | ||
isPrimary | ||
label={t('Submit tip')} | ||
onStart={toggleOpen} | ||
params={[hash, value]} | ||
tx='treasury.tip' | ||
/> | ||
</Modal.Actions> | ||
</Modal> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
export default React.memo(TipEndorse); |
Oops, something went wrong.