chore(orders): 4970 add no rows and error info (#5076)
This commit is contained in:
parent
a98ab775c3
commit
2dfcb02d1e
@ -10,6 +10,19 @@ import type { DataGridStore } from '../../stores/datagrid-store-slice';
|
|||||||
import { OrderStatus } from '@vegaprotocol/types';
|
import { OrderStatus } from '@vegaprotocol/types';
|
||||||
import { Links } from '../../lib/links';
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
|
const resolveNoRowsMessage = (filter?: Filter) => {
|
||||||
|
switch (filter) {
|
||||||
|
case Filter.Open:
|
||||||
|
return t('No open orders');
|
||||||
|
case Filter.Closed:
|
||||||
|
return t('No closed orders');
|
||||||
|
case Filter.Rejected:
|
||||||
|
return t('No rejected orders');
|
||||||
|
default:
|
||||||
|
return t('No orders');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const FilterStatusValue = {
|
export const FilterStatusValue = {
|
||||||
[Filter.Open]: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
|
[Filter.Open]: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
|
||||||
[Filter.Closed]: [
|
[Filter.Closed]: [
|
||||||
@ -43,6 +56,7 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
|||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||||
}
|
}
|
||||||
|
const noRowsMessage = resolveNoRowsMessage(filter);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OrderListManager
|
<OrderListManager
|
||||||
@ -56,6 +70,7 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
|||||||
}
|
}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
gridProps={gridStoreCallbacks}
|
gridProps={gridStoreCallbacks}
|
||||||
|
noRowsMessage={noRowsMessage}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,9 @@ export const CandlesChartContainer = ({
|
|||||||
overlays,
|
overlays,
|
||||||
studies,
|
studies,
|
||||||
notEnoughDataText: (
|
notEnoughDataText: (
|
||||||
<span className="text-xs text-center">{t('No data')}</span>
|
<span className="text-xs text-center">
|
||||||
|
{t('No open orders')}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
initialNumCandlesToDisplay: candlesCount,
|
initialNumCandlesToDisplay: candlesCount,
|
||||||
studySize: STUDY_SIZE,
|
studySize: STUDY_SIZE,
|
||||||
|
@ -238,7 +238,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
volumeFormat={volumeFormat}
|
volumeFormat={volumeFormat}
|
||||||
priceFormat={priceFormat}
|
priceFormat={priceFormat}
|
||||||
notEnoughDataText={
|
notEnoughDataText={
|
||||||
<span className="text-xs text-center">{t('No data')}</span>
|
<span className="text-xs text-center">{t('No open orders')}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -11,14 +11,8 @@ import type {
|
|||||||
MarketDepthQuery,
|
MarketDepthQuery,
|
||||||
MarketDepthQueryVariables,
|
MarketDepthQueryVariables,
|
||||||
MarketDepthUpdateSubscription,
|
MarketDepthUpdateSubscription,
|
||||||
PriceLevelFieldsFragment,
|
|
||||||
} from './__generated__/MarketDepth';
|
} from './__generated__/MarketDepth';
|
||||||
|
|
||||||
export type OrderbookData = {
|
|
||||||
asks: PriceLevelFieldsFragment[];
|
|
||||||
bids: PriceLevelFieldsFragment[];
|
|
||||||
};
|
|
||||||
|
|
||||||
interface OrderbookManagerProps {
|
interface OrderbookManagerProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onClick: (args: { price?: string; size?: string }) => void;
|
onClick: (args: { price?: string; size?: string }) => void;
|
||||||
|
@ -238,7 +238,7 @@ export const Orderbook = ({
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
<Splash>{t('No data')}</Splash>
|
<Splash>{t('No open orders')}</Splash>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
import { render, screen, act } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { OrderListManager } from './order-list-manager';
|
import type { OrderListManagerProps } from './order-list-manager';
|
||||||
|
import { OrderListManager, Filter } from './order-list-manager';
|
||||||
import * as useDataProviderHook from '@vegaprotocol/data-provider';
|
import * as useDataProviderHook from '@vegaprotocol/data-provider';
|
||||||
import type { OrderFieldsFragment } from '../';
|
import type { OrderFieldsFragment } from '../';
|
||||||
import * as orderListMock from '../order-list/order-list';
|
|
||||||
import { forwardRef } from 'react';
|
|
||||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||||
import { MockedProvider } from '@apollo/client/testing';
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
|
||||||
// @ts-ignore OrderList is read only but we need to override with the forwardRef to
|
const generateJsx = (props: Partial<OrderListManagerProps> | null = null) => {
|
||||||
// avoid warnings about padding refs
|
|
||||||
orderListMock.OrderListTable = forwardRef(() => <div>OrderList</div>);
|
|
||||||
|
|
||||||
const generateJsx = () => {
|
|
||||||
const pubKey = '0x123';
|
const pubKey = '0x123';
|
||||||
return (
|
return (
|
||||||
<MockedProvider>
|
<MockedProvider>
|
||||||
<VegaWalletContext.Provider value={{ pubKey } as VegaWalletContextShape}>
|
<VegaWalletContext.Provider value={{ pubKey } as VegaWalletContextShape}>
|
||||||
<OrderListManager partyId={pubKey} isReadOnly={false} />
|
<OrderListManager partyId={pubKey} isReadOnly={false} {...props} />
|
||||||
</VegaWalletContext.Provider>
|
</VegaWalletContext.Provider>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
);
|
);
|
||||||
@ -33,9 +28,46 @@ describe('OrderListManager', () => {
|
|||||||
reload: jest.fn(),
|
reload: jest.fn(),
|
||||||
load: jest.fn(),
|
load: jest.fn(),
|
||||||
});
|
});
|
||||||
await act(async () => {
|
render(generateJsx());
|
||||||
render(generateJsx());
|
|
||||||
|
expect(
|
||||||
|
await screen.getByRole('treegrid', {
|
||||||
|
name: (_, element) => element.classList.contains('ag-root'),
|
||||||
|
})
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display order info', async () => {
|
||||||
|
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||||
|
data: [{ id: '1' } as OrderFieldsFragment],
|
||||||
|
loading: false,
|
||||||
|
error: new Error('Query error'),
|
||||||
|
flush: jest.fn(),
|
||||||
|
reload: jest.fn(),
|
||||||
|
load: jest.fn(),
|
||||||
});
|
});
|
||||||
expect(await screen.findByText('OrderList')).toBeInTheDocument();
|
|
||||||
|
render(generateJsx());
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await screen.getByText('Something went wrong: Query error')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display no rows overlay', async () => {
|
||||||
|
jest.spyOn(useDataProviderHook, 'useDataProvider').mockReturnValue({
|
||||||
|
data: [],
|
||||||
|
loading: false,
|
||||||
|
error: undefined,
|
||||||
|
flush: jest.fn(),
|
||||||
|
reload: jest.fn(),
|
||||||
|
load: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
|
render(
|
||||||
|
generateJsx({ filter: Filter.Closed, noRowsMessage: 'no rows message' })
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('no rows message')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useCallback, useRef, useState } from 'react';
|
import { useCallback, useRef, useState, useEffect } from 'react';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { OrderListTable } from '../order-list/order-list';
|
import type { FilterChangedEvent } from 'ag-grid-community';
|
||||||
|
import { OrderListTable } from '../order-list';
|
||||||
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
|
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
|
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
|
||||||
@ -11,6 +12,7 @@ import type { OrderTxUpdateFieldsFragment } from '@vegaprotocol/web3';
|
|||||||
import { OrderEditDialog } from '../order-list/order-edit-dialog';
|
import { OrderEditDialog } from '../order-list/order-edit-dialog';
|
||||||
import type { Order } from '../order-data-provider';
|
import type { Order } from '../order-data-provider';
|
||||||
import { OrderViewDialog } from '../order-list/order-view-dialog';
|
import { OrderViewDialog } from '../order-list/order-view-dialog';
|
||||||
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
export enum Filter {
|
export enum Filter {
|
||||||
'Open' = 'Open',
|
'Open' = 'Open',
|
||||||
@ -25,6 +27,7 @@ export interface OrderListManagerProps {
|
|||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
gridProps?: ReturnType<typeof useDataGridEvents>;
|
gridProps?: ReturnType<typeof useDataGridEvents>;
|
||||||
|
noRowsMessage?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OrderListManager = ({
|
export const OrderListManager = ({
|
||||||
@ -34,6 +37,7 @@ export const OrderListManager = ({
|
|||||||
isReadOnly,
|
isReadOnly,
|
||||||
filter,
|
filter,
|
||||||
gridProps,
|
gridProps,
|
||||||
|
noRowsMessage,
|
||||||
}: OrderListManagerProps) => {
|
}: OrderListManagerProps) => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const [editOrder, setEditOrder] = useState<Order | null>(null);
|
const [editOrder, setEditOrder] = useState<Order | null>(null);
|
||||||
@ -56,6 +60,29 @@ export const OrderListManager = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onFilterChanged = useCallback(
|
||||||
|
(event: FilterChangedEvent) => {
|
||||||
|
gridProps?.onFilterChanged?.(event);
|
||||||
|
if (event.api) {
|
||||||
|
const isEmpty = event.api.getDisplayedRowCount() === 0;
|
||||||
|
if (isEmpty) {
|
||||||
|
event.api.showNoRowsOverlay();
|
||||||
|
} else {
|
||||||
|
event.api.hideOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[gridProps]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data || !data.length) {
|
||||||
|
gridRef.current?.api?.showNoRowsOverlay();
|
||||||
|
} else {
|
||||||
|
gridRef.current?.api?.hideOverlay();
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const cancel = useCallback(
|
const cancel = useCallback(
|
||||||
(order: Order) => {
|
(order: Order) => {
|
||||||
if (!order.market) return;
|
if (!order.market) return;
|
||||||
@ -69,6 +96,10 @@ export const OrderListManager = ({
|
|||||||
[create]
|
[create]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <Splash>{t(`Something went wrong: ${error.message}`)}</Splash>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="h-full relative">
|
<div className="h-full relative">
|
||||||
@ -82,8 +113,9 @@ export const OrderListManager = ({
|
|||||||
onMarketClick={onMarketClick}
|
onMarketClick={onMarketClick}
|
||||||
onOrderTypeClick={onOrderTypeClick}
|
onOrderTypeClick={onOrderTypeClick}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
overlayNoRowsTemplate={error ? error.message : t('No orders')}
|
overlayNoRowsTemplate={noRowsMessage || t('No orders')}
|
||||||
{...gridProps}
|
{...gridProps}
|
||||||
|
onFilterChanged={onFilterChanged}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{editOrder && (
|
{editOrder && (
|
||||||
|
@ -34,7 +34,7 @@ import type {
|
|||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import type { Order } from '../order-data-provider';
|
import type { Order } from '../order-data-provider';
|
||||||
import { Filter } from '../order-list-manager';
|
import { Filter } from '../order-list-manager/order-list-manager';
|
||||||
import type { ColDef } from 'ag-grid-community';
|
import type { ColDef } from 'ag-grid-community';
|
||||||
|
|
||||||
const defaultColDef = {
|
const defaultColDef = {
|
||||||
|
@ -58,7 +58,7 @@ type ThemeStore = {
|
|||||||
setTheme: (theme?: Theme) => void;
|
setTheme: (theme?: Theme) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useThemeStore = create<ThemeStore>((set) => ({
|
const useThemeStore = create<ThemeStore>()((set) => ({
|
||||||
theme: getCurrentTheme(),
|
theme: getCurrentTheme(),
|
||||||
setTheme: (newTheme) => {
|
setTheme: (newTheme) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user