feat(trading): pane settings view (#5509)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com> Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
parent
d47d894147
commit
4adaeea40a
@ -24,7 +24,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const ref = useRef<AgGridReact>(null);
|
const ref = useRef<AgGridReact>(null);
|
||||||
const showColumnsOnDesktop = () => {
|
const showColumnsOnDesktop = () => {
|
||||||
ref.current?.columnApi.setColumnsVisible(
|
ref.current?.api.setColumnsVisible(
|
||||||
['id', 'type', 'status'],
|
['id', 'type', 'status'],
|
||||||
window.innerWidth > BREAKPOINT_MD
|
window.innerWidth > BREAKPOINT_MD
|
||||||
);
|
);
|
||||||
|
@ -29,7 +29,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
const gridRef = useRef<AgGridReact>(null);
|
const gridRef = useRef<AgGridReact>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const showColumnsOnDesktop = () => {
|
const showColumnsOnDesktop = () => {
|
||||||
gridRef.current?.columnApi.setColumnsVisible(
|
gridRef.current?.api.setColumnsVisible(
|
||||||
['id', 'state', 'asset'],
|
['id', 'state', 'asset'],
|
||||||
window.innerWidth > BREAKPOINT_MD
|
window.innerWidth > BREAKPOINT_MD
|
||||||
);
|
);
|
||||||
|
@ -44,11 +44,11 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
const gridRef = useRef<AgGridReact>(null);
|
const gridRef = useRef<AgGridReact>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const showColumnsOnDesktop = () => {
|
const showColumnsOnDesktop = () => {
|
||||||
gridRef.current?.columnApi.setColumnsVisible(
|
gridRef.current?.api.setColumnsVisible(
|
||||||
['voting', 'cDate', 'eDate', 'type'],
|
['voting', 'cDate', 'eDate', 'type'],
|
||||||
window.innerWidth > BREAKPOINT_MD
|
window.innerWidth > BREAKPOINT_MD
|
||||||
);
|
);
|
||||||
gridRef.current?.columnApi.setColumnWidth(
|
gridRef.current?.api.setColumnWidth(
|
||||||
'actions',
|
'actions',
|
||||||
window.innerWidth > BREAKPOINT_MD ? 221 : 80
|
window.innerWidth > BREAKPOINT_MD ? 221 : 80
|
||||||
);
|
);
|
||||||
|
@ -90,7 +90,11 @@ const MainGrid = memo(
|
|||||||
{market &&
|
{market &&
|
||||||
market.tradableInstrument.instrument.product.__typename ===
|
market.tradableInstrument.instrument.product.__typename ===
|
||||||
'Perpetual' ? (
|
'Perpetual' ? (
|
||||||
<Tab id="funding-payments" name={t('Funding payments')}>
|
<Tab
|
||||||
|
id="funding-payments"
|
||||||
|
name={t('Funding payments')}
|
||||||
|
settings={<TradingViews.fundingPayments.settings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="funding-payments">
|
<ErrorBoundary feature="funding-payments">
|
||||||
<TradingViews.fundingPayments.component
|
<TradingViews.fundingPayments.component
|
||||||
marketId={marketId}
|
marketId={marketId}
|
||||||
@ -112,7 +116,11 @@ const MainGrid = memo(
|
|||||||
<TradingViews.orderbook.component marketId={marketId} />
|
<TradingViews.orderbook.component marketId={marketId} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="trades" name={t('Trades')}>
|
<Tab
|
||||||
|
id="trades"
|
||||||
|
name={t('Trades')}
|
||||||
|
settings={<TradingViews.trades.settings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="trades">
|
<ErrorBoundary feature="trades">
|
||||||
<TradingViews.trades.component marketId={marketId} />
|
<TradingViews.trades.component marketId={marketId} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@ -133,6 +141,7 @@ const MainGrid = memo(
|
|||||||
id="positions"
|
id="positions"
|
||||||
name={t('Positions')}
|
name={t('Positions')}
|
||||||
menu={<TradingViews.positions.menu />}
|
menu={<TradingViews.positions.menu />}
|
||||||
|
settings={<TradingViews.positions.settings />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="positions">
|
<ErrorBoundary feature="positions">
|
||||||
<TradingViews.positions.component />
|
<TradingViews.positions.component />
|
||||||
@ -142,17 +151,26 @@ const MainGrid = memo(
|
|||||||
id="open-orders"
|
id="open-orders"
|
||||||
name={t('Open')}
|
name={t('Open')}
|
||||||
menu={<TradingViews.activeOrders.menu />}
|
menu={<TradingViews.activeOrders.menu />}
|
||||||
|
settings={<TradingViews.activeOrders.settings />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="activeOrders">
|
<ErrorBoundary feature="activeOrders">
|
||||||
<TradingViews.activeOrders.component />
|
<TradingViews.activeOrders.component />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="closed-orders" name={t('Closed')}>
|
<Tab
|
||||||
|
id="closed-orders"
|
||||||
|
name={t('Closed')}
|
||||||
|
settings={<TradingViews.closedOrders.settings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="closedOrders">
|
<ErrorBoundary feature="closedOrders">
|
||||||
<TradingViews.closedOrders.component />
|
<TradingViews.closedOrders.component />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="rejected-orders" name={t('Rejected')}>
|
<Tab
|
||||||
|
id="rejected-orders"
|
||||||
|
name={t('Rejected')}
|
||||||
|
settings={<TradingViews.rejectedOrders.settings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="rejectedOrders">
|
<ErrorBoundary feature="rejectedOrders">
|
||||||
<TradingViews.rejectedOrders.component />
|
<TradingViews.rejectedOrders.component />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@ -161,25 +179,35 @@ const MainGrid = memo(
|
|||||||
id="orders"
|
id="orders"
|
||||||
name={t('All')}
|
name={t('All')}
|
||||||
menu={<TradingViews.orders.menu />}
|
menu={<TradingViews.orders.menu />}
|
||||||
|
settings={<TradingViews.orders.settings />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="orders">
|
<ErrorBoundary feature="orders">
|
||||||
<TradingViews.orders.component />
|
<TradingViews.orders.component />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
{featureFlags.STOP_ORDERS ? (
|
{featureFlags.STOP_ORDERS ? (
|
||||||
<Tab id="stop-orders" name={t('Stop orders')}>
|
<Tab
|
||||||
|
id="stop-orders"
|
||||||
|
name={t('Stop orders')}
|
||||||
|
settings={<TradingViews.stopOrders.settings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="stop-orders">
|
<ErrorBoundary feature="stop-orders">
|
||||||
<TradingViews.stopOrders.component />
|
<TradingViews.stopOrders.component />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
) : null}
|
) : null}
|
||||||
<Tab id="fills" name={t('Fills')}>
|
<Tab
|
||||||
|
id="fills"
|
||||||
|
name={t('Fills')}
|
||||||
|
settings={<TradingViews.fills.settings />}
|
||||||
|
>
|
||||||
<TradingViews.fills.component />
|
<TradingViews.fills.component />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
id="accounts"
|
id="accounts"
|
||||||
name={t('Collateral')}
|
name={t('Collateral')}
|
||||||
menu={<TradingViews.collateral.menu />}
|
menu={<TradingViews.collateral.menu />}
|
||||||
|
settings={<TradingViews.collateral.settings />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="collateral">
|
<ErrorBoundary feature="collateral">
|
||||||
<TradingViews.collateral.component
|
<TradingViews.collateral.component
|
||||||
|
@ -4,7 +4,12 @@ import { OracleBanner } from '@vegaprotocol/markets';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import {
|
||||||
|
Popover,
|
||||||
|
Splash,
|
||||||
|
VegaIcon,
|
||||||
|
VegaIconNames,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import {
|
import {
|
||||||
MarketSuccessorBanner,
|
MarketSuccessorBanner,
|
||||||
@ -24,6 +29,7 @@ interface TradePanelsProps {
|
|||||||
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||||
const [view, setView] = useState<TradingView>('chart');
|
const [view, setView] = useState<TradingView>('chart');
|
||||||
|
const viewCfg = TradingViews[view];
|
||||||
|
|
||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
const Component = TradingViews[view].component;
|
const Component = TradingViews[view].component;
|
||||||
@ -44,19 +50,27 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderMenu = () => {
|
const renderMenu = () => {
|
||||||
const viewCfg = TradingViews[view];
|
if ('menu' in viewCfg || 'settings' in viewCfg) {
|
||||||
|
|
||||||
if ('menu' in viewCfg) {
|
|
||||||
const Menu = viewCfg.menu;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-end gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
<div className="flex items-center justify-end gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
||||||
<Menu />
|
{'menu' in viewCfg ? <viewCfg.menu /> : null}
|
||||||
|
{'settings' in viewCfg ? (
|
||||||
|
<Popover
|
||||||
|
align="end"
|
||||||
|
trigger={
|
||||||
|
<span className="ml-1 flex items-center justify-center h-6 w-6">
|
||||||
|
<VegaIcon name={VegaIconNames.COG} size={16} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="p-4 flex justify-end">
|
||||||
|
<viewCfg.settings />
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -72,7 +86,7 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
|||||||
<OracleBanner marketId={market?.id || ''} />
|
<OracleBanner marketId={market?.id || ''} />
|
||||||
</div>
|
</div>
|
||||||
<div>{renderMenu()}</div>
|
<div>{renderMenu()}</div>
|
||||||
<div className="h-full">
|
<div className="h-full relative">
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
{({ width, height }) => (
|
{({ width, height }) => (
|
||||||
<div style={{ width, height }} className="overflow-auto">
|
<div style={{ width, height }} className="overflow-auto">
|
||||||
@ -110,7 +124,9 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
|||||||
key={key}
|
key={key}
|
||||||
view={key}
|
view={key}
|
||||||
isActive={isActive}
|
isActive={isActive}
|
||||||
onClick={() => setView(key)}
|
onClick={() => {
|
||||||
|
setView(key);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,15 +1,36 @@
|
|||||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||||
import { Filter, OpenOrdersMenu } from '@vegaprotocol/orders';
|
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 { OrderbookContainer } from '../../components/orderbook-container';
|
||||||
import { FillsContainer } from '../../components/fills-container';
|
import {
|
||||||
import { PositionsContainer } from '../../components/positions-container';
|
FillsContainer,
|
||||||
import { AccountsContainer } from '../../components/accounts-container';
|
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 { LiquidityContainer } from '../../components/liquidity-container';
|
||||||
import { FundingContainer } from '../../components/funding-container';
|
import { FundingContainer } from '../../components/funding-container';
|
||||||
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
|
import {
|
||||||
import { OrdersContainer } from '../../components/orders-container';
|
FundingPaymentsContainer,
|
||||||
import { StopOrdersContainer } from '../../components/stop-orders-container';
|
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 { AccountsMenu } from '../../components/accounts-menu';
|
||||||
import { PositionsMenu } from '../../components/positions-menu';
|
import { PositionsMenu } from '../../components/positions-menu';
|
||||||
import { ChartContainer, ChartMenu } from '../../components/chart-container';
|
import { ChartContainer, ChartMenu } from '../../components/chart-container';
|
||||||
@ -32,37 +53,46 @@ export const TradingViews = {
|
|||||||
},
|
},
|
||||||
fundingPayments: {
|
fundingPayments: {
|
||||||
component: FundingPaymentsContainer,
|
component: FundingPaymentsContainer,
|
||||||
|
settings: FundingPaymentsSettings,
|
||||||
},
|
},
|
||||||
orderbook: {
|
orderbook: {
|
||||||
component: OrderbookContainer,
|
component: OrderbookContainer,
|
||||||
},
|
},
|
||||||
trades: {
|
trades: {
|
||||||
component: TradesContainer,
|
component: TradesContainer,
|
||||||
|
settings: TradesSettings,
|
||||||
},
|
},
|
||||||
positions: {
|
positions: {
|
||||||
component: PositionsContainer,
|
component: PositionsContainer,
|
||||||
menu: PositionsMenu,
|
menu: PositionsMenu,
|
||||||
|
settings: PositionsSettings,
|
||||||
},
|
},
|
||||||
activeOrders: {
|
activeOrders: {
|
||||||
component: () => <OrdersContainer filter={Filter.Open} />,
|
component: () => <OrdersContainer filter={Filter.Open} />,
|
||||||
menu: OpenOrdersMenu,
|
menu: OpenOrdersMenu,
|
||||||
|
settings: () => <OrdersSettings filter={Filter.Open} />,
|
||||||
},
|
},
|
||||||
closedOrders: {
|
closedOrders: {
|
||||||
component: () => <OrdersContainer filter={Filter.Closed} />,
|
component: () => <OrdersContainer filter={Filter.Closed} />,
|
||||||
|
settings: () => <OrdersSettings filter={Filter.Closed} />,
|
||||||
},
|
},
|
||||||
rejectedOrders: {
|
rejectedOrders: {
|
||||||
component: () => <OrdersContainer filter={Filter.Rejected} />,
|
component: () => <OrdersContainer filter={Filter.Rejected} />,
|
||||||
|
settings: () => <OrdersSettings filter={Filter.Rejected} />,
|
||||||
},
|
},
|
||||||
orders: {
|
orders: {
|
||||||
component: OrdersContainer,
|
component: OrdersContainer,
|
||||||
menu: OpenOrdersMenu,
|
menu: OpenOrdersMenu,
|
||||||
|
settings: OrdersSettings,
|
||||||
},
|
},
|
||||||
stopOrders: {
|
stopOrders: {
|
||||||
component: StopOrdersContainer,
|
component: StopOrdersContainer,
|
||||||
|
settings: StopOrdersSettings,
|
||||||
},
|
},
|
||||||
collateral: {
|
collateral: {
|
||||||
component: AccountsContainer,
|
component: AccountsContainer,
|
||||||
menu: AccountsMenu,
|
menu: AccountsMenu,
|
||||||
|
settings: AccountsSettings,
|
||||||
},
|
},
|
||||||
fills: { component: FillsContainer },
|
fills: { component: FillsContainer, settings: FillsSettings },
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -42,7 +42,7 @@ export const createDataGridSlice: StateCreator<DataGridSlice> = (set) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const useMarketsStore = create<DataGridSlice>()(
|
export const useMarketsStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_market_list_store',
|
name: 'vega_market_list_store',
|
||||||
})
|
})
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { ErrorBoundary } from '../../components/error-boundary';
|
import { ErrorBoundary } from '../../components/error-boundary';
|
||||||
|
import { MarketsSettings } from './markets-settings';
|
||||||
|
|
||||||
export const MarketsPage = () => {
|
export const MarketsPage = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@ -34,7 +35,11 @@ export const MarketsPage = () => {
|
|||||||
<div className="h-full pt-0.5 pb-3 px-1.5">
|
<div className="h-full pt-0.5 pb-3 px-1.5">
|
||||||
<div className="h-full my-1 border rounded-sm border-default">
|
<div className="h-full my-1 border rounded-sm border-default">
|
||||||
<Tabs storageKey="console-markets">
|
<Tabs storageKey="console-markets">
|
||||||
<Tab id="open-markets" name={t('Open markets')}>
|
<Tab
|
||||||
|
id="open-markets"
|
||||||
|
name={t('Open markets')}
|
||||||
|
settings={<MarketsSettings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="markets-open">
|
<ErrorBoundary feature="markets-open">
|
||||||
<OpenMarkets />
|
<OpenMarkets />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@ -42,6 +47,7 @@ export const MarketsPage = () => {
|
|||||||
<Tab
|
<Tab
|
||||||
id="proposed-markets"
|
id="proposed-markets"
|
||||||
name={t('Proposed markets')}
|
name={t('Proposed markets')}
|
||||||
|
settings={<MarketsSettings />}
|
||||||
menu={
|
menu={
|
||||||
<TradingAnchorButton
|
<TradingAnchorButton
|
||||||
size="extra-small"
|
size="extra-small"
|
||||||
@ -56,7 +62,11 @@ export const MarketsPage = () => {
|
|||||||
<Proposed />
|
<Proposed />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="closed-markets" name={t('Closed markets')}>
|
<Tab
|
||||||
|
id="closed-markets"
|
||||||
|
name={t('Closed markets')}
|
||||||
|
settings={<MarketsSettings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="markets-closed">
|
<ErrorBoundary feature="markets-closed">
|
||||||
<Closed />
|
<Closed />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
8
apps/trading/client-pages/markets/markets-settings.tsx
Normal file
8
apps/trading/client-pages/markets/markets-settings.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../../components/grid-settings/grid-settings';
|
||||||
|
import { useMarketsStore } from './market-list-table';
|
||||||
|
|
||||||
|
export const MarketsSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useMarketsStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -5,14 +5,29 @@ import { titlefy } from '@vegaprotocol/utils';
|
|||||||
import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws';
|
import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws';
|
||||||
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
import { usePageTitleStore } from '../../stores';
|
import { usePageTitleStore } from '../../stores';
|
||||||
import { AccountsContainer } from '../../components/accounts-container';
|
import {
|
||||||
|
AccountsContainer,
|
||||||
|
AccountsSettings,
|
||||||
|
} from '../../components/accounts-container';
|
||||||
import { DepositsContainer } from '../../components/deposits-container';
|
import { DepositsContainer } from '../../components/deposits-container';
|
||||||
import { FillsContainer } from '../../components/fills-container';
|
import {
|
||||||
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
|
FillsContainer,
|
||||||
import { PositionsContainer } from '../../components/positions-container';
|
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 { PositionsMenu } from '../../components/positions-menu';
|
||||||
import { WithdrawalsContainer } from '../../components/withdrawals-container';
|
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 { LedgerContainer } from '../../components/ledger-container';
|
||||||
import {
|
import {
|
||||||
ResizableGrid,
|
ResizableGrid,
|
||||||
@ -76,22 +91,27 @@ export const Portfolio = () => {
|
|||||||
id="positions"
|
id="positions"
|
||||||
name={t('Positions')}
|
name={t('Positions')}
|
||||||
menu={<PositionsMenu />}
|
menu={<PositionsMenu />}
|
||||||
|
settings={<PositionsSettings />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="portfolio-positions">
|
<ErrorBoundary feature="portfolio-positions">
|
||||||
<PositionsContainer allKeys />
|
<PositionsContainer allKeys />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="orders" name={t('Orders')}>
|
<Tab id="orders" name={t('Orders')} settings={<OrdersSettings />}>
|
||||||
<ErrorBoundary feature="portfolio-orders">
|
<ErrorBoundary feature="portfolio-orders">
|
||||||
<OrdersContainer />
|
<OrdersContainer />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="fills" name={t('Fills')}>
|
<Tab id="fills" name={t('Fills')} settings={<FillsSettings />}>
|
||||||
<ErrorBoundary feature="portfolio-fills">
|
<ErrorBoundary feature="portfolio-fills">
|
||||||
<FillsContainer />
|
<FillsContainer />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="funding-payments" name={t('Funding payments')}>
|
<Tab
|
||||||
|
id="funding-payments"
|
||||||
|
name={t('Funding payments')}
|
||||||
|
settings={<FundingPaymentsSettings />}
|
||||||
|
>
|
||||||
<ErrorBoundary feature="portfolio-funding-payments">
|
<ErrorBoundary feature="portfolio-funding-payments">
|
||||||
<FundingPaymentsContainer />
|
<FundingPaymentsContainer />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@ -114,6 +134,7 @@ export const Portfolio = () => {
|
|||||||
<Tab
|
<Tab
|
||||||
id="collateral"
|
id="collateral"
|
||||||
name={t('Collateral')}
|
name={t('Collateral')}
|
||||||
|
settings={<AccountsSettings />}
|
||||||
menu={<AccountsMenu />}
|
menu={<AccountsMenu />}
|
||||||
>
|
>
|
||||||
<ErrorBoundary feature="portfolio-accounts">
|
<ErrorBoundary feature="portfolio-accounts">
|
||||||
|
@ -73,7 +73,7 @@ export const AccountsContainer = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useAccountStore = create<DataGridSlice>()(
|
export const useAccountStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_accounts_store',
|
name: 'vega_accounts_store',
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { useAccountStore } from './accounts-container';
|
||||||
|
|
||||||
|
export const AccountsSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useAccountStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -1 +1,2 @@
|
|||||||
export * from './accounts-container';
|
export * from './accounts-container';
|
||||||
|
export * from './accounts-settings';
|
||||||
|
@ -38,7 +38,7 @@ export const FillsContainer = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useFillsStore = create<DataGridSlice>()(
|
export const useFillsStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_fills_store',
|
name: 'vega_fills_store',
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { useFillsStore } from './fills-container';
|
||||||
|
|
||||||
|
export const FillsSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useFillsStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -1 +1,2 @@
|
|||||||
export * from './fills-container';
|
export * from './fills-container';
|
||||||
|
export * from './fills-settings';
|
||||||
|
@ -45,7 +45,7 @@ export const FundingPaymentsContainer = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useFundingPaymentsStore = create<DataGridSlice>()(
|
export const useFundingPaymentsStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_funding_payments_store',
|
name: 'vega_funding_payments_store',
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { useFundingPaymentsStore } from './funding-payments-container';
|
||||||
|
|
||||||
|
export const FundingPaymentsSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useFundingPaymentsStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -1 +1,2 @@
|
|||||||
export * from './funding-payments-container';
|
export * from './funding-payments-container';
|
||||||
|
export * from './funding-payments-settings';
|
||||||
|
24
apps/trading/components/grid-settings/grid-settings.tsx
Normal file
24
apps/trading/components/grid-settings/grid-settings.tsx
Normal file
@ -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 (
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
updateGridStore({
|
||||||
|
columnState: undefined,
|
||||||
|
filterModel: undefined,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
size="extra-small"
|
||||||
|
>
|
||||||
|
{t('Reset Columns')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
@ -27,7 +27,7 @@ export const MarketHeader = () => {
|
|||||||
title={
|
title={
|
||||||
<Popover
|
<Popover
|
||||||
open={open}
|
open={open}
|
||||||
onChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
trigger={
|
trigger={
|
||||||
<HeaderTitle>
|
<HeaderTitle>
|
||||||
<span>
|
<span>
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
import { act, renderHook } from '@testing-library/react';
|
import { act, renderHook } from '@testing-library/react';
|
||||||
import {
|
import { STORAGE_KEY, useOrderListGridState } from './orders-container';
|
||||||
FilterStatusValue,
|
|
||||||
STORAGE_KEY,
|
|
||||||
useOrderListGridState,
|
|
||||||
} from './orders-container';
|
|
||||||
import { Filter } from '@vegaprotocol/orders';
|
import { Filter } from '@vegaprotocol/orders';
|
||||||
import { OrderType } from '@vegaprotocol/types';
|
import { OrderType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
@ -16,31 +12,6 @@ describe('useOrderListGridState', () => {
|
|||||||
return renderHook(() => useOrderListGridState(filter));
|
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))(
|
it.each(Object.values(Filter))(
|
||||||
'sets and stores column state and filters for %s',
|
'sets and stores column state and filters for %s',
|
||||||
(filter) => {
|
(filter) => {
|
||||||
@ -59,12 +30,7 @@ describe('useOrderListGridState', () => {
|
|||||||
|
|
||||||
expect(result.current.gridState).toEqual({
|
expect(result.current.gridState).toEqual({
|
||||||
columnState: undefined,
|
columnState: undefined,
|
||||||
filterModel: {
|
filterModel,
|
||||||
...filterModel,
|
|
||||||
status: {
|
|
||||||
value: FilterStatusValue[filter],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const columnState = [{ colId: 'status', width: 200 }];
|
const columnState = [{ colId: 'status', width: 200 }];
|
||||||
@ -77,12 +43,7 @@ describe('useOrderListGridState', () => {
|
|||||||
|
|
||||||
expect(result.current.gridState).toEqual({
|
expect(result.current.gridState).toEqual({
|
||||||
columnState,
|
columnState,
|
||||||
filterModel: {
|
filterModel,
|
||||||
...filterModel,
|
|
||||||
status: {
|
|
||||||
value: FilterStatusValue[filter],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const storeKeyMap = {
|
const storeKeyMap = {
|
||||||
|
@ -9,6 +9,7 @@ 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';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
|
||||||
const resolveNoRowsMessage = (
|
const resolveNoRowsMessage = (
|
||||||
filter: Filter | undefined,
|
filter: Filter | undefined,
|
||||||
@ -38,6 +39,24 @@ export const FilterStatusValue = {
|
|||||||
[Filter.Rejected]: [OrderStatus.STATUS_REJECTED],
|
[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 {
|
export interface OrderContainerProps {
|
||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
}
|
}
|
||||||
@ -54,7 +73,8 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
|||||||
(newState) => {
|
(newState) => {
|
||||||
updateGridState(filter, newState);
|
updateGridState(filter, newState);
|
||||||
},
|
},
|
||||||
AUTO_SIZE_COLUMNS
|
AUTO_SIZE_COLUMNS,
|
||||||
|
filter && DefaultFilterModel[filter]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
@ -80,7 +100,7 @@ export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const STORAGE_KEY = 'vega_order_list_store';
|
export const STORAGE_KEY = 'vega_order_list_store';
|
||||||
const useOrderListStore = create<{
|
export const useOrderListStore = create<{
|
||||||
open: DataGridStore;
|
open: DataGridStore;
|
||||||
closed: DataGridStore;
|
closed: DataGridStore;
|
||||||
rejected: DataGridStore;
|
rejected: DataGridStore;
|
||||||
@ -149,34 +169,19 @@ export const useOrderListGridState = (filter: Filter | undefined) => {
|
|||||||
case Filter.Open: {
|
case Filter.Open: {
|
||||||
return {
|
return {
|
||||||
columnState: store.open.columnState,
|
columnState: store.open.columnState,
|
||||||
filterModel: {
|
filterModel: store.open.filterModel,
|
||||||
...store.open.filterModel,
|
|
||||||
status: {
|
|
||||||
value: FilterStatusValue[Filter.Open],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case Filter.Closed: {
|
case Filter.Closed: {
|
||||||
return {
|
return {
|
||||||
columnState: store.closed.columnState,
|
columnState: store.closed.columnState,
|
||||||
filterModel: {
|
filterModel: store.closed.filterModel,
|
||||||
...store.closed.filterModel,
|
|
||||||
status: {
|
|
||||||
value: FilterStatusValue[Filter.Closed],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case Filter.Rejected: {
|
case Filter.Rejected: {
|
||||||
return {
|
return {
|
||||||
columnState: store.rejected.columnState,
|
columnState: store.rejected.columnState,
|
||||||
filterModel: {
|
filterModel: store.rejected.filterModel,
|
||||||
...store.rejected.filterModel,
|
|
||||||
status: {
|
|
||||||
value: FilterStatusValue[Filter.Rejected],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -187,3 +192,14 @@ export const useOrderListGridState = (filter: Filter | undefined) => {
|
|||||||
|
|
||||||
return { gridState, updateGridState };
|
return { gridState, updateGridState };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const OrdersSettings = ({ filter }: { filter?: Filter }) => {
|
||||||
|
const updateGridState = useOrderListStore((state) => state.update);
|
||||||
|
return (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={(gridStore: DataGridStore) =>
|
||||||
|
updateGridState(filter, gridStore)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export * from './positions-container';
|
export * from './positions-container';
|
||||||
|
export * from './positions-settings';
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { usePositionsStore } from './positions-container';
|
||||||
|
|
||||||
|
export const PositionsSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={usePositionsStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -1 +1,3 @@
|
|||||||
export * from './stop-orders-container';
|
export * from './stop-orders-container';
|
||||||
|
|
||||||
|
export * from './stop-orders-settings';
|
||||||
|
@ -35,7 +35,7 @@ export const StopOrdersContainer = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStopOrdersStore = create<DataGridSlice>()(
|
export const useStopOrdersStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_stop_orders_store',
|
name: 'vega_stop_orders_store',
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { useStopOrdersStore } from './stop-orders-container';
|
||||||
|
|
||||||
|
export const StopOrdersSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useStopOrdersStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -1 +1,2 @@
|
|||||||
export * from './trades-container';
|
export * from './trades-container';
|
||||||
|
export * from './trades-settings';
|
||||||
|
@ -17,7 +17,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
|||||||
return <TradesManager marketId={marketId} gridProps={gridStoreCallbacks} />;
|
return <TradesManager marketId={marketId} gridProps={gridStoreCallbacks} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useTradesStore = create<DataGridSlice>()(
|
export const useTradesStore = create<DataGridSlice>()(
|
||||||
persist(createDataGridSlice, {
|
persist(createDataGridSlice, {
|
||||||
name: 'vega_trades_store',
|
name: 'vega_trades_store',
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { GridSettings } from '../grid-settings/grid-settings';
|
||||||
|
import { useTradesStore } from './trades-container';
|
||||||
|
|
||||||
|
export const TradesSettings = () => (
|
||||||
|
<GridSettings
|
||||||
|
updateGridStore={useTradesStore((store) => store.updateGridStore)}
|
||||||
|
/>
|
||||||
|
);
|
@ -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")
|
page.wait_for_selector(".ag-center-cols-container .ag-row")
|
||||||
|
|
||||||
expect(
|
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")
|
).to_have_text("99")
|
||||||
expect(
|
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")
|
).to_have_text("-102")
|
||||||
|
page.pause()
|
||||||
expect(
|
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)")
|
).to_have_text("Limit (Iceberg)")
|
||||||
expect(
|
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")
|
).to_have_text("Active")
|
||||||
expect(page.get_by_test_id("price-10100000")).to_be_visible
|
expect(page.get_by_test_id("price-10100000")).to_be_visible
|
||||||
expect(page.get_by_test_id("ask-vol-10100000")).to_have_text("3")
|
expect(page.get_by_test_id("ask-vol-10100000")).to_have_text("3")
|
||||||
|
@ -16,11 +16,11 @@ def verify_data_grid(page: Page, data_test_id, expected_pattern):
|
|||||||
expect(
|
expect(
|
||||||
page.locator(
|
page.locator(
|
||||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
||||||
)
|
).first
|
||||||
).to_be_visible()
|
).to_be_visible()
|
||||||
actual_text = page.locator(
|
actual_text = page.locator(
|
||||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
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")
|
lines = actual_text.strip().split("\n")
|
||||||
for expected, actual in zip(expected_pattern, lines):
|
for expected, actual in zip(expected_pattern, lines):
|
||||||
# We are using regex so that we can run tests in different timezones.
|
# We are using regex so that we can run tests in different timezones.
|
||||||
|
36
apps/trading/e2e/tests/settings/test_column_settings.py
Normal file
36
apps/trading/e2e/tests/settings/test_column_settings.py
Normal file
@ -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"
|
@ -29,7 +29,7 @@ const AccountBreakdown = ({
|
|||||||
variables: { partyId, assetId },
|
variables: { partyId, assetId },
|
||||||
update: ({ data }) => {
|
update: ({ data }) => {
|
||||||
if (gridRef.current?.api && data?.breakdown) {
|
if (gridRef.current?.api && data?.breakdown) {
|
||||||
gridRef.current?.api.setRowData(data?.breakdown);
|
gridRef.current?.api.setGridOption('rowData', data?.breakdown);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,18 +65,9 @@ export const DateRangeFilter = forwardRef(
|
|||||||
useImperativeHandle(ref, () => {
|
useImperativeHandle(ref, () => {
|
||||||
return {
|
return {
|
||||||
doesFilterPass(params: IDoesFilterPassParams) {
|
doesFilterPass(params: IDoesFilterPassParams) {
|
||||||
const { api, colDef, column, columnApi, context } = props;
|
const { column } = props;
|
||||||
const { node } = params;
|
const { node } = params;
|
||||||
const rowValue = props.valueGetter({
|
const rowValue = props.getValue(node, column);
|
||||||
api,
|
|
||||||
colDef,
|
|
||||||
column,
|
|
||||||
columnApi,
|
|
||||||
context,
|
|
||||||
data: node.data,
|
|
||||||
getValue: (field) => node.data[field],
|
|
||||||
node,
|
|
||||||
});
|
|
||||||
if (
|
if (
|
||||||
value.start &&
|
value.start &&
|
||||||
rowValue &&
|
rowValue &&
|
||||||
|
@ -19,18 +19,9 @@ export const SetFilter = forwardRef(
|
|||||||
useImperativeHandle(ref, () => {
|
useImperativeHandle(ref, () => {
|
||||||
return {
|
return {
|
||||||
doesFilterPass(params: IDoesFilterPassParams) {
|
doesFilterPass(params: IDoesFilterPassParams) {
|
||||||
const { api, colDef, column, columnApi, context } = props;
|
const { column } = props;
|
||||||
const { node } = params;
|
const { node } = params;
|
||||||
const getValue = props.valueGetter({
|
const getValue = props.getValue(node, column);
|
||||||
api,
|
|
||||||
colDef,
|
|
||||||
column,
|
|
||||||
columnApi,
|
|
||||||
context,
|
|
||||||
data: node.data,
|
|
||||||
getValue: (field) => node.data[field],
|
|
||||||
node,
|
|
||||||
});
|
|
||||||
return Array.isArray(value)
|
return Array.isArray(value)
|
||||||
? value.includes(getValue)
|
? value.includes(getValue)
|
||||||
: getValue === value;
|
: getValue === value;
|
||||||
|
@ -61,7 +61,7 @@ describe('useDataGridEvents', () => {
|
|||||||
|
|
||||||
// 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(gridRef?.current?.columnApi.getColumnState()[0].width).toEqual(
|
expect(gridRef?.current?.api.getColumnState()[0].width).toEqual(
|
||||||
gridProps.columnDefs[0].width
|
gridProps.columnDefs[0].width
|
||||||
);
|
);
|
||||||
// no filters set
|
// no filters set
|
||||||
@ -107,16 +107,57 @@ describe('useDataGridEvents', () => {
|
|||||||
columnState: [colState],
|
columnState: [colState],
|
||||||
};
|
};
|
||||||
|
|
||||||
setup(initialState, jest.fn());
|
setup(initialState, jest.fn(), undefined);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
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)
|
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 () => {
|
it('ignores events that were not made via the UI', async () => {
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
const initialState = {
|
const initialState = {
|
||||||
@ -130,7 +171,7 @@ describe('useDataGridEvents', () => {
|
|||||||
|
|
||||||
// Set col width multiple times
|
// Set col width multiple times
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
gridRef?.current?.columnApi.setColumnWidth('id', newWidth);
|
gridRef?.current?.api.setColumnWidth('id', newWidth);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
@ -150,14 +191,14 @@ describe('useDataGridEvents', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { rerender } = setup(initialState, callback, ['id']);
|
const { rerender } = setup(initialState, callback, ['id']);
|
||||||
jest.spyOn(gridRef?.current?.columnApi, 'autoSizeColumns');
|
if (gridRef?.current?.api) {
|
||||||
|
jest.spyOn(gridRef?.current?.api, 'autoSizeColumns');
|
||||||
|
}
|
||||||
rerender(<TestComponent hookParams={[initialState, callback, ['id']]} />);
|
rerender(<TestComponent hookParams={[initialState, callback, ['id']]} />);
|
||||||
act(() => {
|
act(() => {
|
||||||
gridRef?.current?.api.setRowData([{ id: 'test-id' }]);
|
gridRef?.current?.api.setGridOption('rowData', [{ id: 'test-id' }]);
|
||||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
||||||
});
|
});
|
||||||
expect(gridRef?.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([
|
expect(gridRef?.current?.api.autoSizeColumns).toHaveBeenCalledWith(['id']);
|
||||||
'id',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -7,8 +7,9 @@ import {
|
|||||||
type FirstDataRenderedEvent,
|
type FirstDataRenderedEvent,
|
||||||
type SortChangedEvent,
|
type SortChangedEvent,
|
||||||
type GridReadyEvent,
|
type GridReadyEvent,
|
||||||
|
GridApi,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -19,8 +20,32 @@ type State = {
|
|||||||
export const useDataGridEvents = (
|
export const useDataGridEvents = (
|
||||||
state: State,
|
state: State,
|
||||||
callback: (data: State) => void,
|
callback: (data: State) => void,
|
||||||
autoSizeColumns?: string[]
|
autoSizeColumns?: string[],
|
||||||
|
defaultFilterModel?: State['filterModel']
|
||||||
) => {
|
) => {
|
||||||
|
const apiRef = useRef<GridApi | undefined>();
|
||||||
|
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
|
* Callback for filter events
|
||||||
*/
|
*/
|
||||||
@ -39,11 +64,7 @@ export const useDataGridEvents = (
|
|||||||
* store callback unnecessarily
|
* store callback unnecessarily
|
||||||
*/
|
*/
|
||||||
const onDebouncedColumnChange = useCallback(
|
const onDebouncedColumnChange = useCallback(
|
||||||
({
|
({ api, source, finished }: ColumnResizedEvent | ColumnMovedEvent) => {
|
||||||
columnApi,
|
|
||||||
source,
|
|
||||||
finished,
|
|
||||||
}: ColumnResizedEvent | ColumnMovedEvent) => {
|
|
||||||
if (!finished) return;
|
if (!finished) return;
|
||||||
|
|
||||||
// only call back on user interactions, and not events triggered from the api
|
// only call back on user interactions, and not events triggered from the api
|
||||||
@ -57,7 +78,7 @@ export const useDataGridEvents = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnState = columnApi.getColumnState();
|
const columnState = api.getColumnState();
|
||||||
|
|
||||||
callback({ columnState });
|
callback({ columnState });
|
||||||
},
|
},
|
||||||
@ -68,8 +89,8 @@ export const useDataGridEvents = (
|
|||||||
* Callback for sort and visible events
|
* Callback for sort and visible events
|
||||||
*/
|
*/
|
||||||
const onColumnChange = useCallback(
|
const onColumnChange = useCallback(
|
||||||
({ columnApi }: SortChangedEvent | ColumnVisibleEvent) => {
|
({ api }: SortChangedEvent | ColumnVisibleEvent) => {
|
||||||
const columnState = columnApi.getColumnState();
|
const columnState = api.getColumnState();
|
||||||
callback({ columnState });
|
callback({ columnState });
|
||||||
},
|
},
|
||||||
[callback]
|
[callback]
|
||||||
@ -80,11 +101,11 @@ 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 }: GridReadyEvent) => {
|
({ api }: GridReadyEvent) => {
|
||||||
if (!api || !columnApi) return;
|
apiRef.current = api;
|
||||||
|
if (!api) return;
|
||||||
if (state.columnState) {
|
if (state.columnState) {
|
||||||
columnApi.applyColumnState({
|
api.applyColumnState({
|
||||||
state: state.columnState,
|
state: state.columnState,
|
||||||
applyOrder: true,
|
applyOrder: true,
|
||||||
});
|
});
|
||||||
@ -92,18 +113,18 @@ export const useDataGridEvents = (
|
|||||||
api.sizeColumnsToFit();
|
api.sizeColumnsToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.filterModel) {
|
if (state.filterModel || defaultFilterModel) {
|
||||||
api.setFilterModel(state.filterModel);
|
api.setFilterModel({ ...state.filterModel, ...defaultFilterModel });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[state]
|
[state, defaultFilterModel]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onFirstDataRendered = useCallback(
|
const onFirstDataRendered = useCallback(
|
||||||
({ columnApi }: FirstDataRenderedEvent) => {
|
({ api }: FirstDataRenderedEvent) => {
|
||||||
if (!columnApi) return;
|
if (!api) return;
|
||||||
if (!state?.columnState && autoSizeColumns?.length) {
|
if (!state?.columnState && autoSizeColumns?.length) {
|
||||||
columnApi.autoSizeColumns(autoSizeColumns);
|
api.autoSizeColumns(autoSizeColumns);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[state, autoSizeColumns]
|
[state, autoSizeColumns]
|
||||||
|
@ -36,7 +36,7 @@ export const FundingPaymentsManager = ({
|
|||||||
dataProvider: fundingPaymentsWithMarketProvider,
|
dataProvider: fundingPaymentsWithMarketProvider,
|
||||||
update: ({ data }) => {
|
update: ({ data }) => {
|
||||||
if (data?.length && gridRef.current?.api) {
|
if (data?.length && gridRef.current?.api) {
|
||||||
gridRef.current?.api.setRowData(data);
|
gridRef.current?.api.setGridOption('rowData', data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -235,6 +235,7 @@
|
|||||||
"Rejected": "Rejected",
|
"Rejected": "Rejected",
|
||||||
"Required epochs": "Required epochs",
|
"Required epochs": "Required epochs",
|
||||||
"Required for next tier": "Required for next tier",
|
"Required for next tier": "Required for next tier",
|
||||||
|
"Reset Columns": "Reset Columns",
|
||||||
"Resources": "Resources",
|
"Resources": "Resources",
|
||||||
"Rewards": "Rewards",
|
"Rewards": "Rewards",
|
||||||
"Rewards history": "Rewards history",
|
"Rewards history": "Rewards history",
|
||||||
|
@ -15,7 +15,7 @@ const Template: ComponentStory<typeof Popover> = (args) => {
|
|||||||
<div>
|
<div>
|
||||||
<Popover
|
<Popover
|
||||||
open={open}
|
open={open}
|
||||||
onChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
trigger={<Button variant="primary">Trigger</Button>}
|
trigger={<Button variant="primary">Trigger</Button>}
|
||||||
>
|
>
|
||||||
{args.children}
|
{args.children}
|
||||||
|
@ -4,29 +4,29 @@ export interface PopoverProps extends PopoverPrimitive.PopoverProps {
|
|||||||
trigger: React.ReactNode | string;
|
trigger: React.ReactNode | string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
onChange?: (open: boolean) => void;
|
sideOffset?: PopoverPrimitive.PopperContentProps['sideOffset'];
|
||||||
sideOffset?: number;
|
alignOffset?: PopoverPrimitive.PopperContentProps['alignOffset'];
|
||||||
alignOffset?: number;
|
align?: PopoverPrimitive.PopperContentProps['align'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Popover = ({
|
export const Popover = ({
|
||||||
trigger,
|
trigger,
|
||||||
children,
|
children,
|
||||||
open,
|
|
||||||
onChange,
|
|
||||||
sideOffset = 17,
|
sideOffset = 17,
|
||||||
alignOffset = 0,
|
alignOffset = 0,
|
||||||
|
align = 'start',
|
||||||
|
...props
|
||||||
}: PopoverProps) => {
|
}: PopoverProps) => {
|
||||||
return (
|
return (
|
||||||
<PopoverPrimitive.Root open={open} onOpenChange={(x) => onChange?.(x)}>
|
<PopoverPrimitive.Root {...props}>
|
||||||
<PopoverPrimitive.Trigger data-testid="popover-trigger">
|
<PopoverPrimitive.Trigger data-testid="popover-trigger">
|
||||||
{trigger}
|
{trigger}
|
||||||
</PopoverPrimitive.Trigger>
|
</PopoverPrimitive.Trigger>
|
||||||
<PopoverPrimitive.Portal>
|
<PopoverPrimitive.Portal>
|
||||||
<PopoverPrimitive.Content
|
<PopoverPrimitive.Content
|
||||||
data-testid="popover-content"
|
data-testid="popover-content"
|
||||||
align="start"
|
align={align}
|
||||||
className="rounded bg-vega-clight-800 dark:bg-vega-cdark-800 text-default border border-default"
|
className="rounded bg-vega-clight-700 dark:bg-vega-cdark-700 text-default border border-vega-clight-500 dark:border-vega-cdark-500"
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
alignOffset={alignOffset}
|
alignOffset={alignOffset}
|
||||||
>
|
>
|
||||||
|
@ -7,6 +7,9 @@ import {
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { ReactElement, ReactNode } from 'react';
|
import type { ReactElement, ReactNode } from 'react';
|
||||||
import { Children, isValidElement, useRef, useState } 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 {
|
export interface TabsProps extends TabsPrimitive.TabsProps {
|
||||||
children: (ReactElement<TabProps> | null)[];
|
children: (ReactElement<TabProps> | null)[];
|
||||||
}
|
}
|
||||||
@ -18,12 +21,9 @@ export const Tabs = ({
|
|||||||
onValueChange,
|
onValueChange,
|
||||||
...props
|
...props
|
||||||
}: TabsProps) => {
|
}: TabsProps) => {
|
||||||
const [activeTab, setActiveTab] = useState<string | undefined>(() => {
|
const [activeTab, setActiveTab] = useState<string | undefined>(
|
||||||
if (defaultValue) {
|
() => value || defaultValue || children.find((v) => v)?.props.id
|
||||||
return defaultValue;
|
);
|
||||||
}
|
|
||||||
return children.find((v) => v)?.props.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bunch of refs in order to detect wrapping in side the tabs so that we
|
// Bunch of refs in order to detect wrapping in side the tabs so that we
|
||||||
// can apply a bg color
|
// can apply a bg color
|
||||||
@ -42,8 +42,13 @@ export const Tabs = ({
|
|||||||
<TabsPrimitive.Root
|
<TabsPrimitive.Root
|
||||||
{...props}
|
{...props}
|
||||||
value={value || activeTab}
|
value={value || activeTab}
|
||||||
onValueChange={onValueChange || setActiveTab}
|
onValueChange={(value) => {
|
||||||
className="h-full grid grid-rows-[min-content_1fr]"
|
setActiveTab(value);
|
||||||
|
if (onValueChange) {
|
||||||
|
onValueChange(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="h-full grid grid-rows-[min-content_1fr] relative"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
@ -87,7 +92,7 @@ export const Tabs = ({
|
|||||||
</TabsPrimitive.List>
|
</TabsPrimitive.List>
|
||||||
<div
|
<div
|
||||||
ref={menuRef}
|
ref={menuRef}
|
||||||
className={classNames('flex-1 p-1', {
|
className={classNames('flex justify-end flex-1 p-1', {
|
||||||
'bg-vega-clight-700 dark:bg-vega-cdark-700': wrapped,
|
'bg-vega-clight-700 dark:bg-vega-cdark-700': wrapped,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
@ -101,12 +106,26 @@ export const Tabs = ({
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{child.props.menu}
|
{child.props.menu}
|
||||||
|
{isValidElement(child.props.settings) && (
|
||||||
|
<Popover
|
||||||
|
align="end"
|
||||||
|
trigger={
|
||||||
|
<span className="flex items-center justify-center h-6 w-6">
|
||||||
|
<VegaIcon name={VegaIconNames.COG} size={16} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="p-2 lg:p-4 lg:min-w-[290px] flex justify-end">
|
||||||
|
{child.props.settings}
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
</TabsPrimitive.Content>
|
</TabsPrimitive.Content>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full overflow-auto">
|
<div className="relative h-full overflow-auto">
|
||||||
{Children.map(children, (child) => {
|
{Children.map(children, (child) => {
|
||||||
if (!isValidElement(child) || child.props.hidden) return null;
|
if (!isValidElement(child) || child.props.hidden) return null;
|
||||||
return (
|
return (
|
||||||
@ -134,6 +153,7 @@ interface TabProps {
|
|||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
overflowHidden?: boolean;
|
overflowHidden?: boolean;
|
||||||
menu?: ReactNode;
|
menu?: ReactNode;
|
||||||
|
settings?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Tab = ({ children, ...props }: TabProps) => {
|
export const Tab = ({ children, ...props }: TabProps) => {
|
||||||
|
@ -49,8 +49,8 @@
|
|||||||
"@web3-react/metamask": "^8.1.2-beta.0",
|
"@web3-react/metamask": "^8.1.2-beta.0",
|
||||||
"@web3-react/walletconnect": "8.1.3-beta.0",
|
"@web3-react/walletconnect": "8.1.3-beta.0",
|
||||||
"@web3-react/walletconnect-v2": "^8.1.3-beta.0",
|
"@web3-react/walletconnect-v2": "^8.1.3-beta.0",
|
||||||
"ag-grid-community": "^29.3.5",
|
"ag-grid-community": "^31.0.1",
|
||||||
"ag-grid-react": "^29.3.5",
|
"ag-grid-react": "^31.0.1",
|
||||||
"allotment": "1.19.2",
|
"allotment": "1.19.2",
|
||||||
"alpha-lyrae": "vegaprotocol/alpha-lyrae",
|
"alpha-lyrae": "vegaprotocol/alpha-lyrae",
|
||||||
"apollo-link-timeout": "^4.0.0",
|
"apollo-link-timeout": "^4.0.0",
|
||||||
|
17
yarn.lock
17
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"
|
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a"
|
||||||
integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==
|
integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==
|
||||||
|
|
||||||
ag-grid-community@^29.3.5:
|
ag-grid-community@^31.0.1, ag-grid-community@~31.0.1:
|
||||||
version "29.3.5"
|
version "31.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-29.3.5.tgz#16897896d10fa3ecac79279aad50d3aaa17c5f33"
|
resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-31.0.1.tgz#26022b29a7b90a0515076837d630ac9cd24cf28d"
|
||||||
integrity sha512-LxUo21f2/CH31ACEs1C7Q/ggGGI1fQPSTB4aY5OThmM+lBkygZ7QszBE8jpfgWOIjvjdtcdIeQbmbjkHeMsA7A==
|
integrity sha512-RZQlW1DTOJHsUR/tnbnTJQKgAnDlHi05YYyTe5AgNor/1TlX1hoYdcqrGsJjvcHQgTjeEgzWOL0yf+KcqXZzxg==
|
||||||
|
|
||||||
ag-grid-react@^29.3.5:
|
ag-grid-react@^31.0.1:
|
||||||
version "29.3.5"
|
version "31.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-29.3.5.tgz#0eae8934d372c7751e98789542fc663aee0ad6ad"
|
resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-31.0.1.tgz#c7e3cf029ea1b97ab7f1d5134c8bb0086b4d2aac"
|
||||||
integrity sha512-Eg0GJ8hEBuxdVaN5g+qITOzhw0MGL9avL0Oaajr+p7QRtq2pIFHLZSknWsCBzUTjidiu75WZMKwlZjtGEuafdQ==
|
integrity sha512-9nmYPsgH1YUDUDOTiyaFsysoNAx/y72ovFJKuOffZC1V7OrQMadyP6DbqGFWCqzzoLJOY7azOr51dDQzAIXLpw==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
ag-grid-community "~31.0.1"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
agent-base@5:
|
agent-base@5:
|
||||||
|
Loading…
Reference in New Issue
Block a user