chore(trading): add handle of autosizing selected columns - main branch (#4888)
This commit is contained in:
parent
478cc9e753
commit
ff2e2574f6
@ -9,7 +9,7 @@ import {
|
|||||||
testOrderAmendment,
|
testOrderAmendment,
|
||||||
} from '../support/order-validation';
|
} from '../support/order-validation';
|
||||||
|
|
||||||
const orderSymbol = 'market.tradableInstrument.instrument.code';
|
const orderSymbol = 'instrument-code';
|
||||||
const orderSize = 'size';
|
const orderSize = 'size';
|
||||||
const orderType = 'type';
|
const orderType = 'type';
|
||||||
const orderStatus = 'status';
|
const orderStatus = 'status';
|
||||||
@ -229,10 +229,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
|
|||||||
status: Schema.OrderStatus.STATUS_FILLED,
|
status: Schema.OrderStatus.STATUS_FILLED,
|
||||||
});
|
});
|
||||||
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
|
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
|
||||||
cy.get('[col-id="market.tradableInstrument.instrument.code"]').contains(
|
cy.get(`[col-id="${orderSymbol}"]`).contains('[title="Future"]', 'Futr');
|
||||||
'[title="Future"]',
|
|
||||||
'Futr'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('must see a rejected order', () => {
|
it('must see a rejected order', () => {
|
||||||
|
@ -28,14 +28,20 @@ export interface OrderContainerProps {
|
|||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AUTO_SIZE_COLUMNS = ['instrument-code'];
|
||||||
|
|
||||||
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
||||||
const { gridState, updateGridState } = useOrderListGridState(filter);
|
const { gridState, updateGridState } = useOrderListGridState(filter);
|
||||||
const gridStoreCallbacks = useDataGridEvents(gridState, (newState) => {
|
const gridStoreCallbacks = useDataGridEvents(
|
||||||
updateGridState(filter, newState);
|
gridState,
|
||||||
});
|
(newState) => {
|
||||||
|
updateGridState(filter, newState);
|
||||||
|
},
|
||||||
|
AUTO_SIZE_COLUMNS
|
||||||
|
);
|
||||||
|
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||||
|
@ -10,6 +10,8 @@ import { create } from 'zustand';
|
|||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
|
const AUTO_SIZE_COLUMNS = ['marketCode'];
|
||||||
|
|
||||||
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
||||||
@ -17,7 +19,11 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
|||||||
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
|
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
|
||||||
const gridStore = usePositionsStore((store) => store.gridStore);
|
const gridStore = usePositionsStore((store) => store.gridStore);
|
||||||
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
||||||
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
|
const gridStoreCallbacks = useDataGridEvents(
|
||||||
|
gridStore,
|
||||||
|
updateGridStore,
|
||||||
|
AUTO_SIZE_COLUMNS
|
||||||
|
);
|
||||||
|
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
return (
|
return (
|
||||||
|
@ -5,8 +5,6 @@ import type { MutableRefObject } from 'react';
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
|
||||||
const GRID_EVENT_DEBOUNCE_TIME = 500;
|
|
||||||
|
|
||||||
const gridProps = {
|
const gridProps = {
|
||||||
rowData: [{ id: 1 }],
|
rowData: [{ id: 1 }],
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
@ -18,25 +16,29 @@ const gridProps = {
|
|||||||
],
|
],
|
||||||
style: { width: 500, height: 300 },
|
style: { width: 500, height: 300 },
|
||||||
};
|
};
|
||||||
|
const GRID_EVENT_DEBOUNCE_TIME = 300;
|
||||||
|
let gridRef: MutableRefObject<AgGridReact | null>;
|
||||||
|
function TestComponent({
|
||||||
|
hookParams,
|
||||||
|
}: {
|
||||||
|
hookParams: Parameters<typeof useDataGridEvents>;
|
||||||
|
}) {
|
||||||
|
const hookCallbacks = useDataGridEvents(...hookParams);
|
||||||
|
gridRef = useRef<AgGridReact | null>(null);
|
||||||
|
return <AgGridThemed gridRef={gridRef} {...gridProps} {...hookCallbacks} />;
|
||||||
|
}
|
||||||
|
|
||||||
// Not using render hook so I can pass event callbacks
|
// Not using render hook so I can pass event callbacks
|
||||||
// to a rendered grid
|
// to a rendered grid
|
||||||
function setup(...args: Parameters<typeof useDataGridEvents>) {
|
function setup(...args: Parameters<typeof useDataGridEvents>) {
|
||||||
let gridRef;
|
return render(<TestComponent hookParams={args} />);
|
||||||
|
|
||||||
function TestComponent() {
|
|
||||||
const hookCallbacks = useDataGridEvents(...args);
|
|
||||||
gridRef = useRef<AgGridReact | null>(null);
|
|
||||||
return <AgGridThemed gridRef={gridRef} {...gridProps} {...hookCallbacks} />;
|
|
||||||
}
|
|
||||||
render(<TestComponent />);
|
|
||||||
return gridRef as unknown as MutableRefObject<AgGridReact>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('useDataGridEvents', () => {
|
describe('useDataGridEvents', () => {
|
||||||
const originalWarn = console.warn;
|
const originalWarn = console.warn;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
gridRef = undefined;
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
// disabling some ag grid warnings that are caused by test setup only
|
// disabling some ag grid warnings that are caused by test setup only
|
||||||
@ -55,15 +57,15 @@ describe('useDataGridEvents', () => {
|
|||||||
columnState: undefined,
|
columnState: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = setup(initialState, callback);
|
setup(initialState, callback);
|
||||||
|
|
||||||
// column state was not updated, so the default width provided by the
|
// column state was not updated, so the default width provided by the
|
||||||
// col def should be set
|
// col def should be set
|
||||||
expect(result.current.columnApi.getColumnState()[0].width).toEqual(
|
expect(gridRef.current?.columnApi.getColumnState()[0].width).toEqual(
|
||||||
gridProps.columnDefs[0].width
|
gridProps.columnDefs[0].width
|
||||||
);
|
);
|
||||||
// no filters set
|
// no filters set
|
||||||
expect(result.current.api.getFilterModel()).toEqual({});
|
expect(gridRef.current?.api.getFilterModel()).toEqual({});
|
||||||
|
|
||||||
// Set filter
|
// Set filter
|
||||||
const idFilter = {
|
const idFilter = {
|
||||||
@ -72,7 +74,7 @@ describe('useDataGridEvents', () => {
|
|||||||
type: 'equals',
|
type: 'equals',
|
||||||
};
|
};
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.current.api.setFilterModel({
|
gridRef.current?.api.setFilterModel({
|
||||||
id: idFilter,
|
id: idFilter,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -88,7 +90,7 @@ describe('useDataGridEvents', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
callback.mockClear();
|
callback.mockClear();
|
||||||
expect(result.current.api.getFilterModel()['id']).toEqual(idFilter);
|
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('applies grid state on ready', async () => {
|
it('applies grid state on ready', async () => {
|
||||||
@ -105,11 +107,11 @@ describe('useDataGridEvents', () => {
|
|||||||
columnState: [colState],
|
columnState: [colState],
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = setup(initialState, jest.fn());
|
setup(initialState, jest.fn());
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(result.current.api.getFilterModel()['id']).toEqual(idFilter);
|
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||||
expect(result.current.columnApi.getColumnState()[0]).toEqual(
|
expect(gridRef.current?.columnApi.getColumnState()[0]).toEqual(
|
||||||
expect.objectContaining(colState)
|
expect.objectContaining(colState)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -122,13 +124,13 @@ describe('useDataGridEvents', () => {
|
|||||||
columnState: undefined,
|
columnState: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = setup(initialState, callback);
|
setup(initialState, callback);
|
||||||
|
|
||||||
const newWidth = 400;
|
const newWidth = 400;
|
||||||
|
|
||||||
// Set col width multiple times
|
// Set col width multiple times
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
gridRef.current?.columnApi.setColumnWidth('id', newWidth);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
@ -139,4 +141,23 @@ describe('useDataGridEvents', () => {
|
|||||||
|
|
||||||
expect(callback).toHaveBeenCalledTimes(0);
|
expect(callback).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('columns for autosizing should be handle', () => {
|
||||||
|
const callback = jest.fn();
|
||||||
|
const initialState = {
|
||||||
|
filterModel: undefined,
|
||||||
|
columnState: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { rerender } = setup(initialState, callback, ['id']);
|
||||||
|
jest.spyOn(gridRef.current?.columnApi, 'autoSizeColumns');
|
||||||
|
rerender(<TestComponent hookParams={[initialState, callback, ['id']]} />);
|
||||||
|
act(() => {
|
||||||
|
gridRef.current?.api.setRowData([{ id: 'test-id' }]);
|
||||||
|
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
||||||
|
});
|
||||||
|
expect(gridRef.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([
|
||||||
|
'id',
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@ import type {
|
|||||||
FilterChangedEvent,
|
FilterChangedEvent,
|
||||||
FirstDataRenderedEvent,
|
FirstDataRenderedEvent,
|
||||||
SortChangedEvent,
|
SortChangedEvent,
|
||||||
|
GridReadyEvent,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
@ -17,7 +18,8 @@ type State = {
|
|||||||
|
|
||||||
export const useDataGridEvents = (
|
export const useDataGridEvents = (
|
||||||
state: State,
|
state: State,
|
||||||
callback: (data: State) => void
|
callback: (data: State) => void,
|
||||||
|
autoSizeColumns?: string[]
|
||||||
) => {
|
) => {
|
||||||
/**
|
/**
|
||||||
* Callback for filter events
|
* Callback for filter events
|
||||||
@ -78,7 +80,7 @@ export const useDataGridEvents = (
|
|||||||
* State only applied if found, otherwise columns sized to fit available space
|
* State only applied if found, otherwise columns sized to fit available space
|
||||||
*/
|
*/
|
||||||
const onGridReady = useCallback(
|
const onGridReady = useCallback(
|
||||||
({ api, columnApi }: FirstDataRenderedEvent) => {
|
({ api, columnApi }: GridReadyEvent) => {
|
||||||
if (!api || !columnApi) return;
|
if (!api || !columnApi) return;
|
||||||
|
|
||||||
if (state.columnState) {
|
if (state.columnState) {
|
||||||
@ -97,6 +99,16 @@ export const useDataGridEvents = (
|
|||||||
[state]
|
[state]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onFirstDataRendered = useCallback(
|
||||||
|
({ columnApi }: FirstDataRenderedEvent) => {
|
||||||
|
if (!columnApi) return;
|
||||||
|
if (!state?.columnState && autoSizeColumns?.length) {
|
||||||
|
columnApi.autoSizeColumns(autoSizeColumns);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[state, autoSizeColumns]
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onGridReady,
|
onGridReady,
|
||||||
// these events don't use the 'finished' flag
|
// these events don't use the 'finished' flag
|
||||||
@ -106,5 +118,6 @@ export const useDataGridEvents = (
|
|||||||
// these trigger a lot so this callback uses the 'finished' flag
|
// these trigger a lot so this callback uses the 'finished' flag
|
||||||
onColumnMoved: onDebouncedColumnChange,
|
onColumnMoved: onDebouncedColumnChange,
|
||||||
onColumnResized: onDebouncedColumnChange,
|
onColumnResized: onDebouncedColumnChange,
|
||||||
|
onFirstDataRendered,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,7 @@ export const OrderListTable = memo<
|
|||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
headerName: t('Market'),
|
headerName: t('Market'),
|
||||||
|
colId: 'instrument-code',
|
||||||
field: 'market.tradableInstrument.instrument.code',
|
field: 'market.tradableInstrument.instrument.code',
|
||||||
cellRenderer: 'MarketNameCell',
|
cellRenderer: 'MarketNameCell',
|
||||||
cellRendererParams: { idPath: 'market.id', onMarketClick },
|
cellRendererParams: { idPath: 'market.id', onMarketClick },
|
||||||
|
Loading…
Reference in New Issue
Block a user