From f288a265a1c8e9ea218043077bcd4654416a2a49 Mon Sep 17 00:00:00 2001 From: Jaco Date: Fri, 30 Dec 2022 10:38:16 +0200 Subject: [PATCH] Add collapsible rows to democracy (#8656) * Add collapsible rows to democracy * Adjust padding * shortHash * Fix test text * Move bounty links * Fix contacts tests --- .../page-accounts/src/Accounts/Account.tsx | 26 +-- .../page-accounts/src/Accounts/index.spec.ts | 4 +- .../src/Sidebar/Sidebar.spec.tsx | 8 +- .../page-addresses/src/Contacts/Address.tsx | 29 +-- .../page-addresses/src/Contacts/index.spec.ts | 3 +- packages/page-bounties/src/Bounties.tsx | 6 +- packages/page-bounties/src/Bounty.tsx | 96 +++++----- .../page-democracy/src/Overview/External.tsx | 87 +++++---- .../page-democracy/src/Overview/Externals.tsx | 4 +- .../page-democracy/src/Overview/Proposal.tsx | 101 ++++++---- .../src/Overview/ProposalCell.tsx | 13 +- .../page-democracy/src/Overview/Proposals.tsx | 4 +- .../src/Overview/Referendum.tsx | 180 ++++++++++-------- .../src/Overview/Referendums.tsx | 4 +- .../react-components/src/LinkExternal.tsx | 17 +- packages/react-components/src/Table/index.tsx | 9 + packages/react-components/src/Tags.tsx | 2 +- 17 files changed, 314 insertions(+), 279 deletions(-) diff --git a/packages/page-accounts/src/Accounts/Account.tsx b/packages/page-accounts/src/Accounts/Account.tsx index f7ccdf6d21..e61a37cb40 100644 --- a/packages/page-accounts/src/Accounts/Account.tsx +++ b/packages/page-accounts/src/Accounts/Account.tsx @@ -722,22 +722,19 @@ function Account ({ account: { address, meta }, className = '', delegation, filt - + -
+
{ await accountRows[0].assertShortAddress(aliceShortAddress); }); - it('when account is not tagged, account row details displays no tags info', async () => { + it('when account is not tagged, account row details displays none info', async () => { accountsPage.renderDefaultAccounts(1); const rows = await accountsPage.getAccountRows(); - await rows[0].assertTags('no tags'); + await rows[0].assertTags('none'); }); it('when account is tagged, account row details displays tags', async () => { diff --git a/packages/page-accounts/src/Sidebar/Sidebar.spec.tsx b/packages/page-accounts/src/Sidebar/Sidebar.spec.tsx index e013eafeab..1c05481296 100644 --- a/packages/page-accounts/src/Sidebar/Sidebar.spec.tsx +++ b/packages/page-accounts/src/Sidebar/Sidebar.spec.tsx @@ -72,7 +72,7 @@ describe.skip('Sidebar', () => { it('cannot be edited if edit button has not been pressed', async () => { accountsPage.renderDefaultAccounts(1); sideBar = await accountsPage.openSidebarForRow(0); - await sideBar.clickByText('no tags'); + await sideBar.clickByText('none'); expect(sideBar.queryByRole('combobox')).toBeFalsy(); await expect(sideBar.typeAccountName(newName)).rejects.toThrowError(nameInputNotFoundError); @@ -95,7 +95,7 @@ describe.skip('Sidebar', () => { ); sideBar = await accountsPage.openSidebarForRow(0); - await sideBar.assertTags('no tags'); + await sideBar.assertTags('none'); sideBar.edit(); }); @@ -104,7 +104,7 @@ describe.skip('Sidebar', () => { await sideBar.selectTag(defaultTag); sideBar.cancel(); - await sideBar.assertTags('no tags'); + await sideBar.assertTags('none'); await sideBar.assertAccountName(initialName); }); @@ -130,7 +130,7 @@ describe.skip('Sidebar', () => { fireEvent.click(await screen.findByText('accounts')); - await sideBar.assertTags('no tags'); + await sideBar.assertTags('none'); await sideBar.assertAccountName('ALICE'); expect(sideBar.queryByRole('button', { name: 'Cancel' })).toBeFalsy(); diff --git a/packages/page-addresses/src/Contacts/Address.tsx b/packages/page-addresses/src/Contacts/Address.tsx index 84f1add723..57bdc7532c 100644 --- a/packages/page-addresses/src/Contacts/Address.tsx +++ b/packages/page-addresses/src/Contacts/Address.tsx @@ -251,22 +251,19 @@ function Address ({ address, className = '', filter, isFavorite, toggleFavorite - + -
+
{ describe('when some contacts exist', () => { it('the contacts table contains some contact rows', async () => { addressesPage.renderDefaultContacts(2); + const rows = await addressesPage.getAddressesRows(); expect(rows).toHaveLength(2); @@ -97,7 +98,7 @@ describe('Addresses page', () => { addressesPage.renderDefaultContacts(1); const rows = await addressesPage.getAddressesRows(); - await rows[0].assertTags('no tags'); + await rows[0].assertTags('none'); }); it('when a contact is tagged, the details row displays tags', async () => { diff --git a/packages/page-bounties/src/Bounties.tsx b/packages/page-bounties/src/Bounties.tsx index d107e330d5..b387ffadaa 100644 --- a/packages/page-bounties/src/Bounties.tsx +++ b/packages/page-bounties/src/Bounties.tsx @@ -62,15 +62,15 @@ function Bounties ({ className }: Props): React.ReactElement { export default React.memo(styled(Bounties)` .bounties-table-wrapper table { tr { - td, - &:not(.filter) th { + td, &:not(.filter) th { &:last-child { padding-right: 1.14rem; } } } } -.ui--IdentityIcon { + + .ui--IdentityIcon { margin-right: 0.42rem; } diff --git a/packages/page-bounties/src/Bounty.tsx b/packages/page-bounties/src/Bounty.tsx index 4d3dd7cbc9..4b77d8c767 100644 --- a/packages/page-bounties/src/Bounty.tsx +++ b/packages/page-bounties/src/Bounty.tsx @@ -7,7 +7,7 @@ import type { BlockNumber, Bounty as BountyType, BountyIndex } from '@polkadot/t import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { AddressSmall, ExpandButton, LinkExternal } from '@polkadot/react-components'; +import { AddressSmall, Columar, ExpandButton, LinkExternal } from '@polkadot/react-components'; import { useToggle } from '@polkadot/react-hooks'; import { FormatBalance } from '@polkadot/react-query'; import { formatNumber } from '@polkadot/util'; @@ -118,10 +118,6 @@ function Bounty ({ bestNumber, bounty, className = '', description, index, propo
- - -
-
{t('Proposer')}
- -
- - -
-
{t('Bond')}
-
-
- {curator && ( -
-
{t("Curator's fee")}
-
{}
-
- )} -
- {curator && !curatorDeposit.isZero() && ( - <> -
{t("Curator's deposit")}
-
- + + + + + + + +
+
{t('Proposer')}
+ +
+
+
{t('Bond')}
+
+
+ {curator && ( +
+
{t("Curator's fee")}
+
{}
- - )} -
+ )} +
+ {curator && !curatorDeposit.isZero() && ( + <> +
{t("Curator's deposit")}
+
+ +
+ + )} +
+ + @@ -210,31 +219,18 @@ export default React.memo(styled(Bounty)` line-height: normal; } - .label { - text-align: right; - padding: 0 1.7rem 0 0; - line-height: normal; - color: var(--color-label); - text-transform: lowercase; - } - - .label-column-right, .label-column-left{ - display: flex; + .column { align-items: center; + display: flex; + padding: 0 0 0.5rem; - .label { + h5 { + text-align: right; + padding: 0 1.7rem 0 0; width: 50%; } } - .label-column-right { - padding: 0 0 0.5rem; - } - - .label-column-left { - padding: 0 0 0.5rem; - } - & .td-info-action-row { padding-right: 0; } diff --git a/packages/page-democracy/src/Overview/External.tsx b/packages/page-democracy/src/Overview/External.tsx index 5ec4eb93e8..6d60fb3f6a 100644 --- a/packages/page-democracy/src/Overview/External.tsx +++ b/packages/page-democracy/src/Overview/External.tsx @@ -5,8 +5,8 @@ import type { DeriveProposalExternal } from '@polkadot/api-derive/types'; import React from 'react'; -import { AddressMini, Button, LinkExternal } from '@polkadot/react-components'; -import { useCollectiveMembers } from '@polkadot/react-hooks'; +import { AddressMini, Button, Columar, ExpandButton, LinkExternal } from '@polkadot/react-components'; +import { useCollectiveMembers, useToggle } from '@polkadot/react-hooks'; import { FormatBalance } from '@polkadot/react-query'; import Fasttrack from './Fasttrack'; @@ -20,42 +20,59 @@ interface Props { function External ({ className = '', value: { image, imageHash, threshold } }: Props): React.ReactElement | null { const { isMember, members } = useCollectiveMembers('technicalCommittee'); + const [isExpanded, toggleIsExpanded] = useToggle(false); return ( - - - - {image && ( - - )} - - - {image && } - - - - {!image?.proposal && ( - - )} - {threshold && isMember && ( - - )} - - - - + + - - + + {image && ( + + )} + + + {image && } + + + + {!image?.proposal && ( + + )} + {threshold && isMember && ( + + )} + + + + + + + + + + + + + + ); } diff --git a/packages/page-democracy/src/Overview/Externals.tsx b/packages/page-democracy/src/Overview/Externals.tsx index d3e82bf3e6..18a06def8a 100644 --- a/packages/page-democracy/src/Overview/Externals.tsx +++ b/packages/page-democracy/src/Overview/Externals.tsx @@ -24,8 +24,7 @@ function Externals ({ className }: Props): React.ReactElement | null { [t('external'), 'start'], [t('proposer'), 'address'], [t('locked')], - [], - [undefined, 'media--1000'] + [] ]); return ( @@ -33,6 +32,7 @@ function Externals ({ className }: Props): React.ReactElement | null { className={className} empty={external === null && t('No external proposal')} header={headerRef.current} + withCollapsibleRows > {external && } diff --git a/packages/page-democracy/src/Overview/Proposal.tsx b/packages/page-democracy/src/Overview/Proposal.tsx index ccf45895a0..3e1acd9bb2 100644 --- a/packages/page-democracy/src/Overview/Proposal.tsx +++ b/packages/page-democracy/src/Overview/Proposal.tsx @@ -5,7 +5,8 @@ import type { DeriveProposal } from '@polkadot/api-derive/types'; import React, { useCallback, useMemo } from 'react'; -import { AddressMini, Button, ExpanderScroll, LinkExternal } from '@polkadot/react-components'; +import { AddressMini, Button, Columar, ExpandButton, ExpanderScroll, LinkExternal } from '@polkadot/react-components'; +import { useToggle } from '@polkadot/react-hooks'; import { FormatBalance } from '@polkadot/react-query'; import { formatNumber } from '@polkadot/util'; @@ -21,6 +22,7 @@ interface Props { function Proposal ({ className = '', value: { balance, image, imageHash, index, proposer, seconds } }: Props): React.ReactElement { const { t } = useTranslation(); + const [isExpanded, toggleIsExpanded] = useToggle(false); const seconding = useMemo( () => seconds.filter((_address, index) => index !== 0), @@ -40,47 +42,64 @@ function Proposal ({ className = '', value: { balance, image, imageHash, index, ); return ( - -

{formatNumber(index)}

- - - - - - - - - {seconding.length !== 0 && ( - ('No endorsements')} - renderChildren={renderSeconds} - summary={t('Endorsed ({{count}})', { replace: { count: seconding.length } })} - /> - )} - - - - {!image?.proposal && ( - - )} - - - - - + +

{formatNumber(index)}

+ - - + + + + + + + + {seconding.length !== 0 && ( + ('No endorsements')} + renderChildren={renderSeconds} + summary={t('Endorsed ({{count}})', { replace: { count: seconding.length } })} + /> + )} + + + + {!image?.proposal && ( + + )} + + + + + + + + + + + + + + + + ); } diff --git a/packages/page-democracy/src/Overview/ProposalCell.tsx b/packages/page-democracy/src/Overview/ProposalCell.tsx index 426355c810..569a61bced 100644 --- a/packages/page-democracy/src/Overview/ProposalCell.tsx +++ b/packages/page-democracy/src/Overview/ProposalCell.tsx @@ -6,6 +6,7 @@ import type { Hash, Proposal, ProposalIndex } from '@polkadot/types/interfaces'; import type { HexString } from '@polkadot/util/types'; import React from 'react'; +import styled from 'styled-components'; import usePreimage from '@polkadot/app-preimages/usePreimage'; import { CallExpander } from '@polkadot/react-components'; @@ -38,7 +39,7 @@ function ProposalCell ({ className = '', imageHash, proposal }: Props): React.Re return ( - {t('preimage {{hash}}', { replace: { hash: `${textHash.slice(0, 8)}…${textHash.slice(-8)}` } })} +
{textHash.slice(0, 8)}…{textHash.slice(-8)}
); } @@ -65,4 +66,12 @@ function ProposalCell ({ className = '', imageHash, proposal }: Props): React.Re ); } -export default React.memo(ProposalCell); +export default React.memo(styled(ProposalCell)` + .shortHash { + font: var(--font-mono); + + + div { + margin-left: 0.5rem; + } + } +`); diff --git a/packages/page-democracy/src/Overview/Proposals.tsx b/packages/page-democracy/src/Overview/Proposals.tsx index f76496bfe5..2fbe31ece0 100644 --- a/packages/page-democracy/src/Overview/Proposals.tsx +++ b/packages/page-democracy/src/Overview/Proposals.tsx @@ -24,8 +24,7 @@ function Proposals ({ className }: Props): React.ReactElement { [t('proposals'), 'start', 2], [t('proposer'), 'address'], [t('locked'), 'media--1200'], - [undefined, undefined, 2], - [undefined, 'media--1000'] + [undefined, undefined, 2] ]); return ( @@ -33,6 +32,7 @@ function Proposals ({ className }: Props): React.ReactElement { className={className} empty={proposals && t('No active proposals')} header={headerRef.current} + withCollapsibleRows > {proposals?.map((proposal): React.ReactNode => ( (api.query.balances?.totalIssuance); const { changeAye, changeNay } = useChangeCalc(status.threshold, votedAye, votedNay, votedTotal); const threshold = useMemo( @@ -89,88 +90,105 @@ function Referendum ({ className = '', value: { allAye, allNay, image, imageHash const remainBlock = status.end.sub(bestNumber).isub(BN_ONE); return ( - -

{formatNumber(index)}

- - - - {t('{{blocks}} blocks', { replace: { blocks: formatNumber(remainBlock) } })} - - - - #{formatNumber(enactBlock)} - - - {percentages && ( - <> -
{percentages.turnout}
- - )} - - - {isBoolean(isPassing) && ( - ('{{threshold}}, passing', { replace: { threshold } }) - : t('{{threshold}}, not passing', { replace: { threshold } }) - } - icon={isPassing ? 'check' : 'times'} - /> - )} - - - + +

{formatNumber(index)}

+ - - - - - - - - {!image?.proposal && ( - + + + {t('{{blocks}} blocks', { replace: { blocks: formatNumber(remainBlock) } })} + + + + #{formatNumber(enactBlock)} + + + {percentages && ( + <> +
{percentages.turnout}
+ )} - + + {isBoolean(isPassing) && ( + ('{{threshold}}, passing', { replace: { threshold } }) + : t('{{threshold}}, not passing', { replace: { threshold } }) + } + icon={isPassing ? 'check' : 'times'} + /> + )} + + + -
- - - - - - - - + + + + + + + + + + + {!image?.proposal && ( + + )} + + + + + + + + + + + + + + + + ); } diff --git a/packages/page-democracy/src/Overview/Referendums.tsx b/packages/page-democracy/src/Overview/Referendums.tsx index 3deaeb4c53..7e96a1790f 100644 --- a/packages/page-democracy/src/Overview/Referendums.tsx +++ b/packages/page-democracy/src/Overview/Referendums.tsx @@ -26,8 +26,7 @@ function Referendums ({ className = '', referendums }: Props): React.ReactElemen [undefined, 'badge'], [t('votes'), 'expand'], [t('support'), 'media--1000'], - [undefined, undefined, 2], - [undefined, 'media--1000'] + [undefined, undefined, 2] ]); return ( @@ -35,6 +34,7 @@ function Referendums ({ className = '', referendums }: Props): React.ReactElemen className={className} empty={referendums && t('No active referendums')} header={headerRef.current} + withCollapsibleRows > {referendums?.map((referendum): React.ReactNode => ( !!node); } -function LinkExternal ({ className = '', data, hash, isMain, isSidebar, isSmall, isText, type }: Props): React.ReactElement | null { +function LinkExternal ({ className = '', data, hash, isSidebar, isSmall, isText, type, withTitle }: Props): React.ReactElement | null { const { t } = useTranslation(); const { systemChain } = useApi(); const links = useMemo( @@ -69,17 +69,22 @@ function LinkExternal ({ className = '', data, hash, isMain, isSidebar, isSmall, [systemChain, data, hash, isSidebar, isText, type] ); - if (!links.length) { + if (!links.length && !withTitle) { return null; } return ( -
+
{(isText && !isSmall) &&
{t('View this externally')}
} - {isMain && ( + {withTitle && (
{t('external links')}
)} -
{links.map((link, index) => {link})}
+
+ {links.length + ? links.map((link, index) => {link}) + : + } +
); } diff --git a/packages/react-components/src/Table/index.tsx b/packages/react-components/src/Table/index.tsx index 861f340e4d..3083af973c 100644 --- a/packages/react-components/src/Table/index.tsx +++ b/packages/react-components/src/Table/index.tsx @@ -315,6 +315,15 @@ export default React.memo(styled(Table)` vertical-align: top; } + &.columar { + vertical-align: top; + + .ui--Columar .ui--Column { + margin: 1rem 0 0.75rem 0; + padding: 0; + } + } + &.middle { text-align: center; } diff --git a/packages/react-components/src/Tags.tsx b/packages/react-components/src/Tags.tsx index b4eeb6cd72..424014fab2 100644 --- a/packages/react-components/src/Tags.tsx +++ b/packages/react-components/src/Tags.tsx @@ -33,7 +33,7 @@ function Tags ({ children, className = '', isEditable, isEditing, onChange, onSa label={tag} /> )) - : , + : , [t, value] );