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