Expander with optional meta (#2452)

This commit is contained in:
Jaco Greeff 2020-03-24 11:35:28 +01:00 committed by GitHub
parent facfb5bba9
commit c3d8a0be0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 71 deletions

View File

@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { FunctionMetadataLatest, Hash, Proposal } from '@polkadot/types/interfaces';
import { Hash, Proposal } from '@polkadot/types/interfaces';
import React from 'react';
import { registry } from '@polkadot/react-api';
@ -16,21 +16,6 @@ interface Props {
proposalHash: Hash | string;
}
function formatDocs (meta?: FunctionMetadataLatest): React.ReactNode | null {
if (!meta) {
return null;
}
const strings = meta.documentation.map((doc): string => doc.toString().trim());
const firstEmpty = strings.findIndex((doc): boolean => !doc.length);
if (!firstEmpty) {
return null;
}
return strings.slice(0, firstEmpty).join(' ');
}
function ProposalCell ({ className, proposal, proposalHash }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
@ -48,7 +33,7 @@ function ProposalCell ({ className, proposal, proposalHash }: Props): React.Reac
return (
<td className={`${className} all top`}>
<div>{section}.{method}</div>
<Expander summary={formatDocs(meta) || t('Details')}>
<Expander summaryMeta={meta}>
<Call
labelHash={t('proposal hash')}
value={proposal}

View File

@ -50,7 +50,7 @@ function renderExtrinsic (props: Props, extrinsic: Extrinsic, index: number, t:
</div>
)}
</div>
<Expander summary={meta?.documentation.join(' ') || t('Details')}>
<Expander summaryMeta={meta}>
<Call
className='details'
mortality={

View File

@ -53,13 +53,7 @@ function Events ({ emptyLabel, eventClassName, events, withoutIndex }: Props): R
}
</h3>
</div>
<Expander
summary={
event.meta && event.meta.documentation
? event.meta.documentation.join(' ')
: 'Details'
}
>
<Expander summaryMeta={event.meta}>
<EventDisplay
className='details'
value={event}

View File

@ -7,19 +7,48 @@ import { BareProps } from './types';
import React, { useMemo } from 'react';
import styled from 'styled-components';
import { useToggle } from '@polkadot/react-hooks';
import { Text } from '@polkadot/types';
import { useTranslation } from './translate';
import Icon from './Icon';
interface Meta {
documentation: Text[];
}
export interface Props extends BareProps {
children?: React.ReactNode;
isOpen?: boolean;
summary: React.ReactNode;
summary?: React.ReactNode;
summaryMeta?: Meta;
withDot?: boolean;
withHidden?: boolean;
}
function Expander ({ children, className, isOpen, summary, withDot, withHidden }: Props): React.ReactElement<Props> {
function formatMeta (meta?: Meta): React.ReactNode | null {
if (!meta || !meta.documentation.length) {
return null;
}
const strings = meta.documentation.map((doc): string => doc.toString().trim());
const firstEmpty = strings.findIndex((doc): boolean => !doc.length);
return firstEmpty === -1
? strings.join(' ')
: strings.slice(0, firstEmpty).join(' ');
}
function Expander ({ children, className, isOpen, summary, summaryMeta, withDot, withHidden }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [isExpanded, toggleExpanded] = useToggle(isOpen);
const headerMain = useMemo(
() => summary || formatMeta(summaryMeta),
[summary, summaryMeta]
);
const headerSub = useMemo(
() => summary ? formatMeta(summaryMeta) : null,
[summary, summaryMeta]
);
const hasContent = useMemo(
(): boolean => !!children && (!Array.isArray(children) || children.length !== 0),
[children]
@ -31,12 +60,17 @@ function Expander ({ children, className, isOpen, summary, withDot, withHidden }
onClick={toggleExpanded}
>
<div className='ui--Expander-summary'>
{hasContent
? <Icon name={isExpanded ? 'angle double down' : 'angle double right'} />
: withDot
? <Icon name='circle outline' />
: undefined
}{summary}
<div className='ui--Expander-summary-header'>
{hasContent
? <Icon name={isExpanded ? 'angle double down' : 'angle double right'} />
: withDot
? <Icon name='circle outline' />
: undefined
}{headerMain || t('Details')}
</div>
{headerSub && (
<div className='ui--Expander-summary-sub'>{headerSub}</div>
)}
</div>
{hasContent && (isExpanded || withHidden) && (
<div className='ui--Expander-contents'>{children}</div>
@ -68,5 +102,11 @@ export default React.memo(styled(Expander)`
i.icon {
margin-right: 0.5rem;
}
.ui--Expander-summary-sub {
font-size: 1rem;
opacity: 0.6;
padding-left: 1.75rem;
}
}
`);

View File

@ -22,7 +22,6 @@ interface Props {
insetProps?: Partial<InsetProps>;
proposal?: Proposal | null;
idNumber: BN | number | string;
isCollapsible?: boolean;
withLinks?: boolean;
expandNested?: boolean;
}
@ -41,7 +40,7 @@ export const styles = `
}
`;
function ProposedAction ({ className, asInset, idNumber, insetProps, isCollapsible = true, proposal, withLinks, expandNested }: Props): React.ReactElement<Props> {
function ProposedAction ({ className, asInset, idNumber, insetProps, proposal, withLinks, expandNested }: Props): React.ReactElement<Props> {
const stringId = isString(idNumber)
? idNumber
: formatNumber(idNumber);
@ -92,21 +91,9 @@ function ProposedAction ({ className, asInset, idNumber, insetProps, isCollapsib
return (
<div className={`ui--ProposedAction ${className}`}>
<h3>{header}</h3>
{isCollapsible
? (
<Expander>
{documentation}
{params}
</Expander>
)
: (
<>
<Expander>
{documentation}
</Expander>
{params}
</>
)}
<Expander summaryMeta={meta}>
{params}
</Expander>
</div>
);
}

View File

@ -2,7 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { FunctionMetadataLatest } from '@polkadot/types/interfaces';
import { QueueTx } from '@polkadot/react-components/Status/types';
import BN from 'bn.js';
@ -24,25 +23,6 @@ interface Props {
value: QueueTx;
}
function formatMeta (meta?: FunctionMetadataLatest): React.ReactNode | null {
if (!meta) {
return null;
}
const strings = meta.documentation.map((doc): string => doc.toString().trim());
const firstEmpty = strings.findIndex((doc): boolean => !doc.length);
if (!firstEmpty) {
return null;
}
return (
<div className='meta'>
{strings.slice(0, firstEmpty).join(' ')}
</div>
);
}
function Transaction ({ children, className, hideDetails, isSendable, onError, value: { accountId, extrinsic, isUnsigned }, tip }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
@ -75,8 +55,8 @@ function Transaction ({ children, className, hideDetails, isSendable, onError, v
})</span>
</>
}
summaryMeta={meta}
>
{formatMeta(meta)}
<Call
onError={onError}
value={extrinsic}