Majority propose shortcut (council) (#2423)
This commit is contained in:
parent
c25b08e014
commit
042e8a0a16
90
packages/page-council/src/Motions/ProposeExternal.tsx
Normal file
90
packages/page-council/src/Motions/ProposeExternal.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2017-2020 @polkadot/ui-staking 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 { SubmittableExtrinsic } from '@polkadot/api/types';
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Button, Input, InputAddress, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { useApi, useToggle } from '@polkadot/react-hooks';
|
||||
import { isHex } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
isMember: boolean;
|
||||
members: string[];
|
||||
}
|
||||
|
||||
function ProposeExternal ({ className, isMember, members }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [isVisible, toggleVisible] = useToggle();
|
||||
const [accountId, setAcountId] = useState<string | null>(null);
|
||||
const [proposal, setProposal] = useState<SubmittableExtrinsic<'promise'> | null>(null);
|
||||
const [{ isHashValid, hash }, setHash] = useState<{ isHashValid: boolean; hash?: string }>({ isHashValid: false, hash: '' });
|
||||
const threshold = Math.ceil((members.length || 0) * 0.5);
|
||||
|
||||
const _onChangeHash = useCallback(
|
||||
(hash?: string): void => setHash({ isHashValid: isHex(hash, 256), hash }),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
if (isHashValid && hash) {
|
||||
setProposal(() => api.tx.democracy.externalProposeMajority(hash));
|
||||
} else {
|
||||
setProposal(null);
|
||||
}
|
||||
}, [hash, isHashValid]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
icon='add'
|
||||
isDisabled={!isMember}
|
||||
label={t('Propose external')}
|
||||
onClick={toggleVisible}
|
||||
/>
|
||||
{isVisible && (
|
||||
<Modal
|
||||
className={className}
|
||||
header={t('Propose external (majority)')}
|
||||
>
|
||||
<Modal.Content>
|
||||
<InputAddress
|
||||
filter={members}
|
||||
help={t('Select the account you wish to make the proposal with.')}
|
||||
label={t('propose from account')}
|
||||
onChange={setAcountId}
|
||||
type='account'
|
||||
withLabel
|
||||
/>
|
||||
<Input
|
||||
autoFocus
|
||||
help={t('The preimage hash of the proposal')}
|
||||
label={t('preimage hash')}
|
||||
onChange={_onChangeHash}
|
||||
value={hash}
|
||||
/>
|
||||
</Modal.Content>
|
||||
<Modal.Actions onCancel={toggleVisible}>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
icon='plus'
|
||||
isDisabled={!threshold || !members.includes(accountId || '') || !proposal}
|
||||
isPrimary
|
||||
label={t('Propose')}
|
||||
onStart={toggleVisible}
|
||||
params={[threshold, proposal]}
|
||||
tx='council.propose'
|
||||
/>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(ProposeExternal);
|
||||
@ -22,7 +22,7 @@ interface Option {
|
||||
value: number;
|
||||
}
|
||||
|
||||
export default function Slashing ({ className, isMember, members }: Props): React.ReactElement<Props> {
|
||||
function Slashing ({ className, isMember, members }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const slashes = useAvailableSlashes();
|
||||
@ -65,7 +65,7 @@ export default function Slashing ({ className, isMember, members }: Props): Reac
|
||||
<>
|
||||
<Button
|
||||
icon='cancel'
|
||||
isDisabled={!isMember || !members.length || !slashes.length}
|
||||
isDisabled={!isMember || !slashes.length}
|
||||
label={t('Cancel slashes')}
|
||||
onClick={toggleVisible}
|
||||
/>
|
||||
@ -119,3 +119,5 @@ export default function Slashing ({ className, isMember, members }: Props): Reac
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Slashing);
|
||||
|
||||
@ -11,7 +11,8 @@ import { Button, Table } from '@polkadot/react-components';
|
||||
import { useTranslation } from '../translate';
|
||||
import useCouncilMembers from '../useCouncilMembers';
|
||||
import Motion from './Motion';
|
||||
import Propose from './Propose';
|
||||
import ProposeMotion from './ProposeMotion';
|
||||
import ProposeExternal from './ProposeExternal';
|
||||
import Slashing from './Slashing';
|
||||
|
||||
interface Props {
|
||||
@ -27,12 +28,17 @@ function Proposals ({ className, motions, prime }: Props): React.ReactElement<Pr
|
||||
return (
|
||||
<div className={className}>
|
||||
<Button.Group>
|
||||
<Propose
|
||||
<ProposeMotion
|
||||
filter={members}
|
||||
isMember={isMember}
|
||||
members={members}
|
||||
/>
|
||||
<Button.Or />
|
||||
<ProposeExternal
|
||||
isMember={isMember}
|
||||
members={members}
|
||||
/>
|
||||
<Button.Or />
|
||||
<Slashing
|
||||
isMember={isMember}
|
||||
members={members}
|
||||
|
||||
@ -32,6 +32,7 @@ function SetSessionKey ({ controllerId, onClose }: Props): React.ReactElement<Pr
|
||||
label={t('controller account')}
|
||||
/>
|
||||
<Input
|
||||
autoFocus
|
||||
className='medium'
|
||||
help={t('Changing the key only takes effect at the start of the next session. The input here is generates from the author_rotateKeys command')}
|
||||
isError={!keys}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user