chore(trading): add "holding CMD + click" external link (#3273)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
parent
2bfc3abd15
commit
82e5128ba1
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import {
|
import {
|
||||||
@ -13,6 +13,7 @@ import { useGlobalStore, usePageTitleStore } from '../../stores';
|
|||||||
import { TradeGrid, TradePanels } from './trade-grid';
|
import { TradeGrid, TradePanels } from './trade-grid';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links, Routes } from '../../pages/client-router';
|
||||||
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
|
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
|
||||||
return markPrice && decimalPlaces
|
return markPrice && decimalPlaces
|
||||||
@ -66,14 +67,7 @@ export const MarketPage = () => {
|
|||||||
const update = useGlobalStore((store) => store.update);
|
const update = useGlobalStore((store) => store.update);
|
||||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||||
|
|
||||||
const onSelect = useCallback(
|
const onSelect = useMarketClickHandler();
|
||||||
(id: string) => {
|
|
||||||
if (id && id !== marketId) {
|
|
||||||
navigate(Links[Routes.MARKET](id));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[marketId, navigate]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading } = useDataProvider({
|
||||||
dataProvider: marketProvider,
|
dataProvider: marketProvider,
|
||||||
|
@ -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, useCallback, useState } from 'react';
|
import { memo, 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';
|
||||||
@ -27,9 +27,9 @@ import { TradeMarketHeader } from './trade-market-header';
|
|||||||
import { NO_MARKET } from './constants';
|
import { NO_MARKET } from './constants';
|
||||||
import { LiquidityContainer } from '../liquidity/liquidity';
|
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 type { PinnedAsset } from '@vegaprotocol/accounts';
|
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
type MarketDependantView =
|
type MarketDependantView =
|
||||||
| typeof CandlesChartContainer
|
| typeof CandlesChartContainer
|
||||||
@ -66,7 +66,7 @@ type TradingView = keyof typeof TradingViews;
|
|||||||
|
|
||||||
interface TradeGridProps {
|
interface TradeGridProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,15 +78,7 @@ interface BottomPanelProps {
|
|||||||
const MarketBottomPanel = memo(
|
const MarketBottomPanel = memo(
|
||||||
({ marketId, pinnedAsset }: BottomPanelProps) => {
|
({ marketId, pinnedAsset }: BottomPanelProps) => {
|
||||||
const { screenSize } = useScreenDimensions();
|
const { screenSize } = useScreenDimensions();
|
||||||
const navigate = useNavigate();
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
const onMarketClick = useCallback(
|
|
||||||
(marketId: string) => {
|
|
||||||
navigate(Links[Routes.MARKET](marketId), {
|
|
||||||
replace: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[navigate]
|
|
||||||
);
|
|
||||||
|
|
||||||
return 'xxxl' === screenSize ? (
|
return 'xxxl' === screenSize ? (
|
||||||
<ResizableGrid proportionalLayout minSize={200}>
|
<ResizableGrid proportionalLayout minSize={200}>
|
||||||
@ -189,7 +181,7 @@ const MainGrid = memo(
|
|||||||
pinnedAsset,
|
pinnedAsset,
|
||||||
}: {
|
}: {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onSelect?: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -230,12 +222,7 @@ const MainGrid = memo(
|
|||||||
/>
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="info" name={t('Info')}>
|
<Tab id="info" name={t('Info')}>
|
||||||
<TradingViews.Info
|
<TradingViews.Info marketId={marketId} />
|
||||||
marketId={marketId}
|
|
||||||
onSelect={(id: string) => {
|
|
||||||
onSelect?.(id);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
@ -304,7 +291,7 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
|
|||||||
|
|
||||||
interface TradePanelsProps {
|
interface TradePanelsProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string) => void;
|
||||||
onClickCollateral: () => void;
|
onClickCollateral: () => void;
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
@ -320,7 +307,7 @@ export const TradePanels = ({
|
|||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
const Component = memo<{
|
const Component = memo<{
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string) => void;
|
||||||
onClickCollateral: () => void;
|
onClickCollateral: () => void;
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
|
@ -22,7 +22,7 @@ import { MarketState as State } from '@vegaprotocol/types';
|
|||||||
|
|
||||||
interface TradeMarketHeaderProps {
|
interface TradeMarketHeaderProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradeMarketHeader = ({
|
export const TradeMarketHeader = ({
|
||||||
@ -91,7 +91,6 @@ export const TradeMarketHeader = ({
|
|||||||
</HeaderStat>
|
</HeaderStat>
|
||||||
<HeaderStatMarketTradingMode
|
<HeaderStatMarketTradingMode
|
||||||
marketId={market?.id}
|
marketId={market?.id}
|
||||||
onSelect={onSelect}
|
|
||||||
initialTradingMode={market?.tradingMode}
|
initialTradingMode={market?.tradingMode}
|
||||||
/>
|
/>
|
||||||
<MarketState market={market} />
|
<MarketState market={market} />
|
||||||
|
@ -1,16 +1,7 @@
|
|||||||
import { useCallback } from 'react';
|
|
||||||
import { MarketsContainer } from '@vegaprotocol/market-list';
|
import { MarketsContainer } from '@vegaprotocol/market-list';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
|
||||||
|
|
||||||
export const Markets = () => {
|
export const Markets = () => {
|
||||||
const navigate = useNavigate();
|
const handleOnSelect = useMarketClickHandler();
|
||||||
const handleOnSelect = useCallback(
|
|
||||||
(marketId: string) => {
|
|
||||||
navigate(Links[Routes.MARKET](marketId));
|
|
||||||
},
|
|
||||||
[navigate]
|
|
||||||
);
|
|
||||||
|
|
||||||
return <MarketsContainer onSelect={handleOnSelect} />;
|
return <MarketsContainer onSelect={handleOnSelect} />;
|
||||||
};
|
};
|
||||||
|
@ -19,25 +19,18 @@ import { usePageTitleStore } from '../../stores';
|
|||||||
import { LedgerContainer } from '@vegaprotocol/ledger';
|
import { LedgerContainer } from '@vegaprotocol/ledger';
|
||||||
import { AccountsContainer } from '../../components/accounts-container';
|
import { AccountsContainer } from '../../components/accounts-container';
|
||||||
import { AccountHistoryContainer } from './account-history-container';
|
import { AccountHistoryContainer } from './account-history-container';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
|
||||||
|
|
||||||
export const Portfolio = () => {
|
export const Portfolio = () => {
|
||||||
const { updateTitle } = usePageTitleStore((store) => ({
|
const { updateTitle } = usePageTitleStore((store) => ({
|
||||||
updateTitle: store.updateTitle,
|
updateTitle: store.updateTitle,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateTitle(titlefy([t('Portfolio')]));
|
updateTitle(titlefy([t('Portfolio')]));
|
||||||
}, [updateTitle]);
|
}, [updateTitle]);
|
||||||
|
|
||||||
const onMarketClick = (marketId: string) => {
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
navigate(Links[Routes.MARKET](marketId), {
|
|
||||||
replace: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapperClasses = 'h-full max-h-full flex flex-col';
|
const wrapperClasses = 'h-full max-h-full flex flex-col';
|
||||||
return (
|
return (
|
||||||
|
@ -25,7 +25,7 @@ const getTradingModeLabel = (
|
|||||||
|
|
||||||
interface HeaderStatMarketTradingModeProps {
|
interface HeaderStatMarketTradingModeProps {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onSelect?: (marketId: string) => void;
|
onSelect?: (marketId: string, metaKey?: boolean) => void;
|
||||||
initialTradingMode?: Schema.MarketTradingMode;
|
initialTradingMode?: Schema.MarketTradingMode;
|
||||||
initialTrigger?: Schema.AuctionTrigger;
|
initialTrigger?: Schema.AuctionTrigger;
|
||||||
}
|
}
|
||||||
@ -66,7 +66,9 @@ export const MarketTradingMode = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
description={<TradingModeTooltip marketId={marketId} skip={!inView} />}
|
description={
|
||||||
|
<TradingModeTooltip marketId={marketId} skip={!inView} skipGrid />
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span ref={ref}>
|
<span ref={ref}>
|
||||||
{getTradingModeLabel(
|
{getTradingModeLabel(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { RefObject } from 'react';
|
import type { RefObject, MouseEvent } from 'react';
|
||||||
import { FeesCell } from '@vegaprotocol/market-info';
|
import { FeesCell } from '@vegaprotocol/market-info';
|
||||||
import {
|
import {
|
||||||
calcCandleHigh,
|
calcCandleHigh,
|
||||||
@ -157,14 +157,14 @@ export const columnHeaders: Column[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export type OnCellClickHandler = (
|
export type OnCellClickHandler = (
|
||||||
e: React.MouseEvent,
|
e: MouseEvent,
|
||||||
kind: ColumnKind,
|
kind: ColumnKind,
|
||||||
value: string
|
value: string
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export const columns = (
|
export const columns = (
|
||||||
market: MarketMaybeWithDataAndCandles,
|
market: MarketMaybeWithDataAndCandles,
|
||||||
onSelect: (id: string) => void,
|
onSelect: (id: string, metaKey?: boolean) => void,
|
||||||
onCellClick: OnCellClickHandler,
|
onCellClick: OnCellClickHandler,
|
||||||
inViewRoot?: RefObject<HTMLElement>
|
inViewRoot?: RefObject<HTMLElement>
|
||||||
) => {
|
) => {
|
||||||
@ -174,14 +174,7 @@ export const columns = (
|
|||||||
const candleLow = market.candles && calcCandleLow(market.candles);
|
const candleLow = market.candles && calcCandleLow(market.candles);
|
||||||
const candleHigh = market.candles && calcCandleHigh(market.candles);
|
const candleHigh = market.candles && calcCandleHigh(market.candles);
|
||||||
const candleVolume = market.candles && calcCandleVolume(market.candles);
|
const candleVolume = market.candles && calcCandleVolume(market.candles);
|
||||||
const handleKeyPress = (
|
|
||||||
event: React.KeyboardEvent<HTMLAnchorElement>,
|
|
||||||
id: string
|
|
||||||
) => {
|
|
||||||
if (event.key === 'Enter' && onSelect) {
|
|
||||||
return onSelect(id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const selectMarketColumns: Column[] = [
|
const selectMarketColumns: Column[] = [
|
||||||
{
|
{
|
||||||
kind: ColumnKind.Market,
|
kind: ColumnKind.Market,
|
||||||
@ -189,10 +182,10 @@ export const columns = (
|
|||||||
<Link
|
<Link
|
||||||
to={Links[Routes.MARKET](market.id)}
|
to={Links[Routes.MARKET](market.id)}
|
||||||
data-testid={`market-link-${market.id}`}
|
data-testid={`market-link-${market.id}`}
|
||||||
onKeyPress={(event) => handleKeyPress(event, market.id)}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onSelect(market.id);
|
e.stopPropagation();
|
||||||
|
onSelect(market.id, e.metaKey);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<UILink>{market.tradableInstrument.instrument.code}</UILink>
|
<UILink>{market.tradableInstrument.instrument.code}</UILink>
|
||||||
@ -352,7 +345,7 @@ export const columns = (
|
|||||||
|
|
||||||
export const columnsPositionMarkets = (
|
export const columnsPositionMarkets = (
|
||||||
market: MarketMaybeWithDataAndCandles,
|
market: MarketMaybeWithDataAndCandles,
|
||||||
onSelect: (id: string) => void,
|
onSelect: (id: string, metaKey?: boolean) => void,
|
||||||
inViewRoot?: RefObject<HTMLElement>,
|
inViewRoot?: RefObject<HTMLElement>,
|
||||||
openVolume?: string,
|
openVolume?: string,
|
||||||
onCellClick?: OnCellClickHandler
|
onCellClick?: OnCellClickHandler
|
||||||
@ -362,14 +355,6 @@ export const columnsPositionMarkets = (
|
|||||||
.filter((c: string | undefined): c is CandleClose => !isNil(c));
|
.filter((c: string | undefined): c is CandleClose => !isNil(c));
|
||||||
const candleLow = market.candles && calcCandleLow(market.candles);
|
const candleLow = market.candles && calcCandleLow(market.candles);
|
||||||
const candleHigh = market.candles && calcCandleHigh(market.candles);
|
const candleHigh = market.candles && calcCandleHigh(market.candles);
|
||||||
const handleKeyPress = (
|
|
||||||
event: React.KeyboardEvent<HTMLSpanElement>,
|
|
||||||
id: string
|
|
||||||
) => {
|
|
||||||
if (event.key === 'Enter' && onSelect) {
|
|
||||||
return onSelect(id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const candleVolume = market.candles && calcCandleVolume(market.candles);
|
const candleVolume = market.candles && calcCandleVolume(market.candles);
|
||||||
const selectMarketColumns: Column[] = [
|
const selectMarketColumns: Column[] = [
|
||||||
{
|
{
|
||||||
@ -378,10 +363,10 @@ export const columnsPositionMarkets = (
|
|||||||
<Link
|
<Link
|
||||||
to={Links[Routes.MARKET](market.id)}
|
to={Links[Routes.MARKET](market.id)}
|
||||||
data-testid={`market-link-${market.id}`}
|
data-testid={`market-link-${market.id}`}
|
||||||
onKeyPress={(event) => handleKeyPress(event, market.id)}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onSelect(market.id);
|
e.stopPropagation();
|
||||||
|
onSelect(market.id, e.metaKey);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<UILink>{market.tradableInstrument.instrument.code}</UILink>
|
<UILink>{market.tradableInstrument.instrument.code}</UILink>
|
||||||
|
@ -37,14 +37,14 @@ export const SelectMarketTableRow = ({
|
|||||||
}: {
|
}: {
|
||||||
detailed?: boolean;
|
detailed?: boolean;
|
||||||
columns: Column[];
|
columns: Column[];
|
||||||
onSelect: (id: string) => void;
|
onSelect: (id: string, metaKey?: boolean) => void;
|
||||||
marketId: string;
|
marketId: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
className={`hover:bg-neutral-200 dark:hover:bg-neutral-700 cursor-pointer relative h-[34px]`}
|
className={`hover:bg-neutral-200 dark:hover:bg-neutral-700 cursor-pointer relative h-[34px]`}
|
||||||
onClick={() => {
|
onClick={(ev) => {
|
||||||
onSelect(marketId);
|
onSelect(marketId, ev.metaKey);
|
||||||
}}
|
}}
|
||||||
data-testid={`market-link-${marketId}`}
|
data-testid={`market-link-${marketId}`}
|
||||||
>
|
>
|
||||||
|
@ -178,6 +178,6 @@ describe('SelectMarket', () => {
|
|||||||
expect(screen.getByText('25.00%')).toBeTruthy(); // price change
|
expect(screen.getByText('25.00%')).toBeTruthy(); // price change
|
||||||
expect(container).toHaveTextContent(/1,000/); // volume
|
expect(container).toHaveTextContent(/1,000/); // volume
|
||||||
fireEvent.click(screen.getAllByTestId(`market-link-1`)[0]);
|
fireEvent.click(screen.getAllByTestId(`market-link-1`)[0]);
|
||||||
expect(onSelect).toHaveBeenCalledWith('1');
|
expect(onSelect).toHaveBeenCalledWith('1', false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,7 +40,7 @@ export const SelectAllMarketsTableBody = ({
|
|||||||
markets?: MarketMaybeWithDataAndCandles[] | null;
|
markets?: MarketMaybeWithDataAndCandles[] | null;
|
||||||
positions?: PositionFieldsFragment[];
|
positions?: PositionFieldsFragment[];
|
||||||
title?: string;
|
title?: string;
|
||||||
onSelect: (id: string) => void;
|
onSelect: (id: string, metaKey?: boolean) => void;
|
||||||
onCellClick: OnCellClickHandler;
|
onCellClick: OnCellClickHandler;
|
||||||
headers?: Column[];
|
headers?: Column[];
|
||||||
tableColumns?: (
|
tableColumns?: (
|
||||||
@ -95,7 +95,7 @@ export const SelectMarketPopover = ({
|
|||||||
}: {
|
}: {
|
||||||
marketCode: string;
|
marketCode: string;
|
||||||
marketName: string;
|
marketName: string;
|
||||||
onSelect: (id: string) => void;
|
onSelect: (id: string, metaKey?: boolean) => void;
|
||||||
onCellClick: OnCellClickHandler;
|
onCellClick: OnCellClickHandler;
|
||||||
}) => {
|
}) => {
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
@ -116,8 +116,8 @@ export const SelectMarketPopover = ({
|
|||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
});
|
});
|
||||||
const onSelectMarket = useCallback(
|
const onSelectMarket = useCallback(
|
||||||
(marketId: string) => {
|
(marketId: string, metaKey?: boolean) => {
|
||||||
onSelect(marketId);
|
onSelect(marketId, metaKey);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
},
|
},
|
||||||
[onSelect]
|
[onSelect]
|
||||||
|
21
apps/trading/lib/hooks/use-market-click-handler.ts
Normal file
21
apps/trading/lib/hooks/use-market-click-handler.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useNavigate, useParams, useLocation } from 'react-router-dom';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { Links, Routes } from '../../pages/client-router';
|
||||||
|
|
||||||
|
export const useMarketClickHandler = (replace = false) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { marketId } = useParams();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const isMarketPage = pathname.match(/^\/markets\/(.+)/);
|
||||||
|
return useCallback(
|
||||||
|
(selectedId: string, metaKey?: boolean) => {
|
||||||
|
const link = Links[Routes.MARKET](selectedId);
|
||||||
|
if (metaKey) {
|
||||||
|
window.open(`/#${link}`, '_blank');
|
||||||
|
} else if (selectedId !== marketId || !isMarketPage) {
|
||||||
|
navigate(link, { replace });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[navigate, marketId, replace, isMarketPage]
|
||||||
|
);
|
||||||
|
};
|
@ -1,3 +1,5 @@
|
|||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
@ -23,14 +25,12 @@ import {
|
|||||||
import './styles.css';
|
import './styles.css';
|
||||||
import { useGlobalStore, usePageTitleStore } from '../stores';
|
import { useGlobalStore, usePageTitleStore } from '../stores';
|
||||||
import { Footer } from '../components/footer';
|
import { Footer } from '../components/footer';
|
||||||
import { useMemo, useState } from 'react';
|
|
||||||
import DialogsContainer from './dialogs-container';
|
import DialogsContainer from './dialogs-container';
|
||||||
import ToastsManager from './toasts-manager';
|
import ToastsManager from './toasts-manager';
|
||||||
import { HashRouter, useLocation, useSearchParams } from 'react-router-dom';
|
import { HashRouter, useLocation, useSearchParams } from 'react-router-dom';
|
||||||
import { Connectors } from '../lib/vega-connectors';
|
import { Connectors } from '../lib/vega-connectors';
|
||||||
import { ViewingBanner } from '../components/viewing-banner';
|
import { ViewingBanner } from '../components/viewing-banner';
|
||||||
import { Banner } from '../components/banner';
|
import { Banner } from '../components/banner';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { AppLoader, DynamicLoader } from '../components/app-loader';
|
import { AppLoader, DynamicLoader } from '../components/app-loader';
|
||||||
import { Navbar } from '../components/navbar';
|
import { Navbar } from '../components/navbar';
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ const Title = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TransactionsHandler = () => {
|
const InitializeHandlers = () => {
|
||||||
useVegaTransactionManager();
|
useVegaTransactionManager();
|
||||||
useVegaTransactionUpdater();
|
useVegaTransactionUpdater();
|
||||||
useEthTransactionManager();
|
useEthTransactionManager();
|
||||||
@ -93,7 +93,7 @@ function AppBody({ Component }: AppProps) {
|
|||||||
</div>
|
</div>
|
||||||
<DialogsContainer />
|
<DialogsContainer />
|
||||||
<ToastsManager />
|
<ToastsManager />
|
||||||
<TransactionsHandler />
|
<InitializeHandlers />
|
||||||
<MaybeConnectEagerly />
|
<MaybeConnectEagerly />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -9,6 +9,7 @@ export * from './lib/cells/price-change-cell';
|
|||||||
export * from './lib/cells/price-flash-cell';
|
export * from './lib/cells/price-flash-cell';
|
||||||
export * from './lib/cells/vol-cell';
|
export * from './lib/cells/vol-cell';
|
||||||
export * from './lib/cells/centered-grid-cell';
|
export * from './lib/cells/centered-grid-cell';
|
||||||
|
export * from './lib/cells/market-name-cell';
|
||||||
|
|
||||||
export * from './lib/filters/date-range-filter';
|
export * from './lib/filters/date-range-filter';
|
||||||
export * from './lib/filters/set-filter';
|
export * from './lib/filters/set-filter';
|
||||||
|
35
libs/datagrid/src/lib/cells/market-name-cell.tsx
Normal file
35
libs/datagrid/src/lib/cells/market-name-cell.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import type { MouseEvent } from 'react';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import get from 'lodash/get';
|
||||||
|
|
||||||
|
interface MarketNameCellProps {
|
||||||
|
value?: string;
|
||||||
|
data?: { id?: string; marketId?: string; market?: { id: string } };
|
||||||
|
idPath?: string;
|
||||||
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MarketNameCell = ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
idPath,
|
||||||
|
onMarketClick,
|
||||||
|
}: MarketNameCellProps) => {
|
||||||
|
const id = data ? get(data, idPath ?? 'id', 'all') : '';
|
||||||
|
const handleOnClick = useCallback(
|
||||||
|
(ev: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
if (onMarketClick) {
|
||||||
|
onMarketClick(id, ev.metaKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[id, onMarketClick]
|
||||||
|
);
|
||||||
|
if (!data) return null;
|
||||||
|
return (
|
||||||
|
<button onClick={handleOnClick} tabIndex={0}>
|
||||||
|
{value}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
@ -26,7 +26,7 @@ export const compileGridData = (
|
|||||||
| 'targetStake'
|
| 'targetStake'
|
||||||
| 'trigger'
|
| 'trigger'
|
||||||
> | null,
|
> | null,
|
||||||
onSelect?: (id: string) => void
|
onSelect?: (id: string, metaKey?: boolean) => void
|
||||||
): { label: ReactNode; value?: ReactNode }[] => {
|
): { label: ReactNode; value?: ReactNode }[] => {
|
||||||
const grid: SimpleGridProps['grid'] = [];
|
const grid: SimpleGridProps['grid'] = [];
|
||||||
const isLiquidityMonitoringAuction =
|
const isLiquidityMonitoringAuction =
|
||||||
@ -78,7 +78,7 @@ export const compileGridData = (
|
|||||||
label: (
|
label: (
|
||||||
<Link
|
<Link
|
||||||
to={`/liquidity/${market.id}`}
|
to={`/liquidity/${market.id}`}
|
||||||
onClick={() => onSelect && onSelect(market.id)}
|
onClick={(ev) => onSelect && onSelect(market.id, ev.metaKey)}
|
||||||
>
|
>
|
||||||
<UILink>{t('Current liquidity')}</UILink>
|
<UILink>{t('Current liquidity')}</UILink>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -12,14 +12,16 @@ import { useMarket, useStaticMarketData } from '@vegaprotocol/market-list';
|
|||||||
|
|
||||||
type TradingModeTooltipProps = {
|
type TradingModeTooltipProps = {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onSelect?: (marketId: string) => void;
|
onSelect?: (marketId: string, metaKey?: boolean) => void;
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
|
skipGrid?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TradingModeTooltip = ({
|
export const TradingModeTooltip = ({
|
||||||
marketId,
|
marketId,
|
||||||
onSelect,
|
onSelect,
|
||||||
skip,
|
skip,
|
||||||
|
skipGrid,
|
||||||
}: TradingModeTooltipProps) => {
|
}: TradingModeTooltipProps) => {
|
||||||
const { VEGA_DOCS_URL } = useEnvironment();
|
const { VEGA_DOCS_URL } = useEnvironment();
|
||||||
const { data: market } = useMarket(marketId);
|
const { data: market } = useMarket(marketId);
|
||||||
@ -42,7 +44,7 @@ export const TradingModeTooltip = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const compiledGrid =
|
const compiledGrid =
|
||||||
onSelect && compileGridData(market, marketData, onSelect);
|
!skipGrid && compileGridData(market, marketData, onSelect);
|
||||||
|
|
||||||
switch (marketTradingMode) {
|
switch (marketTradingMode) {
|
||||||
case Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS: {
|
case Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS: {
|
||||||
@ -103,6 +105,7 @@ export const TradingModeTooltip = ({
|
|||||||
{VEGA_DOCS_URL && (
|
{VEGA_DOCS_URL && (
|
||||||
<ExternalLink
|
<ExternalLink
|
||||||
href={createDocsLinks(VEGA_DOCS_URL).AUCTION_TYPE_OPENING}
|
href={createDocsLinks(VEGA_DOCS_URL).AUCTION_TYPE_OPENING}
|
||||||
|
className="ml-1"
|
||||||
>
|
>
|
||||||
{t('Find out more')}
|
{t('Find out more')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
@ -129,6 +132,7 @@ export const TradingModeTooltip = ({
|
|||||||
createDocsLinks(VEGA_DOCS_URL)
|
createDocsLinks(VEGA_DOCS_URL)
|
||||||
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
||||||
}
|
}
|
||||||
|
className="ml-1"
|
||||||
>
|
>
|
||||||
{t('Find out more')}
|
{t('Find out more')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
@ -153,6 +157,7 @@ export const TradingModeTooltip = ({
|
|||||||
createDocsLinks(VEGA_DOCS_URL)
|
createDocsLinks(VEGA_DOCS_URL)
|
||||||
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
||||||
}
|
}
|
||||||
|
className="ml-1"
|
||||||
>
|
>
|
||||||
{t('Find out more')}
|
{t('Find out more')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
@ -175,6 +180,7 @@ export const TradingModeTooltip = ({
|
|||||||
createDocsLinks(VEGA_DOCS_URL)
|
createDocsLinks(VEGA_DOCS_URL)
|
||||||
.AUCTION_TYPE_PRICE_MONITORING
|
.AUCTION_TYPE_PRICE_MONITORING
|
||||||
}
|
}
|
||||||
|
className="ml-1"
|
||||||
>
|
>
|
||||||
{t('Find out more')}
|
{t('Find out more')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
|
@ -8,7 +8,7 @@ export const FillsContainer = ({
|
|||||||
onMarketClick,
|
onMarketClick,
|
||||||
}: {
|
}: {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import { useBottomPlaceholder } from '@vegaprotocol/react-helpers';
|
|||||||
interface FillsManagerProps {
|
interface FillsManagerProps {
|
||||||
partyId: string;
|
partyId: string;
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FillsManager = ({
|
export const FillsManager = ({
|
||||||
|
@ -7,6 +7,7 @@ import type { Trade } from './fills-data-provider';
|
|||||||
|
|
||||||
import { FillsTable, getFeesBreakdown } from './fills-table';
|
import { FillsTable, getFeesBreakdown } from './fills-table';
|
||||||
import { generateFill } from './test-helpers';
|
import { generateFill } from './test-helpers';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
describe('FillsTable', () => {
|
describe('FillsTable', () => {
|
||||||
let defaultFill: PartialDeep<Trade>;
|
let defaultFill: PartialDeep<Trade>;
|
||||||
@ -36,7 +37,11 @@ describe('FillsTable', () => {
|
|||||||
|
|
||||||
it('correct columns are rendered', async () => {
|
it('correct columns are rendered', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<FillsTable partyId="party-id" rowData={[generateFill()]} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId="party-id" rowData={[generateFill()]} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const headers = screen.getAllByRole('columnheader');
|
const headers = screen.getAllByRole('columnheader');
|
||||||
@ -67,7 +72,11 @@ describe('FillsTable', () => {
|
|||||||
liquidityFee: '2',
|
liquidityFee: '2',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
render(<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const expectedValues = [
|
const expectedValues = [
|
||||||
buyerFill.market?.tradableInstrument.instrument.name || '',
|
buyerFill.market?.tradableInstrument.instrument.name || '',
|
||||||
@ -100,7 +109,11 @@ describe('FillsTable', () => {
|
|||||||
liquidityFee: '1',
|
liquidityFee: '1',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
render(<FillsTable partyId={partyId} rowData={[buyerFill]} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId={partyId} rowData={[buyerFill]} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const expectedValues = [
|
const expectedValues = [
|
||||||
@ -129,7 +142,9 @@ describe('FillsTable', () => {
|
|||||||
aggressor: Schema.Side.SIDE_SELL,
|
aggressor: Schema.Side.SIDE_SELL,
|
||||||
});
|
});
|
||||||
const { rerender } = render(
|
const { rerender } = render(
|
||||||
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
screen
|
screen
|
||||||
@ -143,7 +158,11 @@ describe('FillsTable', () => {
|
|||||||
},
|
},
|
||||||
aggressor: Schema.Side.SIDE_BUY,
|
aggressor: Schema.Side.SIDE_BUY,
|
||||||
});
|
});
|
||||||
rerender(<FillsTable partyId={partyId} rowData={[makerFill]} />);
|
rerender(
|
||||||
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId={partyId} rowData={[makerFill]} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
screen
|
screen
|
||||||
@ -160,7 +179,11 @@ describe('FillsTable', () => {
|
|||||||
},
|
},
|
||||||
aggressor: Schema.Side.SIDE_SELL,
|
aggressor: Schema.Side.SIDE_SELL,
|
||||||
});
|
});
|
||||||
render(<FillsTable partyId={partyId} rowData={[takerFill]} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
|
||||||
const feeCell = screen
|
const feeCell = screen
|
||||||
.getAllByRole('gridcell')
|
.getAllByRole('gridcell')
|
||||||
|
@ -14,16 +14,13 @@ import {
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import {
|
import {
|
||||||
AgGridDynamic as AgGrid,
|
AgGridDynamic as AgGrid,
|
||||||
positiveClassNames,
|
positiveClassNames,
|
||||||
negativeClassNames,
|
negativeClassNames,
|
||||||
|
MarketNameCell,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type { VegaValueFormatterParams } from '@vegaprotocol/datagrid';
|
||||||
VegaICellRendererParams,
|
|
||||||
VegaValueFormatterParams,
|
|
||||||
} from '@vegaprotocol/datagrid';
|
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import type { Trade } from './fills-data-provider';
|
import type { Trade } from './fills-data-provider';
|
||||||
@ -34,7 +31,7 @@ const MAKER = 'MAKER';
|
|||||||
|
|
||||||
export type Props = (AgGridReactProps | AgReactUiProps) & {
|
export type Props = (AgGridReactProps | AgReactUiProps) & {
|
||||||
partyId: string;
|
partyId: string;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FillsTable = forwardRef<AgGridReact, Props>(
|
export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||||
@ -48,30 +45,14 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
|||||||
getRowId={({ data }) => data?.id}
|
getRowId={({ data }) => data?.id}
|
||||||
tooltipShowDelay={0}
|
tooltipShowDelay={0}
|
||||||
tooltipHideDelay={2000}
|
tooltipHideDelay={2000}
|
||||||
|
components={{ MarketNameCell }}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Market')}
|
headerName={t('Market')}
|
||||||
field="market.tradableInstrument.instrument.name"
|
field="market.tradableInstrument.instrument.name"
|
||||||
cellRenderer={({
|
cellRenderer="MarketNameCell"
|
||||||
value,
|
cellRendererParams={{ idPath: 'market.id', onMarketClick }}
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<
|
|
||||||
Trade,
|
|
||||||
'market.tradableInstrument.instrument.name'
|
|
||||||
>) =>
|
|
||||||
onMarketClick ? (
|
|
||||||
<Link
|
|
||||||
onClick={() =>
|
|
||||||
data?.market?.id && onMarketClick(data?.market?.id)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Size')}
|
headerName={t('Size')}
|
||||||
|
@ -39,12 +39,12 @@ import {
|
|||||||
|
|
||||||
export interface InfoProps {
|
export interface InfoProps {
|
||||||
market: MarketInfoWithDataAndCandles;
|
market: MarketInfoWithDataAndCandles;
|
||||||
onSelect: (id: string) => void;
|
onSelect?: (id: string, metaKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarketInfoContainerProps {
|
export interface MarketInfoContainerProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onSelect?: (id: string) => void;
|
onSelect?: (id: string, metaKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
export const MarketInfoContainer = ({
|
export const MarketInfoContainer = ({
|
||||||
marketId,
|
marketId,
|
||||||
@ -73,7 +73,7 @@ export const MarketInfoContainer = ({
|
|||||||
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
||||||
{data ? (
|
{data ? (
|
||||||
<TinyScroll className="h-full overflow-auto">
|
<TinyScroll className="h-full overflow-auto">
|
||||||
<Info market={data} onSelect={(id) => onSelect?.(id)} />
|
<Info market={data} onSelect={onSelect} />
|
||||||
</TinyScroll>
|
</TinyScroll>
|
||||||
) : (
|
) : (
|
||||||
<Splash>
|
<Splash>
|
||||||
@ -169,7 +169,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
<LiquidityInfoPanel market={market}>
|
<LiquidityInfoPanel market={market}>
|
||||||
<Link
|
<Link
|
||||||
to={`/liquidity/${market.id}`}
|
to={`/liquidity/${market.id}`}
|
||||||
onClick={() => onSelect(market.id)}
|
onClick={(ev) => onSelect?.(market.id, ev.metaKey)}
|
||||||
data-testid="view-liquidity-link"
|
data-testid="view-liquidity-link"
|
||||||
>
|
>
|
||||||
<UILink>{t('View liquidity provision table')}</UILink>
|
<UILink>{t('View liquidity provision table')}</UILink>
|
||||||
|
@ -10,6 +10,7 @@ import type {
|
|||||||
import {
|
import {
|
||||||
AgGridDynamic as AgGrid,
|
AgGridDynamic as AgGrid,
|
||||||
PriceFlashCell,
|
PriceFlashCell,
|
||||||
|
MarketNameCell,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
@ -24,8 +25,10 @@ export const getRowId = ({ data }: { data: { id: string } }) => data.id;
|
|||||||
|
|
||||||
export const MarketListTable = forwardRef<
|
export const MarketListTable = forwardRef<
|
||||||
AgGridReact,
|
AgGridReact,
|
||||||
TypedDataAgGrid<MarketMaybeWithData>
|
TypedDataAgGrid<MarketMaybeWithData> & {
|
||||||
>((props, ref) => {
|
onMarketClick: (marketId: string, metaKey?: boolean) => void;
|
||||||
|
}
|
||||||
|
>(({ onMarketClick, ...props }, ref) => {
|
||||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
@ -41,22 +44,14 @@ export const MarketListTable = forwardRef<
|
|||||||
filterParams: { buttons: ['reset'] },
|
filterParams: { buttons: ['reset'] },
|
||||||
}}
|
}}
|
||||||
suppressCellFocus={true}
|
suppressCellFocus={true}
|
||||||
components={{ PriceFlashCell }}
|
components={{ PriceFlashCell, MarketNameCell }}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Market')}
|
headerName={t('Market')}
|
||||||
field="tradableInstrument.instrument.code"
|
field="tradableInstrument.instrument.code"
|
||||||
cellRenderer={({
|
cellRenderer="MarketNameCell"
|
||||||
value,
|
cellRendererParams={{ onMarketClick }}
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<
|
|
||||||
MarketMaybeWithData,
|
|
||||||
'tradableInstrument.instrument.code'
|
|
||||||
>) => {
|
|
||||||
if (!data) return null;
|
|
||||||
return <span data-testid={`market-${data.id}`}>{value}</span>;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Description')}
|
headerName={t('Description')}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
import type { MouseEvent } from 'react';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { MarketListTable } from './market-list-table';
|
import { MarketListTable } from './market-list-table';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import type { RowClickedEvent } from 'ag-grid-community';
|
import type { CellClickedEvent } from 'ag-grid-community';
|
||||||
import { marketsWithDataProvider as dataProvider } from '../../markets-provider';
|
import { marketsWithDataProvider as dataProvider } from '../../markets-provider';
|
||||||
import type { MarketMaybeWithData } from '../../markets-provider';
|
import type { MarketMaybeWithData } from '../../markets-provider';
|
||||||
|
|
||||||
interface MarketsContainerProps {
|
interface MarketsContainerProps {
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string, metaKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||||
@ -21,16 +23,23 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
|||||||
rowData={error ? [] : data}
|
rowData={error ? [] : data}
|
||||||
suppressLoadingOverlay
|
suppressLoadingOverlay
|
||||||
suppressNoRowsOverlay
|
suppressNoRowsOverlay
|
||||||
onRowClicked={(rowEvent: RowClickedEvent) => {
|
onCellClicked={(cellEvent: CellClickedEvent) => {
|
||||||
const { data, event } = rowEvent;
|
const { data, column, event } = cellEvent;
|
||||||
// filters out clicks on the symbol column because it should display asset details
|
const colId = column.getColId();
|
||||||
if (
|
if (
|
||||||
(event?.target as HTMLElement).tagName.toUpperCase() === 'BUTTON'
|
[
|
||||||
|
'tradableInstrument.instrument.code',
|
||||||
|
'tradableInstrument.instrument.product.settlementAsset',
|
||||||
|
].includes(colId)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onSelect((data as MarketMaybeWithData).id);
|
onSelect(
|
||||||
|
(data as MarketMaybeWithData).id,
|
||||||
|
(event as unknown as MouseEvent)?.metaKey
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
|
onMarketClick={onSelect}
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute inset-0">
|
<div className="pointer-events-none absolute inset-0">
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
|
@ -9,7 +9,7 @@ export const OrderListContainer = ({
|
|||||||
enforceBottomPlaceholder,
|
enforceBottomPlaceholder,
|
||||||
}: {
|
}: {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
enforceBottomPlaceholder?: boolean;
|
enforceBottomPlaceholder?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
|
@ -23,7 +23,7 @@ import type { Order, OrderEdge } from '../order-data-provider';
|
|||||||
export interface OrderListManagerProps {
|
export interface OrderListManagerProps {
|
||||||
partyId: string;
|
partyId: string;
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
enforceBottomPlaceholder?: boolean;
|
enforceBottomPlaceholder?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
limitOrder,
|
limitOrder,
|
||||||
marketOrder,
|
marketOrder,
|
||||||
} from '../mocks/generate-orders';
|
} from '../mocks/generate-orders';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
// Mock theme switcher to get around inconsistent mocking of zustand
|
// Mock theme switcher to get around inconsistent mocking of zustand
|
||||||
// stores
|
// stores
|
||||||
@ -36,9 +37,11 @@ const generateJsx = (
|
|||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<MockedProvider>
|
<MockedProvider>
|
||||||
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
<MemoryRouter>
|
||||||
<OrderListTable {...defaultProps} {...props} />
|
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
||||||
</VegaWalletContext.Provider>
|
<OrderListTable {...defaultProps} {...props} />
|
||||||
|
</VegaWalletContext.Provider>
|
||||||
|
</MemoryRouter>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { memo, forwardRef } from 'react';
|
import { memo, forwardRef } from 'react';
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
DateRangeFilter,
|
DateRangeFilter,
|
||||||
negativeClassNames,
|
negativeClassNames,
|
||||||
positiveClassNames,
|
positiveClassNames,
|
||||||
|
MarketNameCell,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type {
|
||||||
TypedDataAgGrid,
|
TypedDataAgGrid,
|
||||||
@ -29,7 +30,7 @@ type OrderListProps = TypedDataAgGrid<Order> & { marketId?: string };
|
|||||||
export type OrderListTableProps = OrderListProps & {
|
export type OrderListTableProps = OrderListProps & {
|
||||||
cancel: (order: Order) => void;
|
cancel: (order: Order) => void;
|
||||||
setEditOrder: (order: Order) => void;
|
setEditOrder: (order: Order) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,30 +51,14 @@ export const OrderListTable = memo(
|
|||||||
height: '100%',
|
height: '100%',
|
||||||
}}
|
}}
|
||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }) => data.id}
|
||||||
|
components={{ MarketNameCell }}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Market')}
|
headerName={t('Market')}
|
||||||
field="market.tradableInstrument.instrument.code"
|
field="market.tradableInstrument.instrument.code"
|
||||||
cellRenderer={({
|
cellRenderer="MarketNameCell"
|
||||||
value,
|
cellRendererParams={{ idPath: 'market.id', onMarketClick }}
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<
|
|
||||||
Order,
|
|
||||||
'market.tradableInstrument.instrument.code'
|
|
||||||
>) =>
|
|
||||||
onMarketClick ? (
|
|
||||||
<Link
|
|
||||||
onClick={() =>
|
|
||||||
data?.market?.id && onMarketClick(data?.market?.id)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
minWidth={150}
|
minWidth={150}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
@ -6,6 +6,7 @@ import type { Position } from './positions-data-providers';
|
|||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
|
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
|
||||||
import type { ICellRendererParams } from 'ag-grid-community';
|
import type { ICellRendererParams } from 'ag-grid-community';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
const singleRow: Position = {
|
const singleRow: Position = {
|
||||||
marketName: 'ETH/BTC (31 july 2022)',
|
marketName: 'ETH/BTC (31 july 2022)',
|
||||||
@ -37,7 +38,9 @@ const singleRowData = [singleRow];
|
|||||||
it('should render successfully', async () => {
|
it('should render successfully', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
const { baseElement } = render(
|
const { baseElement } = render(
|
||||||
<PositionsTable rowData={[]} isReadOnly={false} />
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={[]} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
expect(baseElement).toBeTruthy();
|
expect(baseElement).toBeTruthy();
|
||||||
});
|
});
|
||||||
@ -45,7 +48,11 @@ it('should render successfully', async () => {
|
|||||||
|
|
||||||
it('render correct columns', async () => {
|
it('render correct columns', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={singleRowData} isReadOnly={true} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={true} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const headers = screen.getAllByRole('columnheader');
|
const headers = screen.getAllByRole('columnheader');
|
||||||
@ -69,7 +76,11 @@ it('render correct columns', async () => {
|
|||||||
|
|
||||||
it('renders market name', async () => {
|
it('renders market name', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
expect(screen.getByText('ETH/BTC (31 july 2022)')).toBeTruthy();
|
expect(screen.getByText('ETH/BTC (31 july 2022)')).toBeTruthy();
|
||||||
});
|
});
|
||||||
@ -80,7 +91,11 @@ it('Does not fail if the market name does not match the split pattern', async ()
|
|||||||
Object.assign({}, singleRow, { marketName: breakingMarketName }),
|
Object.assign({}, singleRow, { marketName: breakingMarketName }),
|
||||||
];
|
];
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={row} isReadOnly={false} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={row} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByText(breakingMarketName)).toBeTruthy();
|
expect(screen.getByText(breakingMarketName)).toBeTruthy();
|
||||||
@ -90,7 +105,9 @@ it('add color and sign to amount, displays positive notional value', async () =>
|
|||||||
let result: RenderResult;
|
let result: RenderResult;
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result = render(
|
result = render(
|
||||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
let cells = screen.getAllByRole('gridcell');
|
let cells = screen.getAllByRole('gridcell');
|
||||||
@ -101,10 +118,12 @@ it('add color and sign to amount, displays positive notional value', async () =>
|
|||||||
expect(cells[1].textContent).toEqual('1,230.0');
|
expect(cells[1].textContent).toEqual('1,230.0');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.rerender(
|
result.rerender(
|
||||||
<PositionsTable
|
<MemoryRouter>
|
||||||
rowData={[{ ...singleRow, openVolume: '-100' }]}
|
<PositionsTable
|
||||||
isReadOnly={false}
|
rowData={[{ ...singleRow, openVolume: '-100' }]}
|
||||||
/>
|
isReadOnly={false}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cells = screen.getAllByRole('gridcell');
|
cells = screen.getAllByRole('gridcell');
|
||||||
@ -118,7 +137,9 @@ it('displays mark price', async () => {
|
|||||||
let result: RenderResult;
|
let result: RenderResult;
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result = render(
|
result = render(
|
||||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -127,16 +148,18 @@ it('displays mark price', async () => {
|
|||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.rerender(
|
result.rerender(
|
||||||
<PositionsTable
|
<MemoryRouter>
|
||||||
rowData={[
|
<PositionsTable
|
||||||
{
|
rowData={[
|
||||||
...singleRow,
|
{
|
||||||
marketTradingMode:
|
...singleRow,
|
||||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
marketTradingMode:
|
||||||
},
|
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||||
]}
|
},
|
||||||
isReadOnly={false}
|
]}
|
||||||
/>
|
isReadOnly={false}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -146,7 +169,11 @@ it('displays mark price', async () => {
|
|||||||
|
|
||||||
it('displays leverage', async () => {
|
it('displays leverage', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
expect(cells[6].textContent).toEqual('1.1');
|
expect(cells[6].textContent).toEqual('1.1');
|
||||||
@ -154,7 +181,11 @@ it('displays leverage', async () => {
|
|||||||
|
|
||||||
it('displays allocated margin', async () => {
|
it('displays allocated margin', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const cell = cells[7];
|
const cell = cells[7];
|
||||||
@ -163,7 +194,11 @@ it('displays allocated margin', async () => {
|
|||||||
|
|
||||||
it('displays realised and unrealised PNL', async () => {
|
it('displays realised and unrealised PNL', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
expect(cells[9].textContent).toEqual('4.56');
|
expect(cells[9].textContent).toEqual('4.56');
|
||||||
@ -172,13 +207,15 @@ it('displays realised and unrealised PNL', async () => {
|
|||||||
it('displays close button', async () => {
|
it('displays close button', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(
|
render(
|
||||||
<PositionsTable
|
<MemoryRouter>
|
||||||
rowData={singleRowData}
|
<PositionsTable
|
||||||
onClose={() => {
|
rowData={singleRowData}
|
||||||
return;
|
onClose={() => {
|
||||||
}}
|
return;
|
||||||
isReadOnly={false}
|
}}
|
||||||
/>
|
isReadOnly={false}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
@ -188,13 +225,15 @@ it('displays close button', async () => {
|
|||||||
it('do not display close button if openVolume is zero', async () => {
|
it('do not display close button if openVolume is zero', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(
|
render(
|
||||||
<PositionsTable
|
<MemoryRouter>
|
||||||
rowData={[{ ...singleRow, openVolume: '0' }]}
|
<PositionsTable
|
||||||
onClose={() => {
|
rowData={[{ ...singleRow, openVolume: '0' }]}
|
||||||
return;
|
onClose={() => {
|
||||||
}}
|
return;
|
||||||
isReadOnly={false}
|
}}
|
||||||
/>
|
isReadOnly={false}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
|
@ -14,12 +14,12 @@ import {
|
|||||||
PriceFlashCell,
|
PriceFlashCell,
|
||||||
signedNumberCssClass,
|
signedNumberCssClass,
|
||||||
signedNumberCssClassRules,
|
signedNumberCssClassRules,
|
||||||
|
MarketNameCell,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import {
|
import {
|
||||||
ButtonLink,
|
ButtonLink,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipCellComponent,
|
TooltipCellComponent,
|
||||||
Link,
|
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
Icon,
|
Icon,
|
||||||
ProgressBarCell,
|
ProgressBarCell,
|
||||||
@ -43,7 +43,7 @@ import { useEnvironment } from '@vegaprotocol/environment';
|
|||||||
|
|
||||||
interface Props extends TypedDataAgGrid<Position> {
|
interface Props extends TypedDataAgGrid<Position> {
|
||||||
onClose?: (data: Position) => void;
|
onClose?: (data: Position) => void;
|
||||||
onMarketClick?: (id: string) => void;
|
onMarketClick?: (id: string, metaKey?: boolean) => void;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
}
|
}
|
||||||
@ -96,26 +96,19 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
|||||||
filterParams: { buttons: ['reset'] },
|
filterParams: { buttons: ['reset'] },
|
||||||
tooltipComponent: TooltipCellComponent,
|
tooltipComponent: TooltipCellComponent,
|
||||||
}}
|
}}
|
||||||
components={{ AmountCell, PriceFlashCell, ProgressBarCell }}
|
components={{
|
||||||
|
AmountCell,
|
||||||
|
PriceFlashCell,
|
||||||
|
ProgressBarCell,
|
||||||
|
MarketNameCell,
|
||||||
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Market')}
|
headerName={t('Market')}
|
||||||
field="marketName"
|
field="marketName"
|
||||||
cellRenderer={({
|
cellRenderer="MarketNameCell"
|
||||||
value,
|
cellRendererParams={{ idPath: 'marketId', onMarketClick }}
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<Position, 'marketName'>) =>
|
|
||||||
onMarketClick ? (
|
|
||||||
<Link
|
|
||||||
onClick={() => data?.marketId && onMarketClick(data?.marketId)}
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
minWidth={190}
|
minWidth={190}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
Loading…
Reference in New Issue
Block a user