fix(trading): use ag grid to handle error,loading and no data message (#4012)
This commit is contained in:
parent
011e4e4cec
commit
0d96c487d9
@ -98,23 +98,14 @@ describe('positions', { tags: '@smoke', testIsolation: true }, () => {
|
||||
},
|
||||
},
|
||||
];
|
||||
const marketData = marketsDataQuery();
|
||||
const edges = marketData.marketsConnection?.edges.map((market) => {
|
||||
const replace =
|
||||
market.node.data?.market.id === 'market-2' ? null : market.node.data;
|
||||
return { ...market, node: { ...market.node, data: replace } };
|
||||
});
|
||||
const overrides = {
|
||||
...marketData,
|
||||
marketsConnection: { ...marketData.marketsConnection, edges },
|
||||
marketsConnection: { edges: [] },
|
||||
};
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'MarketsData', overrides, errors);
|
||||
});
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.get('.pointer-events-none.absolute.inset-0').contains(
|
||||
'Something went wrong:'
|
||||
);
|
||||
cy.get('[data-testid="tab-positions"]').contains('no market data');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -11,14 +11,12 @@ import {
|
||||
formatNumberPercentage,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { updateGridData } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
} from '@vegaprotocol/network-parameters';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import {
|
||||
AsyncRenderer,
|
||||
Tab,
|
||||
Tabs,
|
||||
Link as UiToolkitLink,
|
||||
@ -26,14 +24,13 @@ import {
|
||||
ExternalLink,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { Header, HeaderStat, HeaderTitle } from '../../components/header';
|
||||
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { IGetRowsParams } from 'ag-grid-community';
|
||||
|
||||
import type { LiquidityProvisionData, Filter } from '@vegaprotocol/liquidity';
|
||||
import type { Filter } from '@vegaprotocol/liquidity';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
@ -74,21 +71,12 @@ export const LiquidityContainer = ({
|
||||
}) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { data: market } = useMarket(marketId);
|
||||
const dataRef = useRef<LiquidityProvisionData[] | null>(null);
|
||||
|
||||
// To be removed when liquidityProvision subscriptions are working
|
||||
useReloadLiquidityData(marketId);
|
||||
|
||||
const update = useCallback(
|
||||
({ data }: { data: LiquidityProvisionData[] | null }) => {
|
||||
return updateGridData(dataRef, data, gridRef);
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: lpAggregatedDataProvider,
|
||||
update,
|
||||
variables: { marketId: marketId || '', filter },
|
||||
skip: !marketId,
|
||||
});
|
||||
@ -103,36 +91,16 @@ export const LiquidityContainer = ({
|
||||
]);
|
||||
const stakeToCcyVolume = params.market_liquidity_stakeToCcyVolume;
|
||||
|
||||
const getRows = useCallback(
|
||||
async ({ successCallback, startRow, endRow }: IGetRowsParams) => {
|
||||
const rowsThisBlock = dataRef.current
|
||||
? dataRef.current.slice(startRow, endRow)
|
||||
: [];
|
||||
const lastRow = dataRef.current ? dataRef.current.length : 0;
|
||||
successCallback(rowsThisBlock, lastRow);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<LiquidityTable
|
||||
ref={gridRef}
|
||||
datasource={{ getRows }}
|
||||
rowModelType="infinite"
|
||||
rowData={data}
|
||||
symbol={symbol}
|
||||
assetDecimalPlaces={assetDecimalPlaces}
|
||||
stakeToCcyVolume={stakeToCcyVolume}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No data')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No liquidity provisions')}
|
||||
noDataCondition={(data) => !data?.length}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -27,7 +27,6 @@ import type { ColDef } from 'ag-grid-community';
|
||||
import { SettlementDateCell } from './settlement-date-cell';
|
||||
import { SettlementPriceCell } from './settlement-price-cell';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
type SettlementAsset =
|
||||
MarketMaybeWithData['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
@ -55,7 +54,6 @@ export const Closed = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const {
|
||||
data: marketData,
|
||||
loading,
|
||||
error,
|
||||
reload,
|
||||
} = useDataProvider({
|
||||
@ -117,21 +115,20 @@ export const Closed = () => {
|
||||
});
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<ClosedMarketsDataGrid rowData={rowData} />
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={marketData}
|
||||
noDataMessage={t('No markets')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
<ClosedMarketsDataGrid rowData={rowData} error={error} reload={reload} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
|
||||
const ClosedMarketsDataGrid = ({
|
||||
rowData,
|
||||
error,
|
||||
reload,
|
||||
}: {
|
||||
rowData: Row[];
|
||||
error: Error | undefined;
|
||||
reload: () => void;
|
||||
}) => {
|
||||
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
|
||||
const colDefs = useMemo(() => {
|
||||
const cols: ColDef[] = [
|
||||
@ -315,7 +312,7 @@ const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
}}
|
||||
overlayNoRowsTemplate="No data"
|
||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||
storeKey="closedMarkets"
|
||||
/>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { useDepositDialog, DepositsTable } from '@vegaprotocol/deposits';
|
||||
import { depositsProvider } from '@vegaprotocol/deposits';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
@ -11,7 +11,7 @@ import type { AgGridReact } from 'ag-grid-react';
|
||||
export const DepositsContainer = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: depositsProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
@ -23,21 +23,10 @@ export const DepositsContainer = () => {
|
||||
<div className="h-full relative">
|
||||
<DepositsTable
|
||||
rowData={data || []}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
ref={gridRef}
|
||||
{...bottomPlaceholderProps}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No deposits')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
data={data}
|
||||
loading={loading}
|
||||
error={error}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
noDataMessage={t('No deposits')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!isReadOnly && (
|
||||
<div className="h-auto flex justify-end px-[11px] py-2 bottom-0 right-3 absolute dark:bg-black/75 bg-white/75 rounded">
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
withdrawalProvider,
|
||||
useWithdrawalDialog,
|
||||
@ -11,7 +11,7 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
|
||||
export const WithdrawalsContainer = () => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: withdrawalProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
@ -24,19 +24,8 @@ export const WithdrawalsContainer = () => {
|
||||
<WithdrawalsTable
|
||||
data-testid="withdrawals-history"
|
||||
rowData={data}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
overlayNoRowsTemplate={error ? error.message : t('No withdrawals')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
data={data}
|
||||
loading={loading}
|
||||
error={error}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
noDataMessage={t('No withdrawals')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!isReadOnly && (
|
||||
<div className="h-auto flex justify-end px-[11px] py-2 bottom-0 right-3 absolute dark:bg-black/75 bg-white/75 rounded">
|
||||
|
@ -97,7 +97,7 @@ describe('AccountManager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('splash loading should be displayed', async () => {
|
||||
it('loading should be displayed', async () => {
|
||||
mockedUseDataProvider.mockImplementation((args) => {
|
||||
return {
|
||||
loading: true,
|
||||
@ -113,15 +113,6 @@ describe('AccountManager', () => {
|
||||
/>
|
||||
);
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByText(
|
||||
(content, element) =>
|
||||
Boolean(
|
||||
element?.className.endsWith('flex items-center justify-center')
|
||||
) && content.startsWith('Loading')
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
expect(await screen.findByText('Loading...')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { useRef, memo, useCallback, useState, useEffect } from 'react';
|
||||
import { useRef, memo, useCallback, useState } from 'react';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useBottomPlaceholder } from '@vegaprotocol/datagrid';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { RowDataUpdatedEvent } from 'ag-grid-community';
|
||||
import type { AccountFields } from './accounts-data-provider';
|
||||
import {
|
||||
aggregatedAccountsDataProvider,
|
||||
@ -71,7 +69,6 @@ export const AccountManager = ({
|
||||
storeKey,
|
||||
}: AccountManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [hasData, setHasData] = useState(Boolean(pinnedAsset));
|
||||
const [breakdownAssetId, setBreakdownAssetId] = useState<string>();
|
||||
const update = useCallback(
|
||||
({ data }: { data: AccountFields[] | null }) => {
|
||||
@ -102,7 +99,7 @@ export const AccountManager = ({
|
||||
},
|
||||
[gridRef, pinnedAsset]
|
||||
);
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: aggregatedAccountsDataProvider,
|
||||
variables: { partyId },
|
||||
update,
|
||||
@ -112,45 +109,21 @@ export const AccountManager = ({
|
||||
disabled: noBottomPlaceholder,
|
||||
});
|
||||
|
||||
useEffect(
|
||||
() => setHasData(Boolean(pinnedAsset || data?.length)),
|
||||
[data, pinnedAsset]
|
||||
);
|
||||
|
||||
const onRowDataUpdated = useCallback(
|
||||
(event: RowDataUpdatedEvent) => {
|
||||
setHasData(Boolean(pinnedAsset || event.api?.getModel().getRowCount()));
|
||||
},
|
||||
[pinnedAsset]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative h-full">
|
||||
<AccountTable
|
||||
ref={gridRef}
|
||||
rowData={error ? [] : data}
|
||||
rowData={data}
|
||||
onClickAsset={onClickAsset}
|
||||
onClickDeposit={onClickDeposit}
|
||||
onClickWithdraw={onClickWithdraw}
|
||||
onClickBreakdown={setBreakdownAssetId}
|
||||
onRowDataUpdated={onRowDataUpdated}
|
||||
isReadOnly={isReadOnly}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
pinnedAsset={pinnedAsset}
|
||||
storeKey={storeKey}
|
||||
{...bottomPlaceholderProps}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No accounts')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
data={data}
|
||||
noDataCondition={() => !hasData}
|
||||
error={error}
|
||||
loading={loading}
|
||||
noDataMessage={pinnedAsset ? ' ' : t('No accounts')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
<Dialog
|
||||
size="medium"
|
||||
open={Boolean(breakdownAssetId)}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useColumnSizes } from './use-column-sizes';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -23,6 +24,8 @@ export const AgGridThemed = ({
|
||||
rowHeight: 22,
|
||||
headerHeight: 22,
|
||||
enableCellTextSelection: true,
|
||||
overlayLoadingTemplate: t('Loading...'),
|
||||
overlayNoRowsTemplate: t('No data'),
|
||||
};
|
||||
|
||||
const wrapperClasses = classNames('vega-ag-grid', {
|
||||
|
@ -1,9 +1,8 @@
|
||||
import compact from 'lodash/compact';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useRef } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { FillsTable } from './fills-table';
|
||||
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
||||
import { useFillsList } from './use-fills-list';
|
||||
import { useBottomPlaceholder } from '@vegaprotocol/datagrid';
|
||||
|
||||
@ -22,80 +21,30 @@ export const FillsManager = ({
|
||||
}: FillsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const scrolledToTop = useRef(true);
|
||||
const {
|
||||
data,
|
||||
error,
|
||||
loading,
|
||||
addNewRows,
|
||||
getRows,
|
||||
reload,
|
||||
makeBottomPlaceholders,
|
||||
} = useFillsList({
|
||||
const { data, error } = useFillsList({
|
||||
partyId,
|
||||
marketId,
|
||||
gridRef,
|
||||
scrolledToTop,
|
||||
});
|
||||
|
||||
const checkBottomPlaceholder = useCallback(() => {
|
||||
const rowCont = gridRef.current?.api?.getModel().getRowCount() ?? 0;
|
||||
const lastRowIndex = gridRef.current?.api?.getLastDisplayedRow();
|
||||
if (lastRowIndex && rowCont - 1 === lastRowIndex) {
|
||||
const lastrow = gridRef.current?.api.getDisplayedRowAtIndex(lastRowIndex);
|
||||
lastrow?.setRowHeight(50);
|
||||
makeBottomPlaceholders(lastrow?.data);
|
||||
gridRef.current?.api.onRowHeightChanged();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
}
|
||||
}, [makeBottomPlaceholders]);
|
||||
const bottomPlaceholderProps = useBottomPlaceholder({
|
||||
gridRef,
|
||||
});
|
||||
|
||||
const onBodyScrollEnd = useCallback(
|
||||
(event: BodyScrollEndEvent) => {
|
||||
if (event.top === 0) {
|
||||
addNewRows();
|
||||
}
|
||||
checkBottomPlaceholder();
|
||||
},
|
||||
[addNewRows, checkBottomPlaceholder]
|
||||
);
|
||||
|
||||
const onBodyScroll = useCallback((event: BodyScrollEvent) => {
|
||||
scrolledToTop.current = event.top <= 0;
|
||||
}, []);
|
||||
|
||||
const { isFullWidthRow, fullWidthCellRenderer, rowClassRules, getRowHeight } =
|
||||
useBottomPlaceholder({
|
||||
gridRef,
|
||||
});
|
||||
const fills = compact(data).map((e) => e.node);
|
||||
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<FillsTable
|
||||
ref={gridRef}
|
||||
rowData={fills}
|
||||
partyId={partyId}
|
||||
rowModelType="infinite"
|
||||
datasource={{ getRows }}
|
||||
onBodyScrollEnd={onBodyScrollEnd}
|
||||
onBodyScroll={onBodyScroll}
|
||||
onMarketClick={onMarketClick}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
isFullWidthRow={isFullWidthRow}
|
||||
fullWidthCellRenderer={fullWidthCellRenderer}
|
||||
rowClassRules={rowClassRules}
|
||||
getRowHeight={getRowHeight}
|
||||
storeKey={storeKey}
|
||||
{...bottomPlaceholderProps}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No fills')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No fills')}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { FilterChangedEvent } from 'ag-grid-community';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { subDays, formatRFC3339 } from 'date-fns';
|
||||
import type { AggregatedLedgerEntriesNode } from './ledger-entries-data-provider';
|
||||
import { useLedgerEntriesDataProvider } from './ledger-entries-data-provider';
|
||||
import { LedgerTable } from './ledger-table';
|
||||
import type * as Types from '@vegaprotocol/types';
|
||||
@ -27,9 +25,8 @@ const defaultFilter = {
|
||||
export const LedgerManager = ({ partyId }: { partyId: string }) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [filter, setFilter] = useState<Filter>(defaultFilter);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
|
||||
const { data, error, loading, reload } = useLedgerEntriesDataProvider({
|
||||
const { data, error } = useLedgerEntriesDataProvider({
|
||||
partyId,
|
||||
filter,
|
||||
gridRef,
|
||||
@ -39,16 +36,9 @@ export const LedgerManager = ({ partyId }: { partyId: string }) => {
|
||||
const updatedFilter = { ...defaultFilter, ...event.api.getFilterModel() };
|
||||
setFilter(updatedFilter);
|
||||
}, []);
|
||||
const extractNodesDecorator = useCallback(
|
||||
(data: AggregatedLedgerEntriesNode[] | null, loading: boolean) =>
|
||||
data && !loading ? data.map((item) => item.node) : null,
|
||||
[]
|
||||
);
|
||||
|
||||
const extractedData = extractNodesDecorator(data, loading);
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [extractedData]);
|
||||
// allow passing undefined to grid so that loading state is shown
|
||||
const extractedData = data?.map((item) => item.node);
|
||||
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
@ -56,20 +46,11 @@ export const LedgerManager = ({ partyId }: { partyId: string }) => {
|
||||
ref={gridRef}
|
||||
rowData={extractedData}
|
||||
onFilterChanged={onFilterChanged}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No entries')}
|
||||
/>
|
||||
{extractedData && (
|
||||
<LedgerExportLink entries={extractedData} partyId={partyId} />
|
||||
)}
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No entries')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +1,8 @@
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { CellClickedEvent } from 'ag-grid-community';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketListTable } from './market-list-table';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { marketsWithDataProvider as dataProvider } from '../../markets-provider';
|
||||
@ -16,25 +15,10 @@ interface MarketsContainerProps {
|
||||
|
||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<MarketMaybeWithData[] | null>(null);
|
||||
const [dataCount, setDataCount] = useState(1);
|
||||
const handleDataCount = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
const update = useCallback(
|
||||
({ data }: { data: MarketMaybeWithData[] | null }) => {
|
||||
data && gridRef.current?.api?.setRowData(data);
|
||||
dataRef.current = data;
|
||||
handleDataCount();
|
||||
return true;
|
||||
},
|
||||
[handleDataCount]
|
||||
);
|
||||
|
||||
const { error, loading, reload } = useDataProvider({
|
||||
const { data, error, reload } = useDataProvider({
|
||||
dataProvider,
|
||||
variables: undefined,
|
||||
update,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@ -46,17 +30,11 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
};
|
||||
}, [reload]);
|
||||
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
dataRef?.current && update({ data: dataRef.current });
|
||||
handleDataCount();
|
||||
}, [handleDataCount, update]);
|
||||
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<MarketListTable
|
||||
ref={gridRef}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
rowData={data}
|
||||
onCellClicked={(cellEvent: CellClickedEvent) => {
|
||||
const { data, column, event } = cellEvent;
|
||||
// prevent navigating to the market page if any of the below cells are clicked
|
||||
@ -79,19 +57,8 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
);
|
||||
}}
|
||||
onMarketClick={onSelect}
|
||||
onFilterChanged={handleDataCount}
|
||||
onGridReady={handleOnGridReady}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={dataRef?.current || []}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -24,41 +24,6 @@ const generateJsx = () => {
|
||||
};
|
||||
|
||||
describe('OrderListManager', () => {
|
||||
it('should render a loading state while awaiting orders', async () => {
|
||||
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||
data: [],
|
||||
loading: true,
|
||||
error: undefined,
|
||||
flush: jest.fn(),
|
||||
reload: jest.fn(),
|
||||
load: jest.fn(),
|
||||
totalCount: 0,
|
||||
});
|
||||
await act(async () => {
|
||||
render(generateJsx());
|
||||
});
|
||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render an error state', async () => {
|
||||
const errorMsg = 'Oops! An Error';
|
||||
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||
data: null,
|
||||
loading: false,
|
||||
error: new Error(errorMsg),
|
||||
flush: jest.fn(),
|
||||
reload: jest.fn(),
|
||||
load: jest.fn(),
|
||||
totalCount: undefined,
|
||||
});
|
||||
await act(async () => {
|
||||
render(generateJsx());
|
||||
});
|
||||
expect(
|
||||
screen.getByText(`Something went wrong: ${errorMsg}`)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the order list if orders provided', async () => {
|
||||
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||
data: [{ id: '1' } as OrderFieldsFragment],
|
||||
@ -74,20 +39,4 @@ describe('OrderListManager', () => {
|
||||
});
|
||||
expect(await screen.findByText('OrderList')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show no orders message', async () => {
|
||||
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||
data: [],
|
||||
loading: false,
|
||||
error: undefined,
|
||||
flush: jest.fn(),
|
||||
reload: jest.fn(),
|
||||
load: jest.fn(),
|
||||
totalCount: undefined,
|
||||
});
|
||||
await act(async () => {
|
||||
render(generateJsx());
|
||||
});
|
||||
expect(screen.getByText('No orders')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { GridReadyEvent, FilterChangedEvent } from 'ag-grid-community';
|
||||
@ -72,7 +71,6 @@ export const OrderListManager = ({
|
||||
storeKey,
|
||||
}: OrderListManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [hasData, setHasData] = useState(false);
|
||||
const [editOrder, setEditOrder] = useState<Order | null>(null);
|
||||
const create = useVegaTransactionStore((state) => state.create);
|
||||
const hasAmendableOrder = useHasAmendableOrder(marketId);
|
||||
@ -81,7 +79,7 @@ export const OrderListManager = ({
|
||||
? { partyId, filter: { liveOnly: true } }
|
||||
: { partyId };
|
||||
|
||||
const { data, error, loading, reload } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: ordersWithMarketProvider,
|
||||
variables,
|
||||
update: ({ data }) => {
|
||||
@ -129,22 +127,11 @@ export const OrderListManager = ({
|
||||
|
||||
const onFilterChanged = useCallback(
|
||||
(event: FilterChangedEvent) => {
|
||||
const rowCount = gridRef.current?.api?.getModel().getRowCount();
|
||||
setHasData((rowCount ?? 0) > 0);
|
||||
bottomPlaceholderOnFilterChanged?.();
|
||||
},
|
||||
[bottomPlaceholderOnFilterChanged]
|
||||
);
|
||||
|
||||
const onRowDataChanged = useCallback(() => {
|
||||
const rowCount = gridRef.current?.api?.getModel().getRowCount();
|
||||
setHasData((rowCount ?? 0) > 0);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setHasData(Boolean(data?.length));
|
||||
}, [data]);
|
||||
|
||||
const cancelAll = useCallback(() => {
|
||||
create({
|
||||
orderCancellation: {},
|
||||
@ -164,24 +151,12 @@ export const OrderListManager = ({
|
||||
onMarketClick={onMarketClick}
|
||||
onOrderTypeClick={onOrderTypeClick}
|
||||
onFilterChanged={onFilterChanged}
|
||||
onRowDataChanged={onRowDataChanged}
|
||||
isReadOnly={isReadOnly}
|
||||
storeKey={storeKey}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
suppressAutoSize
|
||||
overlayNoRowsTemplate={error ? error.message : t('No orders')}
|
||||
{...bottomPlaceholderProps}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No orders')}
|
||||
noDataCondition={(data) => !hasData}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!isReadOnly && hasAmendableOrder && (
|
||||
<CancelAllOrdersButton onClick={cancelAll} />
|
||||
|
@ -44,15 +44,6 @@ const generateJsx = (
|
||||
};
|
||||
|
||||
describe('OrderListTable', () => {
|
||||
it('should show no orders message', async () => {
|
||||
await act(async () => {
|
||||
render(generateJsx({ rowData: [] }));
|
||||
});
|
||||
expect(() => screen.getByText('No orders')).toThrow(
|
||||
'Unable to find an element'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render correct columns', async () => {
|
||||
await act(async () => {
|
||||
render(generateJsx({ rowData: [marketOrder, limitOrder] }));
|
||||
|
@ -210,10 +210,13 @@ const positionDataProvider = makeDerivedDataProvider<
|
||||
partyIds: variables.partyIds,
|
||||
}),
|
||||
],
|
||||
(data, variables) =>
|
||||
(data[0] as PositionFieldsFragment[] | null)?.find(
|
||||
(p) => p.market.id === variables?.marketId
|
||||
) || null
|
||||
(data, variables) => {
|
||||
return (
|
||||
(data[0] as PositionFieldsFragment[] | null)?.find(
|
||||
(p) => p.market.id === variables?.marketId
|
||||
) || null
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const openVolumeDataProvider = makeDerivedDataProvider<
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useRef } from 'react';
|
||||
import { usePositionsData } from './use-positions-data';
|
||||
import { PositionsTable } from './positions-table';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
@ -26,8 +25,7 @@ export const PositionsManager = ({
|
||||
}: PositionsManagerProps) => {
|
||||
const { pubKeys, pubKey } = useVegaWallet();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { data, error, loading, reload } = usePositionsData(partyIds, gridRef);
|
||||
const [dataCount, setDataCount] = useState(data?.length ?? 0);
|
||||
const { data, error } = usePositionsData(partyIds, gridRef);
|
||||
const create = useVegaTransactionStore((store) => store.create);
|
||||
const onClose = ({
|
||||
marketId,
|
||||
@ -63,9 +61,6 @@ export const PositionsManager = ({
|
||||
gridRef,
|
||||
disabled: noBottomPlaceholder,
|
||||
});
|
||||
const updateRowCount = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
@ -76,25 +71,12 @@ export const PositionsManager = ({
|
||||
ref={gridRef}
|
||||
onMarketClick={onMarketClick}
|
||||
onClose={onClose}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
isReadOnly={isReadOnly}
|
||||
onFilterChanged={updateRowCount}
|
||||
onRowDataUpdated={updateRowCount}
|
||||
{...bottomPlaceholderProps}
|
||||
storeKey={storeKey}
|
||||
multipleKeys={partyIds.length > 1}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No positions')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No positions')}
|
||||
noDataCondition={(data) => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -110,17 +110,29 @@ describe('ProposalsList', () => {
|
||||
});
|
||||
|
||||
it('empty response should causes no data message display', async () => {
|
||||
const mock: MockedResponse<ProposalsListQuery> = {
|
||||
request: {
|
||||
query: ProposalsListDocument,
|
||||
variables: {
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
proposalsConnection: {
|
||||
__typename: 'ProposalsConnection',
|
||||
edges: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
await act(() => {
|
||||
render(
|
||||
<MockedProvider>
|
||||
<MockedProvider mocks={[mock]}>
|
||||
<ProposalsList />
|
||||
</MockedProvider>
|
||||
);
|
||||
});
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
await waitFor(() => {
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText('No markets')).toBeInTheDocument();
|
||||
expect(await screen.findByText('No markets')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useRef } from 'react';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
@ -20,8 +19,7 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
|
||||
export const ProposalsList = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const { data, loading, error, refetch } = useProposalsListQuery({
|
||||
const { data, error } = useProposalsListQuery({
|
||||
variables: {
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
},
|
||||
@ -31,12 +29,6 @@ export const ProposalsList = () => {
|
||||
removePaginationWrapper(data?.proposalsConnection?.edges)
|
||||
);
|
||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||
const handleDataCount = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
handleDataCount();
|
||||
}, [filteredData, handleDataCount]);
|
||||
|
||||
return (
|
||||
<div className="relative h-full">
|
||||
@ -46,24 +38,11 @@ export const ProposalsList = () => {
|
||||
columnDefs={columnDefs}
|
||||
rowData={filteredData}
|
||||
defaultColDef={defaultColDef}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
onFilterChanged={handleDataCount}
|
||||
storeKey="proposedMarkets"
|
||||
getRowId={({ data }) => data.id}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
onGridReady={handleDataCount}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={refetch}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { makeInfiniteScrollGetRows } from '@vegaprotocol/data-provider';
|
||||
import compact from 'lodash/compact';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
||||
import { useRef } from 'react';
|
||||
import { tradesWithMarketProvider } from './trades-data-provider';
|
||||
import { TradesTable } from './trades-table';
|
||||
import type { Trade, TradeEdge } from './trades-data-provider';
|
||||
import { useOrderStore } from '@vegaprotocol/orders';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
interface TradesContainerProps {
|
||||
marketId: string;
|
||||
@ -15,104 +13,24 @@ interface TradesContainerProps {
|
||||
|
||||
export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<(TradeEdge | null)[] | null>(null);
|
||||
const totalCountRef = useRef<number | undefined>(undefined);
|
||||
const newRows = useRef(0);
|
||||
const scrolledToTop = useRef(true);
|
||||
const updateOrder = useOrderStore((store) => store.update);
|
||||
|
||||
const addNewRows = useCallback(() => {
|
||||
if (newRows.current === 0) {
|
||||
return;
|
||||
}
|
||||
if (totalCountRef.current !== undefined) {
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
gridRef.current?.api?.refreshInfiniteCache();
|
||||
}, []);
|
||||
|
||||
const update = useCallback(
|
||||
({
|
||||
data,
|
||||
delta,
|
||||
}: {
|
||||
data: (TradeEdge | null)[] | null;
|
||||
delta?: Trade[];
|
||||
}) => {
|
||||
if (dataRef.current?.length) {
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0]?.node.createdAt;
|
||||
if (createdAt) {
|
||||
newRows.current += (delta || []).filter(
|
||||
(trade) => trade.createdAt > createdAt
|
||||
).length;
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current?.api?.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
dataRef.current = data;
|
||||
return false;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const insert = useCallback(
|
||||
({
|
||||
data,
|
||||
totalCount,
|
||||
}: {
|
||||
data: (TradeEdge | null)[] | null;
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
dataRef.current = data;
|
||||
totalCountRef.current = totalCount;
|
||||
return true;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: tradesWithMarketProvider,
|
||||
update,
|
||||
insert,
|
||||
variables: { marketId },
|
||||
});
|
||||
totalCountRef.current = totalCount;
|
||||
const getRows = makeInfiniteScrollGetRows<TradeEdge>(
|
||||
dataRef,
|
||||
totalCountRef,
|
||||
load,
|
||||
newRows
|
||||
);
|
||||
|
||||
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
||||
if (event.top === 0) {
|
||||
addNewRows();
|
||||
}
|
||||
};
|
||||
|
||||
const onBodyScroll = (event: BodyScrollEvent) => {
|
||||
scrolledToTop.current = event.top <= 0;
|
||||
};
|
||||
const trades = compact(data).map((d) => d.node);
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data} reload={reload}>
|
||||
<TradesTable
|
||||
ref={gridRef}
|
||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||
rowData={data?.length ? undefined : []}
|
||||
datasource={{ getRows }}
|
||||
onBodyScrollEnd={onBodyScrollEnd}
|
||||
onBodyScroll={onBodyScroll}
|
||||
onClick={(price?: string) => {
|
||||
if (price) {
|
||||
updateOrder(marketId, { price });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
<TradesTable
|
||||
ref={gridRef}
|
||||
rowData={trades}
|
||||
onClick={(price?: string) => {
|
||||
if (price) {
|
||||
updateOrder(marketId, { price });
|
||||
}
|
||||
}}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No trades')}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -2,8 +2,6 @@ import {
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
defaultAppend as append,
|
||||
paginatedCombineDelta as combineDelta,
|
||||
paginatedCombineInsertionData as combineInsertionData,
|
||||
} from '@vegaprotocol/data-provider';
|
||||
import type { PageInfo, Edge } from '@vegaprotocol/data-provider';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
@ -18,7 +16,7 @@ import { TradesDocument, TradesUpdateDocument } from './__generated__/Trades';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import produce from 'immer';
|
||||
|
||||
export const MAX_TRADES = 50;
|
||||
export const MAX_TRADES = 500;
|
||||
|
||||
const getData = (
|
||||
responseData: TradesQuery | null
|
||||
@ -34,32 +32,25 @@ const update = (
|
||||
data: ReturnType<typeof getData> | null,
|
||||
delta: ReturnType<typeof getDelta>
|
||||
) => {
|
||||
if (!data) return data;
|
||||
return produce(data, (draft) => {
|
||||
// for each incoming trade add it to the beginning and remove oldest trade
|
||||
orderBy(delta, 'createdAt', 'desc').forEach((node) => {
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
const index = draft.findIndex((edge) => edge?.node.id === node.id);
|
||||
if (index !== -1) {
|
||||
if (draft?.[index]?.node) {
|
||||
Object.assign(draft[index]?.node as TradeFieldsFragment, node);
|
||||
}
|
||||
} else {
|
||||
const firstNode = draft[0]?.node;
|
||||
if (firstNode && node.createdAt >= firstNode.createdAt) {
|
||||
const { marketId, ...nodeData } = node;
|
||||
draft.unshift({
|
||||
node: {
|
||||
...nodeData,
|
||||
__typename: 'Trade',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: marketId,
|
||||
},
|
||||
},
|
||||
cursor: '',
|
||||
});
|
||||
}
|
||||
const { marketId, ...nodeData } = node;
|
||||
draft.unshift({
|
||||
node: {
|
||||
...nodeData,
|
||||
__typename: 'Trade',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: marketId,
|
||||
},
|
||||
},
|
||||
cursor: '',
|
||||
});
|
||||
|
||||
if (draft.length > MAX_TRADES) {
|
||||
draft.pop();
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -86,7 +77,7 @@ export const tradesProvider = makeDataProvider<
|
||||
pagination: {
|
||||
getPageInfo,
|
||||
append,
|
||||
first: 100,
|
||||
first: MAX_TRADES,
|
||||
},
|
||||
});
|
||||
|
||||
@ -117,7 +108,5 @@ export const tradesWithMarketProvider = makeDerivedDataProvider<
|
||||
node,
|
||||
};
|
||||
});
|
||||
},
|
||||
combineDelta<Trade, ReturnType<typeof getDelta>['0']>,
|
||||
combineInsertionData<Trade>
|
||||
}
|
||||
);
|
||||
|
@ -51,7 +51,6 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
|
||||
return (
|
||||
<AgGrid
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
overlayNoRowsTemplate={t('No trades')}
|
||||
getRowId={({ data }) => data.id}
|
||||
ref={ref}
|
||||
defaultColDef={{
|
||||
|
Loading…
Reference in New Issue
Block a user