chore(trading): handle timeout and offline errors (#2918)
This commit is contained in:
parent
9dfed0a211
commit
b2a115f935
@ -6,7 +6,7 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
|
|||||||
|
|
||||||
export const DepositsContainer = () => {
|
export const DepositsContainer = () => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: depositsProvider,
|
dataProvider: depositsProvider,
|
||||||
variables: { partyId: pubKey || '' },
|
variables: { partyId: pubKey || '' },
|
||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
@ -27,6 +27,7 @@ export const DepositsContainer = () => {
|
|||||||
error={error}
|
error={error}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
noDataMessage={t('No deposits')}
|
noDataMessage={t('No deposits')}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
|||||||
|
|
||||||
export const WithdrawalsContainer = () => {
|
export const WithdrawalsContainer = () => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: withdrawalProvider,
|
dataProvider: withdrawalProvider,
|
||||||
variables: { partyId: pubKey || '' },
|
variables: { partyId: pubKey || '' },
|
||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
@ -33,6 +33,7 @@ export const WithdrawalsContainer = () => {
|
|||||||
error={error}
|
error={error}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
noDataMessage={t('No withdrawals')}
|
noDataMessage={t('No withdrawals')}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,10 @@ export const AccountManager = ({
|
|||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||||
|
|
||||||
const { data, loading, error } = useDataProvider<AccountFields[], never>({
|
const { data, loading, error, reload } = useDataProvider<
|
||||||
|
AccountFields[],
|
||||||
|
never
|
||||||
|
>({
|
||||||
dataProvider: aggregatedAccountsDataProvider,
|
dataProvider: aggregatedAccountsDataProvider,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
@ -32,7 +35,7 @@ export const AccountManager = ({
|
|||||||
<div className="relative h-full">
|
<div className="relative h-full">
|
||||||
<AccountTable
|
<AccountTable
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
rowData={data}
|
rowData={error ? [] : data}
|
||||||
onClickAsset={onClickAsset}
|
onClickAsset={onClickAsset}
|
||||||
onClickDeposit={onClickDeposit}
|
onClickDeposit={onClickDeposit}
|
||||||
onClickWithdraw={onClickWithdraw}
|
onClickWithdraw={onClickWithdraw}
|
||||||
@ -46,6 +49,7 @@ export const AccountManager = ({
|
|||||||
error={error}
|
error={error}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
noDataMessage={t('No accounts')}
|
noDataMessage={t('No accounts')}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,6 +25,7 @@ export const DealTicketContainer = ({
|
|||||||
data: marketData,
|
data: marketData,
|
||||||
error: marketDataError,
|
error: marketDataError,
|
||||||
loading: marketDataLoading,
|
loading: marketDataLoading,
|
||||||
|
reload,
|
||||||
} = useThrottledDataProvider(
|
} = useThrottledDataProvider(
|
||||||
{
|
{
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
@ -39,6 +40,7 @@ export const DealTicketContainer = ({
|
|||||||
data={market && marketData}
|
data={market && marketData}
|
||||||
loading={marketLoading || marketDataLoading}
|
loading={marketLoading || marketDataLoading}
|
||||||
error={marketError || marketDataError}
|
error={marketError || marketDataError}
|
||||||
|
reload={reload}
|
||||||
>
|
>
|
||||||
{market && marketData ? (
|
{market && marketData ? (
|
||||||
<DealTicket
|
<DealTicket
|
||||||
|
@ -19,7 +19,7 @@ export const FillsManager = ({
|
|||||||
}: FillsManagerProps) => {
|
}: FillsManagerProps) => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const scrolledToTop = useRef(true);
|
const scrolledToTop = useRef(true);
|
||||||
const { data, error, loading, addNewRows, getRows } = useFillsList({
|
const { data, error, loading, addNewRows, getRows, reload } = useFillsList({
|
||||||
partyId,
|
partyId,
|
||||||
marketId,
|
marketId,
|
||||||
gridRef,
|
gridRef,
|
||||||
@ -55,6 +55,7 @@ export const FillsManager = ({
|
|||||||
data={data}
|
data={data}
|
||||||
noDataMessage={t('No fills')}
|
noDataMessage={t('No fills')}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +78,7 @@ export const useFillsList = ({
|
|||||||
|
|
||||||
const variables = useMemo(() => ({ partyId, marketId }), [partyId, marketId]);
|
const variables = useMemo(() => ({ partyId, marketId }), [partyId, marketId]);
|
||||||
|
|
||||||
const { data, error, loading, load, totalCount } = useDataProvider<
|
const { data, error, loading, load, totalCount, reload } = useDataProvider<
|
||||||
(TradeEdge | null)[],
|
(TradeEdge | null)[],
|
||||||
Trade[]
|
Trade[]
|
||||||
>({
|
>({
|
||||||
@ -95,5 +95,5 @@ export const useFillsList = ({
|
|||||||
load,
|
load,
|
||||||
newRows
|
newRows
|
||||||
);
|
);
|
||||||
return { data, error, loading, addNewRows, getRows };
|
return { data, error, loading, addNewRows, getRows, reload };
|
||||||
};
|
};
|
||||||
|
@ -29,14 +29,19 @@ export const ProposalsList = () => {
|
|||||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: proposalsListDataProvider,
|
dataProvider: proposalsListDataProvider,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
const filteredData = getNewMarketProposals(data || []);
|
const filteredData = getNewMarketProposals(data || []);
|
||||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer loading={loading} error={error} data={filteredData}>
|
<AsyncRenderer
|
||||||
|
loading={loading}
|
||||||
|
error={error}
|
||||||
|
data={filteredData}
|
||||||
|
reload={reload}
|
||||||
|
>
|
||||||
<AgGrid
|
<AgGrid
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
domLayout="autoHeight"
|
domLayout="autoHeight"
|
||||||
|
@ -35,6 +35,7 @@ query LedgerEntries(
|
|||||||
node {
|
node {
|
||||||
...LedgerEntry
|
...LedgerEntry
|
||||||
}
|
}
|
||||||
|
cursor
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
startCursor
|
startCursor
|
||||||
|
@ -14,7 +14,7 @@ export type LedgerEntriesQueryVariables = Types.Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', node: { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, toAccountType?: Types.AccountType | null, toAccountMarketId?: string | null, toAccountPartyId?: string | null, toAccountBalance: string, fromAccountType?: Types.AccountType | null, fromAccountMarketId?: string | null, fromAccountPartyId?: string | null, fromAccountBalance: string } } | null>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
|
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', cursor: string, node: { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, toAccountType?: Types.AccountType | null, toAccountMarketId?: string | null, toAccountPartyId?: string | null, toAccountBalance: string, fromAccountType?: Types.AccountType | null, fromAccountMarketId?: string | null, fromAccountPartyId?: string | null, fromAccountBalance: string } } | null>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
|
||||||
|
|
||||||
export const LedgerEntryFragmentDoc = gql`
|
export const LedgerEntryFragmentDoc = gql`
|
||||||
fragment LedgerEntry on AggregatedLedgerEntry {
|
fragment LedgerEntry on AggregatedLedgerEntry {
|
||||||
@ -43,6 +43,7 @@ export const LedgerEntriesDocument = gql`
|
|||||||
node {
|
node {
|
||||||
...LedgerEntry
|
...LedgerEntry
|
||||||
}
|
}
|
||||||
|
cursor
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
startCursor
|
startCursor
|
||||||
|
@ -128,7 +128,11 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
|
|||||||
const marketReceiver = markets.find(
|
const marketReceiver = markets.find(
|
||||||
(market: Market) => market.id === entry.toAccountMarketId
|
(market: Market) => market.id === entry.toAccountMarketId
|
||||||
);
|
);
|
||||||
return { node: { ...entry, asset, marketSender, marketReceiver } };
|
const cursor = edge?.cursor;
|
||||||
|
return {
|
||||||
|
node: { ...entry, asset, marketSender, marketReceiver },
|
||||||
|
cursor,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -172,14 +176,13 @@ export const useLedgerEntriesDataProvider = ({
|
|||||||
data: (AggregatedLedgerEntriesEdge | null)[] | null;
|
data: (AggregatedLedgerEntriesEdge | null)[] | null;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
}) => {
|
}) => {
|
||||||
dataRef.current = data;
|
|
||||||
totalCountRef.current = totalCount;
|
totalCountRef.current = totalCount;
|
||||||
return updateGridData(dataRef, data, gridRef);
|
return updateGridData(dataRef, data, gridRef);
|
||||||
},
|
},
|
||||||
[gridRef]
|
[gridRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||||
dataProvider: ledgerEntriesProvider,
|
dataProvider: ledgerEntriesProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
@ -193,5 +196,5 @@ export const useLedgerEntriesDataProvider = ({
|
|||||||
totalCountRef,
|
totalCountRef,
|
||||||
load
|
load
|
||||||
);
|
);
|
||||||
return { loading, error, data, getRows };
|
return { loading, error, data, getRows, reload };
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@ export const ledgerEntriesQuery = (
|
|||||||
edges: ledgerEntries.map((node) => ({
|
edges: ledgerEntries.map((node) => ({
|
||||||
__typename: 'AggregatedLedgerEntriesEdge',
|
__typename: 'AggregatedLedgerEntriesEdge',
|
||||||
node,
|
node,
|
||||||
|
cursor: 'cursor-1',
|
||||||
})),
|
})),
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
startCursor:
|
startCursor:
|
||||||
|
@ -21,11 +21,12 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
|||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const [filter, setFilter] = useState<Filter | undefined>();
|
const [filter, setFilter] = useState<Filter | undefined>();
|
||||||
|
|
||||||
const { data, error, loading, getRows } = useLedgerEntriesDataProvider({
|
const { data, error, loading, getRows, reload } =
|
||||||
partyId,
|
useLedgerEntriesDataProvider({
|
||||||
filter,
|
partyId,
|
||||||
gridRef,
|
filter,
|
||||||
});
|
gridRef,
|
||||||
|
});
|
||||||
|
|
||||||
const onFilterChanged = useCallback(
|
const onFilterChanged = useCallback(
|
||||||
(event: FilterChangedEvent) => {
|
(event: FilterChangedEvent) => {
|
||||||
@ -38,7 +39,11 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
|||||||
},
|
},
|
||||||
[filter]
|
[filter]
|
||||||
);
|
);
|
||||||
|
const getRowId = useCallback(
|
||||||
|
({ data }: { data: Types.AggregatedLedgerEntry }) =>
|
||||||
|
`${data.vegaTime}-${data.fromAccountPartyId}-${data.toAccountPartyId}`,
|
||||||
|
[]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className="h-full relative">
|
<div className="h-full relative">
|
||||||
<LedgerTable
|
<LedgerTable
|
||||||
@ -46,6 +51,7 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
|||||||
rowModelType="infinite"
|
rowModelType="infinite"
|
||||||
datasource={{ getRows }}
|
datasource={{ getRows }}
|
||||||
onFilterChanged={onFilterChanged}
|
onFilterChanged={onFilterChanged}
|
||||||
|
getRowId={getRowId}
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute inset-0">
|
<div className="pointer-events-none absolute inset-0">
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
@ -54,6 +60,7 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
|||||||
data={data}
|
data={data}
|
||||||
noDataMessage={t('No entries')}
|
noDataMessage={t('No entries')}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,7 +85,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
[marketId, updateOrderbookData]
|
[marketId, updateOrderbookData]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading, flush } = useDataProvider({
|
const { data, error, loading, flush, reload } = useDataProvider({
|
||||||
dataProvider: marketDepthProvider,
|
dataProvider: marketDepthProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
@ -156,6 +156,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
loading={loading || marketDataLoading || marketLoading}
|
loading={loading || marketDataLoading || marketLoading}
|
||||||
error={error || marketDataError || marketError}
|
error={error || marketDataError || marketError}
|
||||||
data={data}
|
data={data}
|
||||||
|
reload={reload}
|
||||||
>
|
>
|
||||||
<Orderbook
|
<Orderbook
|
||||||
{...orderbookData}
|
{...orderbookData}
|
||||||
|
@ -69,14 +69,14 @@ export const MarketInfoContainer = ({
|
|||||||
[marketId, yTimestamp]
|
[marketId, yTimestamp]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: marketInfoDataProvider,
|
dataProvider: marketInfoDataProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
||||||
{data && data.market ? (
|
{data && data.market ? (
|
||||||
<Info market={data.market} onSelect={(id) => onSelect?.(id)} />
|
<Info market={data.market} onSelect={(id) => onSelect?.(id)} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -10,7 +10,7 @@ interface MarketsContainerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading, reload } = useDataProvider({
|
||||||
dataProvider,
|
dataProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
});
|
});
|
||||||
@ -18,7 +18,8 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className="h-full relative">
|
<div className="h-full relative">
|
||||||
<MarketListTable
|
<MarketListTable
|
||||||
rowData={data}
|
rowData={error ? [] : data}
|
||||||
|
noRowsOverlayComponent={() => null}
|
||||||
onRowClicked={(rowEvent: RowClickedEvent) => {
|
onRowClicked={(rowEvent: RowClickedEvent) => {
|
||||||
const { data, event } = rowEvent;
|
const { data, event } = rowEvent;
|
||||||
// filters out clicks on the symbol column because it should display asset details
|
// filters out clicks on the symbol column because it should display asset details
|
||||||
@ -36,6 +37,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
|||||||
error={error}
|
error={error}
|
||||||
data={data}
|
data={data}
|
||||||
noDataMessage={t('No markets')}
|
noDataMessage={t('No markets')}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,6 +155,7 @@ export const ordersProvider = makeDataProvider({
|
|||||||
append,
|
append,
|
||||||
first: 100,
|
first: 100,
|
||||||
},
|
},
|
||||||
|
additionalContext: { isEnlargedTimeout: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ordersWithMarketProvider = makeDerivedDataProvider<
|
export const ordersWithMarketProvider = makeDerivedDataProvider<
|
||||||
|
@ -83,14 +83,15 @@ export const OrderListManager = ({
|
|||||||
const create = useVegaTransactionStore((state) => state.create);
|
const create = useVegaTransactionStore((state) => state.create);
|
||||||
const hasActiveOrder = useHasActiveOrder(marketId);
|
const hasActiveOrder = useHasActiveOrder(marketId);
|
||||||
|
|
||||||
const { data, error, loading, addNewRows, getRows } = useOrderListData({
|
const { data, error, loading, addNewRows, getRows, reload } =
|
||||||
partyId,
|
useOrderListData({
|
||||||
marketId,
|
partyId,
|
||||||
sort,
|
marketId,
|
||||||
filter,
|
sort,
|
||||||
gridRef,
|
filter,
|
||||||
scrolledToTop,
|
gridRef,
|
||||||
});
|
scrolledToTop,
|
||||||
|
});
|
||||||
|
|
||||||
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
||||||
if (event.top === 0) {
|
if (event.top === 0) {
|
||||||
@ -128,7 +129,7 @@ export const OrderListManager = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="h-full relative grid grid-rows-[1fr,min-content]">
|
<div className="h-full relative grid grid-rows-[1fr,min-content]">
|
||||||
<div className="h-full relative">
|
<div className="relative">
|
||||||
<OrderListTable
|
<OrderListTable
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
rowModelType="infinite"
|
rowModelType="infinite"
|
||||||
@ -149,6 +150,8 @@ export const OrderListManager = ({
|
|||||||
setEditOrder={setEditOrder}
|
setEditOrder={setEditOrder}
|
||||||
onMarketClick={onMarketClick}
|
onMarketClick={onMarketClick}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
|
hasActiveOrder={hasActiveOrder}
|
||||||
|
blockLoadDebounceMillis={100}
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute inset-0">
|
<div className="pointer-events-none absolute inset-0">
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
@ -157,6 +160,7 @@ export const OrderListManager = ({
|
|||||||
data={data}
|
data={data}
|
||||||
noDataMessage={t('No orders')}
|
noDataMessage={t('No orders')}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -119,7 +119,7 @@ export const useOrderListData = ({
|
|||||||
[gridRef]
|
[gridRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||||
dataProvider: ordersWithMarketProvider,
|
dataProvider: ordersWithMarketProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
@ -133,5 +133,5 @@ export const useOrderListData = ({
|
|||||||
load,
|
load,
|
||||||
newRows
|
newRows
|
||||||
);
|
);
|
||||||
return { loading, error, data, addNewRows, getRows };
|
return { loading, error, data, addNewRows, getRows, reload };
|
||||||
};
|
};
|
||||||
|
@ -33,20 +33,24 @@ export type OrderListTableProps = OrderListProps & {
|
|||||||
setEditOrder: (order: Order) => void;
|
setEditOrder: (order: Order) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string) => void;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
|
hasActiveOrder?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||||
({ cancel, setEditOrder, onMarketClick, ...props }, ref) => {
|
({ cancel, setEditOrder, onMarketClick, hasActiveOrder, ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
ref={ref}
|
ref={ref}
|
||||||
overlayNoRowsTemplate="No orders"
|
overlayNoRowsTemplate={t('No orders')}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
filterParams: { buttons: ['reset'] },
|
filterParams: { buttons: ['reset'] },
|
||||||
}}
|
}}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: hasActiveOrder ? 'calc(100% - 46px)' : '100%',
|
||||||
|
}}
|
||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }) => data.id}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
@ -18,7 +18,11 @@ export const PositionsManager = ({
|
|||||||
isReadOnly,
|
isReadOnly,
|
||||||
}: PositionsManagerProps) => {
|
}: PositionsManagerProps) => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const { data, error, loading } = usePositionsData(partyId, gridRef, true);
|
const { data, error, loading, reload } = usePositionsData(
|
||||||
|
partyId,
|
||||||
|
gridRef,
|
||||||
|
true
|
||||||
|
);
|
||||||
const create = useVegaTransactionStore((store) => store.create);
|
const create = useVegaTransactionStore((store) => store.create);
|
||||||
const onClose = ({
|
const onClose = ({
|
||||||
marketId,
|
marketId,
|
||||||
@ -51,7 +55,7 @@ export const PositionsManager = ({
|
|||||||
return (
|
return (
|
||||||
<div className="h-full relative">
|
<div className="h-full relative">
|
||||||
<PositionsTable
|
<PositionsTable
|
||||||
rowData={data}
|
rowData={error ? [] : data}
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
onMarketClick={onMarketClick}
|
onMarketClick={onMarketClick}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
@ -65,6 +69,7 @@ export const PositionsManager = ({
|
|||||||
data={data}
|
data={data}
|
||||||
noDataMessage={t('No positions')}
|
noDataMessage={t('No positions')}
|
||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +25,7 @@ export const usePositionsData = (
|
|||||||
},
|
},
|
||||||
[gridRef, clientSideModel]
|
[gridRef, clientSideModel]
|
||||||
);
|
);
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading, reload } = useDataProvider({
|
||||||
dataProvider: positionsMetricsProvider,
|
dataProvider: positionsMetricsProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
@ -45,5 +45,6 @@ export const usePositionsData = (
|
|||||||
error,
|
error,
|
||||||
loading,
|
loading,
|
||||||
getRows,
|
getRows,
|
||||||
|
reload,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -80,6 +80,7 @@ export const useDataProvider = <
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
const reload = useCallback((force = false) => {
|
const reload = useCallback((force = false) => {
|
||||||
|
initialized.current = false;
|
||||||
if (reloadRef.current) {
|
if (reloadRef.current) {
|
||||||
reloadRef.current(force);
|
reloadRef.current(force);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ const getLastRow = (
|
|||||||
lastRow = totalCount;
|
lastRow = totalCount;
|
||||||
}
|
}
|
||||||
} else if (blockLength < endRow - startRow) {
|
} else if (blockLength < endRow - startRow) {
|
||||||
lastRow = blockLength;
|
lastRow = blockLength + startRow;
|
||||||
}
|
}
|
||||||
return lastRow;
|
return lastRow;
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||||
dataProvider: tradesWithMarketProvider,
|
dataProvider: tradesWithMarketProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
@ -107,7 +107,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
<AsyncRenderer loading={loading} error={error} data={data} reload={reload}>
|
||||||
<TradesTable
|
<TradesTable
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { render, act, screen } from '@testing-library/react';
|
||||||
|
import { AsyncRenderer } from './async-renderer';
|
||||||
|
|
||||||
|
describe('AsyncRenderer', () => {
|
||||||
|
it('timeout error should render button', async () => {
|
||||||
|
const reload = jest.fn();
|
||||||
|
await act(() => {
|
||||||
|
render(
|
||||||
|
<AsyncRenderer
|
||||||
|
reload={reload}
|
||||||
|
error={new Error('Timeout exceeded')}
|
||||||
|
loading={false}
|
||||||
|
data={undefined}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||||
|
await act(() => {
|
||||||
|
screen.getByRole('button').click();
|
||||||
|
});
|
||||||
|
expect(reload).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -1,6 +1,7 @@
|
|||||||
import { Splash } from '../splash';
|
import { Splash } from '../splash';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { Button } from '../button';
|
||||||
|
|
||||||
interface AsyncRendererProps<T> {
|
interface AsyncRendererProps<T> {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -12,6 +13,7 @@ interface AsyncRendererProps<T> {
|
|||||||
children?: ReactNode | null;
|
children?: ReactNode | null;
|
||||||
render?: (data: T) => ReactNode;
|
render?: (data: T) => ReactNode;
|
||||||
noDataCondition?(data?: T): boolean;
|
noDataCondition?(data?: T): boolean;
|
||||||
|
reload?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AsyncRenderer<T = object>({
|
export function AsyncRenderer<T = object>({
|
||||||
@ -24,15 +26,30 @@ export function AsyncRenderer<T = object>({
|
|||||||
noDataCondition,
|
noDataCondition,
|
||||||
children,
|
children,
|
||||||
render,
|
render,
|
||||||
|
reload,
|
||||||
}: AsyncRendererProps<T>) {
|
}: AsyncRendererProps<T>) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return (
|
return (
|
||||||
<Splash>
|
<div className="h-full flex items-center justify-center">
|
||||||
{errorMessage
|
<div className="h-12 flex flex-col items-center">
|
||||||
? errorMessage
|
<Splash>
|
||||||
: t(`Something went wrong: ${error.message}`)}
|
{errorMessage
|
||||||
</Splash>
|
? errorMessage
|
||||||
|
: t(`Something went wrong: ${error.message}`)}
|
||||||
|
</Splash>
|
||||||
|
{reload && error.message === 'Timeout exceeded' && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
className="pointer-events-auto"
|
||||||
|
type="button"
|
||||||
|
onClick={reload}
|
||||||
|
>
|
||||||
|
{t('Try again')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user