Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Commit

Permalink
Bounties - list layout improvements (polkadot-js#4644)
Browse files Browse the repository at this point in the history
  • Loading branch information
ekowalsk authored Feb 11, 2021
1 parent a180bbc commit a580ac4
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 176 deletions.
1 change: 1 addition & 0 deletions packages/apps/public/locales/en/app-bounties.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"Title too long": "Title too long",
"Unassign curator": "Unassign curator",
"Unassign curator under voting": "Unassign curator under voting",
"Update overdue": "Update overdue",
"Voting": "Voting",
"Voting results": "Voting results",
"Waiting for Bounty Funding": "Waiting for Bounty Funding",
Expand Down
52 changes: 32 additions & 20 deletions packages/page-bounties/src/Bounties.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { keyring } from '@polkadot/ui-keyring';

import { defaultBountyUpdatePeriod, mockBountyHooks } from '../test/hooks/defaults';
import { BountiesPage } from '../test/pages/bountiesPage';
import { BLOCKS_PERCENTAGE_LEFT_TO_SHOW_WARNING } from './BountyInfos';
import { BLOCKS_PERCENTAGE_LEFT_TO_SHOW_WARNING } from './BountyNextActionInfo/BountyActionMessage';

jest.mock('@polkadot/react-hooks/useTreasury', () => ({
useTreasury: () => mockHooks.treasury
Expand Down Expand Up @@ -100,7 +100,7 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty, proposals);

await bountiesPage.expectText('Curator proposal under voting');
await bountiesPage.expectVotingDescription('Curator proposal under voting');
});

it('when voting on bounty approval', async () => {
Expand All @@ -109,7 +109,7 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty, proposals);

await bountiesPage.expectText('Bounty approval under voting');
await bountiesPage.expectVotingDescription('Bounty approval under voting');
});

it('when simultaneous close and approve motions exist, show approved', async () => {
Expand All @@ -121,7 +121,7 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty, proposals);

await bountiesPage.expectText('Bounty approval under voting');
await bountiesPage.expectVotingDescription('Bounty approval under voting');
});

it('when voting on close bounty', async () => {
Expand All @@ -130,7 +130,7 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty, proposals);

await bountiesPage.expectText('Bounty rejection under voting');
await bountiesPage.expectVotingDescription('Bounty rejection under voting');
});

it('when voting on unassign curator', async () => {
Expand All @@ -139,7 +139,7 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty, proposals);

await bountiesPage.expectText('Curator slash under voting');
await bountiesPage.expectVotingDescription('Curator slash under voting');
});

it('when a motion exists that would fail on execution, show nothing', async () => {
Expand All @@ -148,14 +148,7 @@ describe('Bounties', () => {

const { findByTestId } = bountiesPage.renderOne(bounty, proposals);

await expect(findByTestId('extendedVotingStatus')).rejects.toThrow();
});

it('when bounty is claimable', async () => {
const bounty = bountyWith({ status: 'PendingPayout' });
const { findByTestId } = bountiesPage.renderOne(bounty);

expect((await findByTestId('extendedActionStatus')).textContent).toEqual('Claimable');
await expect(findByTestId('voting-description')).rejects.toThrow();
});
});

Expand Down Expand Up @@ -215,7 +208,7 @@ describe('Bounties', () => {

const { findByTestId } = bountiesPage.renderOne(bounty, proposals);

expect((await findByTestId('voting-summary')).textContent).toEqual('Aye 2/4Nay 0/0Voting results');
expect((await findByTestId('voting-summary')).textContent).toEqual('Aye 2/4Nay 0/0Voting');
});

it('is not displayed when not voting', async () => {
Expand Down Expand Up @@ -457,16 +450,28 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty);

await bountiesPage.expectText('Warning');
await bountiesPage.expectText('Close deadline');
});

it('warning when update time is overdue', async () => {
const bounty = aBounty({ status: bountyStatusWith(
{
curator: alice,
status: 'Active',
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
updateDue: mockBountyHooks.bountyApi.bestNumber!.toNumber()
}) });

bountiesPage.renderOne(bounty);

await bountiesPage.expectText('Update overdue');
});

it('info when waiting for bounty funding', async () => {
const bounty = bountyWith({ status: 'Approved' });

bountiesPage.renderOne(bounty);

await bountiesPage.expectText('Info');
await bountiesPage.expectText('Waiting for Bounty Funding');
});

Expand All @@ -475,10 +480,17 @@ describe('Bounties', () => {

bountiesPage.renderOne(bounty);

await bountiesPage.expectText('Info');
await bountiesPage.expectText('Waiting for Curator\'s acceptance');
});

it('info when bounty is claimable', async () => {
const bounty = bountyWith({ status: 'PendingPayout' });

bountiesPage.renderOne(bounty);

await bountiesPage.expectText('Waiting for implementer to claim');
});

it('no warning or info when requirements are not met', async () => {
const bounty = aBounty({ status: bountyStatusWith({
curator: alice,
Expand All @@ -489,11 +501,11 @@ describe('Bounties', () => {
bountiesPage.renderOne(bounty);
await bountiesPage.rendered();

bountiesPage.expectTextAbsent('Warning');
bountiesPage.expectTextAbsent('Close deadline');
bountiesPage.expectTextAbsent('Info');
bountiesPage.expectTextAbsent('Update overdue');
bountiesPage.expectTextAbsent('Waiting for Bounty Funding');
bountiesPage.expectTextAbsent("Waiting for Curator's acceptance");
bountiesPage.expectTextAbsent('Waiting for implementer to claim');
});
});
});
35 changes: 22 additions & 13 deletions packages/page-bounties/src/Bounty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { ThemeProps } from '@polkadot/react-components/types';
import { BlockToTime, FormatBalance } from '@polkadot/react-query';
import { formatNumber } from '@polkadot/util';

import BountyActionMessage from './BountyNextActionInfo/BountyActionMessage';
import { getProposalToDisplay } from './helpers/extendedStatuses';
import VotersColumn from './Voting/VotersColumn';
import { BountyActions } from './BountyActions';
import BountyExtraActions from './BountyExtraActions';
import BountyInfos from './BountyInfos';
Expand All @@ -23,6 +23,7 @@ import Curator from './Curator';
import { useBountyStatus } from './hooks';
import { bountyBorderColor, bountyLabelColor } from './theme';
import { useTranslation } from './translate';
import VotersColumn from './VotersColumn';

interface Props {
bestNumber: BlockNumber;
Expand Down Expand Up @@ -71,12 +72,7 @@ function Bounty ({ bestNumber, bounty, className = '', description, index, propo
<>
<tr className={className}>
<td>
<BountyStatusView
blocksUntilPayout={blocksUntilPayout}
bountyStatus={bountyStatus}
proposals={proposals}
status={status}
/>
<BountyStatusView bountyStatus={bountyStatus}/>
</td>
<td
className='description-column'
Expand Down Expand Up @@ -109,12 +105,16 @@ function Bounty ({ bestNumber, bounty, className = '', description, index, propo
until={'update'}
/>
: ''}
<BountyActionMessage
bestNumber={bestNumber}
blocksUntilUpdate={blocksUntilUpdate}
status={status}
/>
</td>
<td>
<td className='td-info-action-row'>
<div className='td-row'>
<BountyInfos
beneficiary={beneficiary}
blocksUntilUpdate={blocksUntilUpdate}
proposals={proposals}
status={status}
/>
Expand Down Expand Up @@ -240,7 +240,10 @@ export default React.memo(styled(Bounty)(({ theme }: ThemeProps) => `
display: inline-flex;
}
& .fast-actions {
& td.fast-actions {
padding-left: 0.2rem;
width: 1%;
.fast-actions-row {
display: flex;
align-items: center;
Expand Down Expand Up @@ -296,27 +299,33 @@ export default React.memo(styled(Bounty)(({ theme }: ThemeProps) => `
padding: 0 0 1.3rem;
}
& .td-info-action-row {
padding-right: 0;
}
.td-row {
display: flex;
justify-content: space-between;
align-items: center;
& :only-child {
margin-left: auto;
}
}
.bounty-action-row {
display: flex;
justify-content: flex-end;
align-items: center;
margin-left: auto;
& > * + * {
margin-left: 0.6rem;
}
}
.block-to-time {
margin-top: 0.28rem;
font-size: 0.7rem;
line-height: 0.85rem;
line-height: 1.5rem;
color: ${bountyLabelColor[theme.theme]};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@
import type { DeriveCollectiveProposal } from '@polkadot/api-derive/types';
import type { BountyStatus } from '@polkadot/types/interfaces';

import BN from 'bn.js';
import React, { useRef } from 'react';
import styled from 'styled-components';

import { BN_ZERO } from '@polkadot/util';
import { LabelHelp } from '@polkadot/react-components';

import Description from '../Description';
import { proposalNameToDisplay } from '../helpers/extendedStatuses';
import { useTranslation } from '../translate';

interface Props {
blocksUntilPayout?: BN ;
className?: string;
proposals?: DeriveCollectiveProposal[];
proposal: DeriveCollectiveProposal;
status: BountyStatus;
}

function ExtendedStatus ({ blocksUntilPayout, className = '', proposals, status }: Props): React.ReactElement<Props> {
const bestProposalName = proposals ? proposalNameToDisplay(proposals, status) : null;
function VotingDescriptionInfo ({ className, proposal, status }: Props): React.ReactElement<Props> {
const bestProposalName = proposalNameToDisplay(proposal, status);
const { t } = useTranslation();
const votingDescriptions = useRef<Record<string, string>>({
approveBounty: t('Bounty approval under voting'),
Expand All @@ -32,23 +30,17 @@ function ExtendedStatus ({ blocksUntilPayout, className = '', proposals, status
});

return (
<>
<div
className={className}
data-testid='voting-description'
>
{bestProposalName && votingDescriptions.current[bestProposalName] &&
<Description
className={className}
dataTestId='extendedVotingStatus'
description={votingDescriptions.current[bestProposalName]}
/>
<LabelHelp help={votingDescriptions.current[bestProposalName]}/>
}
{blocksUntilPayout?.lt(BN_ZERO) &&
<Description
className={className}
dataTestId='extendedActionStatus'
description={t<string>('Claimable')}
/>
}
</>
</div>
);
}

export default React.memo(ExtendedStatus);
export default React.memo(styled(VotingDescriptionInfo)`
margin-left: 0.2rem;
`);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import React from 'react';
import styled from 'styled-components';

import Description from '../Description';
import { useTranslation } from '../translate';

interface Props {
Expand All @@ -15,13 +14,15 @@ function VotingLink ({ className }: Props): React.ReactElement<Props> {
const { t } = useTranslation();

return (
<div className={className}>
<a href='#/council/motions'>{t<string>('Voting')}</a>
<Description description={t<string>('Go to motions panel')} />
</div>
<a className={className}
href='#/council/motions'>
{t<string>('Voting')}
</a>
);
}

export default React.memo(styled(VotingLink)`
margin: 0 1rem 0 0
line-height: 0.85rem;
font-size: 0.7rem;
text-decoration: underline;
`);
Loading

0 comments on commit a580ac4

Please sign in to comment.