fix(trading): fix proposals not showing (#3859)
This commit is contained in:
parent
65747e8d26
commit
b499c293e3
@ -12,7 +12,7 @@ export const Proposed = () => {
|
|||||||
const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL);
|
const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="min-h-[200px]">
|
<div className="h-[400px]">
|
||||||
<ProposalsList />
|
<ProposalsList />
|
||||||
</div>
|
</div>
|
||||||
<ExternalLink className="py-4 px-[11px] text-sm" href={externalLink}>
|
<ExternalLink className="py-4 px-[11px] text-sm" href={externalLink}>
|
||||||
|
@ -5,57 +5,74 @@ import {
|
|||||||
waitFor,
|
waitFor,
|
||||||
getAllByRole,
|
getAllByRole,
|
||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
|
import merge from 'lodash/merge';
|
||||||
|
import type { MockedResponse } from '@apollo/client/testing';
|
||||||
import { MockedProvider } from '@apollo/client/testing';
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
import { ProposalsList } from './proposals-list';
|
import { ProposalsList } from './proposals-list';
|
||||||
import type { ProposalListFieldsFragment } from '../../lib/proposals-data-provider';
|
|
||||||
import * as Types from '@vegaprotocol/types';
|
import * as Types from '@vegaprotocol/types';
|
||||||
|
import { createProposalListFieldsFragment } from '../../lib/proposals-data-provider/proposals.mock';
|
||||||
const votesMock = {
|
import type { ProposalsListQuery } from '../../lib';
|
||||||
yes: {
|
import { ProposalsListDocument } from '../../lib';
|
||||||
totalTokens: '5000',
|
import type { PartialDeep } from 'type-fest';
|
||||||
},
|
|
||||||
no: {
|
|
||||||
totalTokens: '2000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let marketsProposalMock: ProposalListFieldsFragment[] | null = [
|
|
||||||
{
|
|
||||||
id: 'id-1',
|
|
||||||
state: Types.ProposalState.STATE_OPEN,
|
|
||||||
votes: { ...votesMock },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'id-2',
|
|
||||||
state: Types.ProposalState.STATE_PASSED,
|
|
||||||
votes: { ...votesMock },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'id-3',
|
|
||||||
state: Types.ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
|
||||||
votes: { ...votesMock },
|
|
||||||
},
|
|
||||||
] as ProposalListFieldsFragment[];
|
|
||||||
|
|
||||||
const useDataProvider = () => {
|
|
||||||
return {
|
|
||||||
data: marketsProposalMock,
|
|
||||||
loading: false,
|
|
||||||
error: false,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
|
||||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
|
||||||
useDataProvider: jest.fn(() => useDataProvider()),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('ProposalsList', () => {
|
describe('ProposalsList', () => {
|
||||||
beforeEach(() => {
|
const createProposalsMock = (override?: PartialDeep<ProposalsListQuery>) => {
|
||||||
jest.clearAllMocks();
|
const defaultProposalEdges = [
|
||||||
});
|
{
|
||||||
|
__typename: 'ProposalEdge' as const,
|
||||||
|
node: createProposalListFieldsFragment({
|
||||||
|
id: 'id-1',
|
||||||
|
state: Types.ProposalState.STATE_OPEN,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: 'ProposalEdge' as const,
|
||||||
|
node: createProposalListFieldsFragment({
|
||||||
|
id: 'id-2',
|
||||||
|
state: Types.ProposalState.STATE_PASSED,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: 'ProposalEdge' as const,
|
||||||
|
node: createProposalListFieldsFragment({
|
||||||
|
id: 'id-3',
|
||||||
|
state: Types.ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const data = merge(
|
||||||
|
{
|
||||||
|
proposalsConnection: {
|
||||||
|
__typename: 'ProposalsConnection' as const,
|
||||||
|
edges: defaultProposalEdges,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
override
|
||||||
|
);
|
||||||
|
|
||||||
|
const mock: MockedResponse<ProposalsListQuery> = {
|
||||||
|
request: {
|
||||||
|
query: ProposalsListDocument,
|
||||||
|
variables: {
|
||||||
|
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
};
|
||||||
|
|
||||||
it('should be properly rendered', async () => {
|
it('should be properly rendered', async () => {
|
||||||
|
const mock = createProposalsMock();
|
||||||
await act(() => {
|
await act(() => {
|
||||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
render(
|
||||||
|
<MockedProvider mocks={[mock]}>
|
||||||
|
<ProposalsList />
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const container = document.querySelector('.ag-center-cols-container');
|
const container = document.querySelector('.ag-center-cols-container');
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
@ -65,15 +82,25 @@ describe('ProposalsList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('some of states should be filtered out', async () => {
|
it('some of states should be filtered out', async () => {
|
||||||
marketsProposalMock = [
|
const mock = createProposalsMock({
|
||||||
|
proposalsConnection: {
|
||||||
|
edges: [
|
||||||
{
|
{
|
||||||
...(marketsProposalMock as ProposalListFieldsFragment[])[0],
|
__typename: 'ProposalEdge',
|
||||||
|
node: createProposalListFieldsFragment({
|
||||||
|
id: 'id-1',
|
||||||
state: Types.ProposalState.STATE_ENACTED,
|
state: Types.ProposalState.STATE_ENACTED,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
...(marketsProposalMock as ProposalListFieldsFragment[]).slice(1),
|
],
|
||||||
];
|
},
|
||||||
|
});
|
||||||
await act(() => {
|
await act(() => {
|
||||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
render(
|
||||||
|
<MockedProvider mocks={[mock]}>
|
||||||
|
<ProposalsList />
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const container = document.querySelector('.ag-center-cols-container');
|
const container = document.querySelector('.ag-center-cols-container');
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
@ -83,9 +110,12 @@ describe('ProposalsList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('empty response should causes no data message display', async () => {
|
it('empty response should causes no data message display', async () => {
|
||||||
marketsProposalMock = null;
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
render(
|
||||||
|
<MockedProvider>
|
||||||
|
<ProposalsList />
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const container = document.querySelector('.ag-center-cols-container');
|
const container = document.querySelector('.ag-center-cols-container');
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Types from '@vegaprotocol/types';
|
import * as Types from '@vegaprotocol/types';
|
||||||
import { proposalsDataProvider } from '../../lib/proposals-data-provider';
|
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { useColumnDefs } from './use-column-defs';
|
import { useColumnDefs } from './use-column-defs';
|
||||||
import type { ProposalListFieldsFragment } from '../../lib/proposals-data-provider/__generated__/Proposals';
|
import type { ProposalListFieldsFragment } from '../../lib/proposals-data-provider/__generated__/Proposals';
|
||||||
|
import { useProposalsListQuery } from '../../lib/proposals-data-provider/__generated__/Proposals';
|
||||||
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
|
|
||||||
export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||||
data.filter((proposal) =>
|
data.filter((proposal) =>
|
||||||
@ -21,13 +21,15 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
|||||||
export const ProposalsList = () => {
|
export const ProposalsList = () => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const [dataCount, setDataCount] = useState(0);
|
const [dataCount, setDataCount] = useState(0);
|
||||||
const { data, loading, error, reload } = useDataProvider({
|
const { data, loading, error, refetch } = useProposalsListQuery({
|
||||||
dataProvider: proposalsDataProvider,
|
|
||||||
variables: {
|
variables: {
|
||||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||||
},
|
},
|
||||||
|
errorPolicy: 'all', // currently there are some proposals failing due to proposals existing without settlement asset ids
|
||||||
});
|
});
|
||||||
const filteredData = getNewMarketProposals(data || []);
|
const filteredData = getNewMarketProposals(
|
||||||
|
removePaginationWrapper(data?.proposalsConnection?.edges)
|
||||||
|
);
|
||||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||||
@ -36,11 +38,10 @@ export const ProposalsList = () => {
|
|||||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative h-full">
|
||||||
<AgGrid
|
<AgGrid
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
domLayout="autoHeight"
|
|
||||||
columnDefs={columnDefs}
|
columnDefs={columnDefs}
|
||||||
rowData={filteredData}
|
rowData={filteredData}
|
||||||
defaultColDef={defaultColDef}
|
defaultColDef={defaultColDef}
|
||||||
@ -48,6 +49,8 @@ export const ProposalsList = () => {
|
|||||||
suppressNoRowsOverlay
|
suppressNoRowsOverlay
|
||||||
onFilterChanged={onFilterChanged}
|
onFilterChanged={onFilterChanged}
|
||||||
storeKey="proposedMarkets"
|
storeKey="proposedMarkets"
|
||||||
|
getRowId={({ data }) => data.id}
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute inset-0">
|
<div className="pointer-events-none absolute inset-0">
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
@ -56,7 +59,7 @@ export const ProposalsList = () => {
|
|||||||
data={filteredData}
|
data={filteredData}
|
||||||
noDataMessage={t('No markets')}
|
noDataMessage={t('No markets')}
|
||||||
noDataCondition={() => !dataCount}
|
noDataCondition={() => !dataCount}
|
||||||
reload={reload}
|
reload={refetch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,6 +11,7 @@ export const proposalListQuery = (
|
|||||||
): ProposalsListQuery => {
|
): ProposalsListQuery => {
|
||||||
const defaultResult: ProposalsListQuery = {
|
const defaultResult: ProposalsListQuery = {
|
||||||
proposalsConnection: {
|
proposalsConnection: {
|
||||||
|
__typename: 'ProposalsConnection',
|
||||||
edges: proposalListFields.map((node) => ({
|
edges: proposalListFields.map((node) => ({
|
||||||
__typename: 'ProposalEdge',
|
__typename: 'ProposalEdge',
|
||||||
node,
|
node,
|
||||||
@ -104,8 +105,10 @@ export const marketUpdateProposal: ProposalListFieldsFragment = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const proposalListFields: ProposalListFieldsFragment[] = [
|
export const createProposalListFieldsFragment = (
|
||||||
{
|
override?: PartialDeep<ProposalListFieldsFragment>
|
||||||
|
): ProposalListFieldsFragment => {
|
||||||
|
const defaultProposal: ProposalListFieldsFragment = {
|
||||||
id: 'e9ec6d5c46a7e7bcabf9ba7a893fa5a5eeeec08b731f06f7a6eb7bf0e605b829',
|
id: 'e9ec6d5c46a7e7bcabf9ba7a893fa5a5eeeec08b731f06f7a6eb7bf0e605b829',
|
||||||
reference: 'injected_at_runtime',
|
reference: 'injected_at_runtime',
|
||||||
state: Schema.ProposalState.STATE_OPEN,
|
state: Schema.ProposalState.STATE_OPEN,
|
||||||
@ -194,7 +197,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
|||||||
__typename: 'ProposalTerms',
|
__typename: 'ProposalTerms',
|
||||||
},
|
},
|
||||||
__typename: 'Proposal',
|
__typename: 'Proposal',
|
||||||
},
|
};
|
||||||
|
return merge(defaultProposal, override);
|
||||||
|
};
|
||||||
|
|
||||||
|
const proposalListFields: ProposalListFieldsFragment[] = [
|
||||||
|
createProposalListFieldsFragment(),
|
||||||
{
|
{
|
||||||
id: '1cd1deb532b97fbeb9262fe94499ecec5835e60ae564b7c5af530c90a13c29cb',
|
id: '1cd1deb532b97fbeb9262fe94499ecec5835e60ae564b7c5af530c90a13c29cb',
|
||||||
reference: 'injected_at_runtime',
|
reference: 'injected_at_runtime',
|
||||||
|
Loading…
Reference in New Issue
Block a user