chore(trading): split bottom panel into two parts (#3205)
This commit is contained in:
parent
300019f108
commit
84795b2d6a
@ -10,7 +10,7 @@ export const Footer = () => {
|
||||
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
|
||||
const { screenSize } = useScreenDimensions();
|
||||
const showFullFeedbackLabel = useMemo(
|
||||
() => ['lg', 'xl'].includes(screenSize),
|
||||
() => ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
|
||||
[screenSize]
|
||||
);
|
||||
|
||||
|
@ -216,6 +216,60 @@ describe('Market trading page', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('market bottom panel', { tags: '@smoke' }, () => {
|
||||
it('on xxl screen should be splitted out into two tables', () => {
|
||||
cy.getByTestId('tab-positions').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'active'
|
||||
);
|
||||
cy.getByTestId('tab-orders').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'inactive'
|
||||
);
|
||||
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
|
||||
cy.getByTestId('tab-accounts').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'inactive'
|
||||
);
|
||||
|
||||
cy.viewport(1801, 1000);
|
||||
cy.getByTestId('tab-positions').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'active'
|
||||
);
|
||||
cy.getByTestId('tab-orders').should('have.attr', 'data-state', 'active');
|
||||
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
|
||||
cy.getByTestId('tab-accounts').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'inactive'
|
||||
);
|
||||
|
||||
cy.getByTestId('Fills').click();
|
||||
cy.getByTestId('Collateral').click();
|
||||
cy.getByTestId('tab-positions').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'inactive'
|
||||
);
|
||||
cy.getByTestId('tab-orders').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'inactive'
|
||||
);
|
||||
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'active');
|
||||
cy.getByTestId('tab-accounts').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
'active'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('market states not accepting orders', { tags: '@smoke' }, function () {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
useDataProvider,
|
||||
useScreenDimensions,
|
||||
useThrottledDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
@ -61,7 +61,8 @@ export const MarketPage = () => {
|
||||
const { marketId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { w } = useWindowSize();
|
||||
const { screenSize } = useScreenDimensions();
|
||||
const largeScreen = ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize);
|
||||
const update = useGlobalStore((store) => store.update);
|
||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||
|
||||
@ -87,7 +88,7 @@ export const MarketPage = () => {
|
||||
}, [update, lastMarketId, data?.id]);
|
||||
|
||||
const tradeView = useMemo(() => {
|
||||
if (w > 960) {
|
||||
if (largeScreen) {
|
||||
return (
|
||||
<TradeGrid
|
||||
market={data}
|
||||
@ -105,7 +106,7 @@ export const MarketPage = () => {
|
||||
onClickCollateral={() => navigate('/portfolio')}
|
||||
/>
|
||||
);
|
||||
}, [w, data, onSelect, navigate]);
|
||||
}, [largeScreen, data, onSelect, navigate]);
|
||||
if (!data && marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
@ -140,37 +141,3 @@ export const MarketPage = () => {
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
||||
const useWindowSize = () => {
|
||||
const [windowSize, setWindowSize] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return {
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
};
|
||||
}
|
||||
|
||||
// Something sensible for server rendered page
|
||||
return {
|
||||
w: 1200,
|
||||
h: 900,
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = debounce(({ target }) => {
|
||||
setWindowSize({
|
||||
w: target.innerWidth,
|
||||
h: target.innerHeight,
|
||||
});
|
||||
}, 300);
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return windowSize;
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import { TradesContainer } from '@vegaprotocol/trades';
|
||||
import { LayoutPriority } from 'allotment';
|
||||
import classNames from 'classnames';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { memo, useState } from 'react';
|
||||
import { memo, useCallback, useState } from 'react';
|
||||
import type { ReactNode, ComponentProps } from 'react';
|
||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
||||
@ -29,6 +29,7 @@ import { LiquidityContainer } from '../liquidity/liquidity';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
|
||||
type MarketDependantView =
|
||||
| typeof CandlesChartContainer
|
||||
@ -69,129 +70,204 @@ interface TradeGridProps {
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
const MainGrid = ({
|
||||
marketId,
|
||||
onSelect,
|
||||
pinnedAsset,
|
||||
}: {
|
||||
interface BottomPanelProps {
|
||||
marketId: string;
|
||||
onSelect?: (marketId: string) => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const onMarketClick = (marketId: string) => {
|
||||
navigate(Links[Routes.MARKET](marketId), {
|
||||
replace: true,
|
||||
});
|
||||
};
|
||||
return (
|
||||
<ResizableGrid vertical>
|
||||
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
|
||||
<ResizableGrid proportionalLayout={false} minSize={200}>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.High}
|
||||
minSize={200}
|
||||
preferredSize="50%"
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="chart" name={t('Chart')}>
|
||||
<TradingViews.Candles marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="depth" name={t('Depth')}>
|
||||
<TradingViews.Depth marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="liquidity" name={t('Liquidity')}>
|
||||
<TradingViews.Liquidity marketId={marketId} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize={330}
|
||||
minSize={300}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="ticket" name={t('Ticket')}>
|
||||
<TradingViews.Ticket
|
||||
}
|
||||
|
||||
const MarketBottomPanel = memo(
|
||||
({ marketId, pinnedAsset }: BottomPanelProps) => {
|
||||
const { screenSize } = useScreenDimensions();
|
||||
const navigate = useNavigate();
|
||||
const onMarketClick = useCallback(
|
||||
(marketId: string) => {
|
||||
navigate(Links[Routes.MARKET](marketId), {
|
||||
replace: true,
|
||||
});
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return 'xxxl' === screenSize ? (
|
||||
<ResizableGrid proportionalLayout minSize={200}>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize="50%"
|
||||
minSize={50}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Orders
|
||||
marketId={marketId}
|
||||
onClickCollateral={() => navigate('/portfolio')}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab id="info" name={t('Info')}>
|
||||
<TradingViews.Info
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Fills
|
||||
marketId={marketId}
|
||||
onSelect={(id: string) => {
|
||||
onSelect?.(id);
|
||||
}}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize={430}
|
||||
minSize={200}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="orderbook" name={t('Orderbook')}>
|
||||
<TradingViews.Orderbook marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="trades" name={t('Trades')}>
|
||||
<TradingViews.Trades marketId={marketId} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
</ResizableGrid>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize="25%"
|
||||
minSize={50}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Positions onMarketClick={onMarketClick} />
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Orders
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Fills
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="accounts" name={t('Collateral')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Collateral
|
||||
pinnedAsset={pinnedAsset}
|
||||
hideButtons
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
</ResizableGrid>
|
||||
);
|
||||
};
|
||||
const MainGridWrapped = memo(MainGrid);
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize="50%"
|
||||
minSize={50}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Positions
|
||||
onMarketClick={onMarketClick}
|
||||
noBottomPlaceholder
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="accounts" name={t('Collateral')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Collateral
|
||||
pinnedAsset={pinnedAsset}
|
||||
noBottomPlaceholder
|
||||
hideButtons
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
</ResizableGrid>
|
||||
) : (
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Positions onMarketClick={onMarketClick} />
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Orders
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Fills
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="accounts" name={t('Collateral')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Collateral pinnedAsset={pinnedAsset} hideButtons />
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
);
|
||||
}
|
||||
);
|
||||
MarketBottomPanel.displayName = 'MarketBottomPanel';
|
||||
|
||||
const MainGrid = memo(
|
||||
({
|
||||
marketId,
|
||||
onSelect,
|
||||
pinnedAsset,
|
||||
}: {
|
||||
marketId: string;
|
||||
onSelect?: (marketId: string) => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<ResizableGrid vertical>
|
||||
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
|
||||
<ResizableGrid proportionalLayout={false} minSize={200}>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.High}
|
||||
minSize={200}
|
||||
preferredSize="50%"
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="chart" name={t('Chart')}>
|
||||
<TradingViews.Candles marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="depth" name={t('Depth')}>
|
||||
<TradingViews.Depth marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="liquidity" name={t('Liquidity')}>
|
||||
<TradingViews.Liquidity marketId={marketId} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize={330}
|
||||
minSize={300}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="ticket" name={t('Ticket')}>
|
||||
<TradingViews.Ticket
|
||||
marketId={marketId}
|
||||
onClickCollateral={() => navigate('/portfolio')}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab id="info" name={t('Info')}>
|
||||
<TradingViews.Info
|
||||
marketId={marketId}
|
||||
onSelect={(id: string) => {
|
||||
onSelect?.(id);
|
||||
}}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize={430}
|
||||
minSize={200}
|
||||
>
|
||||
<TradeGridChild>
|
||||
<Tabs>
|
||||
<Tab id="orderbook" name={t('Orderbook')}>
|
||||
<TradingViews.Orderbook marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab id="trades" name={t('Trades')}>
|
||||
<TradingViews.Trades marketId={marketId} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
</ResizableGrid>
|
||||
</ResizableGridPanel>
|
||||
<ResizableGridPanel
|
||||
priority={LayoutPriority.Low}
|
||||
preferredSize="25%"
|
||||
minSize={50}
|
||||
>
|
||||
<MarketBottomPanel marketId={marketId} pinnedAsset={pinnedAsset} />
|
||||
</ResizableGridPanel>
|
||||
</ResizableGrid>
|
||||
);
|
||||
}
|
||||
);
|
||||
MainGrid.displayName = 'MainGrid';
|
||||
|
||||
export const TradeGrid = ({
|
||||
market,
|
||||
@ -201,7 +277,7 @@ export const TradeGrid = ({
|
||||
return (
|
||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||
<TradeMarketHeader market={market} onSelect={onSelect} />
|
||||
<MainGridWrapped
|
||||
<MainGrid
|
||||
marketId={market?.id || ''}
|
||||
onSelect={onSelect}
|
||||
pinnedAsset={pinnedAsset}
|
||||
|
@ -12,9 +12,11 @@ import { useDepositDialog } from '@vegaprotocol/deposits';
|
||||
export const AccountsContainer = ({
|
||||
pinnedAsset,
|
||||
hideButtons,
|
||||
noBottomPlaceholder,
|
||||
}: {
|
||||
pinnedAsset?: PinnedAsset;
|
||||
hideButtons?: boolean;
|
||||
noBottomPlaceholder?: boolean;
|
||||
}) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
@ -46,6 +48,7 @@ export const AccountsContainer = ({
|
||||
onClickDeposit={openDepositDialog}
|
||||
isReadOnly={isReadOnly}
|
||||
pinnedAsset={pinnedAsset}
|
||||
noBottomPlaceholder={noBottomPlaceholder}
|
||||
/>
|
||||
{!isReadOnly && !hideButtons && (
|
||||
<div className="flex gap-2 justify-end p-2 px-[11px] absolute lg:fixed bottom-0 right-3 dark:bg-black/75 bg-white/75 rounded">
|
||||
|
@ -19,6 +19,7 @@ interface AccountManagerProps {
|
||||
onClickDeposit?: (assetId?: string) => void;
|
||||
isReadOnly: boolean;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
noBottomPlaceholder?: boolean;
|
||||
}
|
||||
|
||||
export const AccountManager = ({
|
||||
@ -28,6 +29,7 @@ export const AccountManager = ({
|
||||
partyId,
|
||||
isReadOnly,
|
||||
pinnedAsset,
|
||||
noBottomPlaceholder,
|
||||
}: AccountManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
@ -45,6 +47,7 @@ export const AccountManager = ({
|
||||
const bottomPlaceholderProps = useBottomPlaceholder<AccountFields>({
|
||||
gridRef,
|
||||
setId,
|
||||
disabled: noBottomPlaceholder,
|
||||
});
|
||||
|
||||
const getRowHeight = useCallback(
|
||||
|
@ -68,10 +68,11 @@ export const PositionsManager = ({
|
||||
const bottomPlaceholderProps = useBottomPlaceholder<Position>({
|
||||
gridRef,
|
||||
setId,
|
||||
disabled: noBottomPlaceholder,
|
||||
});
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [data]);
|
||||
}, [data?.length]);
|
||||
const onFilterChanged = useCallback((event: FilterChangedEvent) => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
@ -86,7 +87,7 @@ export const PositionsManager = ({
|
||||
suppressNoRowsOverlay
|
||||
isReadOnly={isReadOnly}
|
||||
onFilterChanged={onFilterChanged}
|
||||
{...(noBottomPlaceholder ? null : bottomPlaceholderProps)}
|
||||
{...bottomPlaceholderProps}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
|
@ -116,6 +116,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
value
|
||||
)
|
||||
}
|
||||
minWidth={190}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Notional')}
|
||||
@ -141,6 +142,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
data.marketDecimalPlaces
|
||||
);
|
||||
}}
|
||||
minWidth={80}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Open volume')}
|
||||
@ -174,6 +176,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
);
|
||||
}}
|
||||
cellRenderer={OpenVolumeCell}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Mark price')}
|
||||
@ -213,8 +216,13 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
data.marketDecimalPlaces
|
||||
);
|
||||
}}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Settlement asset')}
|
||||
field="assetSymbol"
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn headerName={t('Settlement asset')} field="assetSymbol" />
|
||||
<AgGridColumn
|
||||
headerName={t('Entry price')}
|
||||
field="averageEntryPrice"
|
||||
@ -248,6 +256,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
data.marketDecimalPlaces
|
||||
);
|
||||
}}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Leverage')}
|
||||
@ -264,6 +273,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
}: VegaValueFormatterParams<Position, 'currentLeverage'>) =>
|
||||
value === undefined ? undefined : formatNumber(value.toString(), 1)
|
||||
}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Margin allocated')}
|
||||
@ -295,6 +305,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
data.decimals
|
||||
);
|
||||
}}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Realised PNL')}
|
||||
@ -321,6 +332,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.'
|
||||
)}
|
||||
cellRenderer={PNLCell}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Unrealised PNL')}
|
||||
@ -347,6 +359,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
|
||||
)}
|
||||
cellRenderer={PNLCell}
|
||||
minWidth={100}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Updated')}
|
||||
@ -361,6 +374,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
}
|
||||
return getDateTimeFormat().format(new Date(value));
|
||||
}}
|
||||
minWidth={150}
|
||||
/>
|
||||
{onClose && !props.isReadOnly ? (
|
||||
<AgGridColumn
|
||||
@ -375,6 +389,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
||||
</ButtonLink>
|
||||
) : null
|
||||
}
|
||||
minWidth={80}
|
||||
/>
|
||||
) : null}
|
||||
</AgGrid>
|
||||
|
@ -11,11 +11,13 @@ const isFullWidthRow = (params: IsFullWidthRowParams) =>
|
||||
interface Props<T> {
|
||||
gridRef: RefObject<AgGridReact>;
|
||||
setId?: (data: T) => T;
|
||||
disabled?: boolean;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export const useBottomPlaceholder = <T extends {}>({
|
||||
gridRef,
|
||||
setId,
|
||||
disabled,
|
||||
}: Props<T>) => {
|
||||
const onBodyScrollEnd = useCallback(() => {
|
||||
const rowCont = gridRef.current?.api.getModel().getRowCount() ?? 0;
|
||||
@ -58,14 +60,17 @@ export const useBottomPlaceholder = <T extends {}>({
|
||||
}, [gridRef, onBodyScrollEnd]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
onBodyScrollEnd,
|
||||
rowClassRules: NO_HOVER_CSS_RULE,
|
||||
isFullWidthRow,
|
||||
fullWidthCellRenderer,
|
||||
onSortChanged: onRowsChanged,
|
||||
onFilterChange: onRowsChanged,
|
||||
}),
|
||||
[onBodyScrollEnd, onRowsChanged]
|
||||
() =>
|
||||
!disabled
|
||||
? {
|
||||
onBodyScrollEnd,
|
||||
rowClassRules: NO_HOVER_CSS_RULE,
|
||||
isFullWidthRow,
|
||||
fullWidthCellRenderer,
|
||||
onSortChanged: onRowsChanged,
|
||||
onFilterChange: onRowsChanged,
|
||||
}
|
||||
: {},
|
||||
[onBodyScrollEnd, onRowsChanged, disabled]
|
||||
);
|
||||
};
|
||||
|
@ -1,10 +1,19 @@
|
||||
import { useRef, useEffect, useState } from 'react';
|
||||
|
||||
const SERVER_SIDE_DIMENSIONS = {
|
||||
width: 1200,
|
||||
height: 900,
|
||||
};
|
||||
|
||||
export const useResize = () => {
|
||||
const [windowSize, setWindowSize] = useState({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
const [windowSize, setWindowSize] = useState(
|
||||
typeof window !== undefined
|
||||
? {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
}
|
||||
: { ...SERVER_SIDE_DIMENSIONS }
|
||||
);
|
||||
|
||||
const timeout = useRef(0);
|
||||
|
||||
|
@ -1,29 +1,31 @@
|
||||
import { useMemo } from 'react';
|
||||
// @ts-ignore avoid adding declaration file
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { useResize } from './use-resize';
|
||||
|
||||
type Screen = keyof typeof theme.screens;
|
||||
export type Screen = keyof typeof theme.screens;
|
||||
|
||||
interface Props {
|
||||
isMobile: boolean;
|
||||
screenSize: Screen;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export const useScreenDimensions = (): Props => {
|
||||
const { width } = useResize();
|
||||
const isMobile = width < parseInt(theme.screens.md);
|
||||
const screenSize = Object.entries(theme.screens).reduce(
|
||||
(agg: Screen, entry) => {
|
||||
if (width > parseInt(entry[1])) {
|
||||
agg = entry[0] as Screen;
|
||||
}
|
||||
return agg;
|
||||
},
|
||||
'xs'
|
||||
);
|
||||
return useMemo(
|
||||
() => ({
|
||||
width,
|
||||
isMobile: width < parseInt(theme.screens.md),
|
||||
screenSize: Object.entries(theme.screens).reduce((agg: Screen, entry) => {
|
||||
if (width > parseInt(entry[1])) {
|
||||
agg = entry[0] as Screen;
|
||||
}
|
||||
return agg;
|
||||
}, 'xs'),
|
||||
isMobile,
|
||||
screenSize,
|
||||
}),
|
||||
[width]
|
||||
[isMobile, screenSize]
|
||||
);
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ module.exports = {
|
||||
lg: '960px',
|
||||
xl: '1280px',
|
||||
xxl: '1536px',
|
||||
xxxl: '1800px',
|
||||
},
|
||||
colors: {
|
||||
transparent: 'transparent',
|
||||
|
Loading…
Reference in New Issue
Block a user