chore(trading): add filters to the proposals table (#3375)
This commit is contained in:
parent
643d5408cd
commit
7e4aafcb77
@ -1,5 +1,5 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { aliasGQLQuery, checkSorting } from '@vegaprotocol/cypress';
|
||||
import { marketsQuery } from '@vegaprotocol/mock';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
|
||||
@ -85,6 +85,7 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('view-market-list-link')
|
||||
.should('have.attr', 'href', '#/markets/all')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="All markets"]').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
@ -117,6 +118,85 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
|
||||
);
|
||||
});
|
||||
it('proposed markets tab should be sorted properly', () => {
|
||||
cy.getByTestId('view-market-list-link').click();
|
||||
cy.get('[data-testid="Proposed markets"]').click();
|
||||
const marketColDefault = [
|
||||
'ETHUSD',
|
||||
'LINKUSD',
|
||||
'ETHUSD',
|
||||
'ETHDAI.MF21',
|
||||
'AAPL.MF21',
|
||||
'BTCUSD.MF21',
|
||||
'TSLA.QM21',
|
||||
'AAVEDAI.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'UNIDAI.MF21',
|
||||
];
|
||||
const marketColAsc = [
|
||||
'AAPL.MF21',
|
||||
'AAVEDAI.MF21',
|
||||
'BTCUSD.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'ETHDAI.MF21',
|
||||
'ETHUSD',
|
||||
'ETHUSD',
|
||||
'LINKUSD',
|
||||
'TSLA.QM21',
|
||||
'UNIDAI.MF21',
|
||||
];
|
||||
const marketColDesc = [
|
||||
'UNIDAI.MF21',
|
||||
'TSLA.QM21',
|
||||
'LINKUSD',
|
||||
'ETHUSD',
|
||||
'ETHUSD',
|
||||
'ETHDAI.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'BTCUSD.MF21',
|
||||
'AAVEDAI.MF21',
|
||||
'AAPL.MF21',
|
||||
];
|
||||
checkSorting('market', marketColDefault, marketColAsc, marketColDesc);
|
||||
|
||||
const stateColDefault = [
|
||||
'Open',
|
||||
'Passed',
|
||||
'Waiting for Node Vote',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Waiting for Node Vote',
|
||||
'Open',
|
||||
];
|
||||
const stateColAsc = [
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Waiting for Node Vote',
|
||||
'Waiting for Node Vote',
|
||||
];
|
||||
const stateColDesc = [
|
||||
'Waiting for Node Vote',
|
||||
'Waiting for Node Vote',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
];
|
||||
checkSorting('state', stateColDefault, stateColAsc, stateColDesc);
|
||||
});
|
||||
|
||||
it('opening auction subsets should be properly displayed', () => {
|
||||
cy.mockTradingPage(
|
||||
|
@ -52,6 +52,9 @@ export const checkSorting = (
|
||||
cy.get(`[col-id="${column}"]`).click();
|
||||
});
|
||||
checkSortChange(orderTabDesc, column);
|
||||
cy.get('.ag-header-container').within(() => {
|
||||
cy.get(`[col-id="${column}"]`).click();
|
||||
});
|
||||
};
|
||||
|
||||
const checkSortChange = (tabsArr: string[], column: string) => {
|
||||
|
@ -11,12 +11,13 @@ import {
|
||||
AgGridDynamic as AgGrid,
|
||||
PriceFlashCell,
|
||||
MarketNameCell,
|
||||
SetFilter,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { MarketMaybeWithData, MarketFieldsFragment } from '../../';
|
||||
import type { MarketMaybeWithData } from '../../';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
const { MarketTradingMode, AuctionTrigger } = Schema;
|
||||
@ -33,7 +34,6 @@ export const MarketListTable = forwardRef<
|
||||
return (
|
||||
<AgGrid
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
overlayNoRowsTemplate={t('No markets')}
|
||||
getRowId={getRowId}
|
||||
ref={ref}
|
||||
defaultColDef={{
|
||||
@ -43,7 +43,7 @@ export const MarketListTable = forwardRef<
|
||||
filter: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
}}
|
||||
suppressCellFocus={true}
|
||||
suppressCellFocus
|
||||
components={{ PriceFlashCell, MarketNameCell }}
|
||||
{...props}
|
||||
>
|
||||
@ -59,11 +59,11 @@ export const MarketListTable = forwardRef<
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Trading mode')}
|
||||
field="data"
|
||||
field="tradingMode"
|
||||
minWidth={170}
|
||||
valueGetter={({
|
||||
valueFormatter={({
|
||||
data,
|
||||
}: VegaValueGetterParams<MarketMaybeWithData, 'data'>) => {
|
||||
}: VegaValueFormatterParams<MarketMaybeWithData, 'data'>) => {
|
||||
if (!data?.data) return undefined;
|
||||
const { trigger } = data.data;
|
||||
const { tradingMode } = data;
|
||||
@ -75,14 +75,22 @@ export const MarketListTable = forwardRef<
|
||||
- ${Schema.AuctionTriggerMapping[trigger]}`
|
||||
: Schema.MarketTradingModeMapping[tradingMode];
|
||||
}}
|
||||
filter={SetFilter}
|
||||
filterParams={{
|
||||
set: Schema.MarketTradingModeMapping,
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Status')}
|
||||
field="state"
|
||||
valueGetter={({
|
||||
valueFormatter={({
|
||||
data,
|
||||
}: VegaValueGetterParams<MarketFieldsFragment, 'state'>) => {
|
||||
return data?.state ? Schema.MarketStateMapping[data?.state] : '-';
|
||||
}: VegaValueFormatterParams<MarketMaybeWithData, 'state'>) => {
|
||||
return data?.state ? Schema.MarketStateMapping[data.state] : '-';
|
||||
}}
|
||||
filter={SetFilter}
|
||||
filterParams={{
|
||||
set: Schema.MarketStateMapping,
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
|
@ -1,4 +1,6 @@
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketListTable } from './market-list-table';
|
||||
@ -12,15 +14,24 @@ interface MarketsContainerProps {
|
||||
}
|
||||
|
||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const { data, error, loading, reload } = useDataProvider({
|
||||
dataProvider,
|
||||
skipUpdates: true,
|
||||
variables: undefined,
|
||||
});
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [data]);
|
||||
const onFilterChanged = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<MarketListTable
|
||||
rowData={error ? [] : data}
|
||||
ref={gridRef}
|
||||
rowData={data}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
onCellClicked={(cellEvent: CellClickedEvent) => {
|
||||
@ -40,6 +51,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
);
|
||||
}}
|
||||
onMarketClick={onSelect}
|
||||
onFilterChanged={onFilterChanged}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@ -47,6 +59,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
|
@ -91,6 +91,6 @@ describe('ProposalsList', () => {
|
||||
await waitFor(() => {
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText('No Rows To Show')).toBeInTheDocument();
|
||||
expect(screen.getByText('No markets')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,21 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import { proposalsDataProvider } from '../proposals-data-provider';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
import type { ProposalListFieldsFragment } from '../proposals-data-provider/__generated__/Proposals';
|
||||
|
||||
// prevent cutting filter windows by auto-height layout
|
||||
const CUSTOM_GRID_STYLES = `
|
||||
.ag-layout-auto-height {
|
||||
min-height: 200px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
data.filter((proposal) =>
|
||||
[
|
||||
@ -19,6 +27,7 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
|
||||
export const ProposalsList = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
gridRef.current?.api?.sizeColumnsToFit();
|
||||
}, [gridRef]);
|
||||
@ -30,22 +39,37 @@ export const ProposalsList = () => {
|
||||
});
|
||||
const filteredData = getNewMarketProposals(data || []);
|
||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [filteredData]);
|
||||
const onFilterChanged = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
reload={reload}
|
||||
>
|
||||
<div className="relative">
|
||||
<AgGrid
|
||||
ref={gridRef}
|
||||
className="w-full h-full"
|
||||
domLayout="autoHeight"
|
||||
className="min-w-full"
|
||||
columnDefs={columnDefs}
|
||||
rowData={filteredData}
|
||||
defaultColDef={defaultColDef}
|
||||
onGridReady={handleOnGridReady}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
onFilterChanged={onFilterChanged}
|
||||
customThemeParams={CUSTOM_GRID_STYLES}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { DateRangeFilter, SetFilter } from '@vegaprotocol/datagrid';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
@ -73,6 +74,10 @@ export const useColumnDefs = () => {
|
||||
value,
|
||||
}: VegaValueFormatterParams<ProposalListFieldsFragment, 'state'>) =>
|
||||
value ? ProposalStateMapping[value] : '-',
|
||||
filter: SetFilter,
|
||||
filterParams: {
|
||||
set: ProposalStateMapping,
|
||||
},
|
||||
},
|
||||
{
|
||||
colId: 'voting',
|
||||
@ -99,6 +104,7 @@ export const useColumnDefs = () => {
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
filter: false,
|
||||
},
|
||||
{
|
||||
colId: 'closing-date',
|
||||
@ -110,6 +116,7 @@ export const useColumnDefs = () => {
|
||||
ProposalListFieldsFragment,
|
||||
'terms.closingDatetime'
|
||||
>) => (value ? getDateTimeFormat().format(new Date(value)) : '-'),
|
||||
filter: DateRangeFilter,
|
||||
},
|
||||
{
|
||||
colId: 'enactment-date',
|
||||
@ -121,13 +128,18 @@ export const useColumnDefs = () => {
|
||||
ProposalListFieldsFragment,
|
||||
'terms.enactmentDatetime'
|
||||
>) => (value ? getDateTimeFormat().format(new Date(value)) : '-'),
|
||||
filter: DateRangeFilter,
|
||||
},
|
||||
];
|
||||
}, [VEGA_TOKEN_URL, requiredMajorityPercentage]);
|
||||
const defaultColDef: ColDef = useMemo(() => {
|
||||
return {
|
||||
sortable: false,
|
||||
sortable: true,
|
||||
cellClass: cellCss,
|
||||
flex: 1,
|
||||
resizable: true,
|
||||
filter: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
};
|
||||
}, []);
|
||||
return useMemo(
|
||||
|
Loading…
Reference in New Issue
Block a user