Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea/
.vscode/
7 changes: 2 additions & 5 deletions packages/app-tech-comm/src/Overview/Summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.

import { I18nProps } from '@polkadot/react-components/types';
import { AccountId, Hash } from '@polkadot/types/interfaces';
import { ComponentProps } from '../types';

import React from 'react';
import { SummaryBox, CardSummary } from '@polkadot/react-components';
Expand All @@ -14,10 +14,7 @@ import { formatNumber } from '@polkadot/util';

import translate from '../translate';

interface Props extends I18nProps {
members?: AccountId[];
proposals?: Hash[];
}
interface Props extends ComponentProps, I18nProps {}

function Summary ({ className, members, proposals, t }: Props): React.ReactElement<Props> {
const { api } = useApi();
Expand Down
19 changes: 7 additions & 12 deletions packages/app-tech-comm/src/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,27 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { AccountId, Hash } from '@polkadot/types/interfaces';
import { I18nProps } from '@polkadot/react-components/types';
import { ComponentProps } from '../types';

import React from 'react';

import translate from '../translate';
import Members from './Members';
import Summary from './Summary';

interface Props {
className?: string;
members?: AccountId[];
proposals?: Hash[];
}
interface Props extends I18nProps, ComponentProps {}

export default function Overview ({ className, members, proposals }: Props): React.ReactElement<Props> {
function Overview ({ className, members, proposals }: Props): React.ReactElement<Props> {
return (
<div className={className}>
<Summary
members={members}
proposals={proposals}
/>
{/* <Button.Group>
<SubmitCandidacy electionsInfo={electionsInfo} />
<Button.Or />
<Vote electionsInfo={electionsInfo} />
</Button.Group> */}
<Members members={members} />
</div>
);
}

export default translate(Overview);
17 changes: 0 additions & 17 deletions packages/app-tech-comm/src/Overview/types.ts

This file was deleted.

6 changes: 3 additions & 3 deletions packages/app-tech-comm/src/Proposals/Proposal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ interface Props extends I18nProps {

function Proposal ({ className, hash, t }: Props): React.ReactElement<Props> | null {
const { api } = useApi();
const _proposal = trackStream<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [hash]);
const optProposal = trackStream<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [hash]);
const votes = trackStream<Option<Votes>>(api.query.technicalCommittee.voting, [hash]);

if (!votes?.isSome) {
if (!optProposal?.isSome || !votes?.isSome) {
return null;
}

const proposal = _proposal?.unwrapOr(null);
const proposal = optProposal.unwrap();
const { ayes, index, nays, threshold } = votes.unwrap();

return (
Expand Down
83 changes: 83 additions & 0 deletions packages/app-tech-comm/src/Proposals/Propose.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2017-2019 @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 { I18nProps } from '@polkadot/react-components/types';
import { TxSource, TxDef } from '@polkadot/react-hooks/types';
import { Call, Proposal } from '@polkadot/types/interfaces';

import BN from 'bn.js';
import React, { useEffect, useState } from 'react';
import { registry } from '@polkadot/react-api';
import { Extrinsic, InputNumber, TxModalNew as TxModal } from '@polkadot/react-components';
import { useApi, useTx } from '@polkadot/react-hooks';
import { createType } from '@polkadot/types';

import translate from '../translate';

interface Props extends I18nProps {
memberCount?: number;
onClose: () => void;
}

function Propose ({ t, onClose, memberCount = 0 }: Props): React.ReactElement<Props> {
const _hasThreshold = (threshold?: BN | null): boolean =>
!!threshold && !threshold.isZero() && threshold.lten(memberCount);

const { apiDefaultTxSudo } = useApi();
const [proposal, setProposal] = useState<Proposal | null>(null);
const [[threshold, hasThreshold], setThreshold] = useState<[BN | null, boolean]>([
new BN(memberCount / 2 + 1),
true
]);

// FIXME Rework this, unless you know, you can never figure out what all these options mean here
const txState = useTx(
Copy link
Member

@jacogr jacogr Dec 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing is just magic, no description of what is what. We will need to update this to be either an object of not having to pass {...txState} (more magic) to the Modal. Contrast this to TxButton (old), where it is obvious what you are passing.

(Not changing it as part of this PR as it works, but it needs a re-look)

(): TxSource<TxDef> => [
[
'technicalCommittee.propose',
[threshold, proposal]
],
!!proposal && hasThreshold
],
[memberCount, proposal, threshold, hasThreshold],
{}
);

useEffect((): void => {
setThreshold([threshold, _hasThreshold(threshold)]);
}, [memberCount]);

const _onChangeExtrinsic = (method?: Call): void =>
setProposal(method ? createType(registry, 'Proposal', method) : null);
const _onChangeThreshold = (threshold?: BN): void =>
setThreshold([threshold || null, _hasThreshold(threshold)]);

return (
<TxModal
isOpen
onClose={onClose}
{...txState}
header={t('Propose a committee motion')}
>
<InputNumber
className='medium'
label={t('threshold')}
help={t('The minimum number of committee votes required to approve this motion')}
isError={!hasThreshold}
onChange={_onChangeThreshold}
onEnter={txState.sendTx}
placeholder={t('Positive number between 1 and {{memberCount}}', { replace: { memberCount } })}
value={threshold || undefined}
/>
<Extrinsic
defaultValue={apiDefaultTxSudo}
label={t('proposal')}
onChange={_onChangeExtrinsic}
onEnter={txState.sendTx}
/>
</TxModal>
);
}

export default translate(Propose);
34 changes: 25 additions & 9 deletions packages/app-tech-comm/src/Proposals/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { Hash } from '@polkadot/types/interfaces';
import { I18nProps } from '@polkadot/react-components/types';
import { Hash } from '@polkadot/types/interfaces';
import { ComponentProps } from '../types';

import React from 'react';
import { Table } from '@polkadot/react-components';
import React, { useState } from 'react';
import { Button, Table } from '@polkadot/react-components';

import Proposal from './Proposal';
import translate from '../translate';
import Proposal from './Proposal';
import Propose from './Propose';

interface Props extends I18nProps {
proposals?: Hash[];
}
interface Props extends ComponentProps, I18nProps {}

function Proposals ({ className, members, proposals, t }: Props): React.ReactElement<Props> {
const [isProposeOpen, setIsProposeOpen] = useState(false);
const _toggleProposal = (): void => setIsProposeOpen(!isProposeOpen);

function Proposals ({ className, proposals, t }: Props): React.ReactElement<Props> {
return (
<div className={className}>
{/* <Propose /> */}
{isProposeOpen && (
<Propose
memberCount={members?.length}
onClose={_toggleProposal}
/>
)}
<Button.Group>
<Button
isPrimary
label={t('Submit proposal')}
icon='add'
onClick={_toggleProposal}
/>
</Button.Group>
{proposals?.length
? (
<Table>
Expand Down
5 changes: 4 additions & 1 deletion packages/app-tech-comm/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ function App ({ basePath, className, t }: Props): React.ReactElement<Props> {
</header>
<Switch>
<Route path={`${basePath}/proposals`}>
<Proposals proposals={proposals} />
<Proposals
members={members}
proposals={proposals}
/>
</Route>
<Route path={basePath}>
<Overview
Expand Down
11 changes: 11 additions & 0 deletions packages/app-tech-comm/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2017-2019 @polkadot/app-democracy 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 { AccountId, Hash } from '@polkadot/types/interfaces';

export interface ComponentProps {
className?: string;
proposals?: Hash[];
members?: AccountId[];
}
4 changes: 2 additions & 2 deletions packages/react-components/src/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ function InputNumber (props: Props): React.ReactElement<Props> {
}, [value, si, bitLength, maxValue]);

useEffect((): void => {
onChange && isValid && onChange(valueBn);
}, [isValid, valueBn]);
onChange && onChange(valueBn);
}, [valueBn]);

const _onChange = (input: string): void => {
setValues(getValuesFromString(input, si, props));
Expand Down
12 changes: 8 additions & 4 deletions packages/react-components/src/TxModalNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function TxModal<P extends Props> ({
isSending,
trigger: Trigger,
header = t('Submit signed extrinsic'),
content,
children,
preContent,
isDisabled = false,
isSubmittable = true,
Expand Down Expand Up @@ -49,6 +49,11 @@ function TxModal<P extends Props> ({
props.onClose && props.onClose();
};

const onSend = (): void => {
sendTx();
onClose();
};

// const onStart = (): void => {
// props.onSubmit && props.onSubmit();
// };
Expand Down Expand Up @@ -108,7 +113,7 @@ function TxModal<P extends Props> ({
type='account'
{...inputAddressProps}
/>
{content}
{children}
</Modal.Content>
<Modal.Actions>
<Button.Group>
Expand All @@ -120,12 +125,11 @@ function TxModal<P extends Props> ({
/>
<Button.Or />
<Button
isLoading={isSending}
isDisabled={isDisabled || isSending || !accountId || !isSubmittable}
isPrimary
label={submitButtonLabel}
icon={submitButtonIcon}
onClick={sendTx}
onClick={onSend}
{...submitButtonProps}
/>
</Button.Group>
Expand Down
3 changes: 1 addition & 2 deletions packages/react-components/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ export interface TxModalProps extends I18nProps, TxState {
isDisabled?: boolean;
isOpen?: boolean;
isUnsigned?: boolean;
isSubmittable?: boolean;
content: React.ReactNode;
children: React.ReactNode;
preContent?: React.ReactNode;
trigger?: TxTrigger;
onSubmit?: () => void;
Expand Down
7 changes: 6 additions & 1 deletion packages/react-hooks/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { AccountId, Balance, BlockNumber, Call, Hash, SessionIndex } from '@polk
import { IExtrinsic } from '@polkadot/types/types';
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';

export type TxSources = SubmittableExtrinsic | IExtrinsic | Call | [string, any[] | ConstructTxFn] | null;
export type TxDef = [string, any[] | ConstructTxFn];

export type TxDefs = SubmittableExtrinsic | IExtrinsic | Call | TxDef | null;

export type TxSource<T extends TxDefs> = [T, boolean];

export interface Slash {
accountId: AccountId;
Expand All @@ -25,6 +29,7 @@ export interface SessionRewards {

export interface ExtrinsicAndSenders {
extrinsic: SubmittableExtrinsic | null;
isSubmittable: boolean;
sendTx: () => void;
sendUnsigned: () => void;
}
Expand Down
Loading