fix(governance): proposal vote status header component (#4561)
This commit is contained in:
parent
6616aceebb
commit
86e122389c
@ -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(
|
||||
<AppStateProvider>
|
||||
@ -47,6 +49,7 @@ const renderComponent = (
|
||||
proposal={proposal}
|
||||
isListItem={isListItem}
|
||||
networkParams={mockNetworkParams}
|
||||
voteState={voteState}
|
||||
/>
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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<NetworkParamsResult>;
|
||||
isListItem?: boolean;
|
||||
voteState?: VoteState | null;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { voteState } = useUserVote(proposal?.id);
|
||||
const change = proposal?.terms.change;
|
||||
|
||||
let details: ReactNode;
|
||||
|
@ -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(
|
||||
<MemoryRouter>
|
||||
<Proposal
|
||||
restData={{}}
|
||||
proposal={proposal as ProposalQuery['proposal']}
|
||||
networkParams={mockNetworkParams}
|
||||
/>
|
||||
<MockedProvider>
|
||||
<VegaWalletProvider>
|
||||
<Proposal
|
||||
restData={{}}
|
||||
proposal={proposal as ProposalQuery['proposal']}
|
||||
networkParams={mockNetworkParams}
|
||||
/>
|
||||
</VegaWalletProvider>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
|
@ -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 = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ProposalHeader
|
||||
proposal={proposal}
|
||||
isListItem={false}
|
||||
networkParams={networkParams}
|
||||
voteState={voteState}
|
||||
/>
|
||||
|
||||
<div id="details">
|
||||
@ -207,6 +213,10 @@ export const Proposal = ({
|
||||
spamProtectionMinTokens={
|
||||
networkParams?.spam_protection_voting_min_tokens
|
||||
}
|
||||
submit={submit}
|
||||
dialog={Dialog}
|
||||
voteState={voteState}
|
||||
voteDatetime={voteDatetime}
|
||||
/>
|
||||
</RoundedWrapper>
|
||||
</div>
|
||||
|
@ -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 (
|
||||
<li id={proposal.id} data-testid="proposals-list-item">
|
||||
<RoundedWrapper paddingBottom={true} heightFull={true}>
|
||||
<ProposalHeader proposal={proposal} networkParams={networkParams} />
|
||||
<ProposalHeader
|
||||
proposal={proposal}
|
||||
networkParams={networkParams}
|
||||
voteState={voteState}
|
||||
/>
|
||||
<ProposalsListItemDetails proposal={proposal} />
|
||||
</RoundedWrapper>
|
||||
</li>
|
||||
|
@ -188,11 +188,7 @@ export const VoteButtons = ({
|
||||
(voteState === VoteState.Yes || voteState === VoteState.No) && (
|
||||
<p data-testid="you-voted">
|
||||
<span>{t('youVoted')}:</span>{' '}
|
||||
<span
|
||||
className={
|
||||
voteState === VoteState.Yes ? 'text-success' : 'text-danger'
|
||||
}
|
||||
>
|
||||
<span className="text-white font-bold">
|
||||
{t(`voteState_${voteState}`)}
|
||||
</span>{' '}
|
||||
{voteDatetime ? (
|
||||
|
@ -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<void>;
|
||||
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}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user