diff --git a/apps/explorer/src/app/components/assets/assets-table.tsx b/apps/explorer/src/app/components/assets/assets-table.tsx index 55b551c34..879512991 100644 --- a/apps/explorer/src/app/components/assets/assets-table.tsx +++ b/apps/explorer/src/app/components/assets/assets-table.tsx @@ -24,7 +24,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => { const navigate = useNavigate(); const ref = useRef(null); const showColumnsOnDesktop = () => { - ref.current?.columnApi.setColumnsVisible( + ref.current?.api.setColumnsVisible( ['id', 'type', 'status'], window.innerWidth > BREAKPOINT_MD ); diff --git a/apps/explorer/src/app/components/markets/markets-table.tsx b/apps/explorer/src/app/components/markets/markets-table.tsx index 0ecbe5769..babfa7c2c 100644 --- a/apps/explorer/src/app/components/markets/markets-table.tsx +++ b/apps/explorer/src/app/components/markets/markets-table.tsx @@ -29,7 +29,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => { const gridRef = useRef(null); useLayoutEffect(() => { const showColumnsOnDesktop = () => { - gridRef.current?.columnApi.setColumnsVisible( + gridRef.current?.api.setColumnsVisible( ['id', 'state', 'asset'], window.innerWidth > BREAKPOINT_MD ); diff --git a/apps/explorer/src/app/components/proposals/proposals-table.tsx b/apps/explorer/src/app/components/proposals/proposals-table.tsx index 017d12082..88d31a697 100644 --- a/apps/explorer/src/app/components/proposals/proposals-table.tsx +++ b/apps/explorer/src/app/components/proposals/proposals-table.tsx @@ -44,11 +44,11 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => { const gridRef = useRef(null); useLayoutEffect(() => { const showColumnsOnDesktop = () => { - gridRef.current?.columnApi.setColumnsVisible( + gridRef.current?.api.setColumnsVisible( ['voting', 'cDate', 'eDate', 'type'], window.innerWidth > BREAKPOINT_MD ); - gridRef.current?.columnApi.setColumnWidth( + gridRef.current?.api.setColumnWidth( 'actions', window.innerWidth > BREAKPOINT_MD ? 221 : 80 ); diff --git a/apps/trading/client-pages/market/trade-grid.tsx b/apps/trading/client-pages/market/trade-grid.tsx index 50e02ebb9..fea0989b6 100644 --- a/apps/trading/client-pages/market/trade-grid.tsx +++ b/apps/trading/client-pages/market/trade-grid.tsx @@ -90,7 +90,11 @@ const MainGrid = memo( {market && market.tradableInstrument.instrument.product.__typename === 'Perpetual' ? ( - + } + > - + } + > @@ -133,6 +141,7 @@ const MainGrid = memo( id="positions" name={t('Positions')} menu={} + settings={} > @@ -142,17 +151,26 @@ const MainGrid = memo( id="open-orders" name={t('Open')} menu={} + settings={} > - + } + > - + } + > @@ -161,25 +179,35 @@ const MainGrid = memo( id="orders" name={t('All')} menu={} + settings={} > {featureFlags.STOP_ORDERS ? ( - + } + > ) : null} - + } + > } + settings={} > { const featureFlags = useFeatureFlags((state) => state.flags); const [view, setView] = useState('chart'); + const viewCfg = TradingViews[view]; const renderView = () => { const Component = TradingViews[view].component; @@ -44,19 +50,27 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => { }; const renderMenu = () => { - const viewCfg = TradingViews[view]; - - if ('menu' in viewCfg) { - const Menu = viewCfg.menu; - + if ('menu' in viewCfg || 'settings' in viewCfg) { return (
- + {'menu' in viewCfg ? : null} + {'settings' in viewCfg ? ( + + + + } + > +
+ +
+
+ ) : null}
); } - - return null; }; return ( @@ -72,7 +86,7 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
{renderMenu()}
-
+
{({ width, height }) => (
@@ -110,7 +124,9 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => { key={key} view={key} isActive={isActive} - onClick={() => setView(key)} + onClick={() => { + setView(key); + }} /> ); })} diff --git a/apps/trading/client-pages/market/trade-views.tsx b/apps/trading/client-pages/market/trade-views.tsx index d11c40f18..d7bf1dbac 100644 --- a/apps/trading/client-pages/market/trade-views.tsx +++ b/apps/trading/client-pages/market/trade-views.tsx @@ -1,15 +1,36 @@ import { DepthChartContainer } from '@vegaprotocol/market-depth'; import { Filter, OpenOrdersMenu } from '@vegaprotocol/orders'; -import { TradesContainer } from '../../components/trades-container'; +import { + TradesContainer, + TradesSettings, +} from '../../components/trades-container'; import { OrderbookContainer } from '../../components/orderbook-container'; -import { FillsContainer } from '../../components/fills-container'; -import { PositionsContainer } from '../../components/positions-container'; -import { AccountsContainer } from '../../components/accounts-container'; +import { + FillsContainer, + FillsSettings, +} from '../../components/fills-container'; +import { + PositionsContainer, + PositionsSettings, +} from '../../components/positions-container'; +import { + AccountsContainer, + AccountsSettings, +} from '../../components/accounts-container'; import { LiquidityContainer } from '../../components/liquidity-container'; import { FundingContainer } from '../../components/funding-container'; -import { FundingPaymentsContainer } from '../../components/funding-payments-container'; -import { OrdersContainer } from '../../components/orders-container'; -import { StopOrdersContainer } from '../../components/stop-orders-container'; +import { + FundingPaymentsContainer, + FundingPaymentsSettings, +} from '../../components/funding-payments-container'; +import { + OrdersContainer, + OrdersSettings, +} from '../../components/orders-container'; +import { + StopOrdersContainer, + StopOrdersSettings, +} from '../../components/stop-orders-container'; import { AccountsMenu } from '../../components/accounts-menu'; import { PositionsMenu } from '../../components/positions-menu'; import { ChartContainer, ChartMenu } from '../../components/chart-container'; @@ -32,37 +53,46 @@ export const TradingViews = { }, fundingPayments: { component: FundingPaymentsContainer, + settings: FundingPaymentsSettings, }, orderbook: { component: OrderbookContainer, }, trades: { component: TradesContainer, + settings: TradesSettings, }, positions: { component: PositionsContainer, menu: PositionsMenu, + settings: PositionsSettings, }, activeOrders: { component: () => , menu: OpenOrdersMenu, + settings: () => , }, closedOrders: { component: () => , + settings: () => , }, rejectedOrders: { component: () => , + settings: () => , }, orders: { component: OrdersContainer, menu: OpenOrdersMenu, + settings: OrdersSettings, }, stopOrders: { component: StopOrdersContainer, + settings: StopOrdersSettings, }, collateral: { component: AccountsContainer, menu: AccountsMenu, + settings: AccountsSettings, }, - fills: { component: FillsContainer }, + fills: { component: FillsContainer, settings: FillsSettings }, } as const; diff --git a/apps/trading/client-pages/markets/market-list-table.tsx b/apps/trading/client-pages/markets/market-list-table.tsx index a7dabc782..026df47d7 100644 --- a/apps/trading/client-pages/markets/market-list-table.tsx +++ b/apps/trading/client-pages/markets/market-list-table.tsx @@ -42,7 +42,7 @@ export const createDataGridSlice: StateCreator = (set) => ({ }, }); -const useMarketsStore = create()( +export const useMarketsStore = create()( persist(createDataGridSlice, { name: 'vega_market_list_store', }) diff --git a/apps/trading/client-pages/markets/markets-page.tsx b/apps/trading/client-pages/markets/markets-page.tsx index a39cf9a82..795c80b78 100644 --- a/apps/trading/client-pages/markets/markets-page.tsx +++ b/apps/trading/client-pages/markets/markets-page.tsx @@ -16,6 +16,7 @@ import { } from '@vegaprotocol/environment'; import { useT } from '../../lib/use-t'; import { ErrorBoundary } from '../../components/error-boundary'; +import { MarketsSettings } from './markets-settings'; export const MarketsPage = () => { const t = useT(); @@ -34,7 +35,11 @@ export const MarketsPage = () => {
- + } + > @@ -42,6 +47,7 @@ export const MarketsPage = () => { } menu={ { - + } + > diff --git a/apps/trading/client-pages/markets/markets-settings.tsx b/apps/trading/client-pages/markets/markets-settings.tsx new file mode 100644 index 000000000..4a1361fcd --- /dev/null +++ b/apps/trading/client-pages/markets/markets-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../../components/grid-settings/grid-settings'; +import { useMarketsStore } from './market-list-table'; + +export const MarketsSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/client-pages/portfolio/portfolio.tsx b/apps/trading/client-pages/portfolio/portfolio.tsx index 02256ffd9..3799b0500 100644 --- a/apps/trading/client-pages/portfolio/portfolio.tsx +++ b/apps/trading/client-pages/portfolio/portfolio.tsx @@ -5,14 +5,29 @@ import { titlefy } from '@vegaprotocol/utils'; import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws'; import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit'; import { usePageTitleStore } from '../../stores'; -import { AccountsContainer } from '../../components/accounts-container'; +import { + AccountsContainer, + AccountsSettings, +} from '../../components/accounts-container'; import { DepositsContainer } from '../../components/deposits-container'; -import { FillsContainer } from '../../components/fills-container'; -import { FundingPaymentsContainer } from '../../components/funding-payments-container'; -import { PositionsContainer } from '../../components/positions-container'; +import { + FillsContainer, + FillsSettings, +} from '../../components/fills-container'; +import { + FundingPaymentsContainer, + FundingPaymentsSettings, +} from '../../components/funding-payments-container'; +import { + PositionsContainer, + PositionsSettings, +} from '../../components/positions-container'; import { PositionsMenu } from '../../components/positions-menu'; import { WithdrawalsContainer } from '../../components/withdrawals-container'; -import { OrdersContainer } from '../../components/orders-container'; +import { + OrdersContainer, + OrdersSettings, +} from '../../components/orders-container'; import { LedgerContainer } from '../../components/ledger-container'; import { ResizableGrid, @@ -76,22 +91,27 @@ export const Portfolio = () => { id="positions" name={t('Positions')} menu={} + settings={} > - + }> - + }> - + } + > @@ -114,6 +134,7 @@ export const Portfolio = () => { } menu={} > diff --git a/apps/trading/components/accounts-container/accounts-container.tsx b/apps/trading/components/accounts-container/accounts-container.tsx index 0e5886d63..ba560e694 100644 --- a/apps/trading/components/accounts-container/accounts-container.tsx +++ b/apps/trading/components/accounts-container/accounts-container.tsx @@ -73,7 +73,7 @@ export const AccountsContainer = ({ ); }; -const useAccountStore = create()( +export const useAccountStore = create()( persist(createDataGridSlice, { name: 'vega_accounts_store', }) diff --git a/apps/trading/components/accounts-container/accounts-settings.tsx b/apps/trading/components/accounts-container/accounts-settings.tsx new file mode 100644 index 000000000..9fcf69732 --- /dev/null +++ b/apps/trading/components/accounts-container/accounts-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { useAccountStore } from './accounts-container'; + +export const AccountsSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/components/accounts-container/index.ts b/apps/trading/components/accounts-container/index.ts index 9608234c5..e3a380ec3 100644 --- a/apps/trading/components/accounts-container/index.ts +++ b/apps/trading/components/accounts-container/index.ts @@ -1 +1,2 @@ export * from './accounts-container'; +export * from './accounts-settings'; diff --git a/apps/trading/components/fills-container/fills-container.tsx b/apps/trading/components/fills-container/fills-container.tsx index da26c8f9f..3ce056292 100644 --- a/apps/trading/components/fills-container/fills-container.tsx +++ b/apps/trading/components/fills-container/fills-container.tsx @@ -38,7 +38,7 @@ export const FillsContainer = () => { ); }; -const useFillsStore = create()( +export const useFillsStore = create()( persist(createDataGridSlice, { name: 'vega_fills_store', }) diff --git a/apps/trading/components/fills-container/fills-settings.tsx b/apps/trading/components/fills-container/fills-settings.tsx new file mode 100644 index 000000000..d202df6da --- /dev/null +++ b/apps/trading/components/fills-container/fills-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { useFillsStore } from './fills-container'; + +export const FillsSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/components/fills-container/index.ts b/apps/trading/components/fills-container/index.ts index da6122a07..e35d2e8c3 100644 --- a/apps/trading/components/fills-container/index.ts +++ b/apps/trading/components/fills-container/index.ts @@ -1 +1,2 @@ export * from './fills-container'; +export * from './fills-settings'; diff --git a/apps/trading/components/funding-payments-container/funding-payments-container.tsx b/apps/trading/components/funding-payments-container/funding-payments-container.tsx index a053c6c21..3aa21f936 100644 --- a/apps/trading/components/funding-payments-container/funding-payments-container.tsx +++ b/apps/trading/components/funding-payments-container/funding-payments-container.tsx @@ -45,7 +45,7 @@ export const FundingPaymentsContainer = ({ ); }; -const useFundingPaymentsStore = create()( +export const useFundingPaymentsStore = create()( persist(createDataGridSlice, { name: 'vega_funding_payments_store', }) diff --git a/apps/trading/components/funding-payments-container/funding-payments-settings.tsx b/apps/trading/components/funding-payments-container/funding-payments-settings.tsx new file mode 100644 index 000000000..e4128fa50 --- /dev/null +++ b/apps/trading/components/funding-payments-container/funding-payments-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { useFundingPaymentsStore } from './funding-payments-container'; + +export const FundingPaymentsSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/components/funding-payments-container/index.ts b/apps/trading/components/funding-payments-container/index.ts index cf75ae8e1..65810d1c9 100644 --- a/apps/trading/components/funding-payments-container/index.ts +++ b/apps/trading/components/funding-payments-container/index.ts @@ -1 +1,2 @@ export * from './funding-payments-container'; +export * from './funding-payments-settings'; diff --git a/apps/trading/components/grid-settings/grid-settings.tsx b/apps/trading/components/grid-settings/grid-settings.tsx new file mode 100644 index 000000000..3d7501927 --- /dev/null +++ b/apps/trading/components/grid-settings/grid-settings.tsx @@ -0,0 +1,24 @@ +import { useT } from '../../lib/use-t'; +import type { DataGridStore } from '../../stores/datagrid-store-slice'; +import { TradingButton as Button } from '@vegaprotocol/ui-toolkit'; + +export const GridSettings = ({ + updateGridStore, +}: { + updateGridStore: (gridStore: DataGridStore) => void; +}) => { + const t = useT(); + return ( + + ); +}; diff --git a/apps/trading/components/market-header/market-header.tsx b/apps/trading/components/market-header/market-header.tsx index ad6c4aa0a..10167e04f 100644 --- a/apps/trading/components/market-header/market-header.tsx +++ b/apps/trading/components/market-header/market-header.tsx @@ -27,7 +27,7 @@ export const MarketHeader = () => { title={ diff --git a/apps/trading/components/orders-container/orders-container.spec.tsx b/apps/trading/components/orders-container/orders-container.spec.tsx index 531464d50..4a434b61a 100644 --- a/apps/trading/components/orders-container/orders-container.spec.tsx +++ b/apps/trading/components/orders-container/orders-container.spec.tsx @@ -1,9 +1,5 @@ import { act, renderHook } from '@testing-library/react'; -import { - FilterStatusValue, - STORAGE_KEY, - useOrderListGridState, -} from './orders-container'; +import { STORAGE_KEY, useOrderListGridState } from './orders-container'; import { Filter } from '@vegaprotocol/orders'; import { OrderType } from '@vegaprotocol/types'; @@ -16,31 +12,6 @@ describe('useOrderListGridState', () => { return renderHook(() => useOrderListGridState(filter)); }; - it.each(Object.values(Filter))( - 'providers correct AgGrid filter for %s', - (filter) => { - const { result } = setup(filter); - expect(typeof result.current.updateGridState).toBe('function'); - expect(result.current.gridState).toEqual({ - columnState: undefined, - filterModel: { - status: { - value: FilterStatusValue[filter], - }, - }, - }); - } - ); - - it('provides correct AgGrid filter for all', () => { - const { result } = setup(undefined); - expect(typeof result.current.updateGridState).toBe('function'); - expect(result.current.gridState).toEqual({ - columnState: undefined, - filterModel: undefined, - }); - }); - it.each(Object.values(Filter))( 'sets and stores column state and filters for %s', (filter) => { @@ -59,12 +30,7 @@ describe('useOrderListGridState', () => { expect(result.current.gridState).toEqual({ columnState: undefined, - filterModel: { - ...filterModel, - status: { - value: FilterStatusValue[filter], - }, - }, + filterModel, }); const columnState = [{ colId: 'status', width: 200 }]; @@ -77,12 +43,7 @@ describe('useOrderListGridState', () => { expect(result.current.gridState).toEqual({ columnState, - filterModel: { - ...filterModel, - status: { - value: FilterStatusValue[filter], - }, - }, + filterModel, }); const storeKeyMap = { diff --git a/apps/trading/components/orders-container/orders-container.tsx b/apps/trading/components/orders-container/orders-container.tsx index 4c4eb8c7e..c61af42e0 100644 --- a/apps/trading/components/orders-container/orders-container.tsx +++ b/apps/trading/components/orders-container/orders-container.tsx @@ -9,6 +9,7 @@ import type { DataGridStore } from '../../stores/datagrid-store-slice'; import { OrderStatus } from '@vegaprotocol/types'; import { Links } from '../../lib/links'; import { useT } from '../../lib/use-t'; +import { GridSettings } from '../grid-settings/grid-settings'; const resolveNoRowsMessage = ( filter: Filter | undefined, @@ -38,6 +39,24 @@ export const FilterStatusValue = { [Filter.Rejected]: [OrderStatus.STATUS_REJECTED], }; +export const DefaultFilterModel = { + [Filter.Open]: { + status: { + value: FilterStatusValue[Filter.Open], + }, + }, + [Filter.Closed]: { + status: { + value: FilterStatusValue[Filter.Closed], + }, + }, + [Filter.Rejected]: { + status: { + value: FilterStatusValue[Filter.Rejected], + }, + }, +}; + export interface OrderContainerProps { filter?: Filter; } @@ -54,7 +73,8 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => { (newState) => { updateGridState(filter, newState); }, - AUTO_SIZE_COLUMNS + AUTO_SIZE_COLUMNS, + filter && DefaultFilterModel[filter] ); if (!pubKey) { @@ -80,7 +100,7 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => { }; export const STORAGE_KEY = 'vega_order_list_store'; -const useOrderListStore = create<{ +export const useOrderListStore = create<{ open: DataGridStore; closed: DataGridStore; rejected: DataGridStore; @@ -149,34 +169,19 @@ export const useOrderListGridState = (filter: Filter | undefined) => { case Filter.Open: { return { columnState: store.open.columnState, - filterModel: { - ...store.open.filterModel, - status: { - value: FilterStatusValue[Filter.Open], - }, - }, + filterModel: store.open.filterModel, }; } case Filter.Closed: { return { columnState: store.closed.columnState, - filterModel: { - ...store.closed.filterModel, - status: { - value: FilterStatusValue[Filter.Closed], - }, - }, + filterModel: store.closed.filterModel, }; } case Filter.Rejected: { return { columnState: store.rejected.columnState, - filterModel: { - ...store.rejected.filterModel, - status: { - value: FilterStatusValue[Filter.Rejected], - }, - }, + filterModel: store.rejected.filterModel, }; } default: { @@ -187,3 +192,14 @@ export const useOrderListGridState = (filter: Filter | undefined) => { return { gridState, updateGridState }; }; + +export const OrdersSettings = ({ filter }: { filter?: Filter }) => { + const updateGridState = useOrderListStore((state) => state.update); + return ( + + updateGridState(filter, gridStore) + } + /> + ); +}; diff --git a/apps/trading/components/positions-container/index.ts b/apps/trading/components/positions-container/index.ts index 024171651..1e286f91b 100644 --- a/apps/trading/components/positions-container/index.ts +++ b/apps/trading/components/positions-container/index.ts @@ -1 +1,2 @@ export * from './positions-container'; +export * from './positions-settings'; diff --git a/apps/trading/components/positions-container/positions-settings.tsx b/apps/trading/components/positions-container/positions-settings.tsx new file mode 100644 index 000000000..26b1f6f44 --- /dev/null +++ b/apps/trading/components/positions-container/positions-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { usePositionsStore } from './positions-container'; + +export const PositionsSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/components/stop-orders-container/index.ts b/apps/trading/components/stop-orders-container/index.ts index da49afbcd..702646c6e 100644 --- a/apps/trading/components/stop-orders-container/index.ts +++ b/apps/trading/components/stop-orders-container/index.ts @@ -1 +1,3 @@ export * from './stop-orders-container'; + +export * from './stop-orders-settings'; diff --git a/apps/trading/components/stop-orders-container/stop-orders-container.tsx b/apps/trading/components/stop-orders-container/stop-orders-container.tsx index c8b8dd964..4f45ca908 100644 --- a/apps/trading/components/stop-orders-container/stop-orders-container.tsx +++ b/apps/trading/components/stop-orders-container/stop-orders-container.tsx @@ -35,7 +35,7 @@ export const StopOrdersContainer = () => { ); }; -const useStopOrdersStore = create()( +export const useStopOrdersStore = create()( persist(createDataGridSlice, { name: 'vega_stop_orders_store', }) diff --git a/apps/trading/components/stop-orders-container/stop-orders-settings.tsx b/apps/trading/components/stop-orders-container/stop-orders-settings.tsx new file mode 100644 index 000000000..9cdb2be19 --- /dev/null +++ b/apps/trading/components/stop-orders-container/stop-orders-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { useStopOrdersStore } from './stop-orders-container'; + +export const StopOrdersSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/components/trades-container/index.ts b/apps/trading/components/trades-container/index.ts index bdd817b39..4c037800e 100644 --- a/apps/trading/components/trades-container/index.ts +++ b/apps/trading/components/trades-container/index.ts @@ -1 +1,2 @@ export * from './trades-container'; +export * from './trades-settings'; diff --git a/apps/trading/components/trades-container/trades-container.tsx b/apps/trading/components/trades-container/trades-container.tsx index b6c932491..f8fbf584a 100644 --- a/apps/trading/components/trades-container/trades-container.tsx +++ b/apps/trading/components/trades-container/trades-container.tsx @@ -17,7 +17,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => { return ; }; -const useTradesStore = create()( +export const useTradesStore = create()( persist(createDataGridSlice, { name: 'vega_trades_store', }) diff --git a/apps/trading/components/trades-container/trades-settings.tsx b/apps/trading/components/trades-container/trades-settings.tsx new file mode 100644 index 000000000..05740d1ad --- /dev/null +++ b/apps/trading/components/trades-container/trades-settings.tsx @@ -0,0 +1,8 @@ +import { GridSettings } from '../grid-settings/grid-settings'; +import { useTradesStore } from './trades-container'; + +export const TradesSettings = () => ( + store.updateGridStore)} + /> +); diff --git a/apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py b/apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py index ed3ab6a88..154b783c3 100644 --- a/apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py +++ b/apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py @@ -65,16 +65,17 @@ def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page page.wait_for_selector(".ag-center-cols-container .ag-row") expect( - page.locator(".ag-center-cols-container .ag-row [col-id='remaining']") + page.locator(".ag-center-cols-container .ag-row [col-id='remaining']").first ).to_have_text("99") expect( - page.locator(".ag-center-cols-container .ag-row [col-id='size']") + page.locator(".ag-center-cols-container .ag-row [col-id='size']").first ).to_have_text("-102") + page.pause() expect( - page.locator(".ag-center-cols-container .ag-row [col-id='type'] ") + page.locator(".ag-center-cols-container .ag-row [col-id='type'] ").first ).to_have_text("Limit (Iceberg)") expect( - page.locator(".ag-center-cols-container .ag-row [col-id='status']") + page.locator(".ag-center-cols-container .ag-row [col-id='status']").first ).to_have_text("Active") expect(page.get_by_test_id("price-10100000")).to_be_visible expect(page.get_by_test_id("ask-vol-10100000")).to_have_text("3") diff --git a/apps/trading/e2e/tests/order/test_order_match.py b/apps/trading/e2e/tests/order/test_order_match.py index bfb3f35d4..63aa20c1e 100644 --- a/apps/trading/e2e/tests/order/test_order_match.py +++ b/apps/trading/e2e/tests/order/test_order_match.py @@ -16,11 +16,11 @@ def verify_data_grid(page: Page, data_test_id, expected_pattern): expect( page.locator( f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first' - ) + ).first ).to_be_visible() actual_text = page.locator( f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first' - ).text_content() + ).first.text_content() lines = actual_text.strip().split("\n") for expected, actual in zip(expected_pattern, lines): # We are using regex so that we can run tests in different timezones. diff --git a/apps/trading/e2e/tests/settings/test_column_settings.py b/apps/trading/e2e/tests/settings/test_column_settings.py new file mode 100644 index 000000000..8afbf5966 --- /dev/null +++ b/apps/trading/e2e/tests/settings/test_column_settings.py @@ -0,0 +1,36 @@ +import pytest +from playwright.sync_api import expect, Page + +settings_icon = "icon-cog" +settings_column_btn = "popover-trigger" +settings_close_btn = "settings-close" +split_view_view = "split-view-view" + +@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted") +def test_column_settings_is_visible(continuous_market, page: Page): + page.goto(f"/#/markets/{continuous_market}") + expect(page.get_by_test_id(split_view_view).get_by_test_id(settings_column_btn)).to_be_visible() + page.goto("/#/portfolio") + expect(page.get_by_test_id(split_view_view).get_by_test_id(settings_column_btn).nth(0)).to_be_visible() + expect(page.get_by_test_id(split_view_view).get_by_test_id(settings_column_btn).nth(1)).to_be_visible() + page.goto(f"/#/markets/all") + expect(page.get_by_test_id(settings_column_btn)).to_be_visible() + page.click('[data-testid="Proposed markets"]') + expect(page.get_by_test_id(settings_column_btn)).to_be_visible() + page.click('[data-testid="Closed markets"]') + expect(page.get_by_test_id(settings_column_btn)).to_be_visible() + +@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted") +def test_can_reset_columns_state(continuous_market, page: Page): + page.goto(f"/#/markets/all") + col_market = page.locator('[col-id="tradableInstrument.instrument.code"]').first + col_settlement_asset = page.locator('[col-id="tradableInstrument.instrument.product.settlementAsset.symbol"]').first + col_market.drag_to(col_settlement_asset) + + # Check the attribute of the dragged element + attribute_value = col_market.get_attribute("aria-colindex") + assert attribute_value != "1" + page.get_by_test_id(settings_column_btn).click() + page.get_by_role("button", name="Reset Columns").click() + attribute_value_after_reset = col_market.get_attribute("aria-colindex") + assert attribute_value_after_reset == "1" \ No newline at end of file diff --git a/libs/accounts/src/lib/accounts-manager.tsx b/libs/accounts/src/lib/accounts-manager.tsx index 7de06c6d0..80c796bfc 100644 --- a/libs/accounts/src/lib/accounts-manager.tsx +++ b/libs/accounts/src/lib/accounts-manager.tsx @@ -29,7 +29,7 @@ const AccountBreakdown = ({ variables: { partyId, assetId }, update: ({ data }) => { if (gridRef.current?.api && data?.breakdown) { - gridRef.current?.api.setRowData(data?.breakdown); + gridRef.current?.api.setGridOption('rowData', data?.breakdown); return true; } return false; diff --git a/libs/datagrid/src/lib/filters/date-range-filter.tsx b/libs/datagrid/src/lib/filters/date-range-filter.tsx index ecf03219e..96a04c86d 100644 --- a/libs/datagrid/src/lib/filters/date-range-filter.tsx +++ b/libs/datagrid/src/lib/filters/date-range-filter.tsx @@ -65,18 +65,9 @@ export const DateRangeFilter = forwardRef( useImperativeHandle(ref, () => { return { doesFilterPass(params: IDoesFilterPassParams) { - const { api, colDef, column, columnApi, context } = props; + const { column } = props; const { node } = params; - const rowValue = props.valueGetter({ - api, - colDef, - column, - columnApi, - context, - data: node.data, - getValue: (field) => node.data[field], - node, - }); + const rowValue = props.getValue(node, column); if ( value.start && rowValue && diff --git a/libs/datagrid/src/lib/filters/set-filter.tsx b/libs/datagrid/src/lib/filters/set-filter.tsx index 2a58be5cf..fcbe31246 100644 --- a/libs/datagrid/src/lib/filters/set-filter.tsx +++ b/libs/datagrid/src/lib/filters/set-filter.tsx @@ -19,18 +19,9 @@ export const SetFilter = forwardRef( useImperativeHandle(ref, () => { return { doesFilterPass(params: IDoesFilterPassParams) { - const { api, colDef, column, columnApi, context } = props; + const { column } = props; const { node } = params; - const getValue = props.valueGetter({ - api, - colDef, - column, - columnApi, - context, - data: node.data, - getValue: (field) => node.data[field], - node, - }); + const getValue = props.getValue(node, column); return Array.isArray(value) ? value.includes(getValue) : getValue === value; diff --git a/libs/datagrid/src/lib/use-datagrid-events.spec.tsx b/libs/datagrid/src/lib/use-datagrid-events.spec.tsx index f9ce82193..545c5dfa4 100644 --- a/libs/datagrid/src/lib/use-datagrid-events.spec.tsx +++ b/libs/datagrid/src/lib/use-datagrid-events.spec.tsx @@ -61,7 +61,7 @@ describe('useDataGridEvents', () => { // column state was not updated, so the default width provided by the // col def should be set - expect(gridRef?.current?.columnApi.getColumnState()[0].width).toEqual( + expect(gridRef?.current?.api.getColumnState()[0].width).toEqual( gridProps.columnDefs[0].width ); // no filters set @@ -107,16 +107,57 @@ describe('useDataGridEvents', () => { columnState: [colState], }; - setup(initialState, jest.fn()); + setup(initialState, jest.fn(), undefined); await waitFor(() => { expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter); - expect(gridRef?.current?.columnApi.getColumnState()[0]).toEqual( + expect(gridRef?.current?.api.getColumnState()[0]).toEqual( expect.objectContaining(colState) ); }); }); + it('applies default filter model', async () => { + const idFilter = { + filter: 1, + filterType: 'number', + type: 'equals', + }; + + setup({}, jest.fn(), undefined, { + id: idFilter, + }); + + await waitFor(() => { + expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter); + }); + }); + + it('default filter overwrites stored filter model', async () => { + const idFilter = { + filter: 1, + filterType: 'number', + type: 'equals', + }; + + setup( + { + filterModel: { + id: { ...idFilter, filter: 2 }, + }, + }, + jest.fn(), + undefined, + { + id: idFilter, + } + ); + + await waitFor(() => { + expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter); + }); + }); + it('ignores events that were not made via the UI', async () => { const callback = jest.fn(); const initialState = { @@ -130,7 +171,7 @@ describe('useDataGridEvents', () => { // Set col width multiple times await act(async () => { - gridRef?.current?.columnApi.setColumnWidth('id', newWidth); + gridRef?.current?.api.setColumnWidth('id', newWidth); }); expect(callback).not.toHaveBeenCalled(); @@ -150,14 +191,14 @@ describe('useDataGridEvents', () => { }; const { rerender } = setup(initialState, callback, ['id']); - jest.spyOn(gridRef?.current?.columnApi, 'autoSizeColumns'); + if (gridRef?.current?.api) { + jest.spyOn(gridRef?.current?.api, 'autoSizeColumns'); + } rerender(); act(() => { - gridRef?.current?.api.setRowData([{ id: 'test-id' }]); + gridRef?.current?.api.setGridOption('rowData', [{ id: 'test-id' }]); jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME); }); - expect(gridRef?.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([ - 'id', - ]); + expect(gridRef?.current?.api.autoSizeColumns).toHaveBeenCalledWith(['id']); }); }); diff --git a/libs/datagrid/src/lib/use-datagrid-events.ts b/libs/datagrid/src/lib/use-datagrid-events.ts index 42fd0f88e..842a4a137 100644 --- a/libs/datagrid/src/lib/use-datagrid-events.ts +++ b/libs/datagrid/src/lib/use-datagrid-events.ts @@ -7,8 +7,9 @@ import { type FirstDataRenderedEvent, type SortChangedEvent, type GridReadyEvent, + GridApi, } from 'ag-grid-community'; -import { useCallback } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; type State = { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -19,8 +20,32 @@ type State = { export const useDataGridEvents = ( state: State, callback: (data: State) => void, - autoSizeColumns?: string[] + autoSizeColumns?: string[], + defaultFilterModel?: State['filterModel'] ) => { + const apiRef = useRef(); + const hasStateRef = useRef(Boolean(state.columnState || state.filterModel)); + + useEffect(() => { + if (apiRef.current?.isDestroyed()) { + apiRef.current = undefined; + } + const hasState = Boolean(state.columnState || state.filterModel); + if (apiRef.current && hasStateRef.current && !hasState) { + if (!state.columnState) { + apiRef.current.resetColumnState(); + apiRef.current.sizeColumnsToFit(); + if (autoSizeColumns?.length) { + apiRef.current.autoSizeColumns(autoSizeColumns); + } + } + if (!state.filterModel) { + apiRef.current.setFilterModel(defaultFilterModel); + } + } + hasStateRef.current = hasState; + }, [state, defaultFilterModel, autoSizeColumns]); + /** * Callback for filter events */ @@ -39,11 +64,7 @@ export const useDataGridEvents = ( * store callback unnecessarily */ const onDebouncedColumnChange = useCallback( - ({ - columnApi, - source, - finished, - }: ColumnResizedEvent | ColumnMovedEvent) => { + ({ api, source, finished }: ColumnResizedEvent | ColumnMovedEvent) => { if (!finished) return; // only call back on user interactions, and not events triggered from the api @@ -57,7 +78,7 @@ export const useDataGridEvents = ( return; } - const columnState = columnApi.getColumnState(); + const columnState = api.getColumnState(); callback({ columnState }); }, @@ -68,8 +89,8 @@ export const useDataGridEvents = ( * Callback for sort and visible events */ const onColumnChange = useCallback( - ({ columnApi }: SortChangedEvent | ColumnVisibleEvent) => { - const columnState = columnApi.getColumnState(); + ({ api }: SortChangedEvent | ColumnVisibleEvent) => { + const columnState = api.getColumnState(); callback({ columnState }); }, [callback] @@ -80,11 +101,11 @@ export const useDataGridEvents = ( * State only applied if found, otherwise columns sized to fit available space */ const onGridReady = useCallback( - ({ api, columnApi }: GridReadyEvent) => { - if (!api || !columnApi) return; - + ({ api }: GridReadyEvent) => { + apiRef.current = api; + if (!api) return; if (state.columnState) { - columnApi.applyColumnState({ + api.applyColumnState({ state: state.columnState, applyOrder: true, }); @@ -92,18 +113,18 @@ export const useDataGridEvents = ( api.sizeColumnsToFit(); } - if (state.filterModel) { - api.setFilterModel(state.filterModel); + if (state.filterModel || defaultFilterModel) { + api.setFilterModel({ ...state.filterModel, ...defaultFilterModel }); } }, - [state] + [state, defaultFilterModel] ); const onFirstDataRendered = useCallback( - ({ columnApi }: FirstDataRenderedEvent) => { - if (!columnApi) return; + ({ api }: FirstDataRenderedEvent) => { + if (!api) return; if (!state?.columnState && autoSizeColumns?.length) { - columnApi.autoSizeColumns(autoSizeColumns); + api.autoSizeColumns(autoSizeColumns); } }, [state, autoSizeColumns] diff --git a/libs/funding-payments/src/lib/funding-payments-manager.tsx b/libs/funding-payments/src/lib/funding-payments-manager.tsx index ebf8a31df..2178a0afa 100644 --- a/libs/funding-payments/src/lib/funding-payments-manager.tsx +++ b/libs/funding-payments/src/lib/funding-payments-manager.tsx @@ -36,7 +36,7 @@ export const FundingPaymentsManager = ({ dataProvider: fundingPaymentsWithMarketProvider, update: ({ data }) => { if (data?.length && gridRef.current?.api) { - gridRef.current?.api.setRowData(data); + gridRef.current?.api.setGridOption('rowData', data); return true; } return false; diff --git a/libs/i18n/src/locales/en/trading.json b/libs/i18n/src/locales/en/trading.json index 754b47bfb..cc6c859a7 100644 --- a/libs/i18n/src/locales/en/trading.json +++ b/libs/i18n/src/locales/en/trading.json @@ -235,6 +235,7 @@ "Rejected": "Rejected", "Required epochs": "Required epochs", "Required for next tier": "Required for next tier", + "Reset Columns": "Reset Columns", "Resources": "Resources", "Rewards": "Rewards", "Rewards history": "Rewards history", diff --git a/libs/ui-toolkit/src/components/popover/popover.stories.tsx b/libs/ui-toolkit/src/components/popover/popover.stories.tsx index cfb67c017..476e08104 100644 --- a/libs/ui-toolkit/src/components/popover/popover.stories.tsx +++ b/libs/ui-toolkit/src/components/popover/popover.stories.tsx @@ -15,7 +15,7 @@ const Template: ComponentStory = (args) => {
Trigger} > {args.children} diff --git a/libs/ui-toolkit/src/components/popover/popover.tsx b/libs/ui-toolkit/src/components/popover/popover.tsx index 8f46d717d..c695ad3ad 100644 --- a/libs/ui-toolkit/src/components/popover/popover.tsx +++ b/libs/ui-toolkit/src/components/popover/popover.tsx @@ -4,29 +4,29 @@ export interface PopoverProps extends PopoverPrimitive.PopoverProps { trigger: React.ReactNode | string; children: React.ReactNode; open?: boolean; - onChange?: (open: boolean) => void; - sideOffset?: number; - alignOffset?: number; + sideOffset?: PopoverPrimitive.PopperContentProps['sideOffset']; + alignOffset?: PopoverPrimitive.PopperContentProps['alignOffset']; + align?: PopoverPrimitive.PopperContentProps['align']; } export const Popover = ({ trigger, children, - open, - onChange, sideOffset = 17, alignOffset = 0, + align = 'start', + ...props }: PopoverProps) => { return ( - onChange?.(x)}> + {trigger} diff --git a/libs/ui-toolkit/src/components/tabs/tabs.tsx b/libs/ui-toolkit/src/components/tabs/tabs.tsx index 66a8a1b60..37ab6c08f 100644 --- a/libs/ui-toolkit/src/components/tabs/tabs.tsx +++ b/libs/ui-toolkit/src/components/tabs/tabs.tsx @@ -7,6 +7,9 @@ import { import classNames from 'classnames'; import type { ReactElement, ReactNode } from 'react'; import { Children, isValidElement, useRef, useState } from 'react'; +import { VegaIcon } from '../icon/vega-icons/vega-icon'; +import { VegaIconNames } from '../icon/vega-icons/vega-icon-record'; +import { Popover } from '../popover/popover'; export interface TabsProps extends TabsPrimitive.TabsProps { children: (ReactElement | null)[]; } @@ -18,12 +21,9 @@ export const Tabs = ({ onValueChange, ...props }: TabsProps) => { - const [activeTab, setActiveTab] = useState(() => { - if (defaultValue) { - return defaultValue; - } - return children.find((v) => v)?.props.id; - }); + const [activeTab, setActiveTab] = useState( + () => value || defaultValue || children.find((v) => v)?.props.id + ); // Bunch of refs in order to detect wrapping in side the tabs so that we // can apply a bg color @@ -42,8 +42,13 @@ export const Tabs = ({ { + setActiveTab(value); + if (onValueChange) { + onValueChange(value); + } + }} + className="h-full grid grid-rows-[min-content_1fr] relative" >
@@ -101,12 +106,26 @@ export const Tabs = ({ })} > {child.props.menu} + {isValidElement(child.props.settings) && ( + + + + } + > +
+ {child.props.settings} +
+
+ )} ); })}
-
+
{Children.map(children, (child) => { if (!isValidElement(child) || child.props.hidden) return null; return ( @@ -134,6 +153,7 @@ interface TabProps { hidden?: boolean; overflowHidden?: boolean; menu?: ReactNode; + settings?: ReactNode; } export const Tab = ({ children, ...props }: TabProps) => { diff --git a/package.json b/package.json index 239d6f598..876c0a357 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,8 @@ "@web3-react/metamask": "^8.1.2-beta.0", "@web3-react/walletconnect": "8.1.3-beta.0", "@web3-react/walletconnect-v2": "^8.1.3-beta.0", - "ag-grid-community": "^29.3.5", - "ag-grid-react": "^29.3.5", + "ag-grid-community": "^31.0.1", + "ag-grid-react": "^31.0.1", "allotment": "1.19.2", "alpha-lyrae": "vegaprotocol/alpha-lyrae", "apollo-link-timeout": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 1e60af44c..7fd35f3d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8609,16 +8609,17 @@ aes-js@^3.1.2: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== -ag-grid-community@^29.3.5: - version "29.3.5" - resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-29.3.5.tgz#16897896d10fa3ecac79279aad50d3aaa17c5f33" - integrity sha512-LxUo21f2/CH31ACEs1C7Q/ggGGI1fQPSTB4aY5OThmM+lBkygZ7QszBE8jpfgWOIjvjdtcdIeQbmbjkHeMsA7A== +ag-grid-community@^31.0.1, ag-grid-community@~31.0.1: + version "31.0.1" + resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-31.0.1.tgz#26022b29a7b90a0515076837d630ac9cd24cf28d" + integrity sha512-RZQlW1DTOJHsUR/tnbnTJQKgAnDlHi05YYyTe5AgNor/1TlX1hoYdcqrGsJjvcHQgTjeEgzWOL0yf+KcqXZzxg== -ag-grid-react@^29.3.5: - version "29.3.5" - resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-29.3.5.tgz#0eae8934d372c7751e98789542fc663aee0ad6ad" - integrity sha512-Eg0GJ8hEBuxdVaN5g+qITOzhw0MGL9avL0Oaajr+p7QRtq2pIFHLZSknWsCBzUTjidiu75WZMKwlZjtGEuafdQ== +ag-grid-react@^31.0.1: + version "31.0.1" + resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-31.0.1.tgz#c7e3cf029ea1b97ab7f1d5134c8bb0086b4d2aac" + integrity sha512-9nmYPsgH1YUDUDOTiyaFsysoNAx/y72ovFJKuOffZC1V7OrQMadyP6DbqGFWCqzzoLJOY7azOr51dDQzAIXLpw== dependencies: + ag-grid-community "~31.0.1" prop-types "^15.8.1" agent-base@5: