chore: proposal schema change (1057) (#1169)

* chore: moved proposal queries to lib/governance

* chore: used new rationale title and description

* chore: addressed PR comments, refactored

* chore: moved proposal queries to lib/governance

* chore: used new rationale title and description

* chore: addressed PR comments, refactored

* fix: dropped s after merge

* fix: fixed lodash imports
This commit is contained in:
Art 2022-09-07 18:35:29 +02:00 committed by GitHub
parent 9de3683bf3
commit d2791f2e59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 610 additions and 466 deletions

View File

@ -9,7 +9,23 @@ import { ProposalState, ProposalRejectionReason, VoteValue } from "@vegaprotocol
// GraphQL query operation: ProposalsQuery // GraphQL query operation: ProposalsQuery
// ==================================================== // ====================================================
export interface ProposalsQuery_proposals_party { export interface ProposalsQuery_proposalsConnection_edges_node_rationale {
__typename: "ProposalRationale";
/**
* Title to be used to give a short description of the proposal in lists.
* This is to be between 0 and 100 unicode characters.
* This is mandatory for all proposals.
*/
title: string;
/**
* Description to show a short title / something in case the link goes offline.
* This is to be between 0 and 20k unicode characters.
* This is mandatory for all proposals.
*/
description: string;
}
export interface ProposalsQuery_proposalsConnection_edges_node_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -17,11 +33,11 @@ export interface ProposalsQuery_proposals_party {
id: string; id: string;
} }
export interface ProposalsQuery_proposals_terms_change_UpdateAsset { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateAsset {
__typename: "UpdateAsset" | "NewFreeform"; __typename: "UpdateAsset" | "NewFreeform";
} }
export interface ProposalsQuery_proposals_terms_change_NewMarket_instrument { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_NewMarket_instrument {
__typename: "InstrumentConfiguration"; __typename: "InstrumentConfiguration";
/** /**
* Full and fairly descriptive name for the instrument * Full and fairly descriptive name for the instrument
@ -29,20 +45,20 @@ export interface ProposalsQuery_proposals_terms_change_NewMarket_instrument {
name: string; name: string;
} }
export interface ProposalsQuery_proposals_terms_change_NewMarket { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_NewMarket {
__typename: "NewMarket"; __typename: "NewMarket";
/** /**
* New market instrument configuration * New market instrument configuration
*/ */
instrument: ProposalsQuery_proposals_terms_change_NewMarket_instrument; instrument: ProposalsQuery_proposalsConnection_edges_node_terms_change_NewMarket_instrument;
} }
export interface ProposalsQuery_proposals_terms_change_UpdateMarket { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateMarket {
__typename: "UpdateMarket"; __typename: "UpdateMarket";
marketId: string; marketId: string;
} }
export interface ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source_BuiltinAsset {
__typename: "BuiltinAsset"; __typename: "BuiltinAsset";
/** /**
* Maximum amount that can be requested by a party through the built-in asset faucet at a time * Maximum amount that can be requested by a party through the built-in asset faucet at a time
@ -50,7 +66,7 @@ export interface ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAs
maxFaucetAmountMint: string; maxFaucetAmountMint: string;
} }
export interface ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20 { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source_ERC20 {
__typename: "ERC20"; __typename: "ERC20";
/** /**
* The address of the ERC20 contract * The address of the ERC20 contract
@ -58,9 +74,9 @@ export interface ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20 {
contractAddress: string; contractAddress: string;
} }
export type ProposalsQuery_proposals_terms_change_NewAsset_source = ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset | ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20; export type ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source = ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source_BuiltinAsset | ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source_ERC20;
export interface ProposalsQuery_proposals_terms_change_NewAsset { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset {
__typename: "NewAsset"; __typename: "NewAsset";
/** /**
* The symbol of the asset (e.g: GBP) * The symbol of the asset (e.g: GBP)
@ -69,10 +85,10 @@ export interface ProposalsQuery_proposals_terms_change_NewAsset {
/** /**
* The source of the new asset * The source of the new asset
*/ */
source: ProposalsQuery_proposals_terms_change_NewAsset_source; source: ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset_source;
} }
export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter_networkParameter {
__typename: "NetworkParameter"; __typename: "NetworkParameter";
/** /**
* The name of the network parameter * The name of the network parameter
@ -84,14 +100,14 @@ export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_ne
value: string; value: string;
} }
export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter { export interface ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter {
__typename: "UpdateNetworkParameter"; __typename: "UpdateNetworkParameter";
networkParameter: ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter; networkParameter: ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter_networkParameter;
} }
export type ProposalsQuery_proposals_terms_change = ProposalsQuery_proposals_terms_change_UpdateAsset | ProposalsQuery_proposals_terms_change_NewMarket | ProposalsQuery_proposals_terms_change_UpdateMarket | ProposalsQuery_proposals_terms_change_NewAsset | ProposalsQuery_proposals_terms_change_UpdateNetworkParameter; export type ProposalsQuery_proposalsConnection_edges_node_terms_change = ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateAsset | ProposalsQuery_proposalsConnection_edges_node_terms_change_NewMarket | ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateMarket | ProposalsQuery_proposalsConnection_edges_node_terms_change_NewAsset | ProposalsQuery_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter;
export interface ProposalsQuery_proposals_terms { export interface ProposalsQuery_proposalsConnection_edges_node_terms {
__typename: "ProposalTerms"; __typename: "ProposalTerms";
/** /**
* RFC3339Nano time and date when voting closes for this proposal. * RFC3339Nano time and date when voting closes for this proposal.
@ -107,18 +123,18 @@ export interface ProposalsQuery_proposals_terms {
/** /**
* Actual change being introduced by the proposal - action the proposal triggers if passed and enacted. * Actual change being introduced by the proposal - action the proposal triggers if passed and enacted.
*/ */
change: ProposalsQuery_proposals_terms_change; change: ProposalsQuery_proposalsConnection_edges_node_terms_change;
} }
export interface ProposalsQuery_proposals_votes_yes_votes_party_stake { export interface ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
currentStakeAvailable: string; currentStakeAvailable: string;
} }
export interface ProposalsQuery_proposals_votes_yes_votes_party { export interface ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -127,10 +143,10 @@ export interface ProposalsQuery_proposals_votes_yes_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: ProposalsQuery_proposals_votes_yes_votes_party_stake; stakingSummary: ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes_party_stakingSummary;
} }
export interface ProposalsQuery_proposals_votes_yes_votes { export interface ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes {
__typename: "Vote"; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
@ -139,14 +155,14 @@ export interface ProposalsQuery_proposals_votes_yes_votes {
/** /**
* The party casting the vote * The party casting the vote
*/ */
party: ProposalsQuery_proposals_votes_yes_votes_party; party: ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes_party;
/** /**
* RFC3339Nano time and date when the vote reached Vega network * RFC3339Nano time and date when the vote reached Vega network
*/ */
datetime: string; datetime: string;
} }
export interface ProposalsQuery_proposals_votes_yes { export interface ProposalsQuery_proposalsConnection_edges_node_votes_yes {
__typename: "ProposalVoteSide"; __typename: "ProposalVoteSide";
/** /**
* Total number of governance tokens from the votes cast for this side * Total number of governance tokens from the votes cast for this side
@ -159,18 +175,18 @@ export interface ProposalsQuery_proposals_votes_yes {
/** /**
* All votes cast for this side * All votes cast for this side
*/ */
votes: ProposalsQuery_proposals_votes_yes_votes[] | null; votes: ProposalsQuery_proposalsConnection_edges_node_votes_yes_votes[] | null;
} }
export interface ProposalsQuery_proposals_votes_no_votes_party_stake { export interface ProposalsQuery_proposalsConnection_edges_node_votes_no_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
currentStakeAvailable: string; currentStakeAvailable: string;
} }
export interface ProposalsQuery_proposals_votes_no_votes_party { export interface ProposalsQuery_proposalsConnection_edges_node_votes_no_votes_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -179,10 +195,10 @@ export interface ProposalsQuery_proposals_votes_no_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: ProposalsQuery_proposals_votes_no_votes_party_stake; stakingSummary: ProposalsQuery_proposalsConnection_edges_node_votes_no_votes_party_stakingSummary;
} }
export interface ProposalsQuery_proposals_votes_no_votes { export interface ProposalsQuery_proposalsConnection_edges_node_votes_no_votes {
__typename: "Vote"; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
@ -191,14 +207,14 @@ export interface ProposalsQuery_proposals_votes_no_votes {
/** /**
* The party casting the vote * The party casting the vote
*/ */
party: ProposalsQuery_proposals_votes_no_votes_party; party: ProposalsQuery_proposalsConnection_edges_node_votes_no_votes_party;
/** /**
* RFC3339Nano time and date when the vote reached Vega network * RFC3339Nano time and date when the vote reached Vega network
*/ */
datetime: string; datetime: string;
} }
export interface ProposalsQuery_proposals_votes_no { export interface ProposalsQuery_proposalsConnection_edges_node_votes_no {
__typename: "ProposalVoteSide"; __typename: "ProposalVoteSide";
/** /**
* Total number of governance tokens from the votes cast for this side * Total number of governance tokens from the votes cast for this side
@ -211,27 +227,31 @@ export interface ProposalsQuery_proposals_votes_no {
/** /**
* All votes cast for this side * All votes cast for this side
*/ */
votes: ProposalsQuery_proposals_votes_no_votes[] | null; votes: ProposalsQuery_proposalsConnection_edges_node_votes_no_votes[] | null;
} }
export interface ProposalsQuery_proposals_votes { export interface ProposalsQuery_proposalsConnection_edges_node_votes {
__typename: "ProposalVotes"; __typename: "ProposalVotes";
/** /**
* Yes votes cast for this proposal * Yes votes cast for this proposal
*/ */
yes: ProposalsQuery_proposals_votes_yes; yes: ProposalsQuery_proposalsConnection_edges_node_votes_yes;
/** /**
* No votes cast for this proposal * No votes cast for this proposal
*/ */
no: ProposalsQuery_proposals_votes_no; no: ProposalsQuery_proposalsConnection_edges_node_votes_no;
} }
export interface ProposalsQuery_proposals { export interface ProposalsQuery_proposalsConnection_edges_node {
__typename: "Proposal"; __typename: "Proposal";
/** /**
* Proposal ID that is filled by Vega once proposal reaches the network * Proposal ID that is filled by Vega once proposal reaches the network
*/ */
id: string | null; id: string | null;
/**
* Rationale behind the proposal
*/
rationale: ProposalsQuery_proposalsConnection_edges_node_rationale;
/** /**
* A UUID reference to aid tracking proposals on Vega * A UUID reference to aid tracking proposals on Vega
*/ */
@ -251,20 +271,36 @@ export interface ProposalsQuery_proposals {
/** /**
* Party that prepared the proposal * Party that prepared the proposal
*/ */
party: ProposalsQuery_proposals_party; party: ProposalsQuery_proposalsConnection_edges_node_party;
/** /**
* Terms of the proposal * Terms of the proposal
*/ */
terms: ProposalsQuery_proposals_terms; terms: ProposalsQuery_proposalsConnection_edges_node_terms;
/** /**
* Votes cast for this proposal * Votes cast for this proposal
*/ */
votes: ProposalsQuery_proposals_votes; votes: ProposalsQuery_proposalsConnection_edges_node_votes;
}
export interface ProposalsQuery_proposalsConnection_edges {
__typename: "ProposalEdge";
/**
* The proposal data
*/
node: ProposalsQuery_proposalsConnection_edges_node;
}
export interface ProposalsQuery_proposalsConnection {
__typename: "ProposalsConnection";
/**
* List of proposals available for the connection
*/
edges: (ProposalsQuery_proposalsConnection_edges | null)[] | null;
} }
export interface ProposalsQuery { export interface ProposalsQuery {
/** /**
* All governance proposals in the Vega network * All governance proposals in the Vega network
*/ */
proposals: ProposalsQuery_proposals[] | null; proposalsConnection: ProposalsQuery_proposalsConnection;
} }

View File

@ -4,95 +4,90 @@ import React from 'react';
import { RouteTitle } from '../../components/route-title'; import { RouteTitle } from '../../components/route-title';
import { SubHeading } from '../../components/sub-heading'; import { SubHeading } from '../../components/sub-heading';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit'; import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { getProposals } from '@vegaprotocol/governance';
import type { import type {
ProposalsQuery, ProposalsQuery,
ProposalsQuery_proposals_terms_change, ProposalsQuery_proposalsConnection_edges_node,
} from './__generated__/ProposalsQuery'; } from './__generated__/ProposalsQuery';
export function getProposalName(change: ProposalsQuery_proposals_terms_change) { const PROPOSALS_QUERY = gql`
if (change.__typename === 'NewAsset') {
return t(`New asset: ${change.symbol}`);
} else if (change.__typename === 'NewMarket') {
return t(`New market: ${change.instrument.name}`);
} else if (change.__typename === 'UpdateMarket') {
return t(`Update market: ${change.marketId}`);
} else if (change.__typename === 'UpdateNetworkParameter') {
return t(`Update network: ${change.networkParameter.key}`);
}
return t('Unknown proposal');
}
const PROPOSAL_QUERY = gql`
query ProposalsQuery { query ProposalsQuery {
proposals { proposalsConnection {
id edges {
reference node {
state id
datetime rationale {
rejectionReason title
party { description
id
}
terms {
closingDatetime
enactmentDatetime
change {
... on NewMarket {
instrument {
name
}
} }
... on UpdateMarket { reference
marketId state
datetime
rejectionReason
party {
id
} }
... on NewAsset { terms {
__typename closingDatetime
symbol enactmentDatetime
source { change {
... on BuiltinAsset { ... on NewMarket {
maxFaucetAmountMint instrument {
name
}
} }
... on ERC20 { ... on UpdateMarket {
contractAddress marketId
}
... on NewAsset {
__typename
symbol
source {
... on BuiltinAsset {
maxFaucetAmountMint
}
... on ERC20 {
contractAddress
}
}
}
... on UpdateNetworkParameter {
networkParameter {
key
value
}
} }
} }
} }
... on UpdateNetworkParameter {
networkParameter {
key
value
}
}
}
}
votes {
yes {
totalTokens
totalNumber
votes { votes {
value yes {
party { totalTokens
id totalNumber
stake { votes {
currentStakeAvailable value
party {
id
stakingSummary {
currentStakeAvailable
}
}
datetime
} }
} }
datetime no {
} totalTokens
} totalNumber
no { votes {
totalTokens value
totalNumber party {
votes { id
value stakingSummary {
party { currentStakeAvailable
id }
stake { }
currentStakeAvailable datetime
} }
} }
datetime
} }
} }
} }
@ -101,9 +96,12 @@ const PROPOSAL_QUERY = gql`
`; `;
const Governance = () => { const Governance = () => {
const { data } = useQuery<ProposalsQuery>(PROPOSAL_QUERY, { const { data } = useQuery<ProposalsQuery>(PROPOSALS_QUERY, {
errorPolicy: 'ignore', errorPolicy: 'ignore',
}); });
const proposals = getProposals(
data
) as ProposalsQuery_proposalsConnection_edges_node[];
if (!data) return null; if (!data) return null;
return ( return (
@ -111,9 +109,11 @@ const Governance = () => {
<RouteTitle data-testid="governance-header"> <RouteTitle data-testid="governance-header">
{t('Governance Proposals')} {t('Governance Proposals')}
</RouteTitle> </RouteTitle>
{data.proposals?.map((p) => ( {proposals.map((p) => (
<React.Fragment key={p.id}> <React.Fragment key={p.id}>
<SubHeading>{getProposalName(p.terms.change)}</SubHeading> <SubHeading>
{p.rationale.title || p.rationale.description}
</SubHeading>
<SyntaxHighlighter data={p} /> <SyntaxHighlighter data={p} />
</React.Fragment> </React.Fragment>
))} ))}

View File

@ -9,6 +9,22 @@ import { ProposalState, ProposalRejectionReason, VoteValue } from "@vegaprotocol
// GraphQL fragment: ProposalFields // GraphQL fragment: ProposalFields
// ==================================================== // ====================================================
export interface ProposalFields_rationale {
__typename: "ProposalRationale";
/**
* Title to be used to give a short description of the proposal in lists.
* This is to be between 0 and 100 unicode characters.
* This is mandatory for all proposals.
*/
title: string;
/**
* Description to show a short title / something in case the link goes offline.
* This is to be between 0 and 20k unicode characters.
* This is mandatory for all proposals.
*/
description: string;
}
export interface ProposalFields_party { export interface ProposalFields_party {
__typename: "Party"; __typename: "Party";
/** /**
@ -55,14 +71,6 @@ export interface ProposalFields_terms_change_NewMarket_instrument {
export interface ProposalFields_terms_change_NewMarket { export interface ProposalFields_terms_change_NewMarket {
__typename: "NewMarket"; __typename: "NewMarket";
/**
* Decimal places used for the new market, sets the smallest price increment on the book
*/
decimalPlaces: number;
/**
* Metadata for this instrument, tags
*/
metadata: string[] | null;
/** /**
* New market instrument configuration * New market instrument configuration
*/ */
@ -146,8 +154,8 @@ export interface ProposalFields_terms {
change: ProposalFields_terms_change; change: ProposalFields_terms_change;
} }
export interface ProposalFields_votes_yes_votes_party_stake { export interface ProposalFields_votes_yes_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -163,7 +171,7 @@ export interface ProposalFields_votes_yes_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: ProposalFields_votes_yes_votes_party_stake; stakingSummary: ProposalFields_votes_yes_votes_party_stakingSummary;
} }
export interface ProposalFields_votes_yes_votes { export interface ProposalFields_votes_yes_votes {
@ -198,8 +206,8 @@ export interface ProposalFields_votes_yes {
votes: ProposalFields_votes_yes_votes[] | null; votes: ProposalFields_votes_yes_votes[] | null;
} }
export interface ProposalFields_votes_no_votes_party_stake { export interface ProposalFields_votes_no_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -215,7 +223,7 @@ export interface ProposalFields_votes_no_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: ProposalFields_votes_no_votes_party_stake; stakingSummary: ProposalFields_votes_no_votes_party_stakingSummary;
} }
export interface ProposalFields_votes_no_votes { export interface ProposalFields_votes_no_votes {
@ -268,6 +276,10 @@ export interface ProposalFields {
* Proposal ID that is filled by Vega once proposal reaches the network * Proposal ID that is filled by Vega once proposal reaches the network
*/ */
id: string | null; id: string | null;
/**
* Rationale behind the proposal
*/
rationale: ProposalFields_rationale;
/** /**
* A UUID reference to aid tracking proposals on Vega * A UUID reference to aid tracking proposals on Vega
*/ */
@ -284,14 +296,14 @@ export interface ProposalFields {
* Reason for the proposal to be rejected by the core * Reason for the proposal to be rejected by the core
*/ */
rejectionReason: ProposalRejectionReason | null; rejectionReason: ProposalRejectionReason | null;
/**
* Error details of the rejectionReason
*/
errorDetails: string | null;
/** /**
* Party that prepared the proposal * Party that prepared the proposal
*/ */
party: ProposalFields_party; party: ProposalFields_party;
/**
* Error details of the rejectionReason
*/
errorDetails: string | null;
/** /**
* Terms of the proposal * Terms of the proposal
*/ */

View File

@ -1,10 +1,10 @@
import { ProposalState } from '@vegaprotocol/types'; import { ProposalState } from '@vegaprotocol/types';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { ProposalFields } from '../../__generated__/ProposalFields';
export const CurrentProposalState = ({ export const CurrentProposalState = ({
proposal, proposal,
}: { }: {
proposal: Proposals_proposals; proposal: ProposalFields;
}) => { }) => {
const { state } = proposal; const { state } = proposal;
let className = 'text-white'; let className = 'text-white';

View File

@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import { ProposalState } from '@vegaprotocol/types'; import { ProposalState } from '@vegaprotocol/types';
import { useVoteInformation } from '../../hooks'; import { useVoteInformation } from '../../hooks';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { ProposalFields } from '../../__generated__/ProposalFields';
export const StatusPass = ({ children }: { children: React.ReactNode }) => ( export const StatusPass = ({ children }: { children: React.ReactNode }) => (
<span className="text-vega-green">{children}</span> <span className="text-vega-green">{children}</span>
@ -17,7 +17,7 @@ export const StatusFail = ({ children }: { children: React.ReactNode }) => (
export const CurrentProposalStatus = ({ export const CurrentProposalStatus = ({
proposal, proposal,
}: { }: {
proposal: Proposals_proposals; proposal: ProposalFields;
}) => { }) => {
const { willPass, majorityMet, participationMet } = useVoteInformation({ const { willPass, majorityMet, participationMet } = useVoteInformation({
proposal, proposal,

View File

@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next';
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit'; import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats'; import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
import { CurrentProposalState } from '../current-proposal-state'; import { CurrentProposalState } from '../current-proposal-state';
import type { ProposalFields } from '../../__generated__/ProposalFields';
interface ProposalChangeTableProps { interface ProposalChangeTableProps {
proposal: Proposals_proposals; proposal: ProposalFields;
} }
export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => { export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {

View File

@ -1,9 +1,9 @@
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import { generateProposal } from '../../test-helpers/generate-proposals'; import { generateProposal } from '../../test-helpers/generate-proposals';
import { ProposalHeader } from './proposal-header'; import { ProposalHeader } from './proposal-header';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { Proposal_proposal } from '@vegaprotocol/governance';
const renderComponent = (proposal: Proposals_proposals) => ( const renderComponent = (proposal: Proposal_proposal) => (
<ProposalHeader proposal={proposal} /> <ProposalHeader proposal={proposal} />
); );
@ -12,10 +12,13 @@ describe('Proposal header', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
rationale: {
title: 'New some market',
description: 'A new some market',
},
terms: { terms: {
change: { change: {
__typename: 'NewMarket', __typename: 'NewMarket',
decimalPlaces: 1,
instrument: { instrument: {
__typename: 'InstrumentConfiguration', __typename: 'InstrumentConfiguration',
name: 'Some market', name: 'Some market',
@ -28,16 +31,18 @@ describe('Proposal header', () => {
}, },
}, },
}, },
metadata: [],
}, },
}, },
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'New market: Some market' 'New some market'
); );
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent( expect(screen.getByTestId('proposal-description')).toHaveTextContent(
'A new some market'
);
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'tGBP settled future.' 'tGBP settled future.'
); );
}); });
@ -46,6 +51,9 @@ describe('Proposal header', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
rationale: {
title: 'New market id',
},
terms: { terms: {
change: { change: {
__typename: 'UpdateMarket', __typename: 'UpdateMarket',
@ -55,7 +63,13 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'New market id'
);
expect(
screen.queryByTestId('proposal-description')
).not.toBeInTheDocument();
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'Market change: MarketId' 'Market change: MarketId'
); );
}); });
@ -64,6 +78,10 @@ describe('Proposal header', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
rationale: {
title: 'New asset: Fake currency',
description: '',
},
terms: { terms: {
change: { change: {
__typename: 'NewAsset', __typename: 'NewAsset',
@ -78,10 +96,10 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'New asset: Fake currency' 'New asset: Fake currency'
); );
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'Symbol: FAKE. ERC20 0x0' 'Symbol: FAKE. ERC20 0x0'
); );
}); });
@ -104,10 +122,10 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'New asset: Fake currency' 'Unknown proposal'
); );
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'Symbol: BIA. Max faucet amount mint: 300' 'Symbol: BIA. Max faucet amount mint: 300'
); );
}); });
@ -116,6 +134,9 @@ describe('Proposal header', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
rationale: {
title: 'Network parameter',
},
terms: { terms: {
change: { change: {
__typename: 'UpdateNetworkParameter', __typename: 'UpdateNetworkParameter',
@ -129,25 +150,22 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'Network parameter' 'Network parameter'
); );
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'Network key to Network value' 'Network key to Network value'
); );
}); });
// Skipped until proposals have rationale - https://github.com/vegaprotocol/frontend-monorepo/issues/824 it('Renders Freeform network - short rationale', () => {
// eslint-disable-next-line jest/no-disabled-tests
it.skip('Renders Freeform network - short rationale', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
id: 'short', id: 'short',
// rationale: { rationale: {
// hash: '0x0', title: '0x0',
// description: 'freeform description', },
// },
terms: { terms: {
change: { change: {
__typename: 'NewFreeform', __typename: 'NewFreeform',
@ -156,27 +174,23 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent('0x0');
'freeform description' expect(
); screen.queryByTestId('proposal-description')
expect(screen.getByTestId('proposal-details-one')).toBeEmptyDOMElement(); ).not.toBeInTheDocument();
expect(screen.getByTestId('proposal-details-two')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent('short');
'short'
);
}); });
// Skipped until proposals have rationale it('Renders Freeform proposal - long rationale (105 chars)', () => {
// eslint-disable-next-line jest/no-disabled-tests
it.skip('Renders Freeform proposal - long rationale (105 chars)', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
id: 'long', id: 'long',
// rationale: { rationale: {
// hash: '0x0', title: '0x0',
// description: description:
// 'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dolor.', 'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dolor.',
// }, },
terms: { terms: {
change: { change: {
__typename: 'NewFreeform', __typename: 'NewFreeform',
@ -187,29 +201,24 @@ describe('Proposal header', () => {
); );
// For a rationale over 100 chars, we expect the header to be truncated at // For a rationale over 100 chars, we expect the header to be truncated at
// 100 chars with ellipsis and the details-one element to contain the rest. // 100 chars with ellipsis and the details-one element to contain the rest.
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent('0x0');
'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean…' expect(screen.getByTestId('proposal-description')).toHaveTextContent(
); 'Class aptent taciti sociosqu ad litora torquent per conubia'
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent(
'dolor'
);
expect(screen.getByTestId('proposal-details-two')).toHaveTextContent(
'long'
); );
expect(screen.getByTestId('proposal-details')).toHaveTextContent('long');
}); });
// Skipped until proposals have rationale it('Renders Freeform proposal - extra long rationale (165 chars)', () => {
// eslint-disable-next-line jest/no-disabled-tests
it.skip('Renders Freeform proposal - extra long rationale (165 chars)', () => {
render( render(
renderComponent( renderComponent(
generateProposal({ generateProposal({
id: 'extraLong', id: 'extraLong',
// rationale: { rationale: {
// hash: '0x0', title:
// description: 'Aenean sem odio, eleifend non sodales vitae, porttitor eu ex. Aliquam erat volutpat. Fusce pharetra libero quis risus lobortis, sed ornare leo efficitur turpis duis.',
// 'Aenean sem odio, eleifend non sodales vitae, porttitor eu ex. Aliquam erat volutpat. Fusce pharetra libero quis risus lobortis, sed ornare leo efficitur turpis duis.', description:
// }, 'Aenean sem odio, eleifend non sodales vitae, porttitor eu ex. Aliquam erat volutpat. Fusce pharetra libero quis risus lobortis, sed ornare leo efficitur turpis duis.',
},
terms: { terms: {
change: { change: {
__typename: 'NewFreeform', __typename: 'NewFreeform',
@ -221,13 +230,13 @@ describe('Proposal header', () => {
// For a rationale over 160 chars, we expect the header to be truncated at 100 // For a rationale over 160 chars, we expect the header to be truncated at 100
// chars with ellipsis and the details-one element to contain 60 chars and also // chars with ellipsis and the details-one element to contain 60 chars and also
// be truncated with an ellipsis. // be truncated with an ellipsis.
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'Aenean sem odio, eleifend non sodales vitae, porttitor eu ex. Aliquam erat volutpat. Fusce pharetra…' 'Aenean sem odio, eleifend non sodales vitae, porttitor eu ex. Aliquam erat volutpat. Fusce pharetra…'
); );
expect(screen.getByTestId('proposal-details-one')).toHaveTextContent( expect(screen.getByTestId('proposal-description')).toHaveTextContent(
'libero quis risus lobortis, sed ornare leo efficitur turpis…' 'Aenean sem odio, eleifend non sodales vitae, porttitor eu e…'
); );
expect(screen.getByTestId('proposal-details-two')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'extraLong' 'extraLong'
); );
}); });
@ -238,6 +247,9 @@ describe('Proposal header', () => {
renderComponent( renderComponent(
generateProposal({ generateProposal({
id: 'freeform id', id: 'freeform id',
rationale: {
title: 'freeform',
},
terms: { terms: {
change: { change: {
__typename: 'NewFreeform', __typename: 'NewFreeform',
@ -246,15 +258,13 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent('freeform');
'Freeform proposal: freeform id' expect(
screen.queryByTestId('proposal-description')
).not.toBeInTheDocument();
expect(screen.queryByTestId('proposal-details')).toHaveTextContent(
'freeform id'
); );
expect(
screen.queryByTestId('proposal-details-one')
).not.toBeInTheDocument();
expect(
screen.queryByTestId('proposal-details-two')
).not.toBeInTheDocument();
}); });
it("Renders unknown proposal if it's a different proposal type", () => { it("Renders unknown proposal if it's a different proposal type", () => {
@ -270,7 +280,7 @@ describe('Proposal header', () => {
}) })
) )
); );
expect(screen.getByTestId('proposal-header')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'Unknown proposal' 'Unknown proposal'
); );
}); });

View File

@ -1,24 +1,28 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Lozenge } from '@vegaprotocol/ui-toolkit'; import { Lozenge } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import { shorten } from '@vegaprotocol/react-helpers';
import type { ProposalFields } from '../../__generated__/ProposalFields';
export const ProposalHeader = ({ export const ProposalHeader = ({ proposal }: { proposal: ProposalFields }) => {
proposal,
}: {
proposal: Proposals_proposals;
}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { change } = proposal.terms; const { change } = proposal.terms;
let headerText: string; let details: ReactNode;
let detailsOne: ReactNode;
let detailsTwo: ReactNode; let title = proposal.rationale.title.trim();
let description = proposal.rationale.description.trim();
if (title.length === 0 && description.length > 0) {
title = description;
description = '';
}
const titleContent = shorten(title, 100);
const descriptionContent = shorten(description, 60);
switch (change.__typename) { switch (change.__typename) {
case 'NewMarket': { case 'NewMarket': {
headerText = `${t('New market')}: ${change.instrument.name}`; details = (
detailsOne = (
<> <>
{t('Code')}: {change.instrument.code}.{' '} {t('Code')}: {change.instrument.code}.{' '}
{change.instrument.futureProduct?.settlementAsset.symbol ? ( {change.instrument.futureProduct?.settlementAsset.symbol ? (
@ -36,12 +40,11 @@ export const ProposalHeader = ({
break; break;
} }
case 'UpdateMarket': { case 'UpdateMarket': {
headerText = `${t('Market change')}: ${change.marketId}`; details = `${t('Market change')}: ${change.marketId}`;
break; break;
} }
case 'NewAsset': { case 'NewAsset': {
headerText = `${t('New asset')}: ${change.name}`; details = (
detailsOne = (
<> <>
{t('Symbol')}: {change.symbol}.{' '} {t('Symbol')}: {change.symbol}.{' '}
<Lozenge> <Lozenge>
@ -57,8 +60,7 @@ export const ProposalHeader = ({
} }
case 'UpdateNetworkParameter': { case 'UpdateNetworkParameter': {
const parametersClasses = 'font-mono leading-none'; const parametersClasses = 'font-mono leading-none';
headerText = `${t('Network parameter')}`; details = (
detailsOne = (
<> <>
<span className={`${parametersClasses} mr-2`}> <span className={`${parametersClasses} mr-2`}>
{change.networkParameter.key} {change.networkParameter.key}
@ -72,44 +74,34 @@ export const ProposalHeader = ({
break; break;
} }
case 'NewFreeform': { case 'NewFreeform': {
// When rationale exists (https://github.com/vegaprotocol/frontend-monorepo/issues/824): details = `${proposal.id}`;
// const description = proposal.rationale.description.trim();
// const headerMaxLength = 100;
// const descriptionOneMaxLength = 60;
// const headerOverflow = description.length > headerMaxLength;
// const descriptionOneOverflow =
// description.length > headerMaxLength + descriptionOneMaxLength;
//
// headerText = `${description.substring(0, headerMaxLength - 1).trim()}${
// headerOverflow ? '…' : ''
// }`;
// detailsOne = headerOverflow
// ? `${description
// .substring(
// headerMaxLength - 1,
// headerMaxLength + descriptionOneMaxLength - 1
// )
// .trim()}${descriptionOneOverflow ? '…' : ''}`
// : '';
// detailsTwo = `${proposal.id}`;
headerText = proposal.id
? `${t('Freeform proposal')}: ${proposal.id.trim()}`
: `${t('Unknown proposal')}`;
break; break;
} }
default: {
headerText = `${t('Unknown proposal')}`;
}
} }
return ( return (
<div className="text-sm mb-2"> <div className="text-sm mb-2">
<header data-testid="proposal-header"> <header data-testid="proposal-title">
<h2 className="text-lg mx-0 mt-0 mb-1 font-semibold">{headerText}</h2> <h2
{...(title && title.length > titleContent.length && { title: title })}
className="text-lg mx-0 mt-0 mb-1 font-semibold"
>
{titleContent || t('Unknown proposal')}
</h2>
</header> </header>
{detailsOne && <div data-testid="proposal-details-one">{detailsOne}</div>} {descriptionContent && (
{detailsTwo && <div data-testid="proposal-details-two">{detailsTwo}</div>} <div
className="mb-4"
{...(description.length > descriptionContent.length && {
title: description,
})}
data-testid="proposal-description"
>
{descriptionContent}
</div>
)}
{details && <div data-testid="proposal-details">{details}</div>}
</div> </div>
); );
}; };

View File

@ -1,11 +1,11 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit'; import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import type { Proposal_proposal_terms } from '../../proposal/__generated__/Proposal'; import type { ProposalFields_terms } from '../../__generated__/ProposalFields';
export const ProposalTermsJson = ({ export const ProposalTermsJson = ({
terms, terms,
}: { }: {
terms: Proposal_proposal_terms; terms: ProposalFields_terms;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (

View File

@ -6,11 +6,11 @@ import {
formatNumberPercentage, formatNumberPercentage,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { useVoteInformation } from '../../hooks'; import { useVoteInformation } from '../../hooks';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
import { useAppState } from '../../../../contexts/app-state/app-state-context'; import { useAppState } from '../../../../contexts/app-state/app-state-context';
import type { ProposalFields } from '../../__generated__/ProposalFields';
interface ProposalVotesTableProps { interface ProposalVotesTableProps {
proposal: Proposals_proposals; proposal: ProposalFields;
} }
export const ProposalVotesTable = ({ proposal }: ProposalVotesTableProps) => { export const ProposalVotesTable = ({ proposal }: ProposalVotesTableProps) => {

View File

@ -26,10 +26,10 @@ import {
lastWeek, lastWeek,
nextWeek, nextWeek,
} from '../../test-helpers/mocks'; } from '../../test-helpers/mocks';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { ProposalsConnection_proposalsConnection_edges_node as ProposalNode } from '@vegaprotocol/governance';
const renderComponent = ( const renderComponent = (
proposal: Proposals_proposals, proposal: ProposalNode,
mock = networkParamsQueryMock mock = networkParamsQueryMock
) => ( ) => (
<Router> <Router>
@ -173,8 +173,8 @@ describe('Proposals list item details', () => {
party: { party: {
__typename: 'Party', __typename: 'Party',
id: mockPubkey, id: mockPubkey,
stake: { stakingSummary: {
__typename: 'PartyStake', __typename: 'StakingSummary',
currentStakeAvailable: '1000', currentStakeAvailable: '1000',
}, },
}, },
@ -211,8 +211,8 @@ describe('Proposals list item details', () => {
party: { party: {
__typename: 'Party', __typename: 'Party',
id: mockPubkey, id: mockPubkey,
stake: { stakingSummary: {
__typename: 'PartyStake', __typename: 'StakingSummary',
currentStakeAvailable: '1000', currentStakeAvailable: '1000',
}, },
}, },

View File

@ -10,12 +10,12 @@ import { format, formatDistanceToNowStrict } from 'date-fns';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats'; import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
import { import {
ProposalRejectionReasonMapping, ProposalRejectionReasonMapping,
ProposalState, ProposalState,
} from '@vegaprotocol/types'; } from '@vegaprotocol/types';
import Routes from '../../../routes'; import Routes from '../../../routes';
import type { ProposalFields } from '../../__generated__/ProposalFields';
const MajorityNotReached = () => { const MajorityNotReached = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -37,7 +37,7 @@ const ParticipationNotReached = () => {
export const ProposalsListItemDetails = ({ export const ProposalsListItemDetails = ({
proposal, proposal,
}: { }: {
proposal: Proposals_proposals; proposal: ProposalFields;
}) => { }) => {
const { state } = proposal; const { state } = proposal;
const { willPass, majorityMet, participationMet } = useVoteInformation({ const { willPass, majorityMet, participationMet } = useVoteInformation({

View File

@ -1,9 +1,9 @@
import type { ProposalFields } from '../../__generated__/ProposalFields';
import { ProposalHeader } from '../proposal-detail-header/proposal-header'; import { ProposalHeader } from '../proposal-detail-header/proposal-header';
import { ProposalsListItemDetails } from './proposals-list-item-details'; import { ProposalsListItemDetails } from './proposals-list-item-details';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
interface ProposalsListItemProps { interface ProposalsListItemProps {
proposal: Proposals_proposals; proposal: ProposalFields;
} }
export const ProposalsListItem = ({ proposal }: ProposalsListItemProps) => { export const ProposalsListItem = ({ proposal }: ProposalsListItemProps) => {

View File

@ -14,7 +14,7 @@ import {
lastMonth, lastMonth,
nextMonth, nextMonth,
} from '../../test-helpers/mocks'; } from '../../test-helpers/mocks';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { ProposalsConnection_proposalsConnection_edges_node as ProposalNode } from '@vegaprotocol/governance';
const openProposalClosesNextMonth = generateProposal({ const openProposalClosesNextMonth = generateProposal({
id: 'proposal1', id: 'proposal1',
@ -58,7 +58,7 @@ const failedProposalClosedLastMonth = generateProposal({
}, },
}); });
const renderComponent = (proposals: Proposals_proposals[]) => ( const renderComponent = (proposals: ProposalNode[]) => (
<Router> <Router>
<MockedProvider mocks={[networkParamsQueryMock]}> <MockedProvider mocks={[networkParamsQueryMock]}>
<AppStateProvider> <AppStateProvider>

View File

@ -4,20 +4,20 @@ import { useTranslation } from 'react-i18next';
import { Heading } from '../../../../components/heading'; import { Heading } from '../../../../components/heading';
import { ProposalsListItem } from '../proposals-list-item'; import { ProposalsListItem } from '../proposals-list-item';
import { ProposalsListFilter } from '../proposals-list-filter'; import { ProposalsListFilter } from '../proposals-list-filter';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
import Routes from '../../../routes'; import Routes from '../../../routes';
import { Button } from '@vegaprotocol/ui-toolkit'; import { Button } from '@vegaprotocol/ui-toolkit';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import type { ProposalFields } from '../../__generated__/ProposalFields';
import { Links } from '../../../../config'; import { Links } from '../../../../config';
import { ExternalLink } from '@vegaprotocol/ui-toolkit'; import { ExternalLink } from '@vegaprotocol/ui-toolkit';
interface ProposalsListProps { interface ProposalsListProps {
proposals: Proposals_proposals[]; proposals: ProposalFields[];
} }
interface SortedProposalsProps { interface SortedProposalsProps {
open: Proposals_proposals[]; open: ProposalFields[];
closed: Proposals_proposals[]; closed: ProposalFields[];
} }
export const ProposalsList = ({ proposals }: ProposalsListProps) => { export const ProposalsList = ({ proposals }: ProposalsListProps) => {
@ -39,7 +39,7 @@ export const ProposalsList = ({ proposals }: ProposalsListProps) => {
} }
); );
const filterPredicate = (p: Proposals_proposals) => const filterPredicate = (p: ProposalFields) =>
p.id?.includes(filterString) || p.id?.includes(filterString) ||
p.party?.id?.toString().includes(filterString); p.party?.id?.toString().includes(filterString);

View File

@ -12,11 +12,11 @@ import {
nextWeek, nextWeek,
lastMonth, lastMonth,
} from '../../test-helpers/mocks'; } from '../../test-helpers/mocks';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { ProposalsConnection_proposalsConnection_edges_node as ProposalNode } from '@vegaprotocol/governance';
const rejectedProposalClosesNextWeek = generateProposal({ const rejectedProposalClosesNextWeek = generateProposal({
id: 'rejected1', id: 'rejected1',
state: ProposalState.Open, state: ProposalState.STATE_OPEN,
party: { party: {
id: 'bvcx', id: 'bvcx',
}, },
@ -28,14 +28,14 @@ const rejectedProposalClosesNextWeek = generateProposal({
const rejectedProposalClosedLastMonth = generateProposal({ const rejectedProposalClosedLastMonth = generateProposal({
id: 'rejected2', id: 'rejected2',
state: ProposalState.Rejected, state: ProposalState.STATE_REJECTED,
terms: { terms: {
closingDatetime: lastMonth.toString(), closingDatetime: lastMonth.toString(),
enactmentDatetime: lastMonth.toString(), enactmentDatetime: lastMonth.toString(),
}, },
}); });
const renderComponent = (proposals: Proposals_proposals[]) => ( const renderComponent = (proposals: ProposalNode[]) => (
<Router> <Router>
<MockedProvider mocks={[networkParamsQueryMock]}> <MockedProvider mocks={[networkParamsQueryMock]}>
<AppStateProvider> <AppStateProvider>

View File

@ -3,17 +3,17 @@ import { useTranslation } from 'react-i18next';
import { Heading } from '../../../../components/heading'; import { Heading } from '../../../../components/heading';
import { ProposalsListItem } from '../proposals-list-item'; import { ProposalsListItem } from '../proposals-list-item';
import { ProposalsListFilter } from '../proposals-list-filter'; import { ProposalsListFilter } from '../proposals-list-filter';
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals'; import type { Proposals_proposalsConnection_edges_node } from '../../proposals/__generated__/Proposals';
interface ProposalsListProps { interface ProposalsListProps {
proposals: Proposals_proposals[]; proposals: Proposals_proposalsConnection_edges_node[];
} }
export const RejectedProposalsList = ({ proposals }: ProposalsListProps) => { export const RejectedProposalsList = ({ proposals }: ProposalsListProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [filterString, setFilterString] = useState(''); const [filterString, setFilterString] = useState('');
const filterPredicate = (p: Proposals_proposals) => const filterPredicate = (p: Proposals_proposalsConnection_edges_node) =>
p.id?.includes(filterString) || p.id?.includes(filterString) ||
p.party?.id?.toString().includes(filterString); p.party?.id?.toString().includes(filterString);

View File

@ -4,13 +4,13 @@ import { useTranslation } from 'react-i18next';
import { formatNumber } from '../../../../lib/format-number'; import { formatNumber } from '../../../../lib/format-number';
import { ConnectToVega } from '../../../staking/connect-to-vega'; import { ConnectToVega } from '../../../staking/connect-to-vega';
import { useVoteInformation } from '../../hooks'; import { useVoteInformation } from '../../hooks';
import type { Proposal_proposal } from '../../proposal/__generated__/Proposal';
import { CurrentProposalStatus } from '../current-proposal-status'; import { CurrentProposalStatus } from '../current-proposal-status';
import { useUserVote } from './use-user-vote'; import { useUserVote } from './use-user-vote';
import { VoteButtonsContainer } from './vote-buttons'; import { VoteButtonsContainer } from './vote-buttons';
import { VoteProgress } from './vote-progress'; import { VoteProgress } from './vote-progress';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { ProposalState } from '@vegaprotocol/types'; import { ProposalState } from '@vegaprotocol/types';
import type { Proposal_proposal } from '../../proposal/__generated__/Proposal';
interface VoteDetailsProps { interface VoteDetailsProps {
proposal: Proposal_proposal; proposal: Proposal_proposal;

View File

@ -6,15 +6,15 @@ import { useAppState } from '../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../lib/bignumber'; import { BigNumber } from '../../../lib/bignumber';
import { addDecimal } from '../../../lib/decimals'; import { addDecimal } from '../../../lib/decimals';
import type { import type {
Proposal_proposal_votes_no_votes, ProposalFields,
Proposal_proposal_votes_yes_votes, ProposalFields_votes_no_votes,
} from '../proposal/__generated__/Proposal'; ProposalFields_votes_yes_votes,
import type { Proposals_proposals } from '../proposals/__generated__/Proposals'; } from '../__generated__/ProposalFields';
const useProposalNetworkParams = ({ const useProposalNetworkParams = ({
proposal, proposal,
}: { }: {
proposal: Proposals_proposals; proposal: ProposalFields;
}) => { }) => {
const { data, loading } = useNetworkParams([ const { data, loading } = useNetworkParams([
NetworkParams.GOV_UPDATE_MARKET_REQUIRED_MAJORITY, NetworkParams.GOV_UPDATE_MARKET_REQUIRED_MAJORITY,
@ -82,7 +82,7 @@ const useProposalNetworkParams = ({
export const useVoteInformation = ({ export const useVoteInformation = ({
proposal, proposal,
}: { }: {
proposal: Proposals_proposals; proposal: ProposalFields;
}) => { }) => {
const { const {
appState: { totalSupply }, appState: { totalSupply },
@ -105,10 +105,10 @@ export const useVoteInformation = ({
return new BigNumber(0); return new BigNumber(0);
} }
const totalNoVotes = proposal.votes.no.votes.reduce( const totalNoVotes = proposal.votes.no.votes.reduce(
(prevValue: BigNumber, newValue: Proposal_proposal_votes_no_votes) => { (prevValue: BigNumber, newValue: ProposalFields_votes_no_votes) => {
return new BigNumber(newValue.party.stake.currentStakeAvailable).plus( return new BigNumber(
prevValue newValue.party.stakingSummary.currentStakeAvailable
); ).plus(prevValue);
}, },
new BigNumber(0) new BigNumber(0)
); );
@ -120,10 +120,10 @@ export const useVoteInformation = ({
return new BigNumber(0); return new BigNumber(0);
} }
const totalYesVotes = proposal.votes.yes.votes.reduce( const totalYesVotes = proposal.votes.yes.votes.reduce(
(prevValue: BigNumber, newValue: Proposal_proposal_votes_yes_votes) => { (prevValue: BigNumber, newValue: ProposalFields_votes_yes_votes) => {
return new BigNumber(newValue.party.stake.currentStakeAvailable).plus( return new BigNumber(
prevValue newValue.party.stakingSummary.currentStakeAvailable
); ).plus(prevValue);
}, },
new BigNumber(0) new BigNumber(0)
); );

View File

@ -1,23 +1,25 @@
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
export const PROPOSALS_FRAGMENT = gql` export const PROPOSAL_FRAGMENT = gql`
fragment ProposalFields on Proposal { fragment ProposalFields on Proposal {
id id
rationale {
title
description
}
reference reference
state state
datetime datetime
rejectionReason rejectionReason
errorDetails
party { party {
id id
} }
errorDetails
terms { terms {
closingDatetime closingDatetime
enactmentDatetime enactmentDatetime
change { change {
... on NewMarket { ... on NewMarket {
decimalPlaces
metadata
instrument { instrument {
name name
code code
@ -37,11 +39,9 @@ export const PROPOSALS_FRAGMENT = gql`
symbol symbol
source { source {
... on BuiltinAsset { ... on BuiltinAsset {
__typename
maxFaucetAmountMint maxFaucetAmountMint
} }
... on ERC20 { ... on ERC20 {
__typename
contractAddress contractAddress
} }
} }
@ -62,7 +62,7 @@ export const PROPOSALS_FRAGMENT = gql`
value value
party { party {
id id
stake { stakingSummary {
currentStakeAvailable currentStakeAvailable
} }
} }
@ -76,7 +76,7 @@ export const PROPOSALS_FRAGMENT = gql`
value value
party { party {
id id
stake { stakingSummary {
currentStakeAvailable currentStakeAvailable
} }
} }

View File

@ -9,6 +9,22 @@ import { ProposalState, ProposalRejectionReason, VoteValue } from "@vegaprotocol
// GraphQL query operation: Proposal // GraphQL query operation: Proposal
// ==================================================== // ====================================================
export interface Proposal_proposal_rationale {
__typename: "ProposalRationale";
/**
* Title to be used to give a short description of the proposal in lists.
* This is to be between 0 and 100 unicode characters.
* This is mandatory for all proposals.
*/
title: string;
/**
* Description to show a short title / something in case the link goes offline.
* This is to be between 0 and 20k unicode characters.
* This is mandatory for all proposals.
*/
description: string;
}
export interface Proposal_proposal_party { export interface Proposal_proposal_party {
__typename: "Party"; __typename: "Party";
/** /**
@ -55,14 +71,6 @@ export interface Proposal_proposal_terms_change_NewMarket_instrument {
export interface Proposal_proposal_terms_change_NewMarket { export interface Proposal_proposal_terms_change_NewMarket {
__typename: "NewMarket"; __typename: "NewMarket";
/**
* Decimal places used for the new market, sets the smallest price increment on the book
*/
decimalPlaces: number;
/**
* Metadata for this instrument, tags
*/
metadata: string[] | null;
/** /**
* New market instrument configuration * New market instrument configuration
*/ */
@ -146,8 +154,8 @@ export interface Proposal_proposal_terms {
change: Proposal_proposal_terms_change; change: Proposal_proposal_terms_change;
} }
export interface Proposal_proposal_votes_yes_votes_party_stake { export interface Proposal_proposal_votes_yes_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -163,7 +171,7 @@ export interface Proposal_proposal_votes_yes_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: Proposal_proposal_votes_yes_votes_party_stake; stakingSummary: Proposal_proposal_votes_yes_votes_party_stakingSummary;
} }
export interface Proposal_proposal_votes_yes_votes { export interface Proposal_proposal_votes_yes_votes {
@ -198,8 +206,8 @@ export interface Proposal_proposal_votes_yes {
votes: Proposal_proposal_votes_yes_votes[] | null; votes: Proposal_proposal_votes_yes_votes[] | null;
} }
export interface Proposal_proposal_votes_no_votes_party_stake { export interface Proposal_proposal_votes_no_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -215,7 +223,7 @@ export interface Proposal_proposal_votes_no_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: Proposal_proposal_votes_no_votes_party_stake; stakingSummary: Proposal_proposal_votes_no_votes_party_stakingSummary;
} }
export interface Proposal_proposal_votes_no_votes { export interface Proposal_proposal_votes_no_votes {
@ -268,6 +276,10 @@ export interface Proposal_proposal {
* Proposal ID that is filled by Vega once proposal reaches the network * Proposal ID that is filled by Vega once proposal reaches the network
*/ */
id: string | null; id: string | null;
/**
* Rationale behind the proposal
*/
rationale: Proposal_proposal_rationale;
/** /**
* A UUID reference to aid tracking proposals on Vega * A UUID reference to aid tracking proposals on Vega
*/ */
@ -284,14 +296,14 @@ export interface Proposal_proposal {
* Reason for the proposal to be rejected by the core * Reason for the proposal to be rejected by the core
*/ */
rejectionReason: ProposalRejectionReason | null; rejectionReason: ProposalRejectionReason | null;
/**
* Error details of the rejectionReason
*/
errorDetails: string | null;
/** /**
* Party that prepared the proposal * Party that prepared the proposal
*/ */
party: Proposal_proposal_party; party: Proposal_proposal_party;
/**
* Error details of the rejectionReason
*/
errorDetails: string | null;
/** /**
* Terms of the proposal * Terms of the proposal
*/ */

View File

@ -1,5 +1,4 @@
export { export {
ProposalContainer, ProposalContainer,
PROPOSAL_QUERY,
ProposalContainer as default, ProposalContainer as default,
} from './proposal-container'; } from './proposal-container';

View File

@ -4,14 +4,14 @@ import { useEffect } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Proposal } from '../components/proposal'; import { Proposal } from '../components/proposal';
import { PROPOSALS_FRAGMENT } from '../proposal-fragment'; import { PROPOSAL_FRAGMENT } from '../proposal-fragment';
import type { import type {
Proposal as ProposalQueryResult, Proposal as ProposalQueryResult,
ProposalVariables, ProposalVariables,
} from './__generated__/Proposal'; } from './__generated__/Proposal';
export const PROPOSAL_QUERY = gql` export const PROPOSAL_QUERY = gql`
${PROPOSALS_FRAGMENT} ${PROPOSAL_FRAGMENT}
query Proposal($proposalId: ID!) { query Proposal($proposalId: ID!) {
proposal(id: $proposalId) { proposal(id: $proposalId) {
...ProposalFields ...ProposalFields

View File

@ -9,7 +9,23 @@ import { ProposalState, ProposalRejectionReason, VoteValue } from "@vegaprotocol
// GraphQL query operation: Proposals // GraphQL query operation: Proposals
// ==================================================== // ====================================================
export interface Proposals_proposals_party { export interface Proposals_proposalsConnection_edges_node_rationale {
__typename: "ProposalRationale";
/**
* Title to be used to give a short description of the proposal in lists.
* This is to be between 0 and 100 unicode characters.
* This is mandatory for all proposals.
*/
title: string;
/**
* Description to show a short title / something in case the link goes offline.
* This is to be between 0 and 20k unicode characters.
* This is mandatory for all proposals.
*/
description: string;
}
export interface Proposals_proposalsConnection_edges_node_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -17,11 +33,11 @@ export interface Proposals_proposals_party {
id: string; id: string;
} }
export interface Proposals_proposals_terms_change_UpdateAsset { export interface Proposals_proposalsConnection_edges_node_terms_change_UpdateAsset {
__typename: "UpdateAsset" | "NewFreeform"; __typename: "UpdateAsset" | "NewFreeform";
} }
export interface Proposals_proposals_terms_change_NewMarket_instrument_futureProduct_settlementAsset { export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct_settlementAsset {
__typename: "Asset"; __typename: "Asset";
/** /**
* The symbol of the asset (e.g: GBP) * The symbol of the asset (e.g: GBP)
@ -29,15 +45,15 @@ export interface Proposals_proposals_terms_change_NewMarket_instrument_futurePro
symbol: string; symbol: string;
} }
export interface Proposals_proposals_terms_change_NewMarket_instrument_futureProduct { export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct {
__typename: "FutureProduct"; __typename: "FutureProduct";
/** /**
* Product asset ID * Product asset ID
*/ */
settlementAsset: Proposals_proposals_terms_change_NewMarket_instrument_futureProduct_settlementAsset; settlementAsset: Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct_settlementAsset;
} }
export interface Proposals_proposals_terms_change_NewMarket_instrument { export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument {
__typename: "InstrumentConfiguration"; __typename: "InstrumentConfiguration";
/** /**
* Full and fairly descriptive name for the instrument * Full and fairly descriptive name for the instrument
@ -50,31 +66,23 @@ export interface Proposals_proposals_terms_change_NewMarket_instrument {
/** /**
* Future product specification * Future product specification
*/ */
futureProduct: Proposals_proposals_terms_change_NewMarket_instrument_futureProduct | null; futureProduct: Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct | null;
} }
export interface Proposals_proposals_terms_change_NewMarket { export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket {
__typename: "NewMarket"; __typename: "NewMarket";
/**
* Decimal places used for the new market, sets the smallest price increment on the book
*/
decimalPlaces: number;
/**
* Metadata for this instrument, tags
*/
metadata: string[] | null;
/** /**
* New market instrument configuration * New market instrument configuration
*/ */
instrument: Proposals_proposals_terms_change_NewMarket_instrument; instrument: Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument;
} }
export interface Proposals_proposals_terms_change_UpdateMarket { export interface Proposals_proposalsConnection_edges_node_terms_change_UpdateMarket {
__typename: "UpdateMarket"; __typename: "UpdateMarket";
marketId: string; marketId: string;
} }
export interface Proposals_proposals_terms_change_NewAsset_source_BuiltinAsset { export interface Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source_BuiltinAsset {
__typename: "BuiltinAsset"; __typename: "BuiltinAsset";
/** /**
* Maximum amount that can be requested by a party through the built-in asset faucet at a time * Maximum amount that can be requested by a party through the built-in asset faucet at a time
@ -82,7 +90,7 @@ export interface Proposals_proposals_terms_change_NewAsset_source_BuiltinAsset {
maxFaucetAmountMint: string; maxFaucetAmountMint: string;
} }
export interface Proposals_proposals_terms_change_NewAsset_source_ERC20 { export interface Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source_ERC20 {
__typename: "ERC20"; __typename: "ERC20";
/** /**
* The address of the ERC20 contract * The address of the ERC20 contract
@ -90,9 +98,9 @@ export interface Proposals_proposals_terms_change_NewAsset_source_ERC20 {
contractAddress: string; contractAddress: string;
} }
export type Proposals_proposals_terms_change_NewAsset_source = Proposals_proposals_terms_change_NewAsset_source_BuiltinAsset | Proposals_proposals_terms_change_NewAsset_source_ERC20; export type Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source = Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source_BuiltinAsset | Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source_ERC20;
export interface Proposals_proposals_terms_change_NewAsset { export interface Proposals_proposalsConnection_edges_node_terms_change_NewAsset {
__typename: "NewAsset"; __typename: "NewAsset";
/** /**
* The full name of the asset (e.g: Great British Pound) * The full name of the asset (e.g: Great British Pound)
@ -105,10 +113,10 @@ export interface Proposals_proposals_terms_change_NewAsset {
/** /**
* The source of the new asset * The source of the new asset
*/ */
source: Proposals_proposals_terms_change_NewAsset_source; source: Proposals_proposalsConnection_edges_node_terms_change_NewAsset_source;
} }
export interface Proposals_proposals_terms_change_UpdateNetworkParameter_networkParameter { export interface Proposals_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter_networkParameter {
__typename: "NetworkParameter"; __typename: "NetworkParameter";
/** /**
* The name of the network parameter * The name of the network parameter
@ -120,14 +128,14 @@ export interface Proposals_proposals_terms_change_UpdateNetworkParameter_network
value: string; value: string;
} }
export interface Proposals_proposals_terms_change_UpdateNetworkParameter { export interface Proposals_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter {
__typename: "UpdateNetworkParameter"; __typename: "UpdateNetworkParameter";
networkParameter: Proposals_proposals_terms_change_UpdateNetworkParameter_networkParameter; networkParameter: Proposals_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter_networkParameter;
} }
export type Proposals_proposals_terms_change = Proposals_proposals_terms_change_UpdateAsset | Proposals_proposals_terms_change_NewMarket | Proposals_proposals_terms_change_UpdateMarket | Proposals_proposals_terms_change_NewAsset | Proposals_proposals_terms_change_UpdateNetworkParameter; export type Proposals_proposalsConnection_edges_node_terms_change = Proposals_proposalsConnection_edges_node_terms_change_UpdateAsset | Proposals_proposalsConnection_edges_node_terms_change_NewMarket | Proposals_proposalsConnection_edges_node_terms_change_UpdateMarket | Proposals_proposalsConnection_edges_node_terms_change_NewAsset | Proposals_proposalsConnection_edges_node_terms_change_UpdateNetworkParameter;
export interface Proposals_proposals_terms { export interface Proposals_proposalsConnection_edges_node_terms {
__typename: "ProposalTerms"; __typename: "ProposalTerms";
/** /**
* RFC3339Nano time and date when voting closes for this proposal. * RFC3339Nano time and date when voting closes for this proposal.
@ -143,18 +151,18 @@ export interface Proposals_proposals_terms {
/** /**
* Actual change being introduced by the proposal - action the proposal triggers if passed and enacted. * Actual change being introduced by the proposal - action the proposal triggers if passed and enacted.
*/ */
change: Proposals_proposals_terms_change; change: Proposals_proposalsConnection_edges_node_terms_change;
} }
export interface Proposals_proposals_votes_yes_votes_party_stake { export interface Proposals_proposalsConnection_edges_node_votes_yes_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
currentStakeAvailable: string; currentStakeAvailable: string;
} }
export interface Proposals_proposals_votes_yes_votes_party { export interface Proposals_proposalsConnection_edges_node_votes_yes_votes_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -163,10 +171,10 @@ export interface Proposals_proposals_votes_yes_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: Proposals_proposals_votes_yes_votes_party_stake; stakingSummary: Proposals_proposalsConnection_edges_node_votes_yes_votes_party_stakingSummary;
} }
export interface Proposals_proposals_votes_yes_votes { export interface Proposals_proposalsConnection_edges_node_votes_yes_votes {
__typename: "Vote"; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
@ -175,14 +183,14 @@ export interface Proposals_proposals_votes_yes_votes {
/** /**
* The party casting the vote * The party casting the vote
*/ */
party: Proposals_proposals_votes_yes_votes_party; party: Proposals_proposalsConnection_edges_node_votes_yes_votes_party;
/** /**
* RFC3339Nano time and date when the vote reached Vega network * RFC3339Nano time and date when the vote reached Vega network
*/ */
datetime: string; datetime: string;
} }
export interface Proposals_proposals_votes_yes { export interface Proposals_proposalsConnection_edges_node_votes_yes {
__typename: "ProposalVoteSide"; __typename: "ProposalVoteSide";
/** /**
* Total number of governance tokens from the votes cast for this side * Total number of governance tokens from the votes cast for this side
@ -195,18 +203,18 @@ export interface Proposals_proposals_votes_yes {
/** /**
* All votes cast for this side * All votes cast for this side
*/ */
votes: Proposals_proposals_votes_yes_votes[] | null; votes: Proposals_proposalsConnection_edges_node_votes_yes_votes[] | null;
} }
export interface Proposals_proposals_votes_no_votes_party_stake { export interface Proposals_proposalsConnection_edges_node_votes_no_votes_party_stakingSummary {
__typename: "PartyStake"; __typename: "StakingSummary";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
currentStakeAvailable: string; currentStakeAvailable: string;
} }
export interface Proposals_proposals_votes_no_votes_party { export interface Proposals_proposalsConnection_edges_node_votes_no_votes_party {
__typename: "Party"; __typename: "Party";
/** /**
* Party identifier * Party identifier
@ -215,10 +223,10 @@ export interface Proposals_proposals_votes_no_votes_party {
/** /**
* The staking information for this Party * The staking information for this Party
*/ */
stake: Proposals_proposals_votes_no_votes_party_stake; stakingSummary: Proposals_proposalsConnection_edges_node_votes_no_votes_party_stakingSummary;
} }
export interface Proposals_proposals_votes_no_votes { export interface Proposals_proposalsConnection_edges_node_votes_no_votes {
__typename: "Vote"; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
@ -227,14 +235,14 @@ export interface Proposals_proposals_votes_no_votes {
/** /**
* The party casting the vote * The party casting the vote
*/ */
party: Proposals_proposals_votes_no_votes_party; party: Proposals_proposalsConnection_edges_node_votes_no_votes_party;
/** /**
* RFC3339Nano time and date when the vote reached Vega network * RFC3339Nano time and date when the vote reached Vega network
*/ */
datetime: string; datetime: string;
} }
export interface Proposals_proposals_votes_no { export interface Proposals_proposalsConnection_edges_node_votes_no {
__typename: "ProposalVoteSide"; __typename: "ProposalVoteSide";
/** /**
* Total number of governance tokens from the votes cast for this side * Total number of governance tokens from the votes cast for this side
@ -247,27 +255,31 @@ export interface Proposals_proposals_votes_no {
/** /**
* All votes cast for this side * All votes cast for this side
*/ */
votes: Proposals_proposals_votes_no_votes[] | null; votes: Proposals_proposalsConnection_edges_node_votes_no_votes[] | null;
} }
export interface Proposals_proposals_votes { export interface Proposals_proposalsConnection_edges_node_votes {
__typename: "ProposalVotes"; __typename: "ProposalVotes";
/** /**
* Yes votes cast for this proposal * Yes votes cast for this proposal
*/ */
yes: Proposals_proposals_votes_yes; yes: Proposals_proposalsConnection_edges_node_votes_yes;
/** /**
* No votes cast for this proposal * No votes cast for this proposal
*/ */
no: Proposals_proposals_votes_no; no: Proposals_proposalsConnection_edges_node_votes_no;
} }
export interface Proposals_proposals { export interface Proposals_proposalsConnection_edges_node {
__typename: "Proposal"; __typename: "Proposal";
/** /**
* Proposal ID that is filled by Vega once proposal reaches the network * Proposal ID that is filled by Vega once proposal reaches the network
*/ */
id: string | null; id: string | null;
/**
* Rationale behind the proposal
*/
rationale: Proposals_proposalsConnection_edges_node_rationale;
/** /**
* A UUID reference to aid tracking proposals on Vega * A UUID reference to aid tracking proposals on Vega
*/ */
@ -284,27 +296,43 @@ export interface Proposals_proposals {
* Reason for the proposal to be rejected by the core * Reason for the proposal to be rejected by the core
*/ */
rejectionReason: ProposalRejectionReason | null; rejectionReason: ProposalRejectionReason | null;
/**
* Party that prepared the proposal
*/
party: Proposals_proposalsConnection_edges_node_party;
/** /**
* Error details of the rejectionReason * Error details of the rejectionReason
*/ */
errorDetails: string | null; errorDetails: string | null;
/**
* Party that prepared the proposal
*/
party: Proposals_proposals_party;
/** /**
* Terms of the proposal * Terms of the proposal
*/ */
terms: Proposals_proposals_terms; terms: Proposals_proposalsConnection_edges_node_terms;
/** /**
* Votes cast for this proposal * Votes cast for this proposal
*/ */
votes: Proposals_proposals_votes; votes: Proposals_proposalsConnection_edges_node_votes;
}
export interface Proposals_proposalsConnection_edges {
__typename: "ProposalEdge";
/**
* The proposal data
*/
node: Proposals_proposalsConnection_edges_node;
}
export interface Proposals_proposalsConnection {
__typename: "ProposalsConnection";
/**
* List of proposals available for the connection
*/
edges: (Proposals_proposalsConnection_edges | null)[] | null;
} }
export interface Proposals { export interface Proposals {
/** /**
* All governance proposals in the Vega network * All governance proposals in the Vega network
*/ */
proposals: Proposals_proposals[] | null; proposalsConnection: Proposals_proposalsConnection;
} }

View File

@ -1,5 +1,5 @@
export { export {
ProposalsContainer, ProposalsContainer,
PROPOSALS_QUERY,
ProposalsContainer as default, ProposalsContainer as default,
PROPOSALS_QUERY,
} from './proposals-container'; } from './proposals-container';

View File

@ -1,56 +1,36 @@
import { gql, useQuery } from '@apollo/client'; import { gql, useQuery } from '@apollo/client';
import { ProposalState } from '@vegaprotocol/types'; import { getNotRejectedProposals } from '@vegaprotocol/governance';
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit'; import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
import compact from 'lodash/compact'; import { useMemo } from 'react';
import filter from 'lodash/filter';
import flow from 'lodash/flow';
import orderBy from 'lodash/orderBy';
import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { SplashLoader } from '../../../components/splash-loader'; import { SplashLoader } from '../../../components/splash-loader';
import { ProposalsList } from '../components/proposals-list'; import { ProposalsList } from '../components/proposals-list';
import { PROPOSALS_FRAGMENT } from '../proposal-fragment'; import { PROPOSAL_FRAGMENT } from '../proposal-fragment';
import type { Proposals } from './__generated__/Proposals'; import type { Proposals } from './__generated__/Proposals';
export const PROPOSALS_QUERY = gql` export const PROPOSALS_QUERY = gql`
${PROPOSALS_FRAGMENT} ${PROPOSAL_FRAGMENT}
query Proposals { query Proposals {
proposals { proposalsConnection {
...ProposalFields edges {
node {
...ProposalFields
}
}
} }
} }
`; `;
export const ProposalsContainer = () => { export const ProposalsContainer = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, loading, error } = useQuery<Proposals, never>(PROPOSALS_QUERY, { const { data, loading, error } = useQuery<Proposals>(PROPOSALS_QUERY, {
pollInterval: 5000, pollInterval: 5000,
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
errorPolicy: 'ignore', // this is to get around some backend issues and should be removed in future errorPolicy: 'ignore',
}); });
const proposals = React.useMemo(() => { const proposals = useMemo(() => getNotRejectedProposals(data), [data]);
if (!data?.proposals?.length) {
return [];
}
return flow([
compact,
(arr) =>
filter(arr, ({ state }) => state !== ProposalState.STATE_REJECTED),
(arr) =>
orderBy(
arr,
[
(p) => new Date(p.terms.enactmentDatetime).getTime(),
(p) => new Date(p.terms.closingDatetime).getTime(),
(p) => p.id,
],
['desc', 'desc', 'desc']
),
])(data.proposals);
}, [data]);
if (error) { if (error) {
return ( return (

View File

@ -1,46 +1,19 @@
import { useQuery } from '@apollo/client'; import { useQuery } from '@apollo/client';
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit'; import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
import compact from 'lodash/compact'; import { useMemo } from 'react';
import filter from 'lodash/filter';
import flow from 'lodash/flow';
import orderBy from 'lodash/orderBy';
import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PROPOSALS_QUERY } from '../proposals';
import { SplashLoader } from '../../../components/splash-loader'; import { SplashLoader } from '../../../components/splash-loader';
import { RejectedProposalsList } from '../components/proposals-list'; import { RejectedProposalsList } from '../components/proposals-list';
import { getRejectedProposals } from '@vegaprotocol/governance';
import { PROPOSALS_QUERY } from '../proposals';
import type { Proposals } from '../proposals/__generated__/Proposals'; import type { Proposals } from '../proposals/__generated__/Proposals';
import { ProposalState } from '@vegaprotocol/types';
export const RejectedProposalsContainer = () => { export const RejectedProposalsContainer = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, loading, error } = useQuery<Proposals, never>(PROPOSALS_QUERY, { const { data, loading, error } = useQuery<Proposals>(PROPOSALS_QUERY);
pollInterval: 5000,
errorPolicy: 'ignore', // this is to get around some backend issues and should be removed in future
});
const proposals = React.useMemo(() => { const proposals = useMemo(() => getRejectedProposals(data), [data]);
if (!data?.proposals?.length) {
return [];
}
return flow([
compact,
(arr) =>
filter(arr, ({ state }) => state === ProposalState.STATE_REJECTED),
(arr) =>
orderBy(
arr,
[
(p) => new Date(p.terms.enactmentDatetime).getTime(),
(p) => new Date(p.terms.closingDatetime).getTime(),
(p) => p.id,
],
['desc', 'desc', 'desc']
),
])(data.proposals);
}, [data]);
if (error) { if (error) {
return ( return (

View File

@ -16,6 +16,11 @@ export function generateProposal(
const defaultProposal: ProposalFields = { const defaultProposal: ProposalFields = {
__typename: 'Proposal', __typename: 'Proposal',
id: faker.datatype.uuid(), id: faker.datatype.uuid(),
rationale: {
__typename: 'ProposalRationale',
title: '',
description: '',
},
reference: 'ref' + faker.datatype.uuid(), reference: 'ref' + faker.datatype.uuid(),
state: ProposalState.STATE_OPEN, state: ProposalState.STATE_OPEN,
datetime: faker.date.past().toISOString(), datetime: faker.date.past().toISOString(),
@ -84,8 +89,8 @@ export const generateYesVotes = (
party: { party: {
id: faker.datatype.uuid(), id: faker.datatype.uuid(),
__typename: 'Party', __typename: 'Party',
stake: { stakingSummary: {
__typename: 'PartyStake', __typename: 'StakingSummary',
currentStakeAvailable: fixedTokenValue currentStakeAvailable: fixedTokenValue
? fixedTokenValue.toString() ? fixedTokenValue.toString()
: faker.datatype : faker.datatype
@ -119,8 +124,8 @@ export const generateNoVotes = (
party: { party: {
id: faker.datatype.uuid(), id: faker.datatype.uuid(),
__typename: 'Party', __typename: 'Party',
stake: { stakingSummary: {
__typename: 'PartyStake', __typename: 'StakingSummary',
currentStakeAvailable: fixedTokenValue currentStakeAvailable: fixedTokenValue
? fixedTokenValue.toString() ? fixedTokenValue.toString()
: faker.datatype : faker.datatype

View File

@ -1,2 +1,3 @@
export * from './proposals-hooks'; export * from './proposals-hooks';
export * from './proposal-form'; export * from './proposal-form';
export * from './proposals-queries';

View File

@ -0,0 +1 @@
export * from './proposals-queries';

View File

@ -0,0 +1,61 @@
import compact from 'lodash/compact';
import filter from 'lodash/filter';
import flow from 'lodash/flow';
import orderBy from 'lodash/orderBy';
import { ProposalState } from '@vegaprotocol/types';
type Proposal = {
__typename: 'Proposal';
id: string | null;
state: ProposalState;
terms: {
enactmentDatetime: string | null;
closingDatetime: string;
};
};
type ProposalEdge = {
node: Proposal;
};
type ProposalsConnection = {
proposalsConnection: {
edges: (ProposalEdge | null)[] | null;
};
};
export const getProposals = (data?: ProposalsConnection) => {
const proposals = data?.proposalsConnection.edges
?.filter((e) => e?.node)
.map((e) => e?.node);
return proposals ? (proposals as Proposal[]) : [];
};
const orderByDate = (arr: Proposal[]) =>
orderBy(
arr,
[
(p) => new Date(p.terms.enactmentDatetime || 0).getTime(), // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered.
(p) => new Date(p.terms.closingDatetime).getTime(),
(p) => p.id,
],
['desc', 'desc', 'desc']
);
export const getNotRejectedProposals = (data?: ProposalsConnection) => {
const proposals = getProposals(data);
return flow([
compact,
(arr: Proposal[]) =>
filter(arr, ({ state }) => state !== ProposalState.STATE_REJECTED),
orderByDate,
])(proposals);
};
export const getRejectedProposals = (data?: ProposalsConnection) => {
const proposals = getProposals(data);
return flow([
compact,
(arr: Proposal[]) =>
filter(arr, ({ state }) => state === ProposalState.STATE_REJECTED),
orderByDate,
])(proposals);
};

View File

@ -1,5 +1,5 @@
export * from './date'; export * from './date';
export * from './number'; export * from './number';
export * from './size'; export * from './size';
export * from './truncate'; export * from './strings';
export * from './utils'; export * from './utils';

View File

@ -0,0 +1,29 @@
import { truncateByChars, ELLIPSIS, shorten } from './strings';
describe('truncateByChars', () => {
it.each([
{
i: '12345678901234567890',
s: undefined,
e: undefined,
o: `123456${ELLIPSIS}567890`,
},
{ i: '12345678901234567890', s: 0, e: 10, o: `${ELLIPSIS}1234567890` },
{ i: '123', s: 0, e: 4, o: '123' },
])('should truncate given string by specific chars', ({ i, s, e, o }) => {
expect(truncateByChars(i, s, e)).toStrictEqual(o);
});
});
describe('shorten', () => {
it.each([
{ i: '12345678901234567890', l: undefined, o: '12345678901234567890' },
{ i: '12345678901234567890', l: 0, o: `12345678901234567890` },
{ i: '12345678901234567890', l: 10, o: `123456789${ELLIPSIS}` },
{ i: '12345678901234567890', l: 20, o: `1234567890123456789${ELLIPSIS}` },
{ i: '12345678901234567890', l: 30, o: `12345678901234567890` },
])('should shorten given string by specific limit', ({ i, l, o }) => {
const output = shorten(i, l);
expect(output).toStrictEqual(o);
});
});

View File

@ -0,0 +1,19 @@
export const ELLIPSIS = '\u2026';
export function truncateByChars(input: string, start = 6, end = 6) {
// if the text is shorted than the total number of chars to show
// no truncation is needed. Plus one is to account for the ellipsis
if (input.length <= start + end + 1) {
return input;
}
return input.slice(0, start) + ELLIPSIS + input.slice(-end);
}
export function shorten(input: string, limit?: number) {
if (!input || !limit || input.length < limit || limit <= 0) {
return input;
}
const output = input.substring(0, limit - 1);
const suffix = output.length < limit ? ELLIPSIS : '';
return input.substring(0, limit - 1) + suffix;
}

View File

@ -1,14 +0,0 @@
export function truncateByChars(s: string, startChars = 6, endChars = 6) {
const ELLIPSIS = '\u2026';
// if the text is shorted than the total number of chars to show
// no truncation is needed. Plus one is to account for the ellipsis
if (s.length <= startChars + endChars + 1) {
return s;
}
const start = s.slice(0, startChars);
const end = s.slice(-endChars);
return start + ELLIPSIS + end;
}