From 86e122389c8bdddc485d372332d713495e3abf94 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Wed, 16 Aug 2023 16:53:32 +0100 Subject: [PATCH] fix(governance): proposal vote status header component (#4561) --- .../proposal-header.spec.tsx | 31 +++++++++++++------ .../proposal-header.tsx | 5 +-- .../components/proposal/proposal.spec.tsx | 16 +++++++--- .../components/proposal/proposal.tsx | 10 ++++++ .../proposals-list-item.tsx | 8 ++++- .../components/vote-details/vote-buttons.tsx | 6 +--- .../components/vote-details/vote-details.tsx | 19 +++++++++--- 7 files changed, 68 insertions(+), 27 deletions(-) diff --git a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.spec.tsx b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.spec.tsx index f4a39187f..be59889e9 100644 --- a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.spec.tsx +++ b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.spec.tsx @@ -24,6 +24,7 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { MockedResponse } from '@apollo/client/testing'; import { FLAGS } from '@vegaprotocol/environment'; import { BrowserRouter } from 'react-router-dom'; +import { VoteState } from '../vote-details/use-user-vote'; jest.mock('@vegaprotocol/proposals', () => ({ ...jest.requireActual('@vegaprotocol/proposals'), @@ -36,7 +37,8 @@ jest.mock('@vegaprotocol/proposals', () => ({ const renderComponent = ( proposal: ProposalQuery['proposal'], isListItem = true, - mocks: MockedResponse[] = [] + mocks: MockedResponse[] = [], + voteState?: VoteState ) => render( @@ -47,6 +49,7 @@ const renderComponent = ( proposal={proposal} isListItem={isListItem} networkParams={mockNetworkParams} + voteState={voteState} /> @@ -386,10 +389,15 @@ describe('Proposal header', () => { closingDatetime: nextWeek.toString(), }, }); - renderComponent(proposal, true, [ - // @ts-ignore generateProposal always creates an id - createUserVoteQueryMock(proposal.id, VoteValue.VALUE_NO), - ]); + renderComponent( + proposal, + true, + [ + // @ts-ignore generateProposal always creates an id + createUserVoteQueryMock(proposal.id, VoteValue.VALUE_NO), + ], + VoteState.No + ); expect(await screen.findByTestId('user-voted-no')).toBeInTheDocument(); }); @@ -400,10 +408,15 @@ describe('Proposal header', () => { closingDatetime: nextWeek.toString(), }, }); - renderComponent(proposal, true, [ - // @ts-ignore generateProposal always creates an id - createUserVoteQueryMock(proposal.id, VoteValue.VALUE_YES), - ]); + renderComponent( + proposal, + true, + [ + // @ts-ignore generateProposal always creates an id + createUserVoteQueryMock(proposal.id, VoteValue.VALUE_YES), + ], + VoteState.Yes + ); expect(await screen.findByTestId('user-voted-yes')).toBeInTheDocument(); }); }); diff --git a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx index f07919749..8507212e5 100644 --- a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx +++ b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx @@ -8,25 +8,26 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import { truncateMiddle } from '../../../../lib/truncate-middle'; import { CurrentProposalState } from '../current-proposal-state'; import { ProposalInfoLabel } from '../proposal-info-label'; -import { useUserVote } from '../vote-details/use-user-vote'; import { ProposalVotingStatus } from '../proposal-voting-status'; import type { NetworkParamsResult } from '@vegaprotocol/network-parameters'; import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals'; import { FLAGS } from '@vegaprotocol/environment'; import Routes from '../../../routes'; import { Link } from 'react-router-dom'; +import type { VoteState } from '../vote-details/use-user-vote'; export const ProposalHeader = ({ proposal, networkParams, isListItem = true, + voteState, }: { proposal: ProposalFieldsFragment | ProposalQuery['proposal']; networkParams: Partial; isListItem?: boolean; + voteState?: VoteState | null; }) => { const { t } = useTranslation(); - const { voteState } = useUserVote(proposal?.id); const change = proposal?.terms.change; let details: ReactNode; diff --git a/apps/governance/src/routes/proposals/components/proposal/proposal.spec.tsx b/apps/governance/src/routes/proposals/components/proposal/proposal.spec.tsx index c334ee137..4d664b043 100644 --- a/apps/governance/src/routes/proposals/components/proposal/proposal.spec.tsx +++ b/apps/governance/src/routes/proposals/components/proposal/proposal.spec.tsx @@ -1,4 +1,6 @@ import { MemoryRouter } from 'react-router-dom'; +import { MockedProvider } from '@apollo/client/testing'; +import { VegaWalletProvider } from '@vegaprotocol/wallet'; import { render, screen } from '@testing-library/react'; import { generateProposal } from '../../test-helpers/generate-proposals'; import { Proposal } from './proposal'; @@ -44,11 +46,15 @@ jest.mock('../list-asset', () => ({ const renderComponent = (proposal: ProposalQuery['proposal']) => { render( - + + + + + ); }; diff --git a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx index 6a93c3167..076ac0fd5 100644 --- a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx +++ b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx @@ -19,6 +19,8 @@ import { removePaginationWrapper } from '@vegaprotocol/utils'; import { ProposalState } from '@vegaprotocol/types'; import { ProposalMarketChanges } from '../proposal-market-changes'; import type { NetworkParamsResult } from '@vegaprotocol/network-parameters'; +import { useVoteSubmit } from '@vegaprotocol/proposals'; +import { useUserVote } from '../vote-details/use-user-vote'; export enum ProposalType { PROPOSAL_NEW_MARKET = 'PROPOSAL_NEW_MARKET', @@ -53,6 +55,8 @@ export const Proposal = ({ mostRecentlyEnactedAssociatedMarketProposal, }: ProposalProps) => { const { t } = useTranslation(); + const { submit, Dialog, finalizedVote } = useVoteSubmit(); + const { voteState, voteDatetime } = useUserVote(proposal?.id, finalizedVote); if (!proposal) { return null; @@ -132,10 +136,12 @@ export const Proposal = ({ )} +
@@ -207,6 +213,10 @@ export const Proposal = ({ spamProtectionMinTokens={ networkParams?.spam_protection_voting_min_tokens } + submit={submit} + dialog={Dialog} + voteState={voteState} + voteDatetime={voteDatetime} />
diff --git a/apps/governance/src/routes/proposals/components/proposals-list-item/proposals-list-item.tsx b/apps/governance/src/routes/proposals/components/proposals-list-item/proposals-list-item.tsx index 49de00fea..ba9664323 100644 --- a/apps/governance/src/routes/proposals/components/proposals-list-item/proposals-list-item.tsx +++ b/apps/governance/src/routes/proposals/components/proposals-list-item/proposals-list-item.tsx @@ -1,6 +1,7 @@ import { RoundedWrapper } from '@vegaprotocol/ui-toolkit'; import { ProposalHeader } from '../proposal-detail-header/proposal-header'; import { ProposalsListItemDetails } from './proposals-list-item-details'; +import { useUserVote } from '../vote-details/use-user-vote'; import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { NetworkParamsResult } from '@vegaprotocol/network-parameters'; @@ -14,12 +15,17 @@ export const ProposalsListItem = ({ proposal, networkParams, }: ProposalsListItemProps) => { + const { voteState } = useUserVote(proposal?.id); if (!proposal || !proposal.id || !networkParams) return null; return (
  • - +
  • diff --git a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx index 6b5ad3016..919c6b423 100644 --- a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx +++ b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx @@ -188,11 +188,7 @@ export const VoteButtons = ({ (voteState === VoteState.Yes || voteState === VoteState.No) && (

    {t('youVoted')}:{' '} - + {t(`voteState_${voteState}`)} {' '} {voteDatetime ? ( diff --git a/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx b/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx index 2e3b3b533..db36adfce 100644 --- a/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx +++ b/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx @@ -3,23 +3,29 @@ import { formatDistanceToNow } from 'date-fns'; import { RoundedWrapper, Icon, ExternalLink } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { ProposalState } from '@vegaprotocol/types'; -import { useVoteSubmit, VoteProgress } from '@vegaprotocol/proposals'; +import { VoteProgress } from '@vegaprotocol/proposals'; import { formatNumber } from '../../../../lib/format-number'; import { ConnectToVega } from '../../../../components/connect-to-vega'; import { useVoteInformation } from '../../hooks'; -import { useUserVote } from './use-user-vote'; import { CurrentProposalStatus } from '../current-proposal-status'; import { VoteButtonsContainer } from './vote-buttons'; import { SubHeading } from '../../../../components/heading'; import { ProposalType } from '../proposal/proposal'; +import type { VoteValue } from '@vegaprotocol/types'; +import type { DialogProps } from '@vegaprotocol/wallet'; import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; +import type { VoteState } from './use-user-vote'; interface VoteDetailsProps { proposal: ProposalFieldsFragment | ProposalQuery['proposal']; minVoterBalance: string | null | undefined; spamProtectionMinTokens: string | null | undefined; proposalType: ProposalType | null; + submit: (voteValue: VoteValue, proposalId: string | null) => Promise; + dialog: (props: DialogProps) => JSX.Element; + voteState: VoteState | null; + voteDatetime: Date | null; } export const VoteDetails = ({ @@ -27,6 +33,10 @@ export const VoteDetails = ({ minVoterBalance, spamProtectionMinTokens, proposalType, + submit, + dialog, + voteState, + voteDatetime, }: VoteDetailsProps) => { const { pubKey } = useVegaWallet(); const { @@ -48,8 +58,7 @@ export const VoteDetails = ({ } = useVoteInformation({ proposal }); const { t } = useTranslation(); - const { submit, Dialog, finalizedVote } = useVoteSubmit(); - const { voteState, voteDatetime } = useUserVote(proposal?.id, finalizedVote); + const defaultDecimals = 2; const daysLeft = t('daysLeft', { daysLeft: formatDistanceToNow(new Date(proposal?.terms.closingDatetime)), @@ -219,7 +228,7 @@ export const VoteDetails = ({ spamProtectionMinTokens={spamProtectionMinTokens} className="flex" submit={submit} - dialog={Dialog} + dialog={dialog} /> ) ) : (