chore(2220): partial live update of market dropdown (#2263)

* chore: partial live update of market dropdown

* chore: partial live update of market dropdown

* chore: partial live update of market dropdown - some refactor

* chore: partial live update of market dropdown - some refactor

* chore: partial live update of market dropdown - fix lint error

* chore: partial live update of market dropdown - fix failing tests

* chore: partial live update of market dropdown - fix failing tests
This commit is contained in:
macqbat 2022-11-30 12:02:59 +01:00 committed by GitHub
parent 03f659ebb3
commit b67bc33c49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 299 additions and 204 deletions

View File

@ -159,10 +159,26 @@ export const TradeMarketHeader = ({
> >
<ExpiryLabel market={market} /> <ExpiryLabel market={market} />
</HeaderStat> </HeaderStat>
<MarketMarkPrice marketId={market?.id} /> <MarketMarkPrice
<Last24hPriceChange marketId={market?.id} /> marketId={market?.id}
<Last24hVolume marketId={market?.id} /> decimalPlaces={market?.decimalPlaces}
<MarketTradingModeComponent marketId={market?.id} onSelect={onSelect} /> isHeader
/>
<Last24hPriceChange
marketId={market?.id}
decimalPlaces={market?.decimalPlaces}
isHeader
/>
<Last24hVolume
marketId={market?.id}
positionDecimalPlaces={market?.positionDecimalPlaces}
isHeader
/>
<MarketTradingModeComponent
marketId={market?.id}
onSelect={onSelect}
isHeader
/>
{asset ? ( {asset ? (
<HeaderStat <HeaderStat
heading={t('Settlement asset')} heading={t('Settlement asset')}

View File

@ -1,22 +1,37 @@
import { useCallback, useMemo, useRef, useState } from 'react'; import { useCallback, useMemo, useRef, useState } from 'react';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import { t, useDataProvider, useYesterday } from '@vegaprotocol/react-helpers'; import {
isNumeric,
t,
useDataProvider,
useYesterday,
} from '@vegaprotocol/react-helpers';
import { PriceCellChange } from '@vegaprotocol/ui-toolkit'; import { PriceCellChange } from '@vegaprotocol/ui-toolkit';
import { Schema } from '@vegaprotocol/types'; import { Schema } from '@vegaprotocol/types';
import type { CandleClose } from '@vegaprotocol/types'; import type { CandleClose } from '@vegaprotocol/types';
import type { import type { Candle } from '@vegaprotocol/market-list';
SingleMarketFieldsFragment, import { marketCandlesProvider } from '@vegaprotocol/market-list';
Candle,
} from '@vegaprotocol/market-list';
import {
marketCandlesProvider,
marketProvider,
} from '@vegaprotocol/market-list';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
import * as constants from '../constants'; import * as constants from '../constants';
export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => { interface Props {
const [candlesClose, setCandlesClose] = useState<string[]>([]); marketId?: string;
decimalPlaces?: number;
initialValue?: string[];
isHeader?: boolean;
noUpdate?: boolean;
}
export const Last24hPriceChange = ({
marketId,
decimalPlaces,
initialValue,
isHeader = false,
noUpdate = false,
}: Props) => {
const [candlesClose, setCandlesClose] = useState<string[]>(
initialValue || []
);
const yesterday = useYesterday(); const yesterday = useYesterday();
// Cache timestamp for yesterday to prevent full unmount of market page when // Cache timestamp for yesterday to prevent full unmount of market page when
// a rerender occurs // a rerender occurs
@ -24,13 +39,6 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
return new Date(yesterday).toISOString(); return new Date(yesterday).toISOString();
}, [yesterday]); }, [yesterday]);
const marketVariables = useMemo(
() => ({
marketId: marketId,
}),
[marketId]
);
const variables = useMemo( const variables = useMemo(
() => ({ () => ({
marketId: marketId, marketId: marketId,
@ -40,18 +48,14 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
[marketId, yTimestamp] [marketId, yTimestamp]
); );
const { data, error } = useDataProvider<SingleMarketFieldsFragment, never>({
dataProvider: marketProvider,
variables: marketVariables,
skip: !marketId,
});
const throttledSetCandles = useRef( const throttledSetCandles = useRef(
throttle((data: Candle[]) => { throttle((data: Candle[]) => {
const candlesClose: string[] = data if (!noUpdate) {
.map((candle) => candle?.close) const candlesClose: string[] = data
.filter((c): c is CandleClose => c !== null); .map((candle) => candle?.close)
setCandlesClose(candlesClose); .filter((c): c is CandleClose => c !== null);
setCandlesClose(candlesClose);
}
}, constants.DEBOUNCE_UPDATE_TIME) }, constants.DEBOUNCE_UPDATE_TIME)
).current; ).current;
const update = useCallback( const update = useCallback(
@ -64,23 +68,27 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
[throttledSetCandles] [throttledSetCandles]
); );
useDataProvider<Candle[], Candle>({ const { error } = useDataProvider<Candle[], Candle>({
dataProvider: marketCandlesProvider, dataProvider: marketCandlesProvider,
update, update,
variables, variables,
skip: !marketId || !data, skip: noUpdate || !marketId,
}); });
return ( const content = useMemo(() => {
if (error || !isNumeric(decimalPlaces)) {
return <>-</>;
}
return (
<PriceCellChange candles={candlesClose} decimalPlaces={decimalPlaces} />
);
}, [candlesClose, decimalPlaces, error]);
return isHeader ? (
<HeaderStat heading={t('Change (24h)')} testId="market-change"> <HeaderStat heading={t('Change (24h)')} testId="market-change">
{!error && data?.decimalPlaces ? ( {content}
<PriceCellChange
candles={candlesClose}
decimalPlaces={data.decimalPlaces}
/>
) : (
'-'
)}
</HeaderStat> </HeaderStat>
) : (
content
); );
}; };

View File

@ -1,27 +1,37 @@
import { import {
calcCandleVolume, calcCandleVolume,
marketCandlesProvider, marketCandlesProvider,
marketProvider,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { import {
addDecimalsFormatNumber, addDecimalsFormatNumber,
t, t,
useDataProvider, useDataProvider,
useYesterday, useYesterday,
isNumeric,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types'; import { Schema } from '@vegaprotocol/types';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import { useCallback, useMemo, useRef, useState } from 'react'; import { useCallback, useMemo, useRef, useState } from 'react';
import * as constants from '../constants'; import * as constants from '../constants';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
import type { Candle } from '@vegaprotocol/market-list';
import type { interface Props {
SingleMarketFieldsFragment, marketId?: string;
Candle, positionDecimalPlaces?: number;
} from '@vegaprotocol/market-list'; noUpdate?: boolean;
export const Last24hVolume = ({ marketId }: { marketId?: string }) => { isHeader?: boolean;
const [candleVolume, setCandleVolume] = useState<string>(); initialValue?: string;
}
export const Last24hVolume = ({
marketId,
positionDecimalPlaces,
noUpdate = false,
isHeader = false,
initialValue,
}: Props) => {
const [candleVolume, setCandleVolume] = useState<string>(initialValue || '');
const yesterday = useYesterday(); const yesterday = useYesterday();
// Cache timestamp for yesterday to prevent full unmount of market page when // Cache timestamp for yesterday to prevent full unmount of market page when
// a rerender occurs // a rerender occurs
@ -29,13 +39,6 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
return new Date(yesterday).toISOString(); return new Date(yesterday).toISOString();
}, [yesterday]); }, [yesterday]);
const marketVariables = useMemo(
() => ({
marketId: marketId,
}),
[marketId]
);
const variables = useMemo( const variables = useMemo(
() => ({ () => ({
marketId: marketId, marketId: marketId,
@ -45,15 +48,9 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
[marketId, yTimestamp] [marketId, yTimestamp]
); );
const { data, error } = useDataProvider<SingleMarketFieldsFragment, never>({
dataProvider: marketProvider,
variables: marketVariables,
skip: !marketId,
});
const throttledSetCandles = useRef( const throttledSetCandles = useRef(
throttle((data: Candle[]) => { throttle((data: Candle[]) => {
setCandleVolume(calcCandleVolume(data)); noUpdate || setCandleVolume(calcCandleVolume(data) || '');
}, constants.DEBOUNCE_UPDATE_TIME) }, constants.DEBOUNCE_UPDATE_TIME)
).current; ).current;
const update = useCallback( const update = useCallback(
@ -66,26 +63,40 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
[throttledSetCandles] [throttledSetCandles]
); );
useDataProvider<Candle[], Candle>({ const { error } = useDataProvider<Candle[], Candle>({
dataProvider: marketCandlesProvider, dataProvider: marketCandlesProvider,
update, update,
variables, variables,
skip: !marketId || !data, skip: noUpdate || !marketId,
}); });
return ( const formatDecimals = isHeader ? positionDecimalPlaces || 0 : 2;
const content = useMemo(() => {
return (
<>
{!error && candleVolume && isNumeric(positionDecimalPlaces)
? addDecimalsFormatNumber(
candleVolume,
positionDecimalPlaces,
formatDecimals
)
: '-'}
</>
);
}, [error, candleVolume, positionDecimalPlaces, formatDecimals]);
return isHeader ? (
<HeaderStat <HeaderStat
heading={t('Volume (24h)')} heading={t('Volume (24h)')}
testId="market-volume" testId="market-volume"
description={ description={
error && candleVolume && data?.positionDecimalPlaces error && candleVolume && positionDecimalPlaces
? t('The total amount of assets traded in the last 24 hours.') ? t('The total amount of assets traded in the last 24 hours.')
: null : null
} }
> >
{!error && candleVolume && data?.positionDecimalPlaces {content}
? addDecimalsFormatNumber(candleVolume, data.positionDecimalPlaces)
: '-'}
</HeaderStat> </HeaderStat>
) : (
content
); );
}; };

View File

@ -3,57 +3,82 @@ import throttle from 'lodash/throttle';
import { import {
addDecimalsFormatNumber, addDecimalsFormatNumber,
t, t,
PriceCell,
useDataProvider, useDataProvider,
isNumeric,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import type { import type {
MarketData, MarketData,
MarketDataUpdateFieldsFragment, MarketDataUpdateFieldsFragment,
SingleMarketFieldsFragment,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list'; import { marketDataProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
import * as constants from '../constants'; import * as constants from '../constants';
export const MarketMarkPrice = ({ marketId }: { marketId?: string }) => { interface Props {
const [marketPrice, setMarketPrice] = useState<string | null>(null); marketId?: string;
decimalPlaces?: number;
isHeader?: boolean;
noUpdate?: boolean;
initialValue?: string;
}
export const MarketMarkPrice = ({
marketId,
decimalPlaces,
initialValue,
isHeader = false,
noUpdate = false,
}: Props) => {
const [marketPrice, setMarketPrice] = useState<string | null>(
initialValue || null
);
const variables = useMemo( const variables = useMemo(
() => ({ () => ({
marketId: marketId, marketId: marketId,
}), }),
[marketId] [marketId]
); );
const { data } = useDataProvider<SingleMarketFieldsFragment, never>({
dataProvider: marketProvider,
variables,
skip: !marketId,
});
const throttledSetMarketPrice = useRef( const throttledSetMarketPrice = useRef(
throttle((price: string) => { throttle((price: string) => {
setMarketPrice(price); noUpdate || setMarketPrice(price);
}, constants.DEBOUNCE_UPDATE_TIME) }, constants.DEBOUNCE_UPDATE_TIME)
).current; ).current;
const update = useCallback( const update = useCallback(
({ data: marketData }: { data: MarketData | null }) => { ({ data: marketData }: { data: MarketData | null }) => {
throttledSetMarketPrice( throttledSetMarketPrice(marketData?.markPrice || '');
marketData?.markPrice && data?.decimalPlaces
? addDecimalsFormatNumber(marketData.markPrice, data.decimalPlaces)
: '-'
);
return true; return true;
}, },
[data?.decimalPlaces, throttledSetMarketPrice] [throttledSetMarketPrice]
); );
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({ useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider, dataProvider: marketDataProvider,
update, update,
variables, variables,
skip: !marketId || !data, skip: noUpdate || !marketId,
}); });
return ( const content = useMemo(() => {
if (!marketPrice || !isNumeric(decimalPlaces)) {
return <>-</>;
}
return isHeader ? (
<div>{addDecimalsFormatNumber(marketPrice, decimalPlaces)}</div>
) : (
<PriceCell
value={Number(marketPrice)}
valueFormatted={addDecimalsFormatNumber(marketPrice, decimalPlaces, 2)}
/>
);
}, [marketPrice, decimalPlaces, isHeader]);
return isHeader ? (
<HeaderStat heading={t('Price')} testId="market-price"> <HeaderStat heading={t('Price')} testId="market-price">
<div>{marketPrice}</div> {content}
</HeaderStat> </HeaderStat>
) : (
content
); );
}; };

View File

@ -15,16 +15,30 @@ import type {
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list'; import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
interface Props { interface Props {
marketId?: string; marketId?: string;
onSelect?: (marketId: string) => void; onSelect?: (marketId: string) => void;
isHeader?: boolean;
noUpdate?: boolean;
initialMode?: Types.MarketTradingMode;
initialTrigger?: Types.AuctionTrigger;
} }
export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => { export const MarketTradingModeComponent = ({
marketId,
onSelect,
isHeader = false,
noUpdate = false,
initialMode,
initialTrigger,
}: Props) => {
const [tradingMode, setTradingMode] = const [tradingMode, setTradingMode] =
useState<Types.MarketTradingMode | null>(null); useState<Types.MarketTradingMode | null>(initialMode || null);
const [trigger, setTrigger] = useState<Types.AuctionTrigger | null>(null); const [trigger, setTrigger] = useState<Types.AuctionTrigger | null>(
initialTrigger || null
);
const [market, setMarket] = useState<MarketDealTicket | null>(null); const [market, setMarket] = useState<MarketDealTicket | null>(null);
const variables = useMemo( const variables = useMemo(
() => ({ () => ({
@ -41,7 +55,7 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
const update = useCallback( const update = useCallback(
({ data: marketData }: { data: MarketData | null }) => { ({ data: marketData }: { data: MarketData | null }) => {
if (marketData) { if (!noUpdate && marketData) {
setTradingMode(marketData.marketTradingMode); setTradingMode(marketData.marketTradingMode);
setTrigger(marketData.trigger); setTrigger(marketData.trigger);
setMarket({ setMarket({
@ -51,24 +65,25 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
} }
return true; return true;
}, },
[data] [noUpdate, data]
); );
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({ useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider, dataProvider: marketDataProvider,
update, update,
variables, variables,
skip: !marketId || !data, skip: noUpdate || !marketId || !data,
}); });
const content = const content =
tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION && (tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
trigger && trigger &&
trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
? `${MarketTradingModeMapping[tradingMode]} - ${AuctionTriggerMapping[trigger]}` ? `${MarketTradingModeMapping[tradingMode]} - ${AuctionTriggerMapping[trigger]}`
: MarketTradingModeMapping[tradingMode as Types.MarketTradingMode]; : MarketTradingModeMapping[tradingMode as Types.MarketTradingMode]) ||
'-';
return ( return isHeader ? (
<HeaderStat <HeaderStat
heading={t('Trading mode')} heading={t('Trading mode')}
description={ description={
@ -82,7 +97,18 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
} }
testId="market-trading-mode" testId="market-trading-mode"
> >
<div>{content || '-'}</div> <div>{content}</div>
</HeaderStat> </HeaderStat>
) : (
<Tooltip
description={
tradingMode &&
trigger && (
<TradingModeTooltip tradingMode={tradingMode} trigger={trigger} />
)
}
>
<span>{content}</span>
</Tooltip>
); );
}; };

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TradingModeTooltip } from '@vegaprotocol/deal-ticket';
import { FeesCell } from '@vegaprotocol/market-info'; import { FeesCell } from '@vegaprotocol/market-info';
import { import {
calcCandleHigh, calcCandleHigh,
@ -12,56 +10,23 @@ import {
signedNumberCssClass, signedNumberCssClass,
t, t,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { import { Link as UILink, Sparkline, Tooltip } from '@vegaprotocol/ui-toolkit';
AuctionTriggerMapping,
MarketTradingModeMapping,
Schema,
} from '@vegaprotocol/types';
import {
Link as UILink,
PriceCellChange,
Sparkline,
Tooltip,
} from '@vegaprotocol/ui-toolkit';
import isNil from 'lodash/isNil'; import isNil from 'lodash/isNil';
import type { CandleClose } from '@vegaprotocol/types'; import type { CandleClose } from '@vegaprotocol/types';
import type { import type {
MarketWithData, MarketWithData,
MarketWithCandles, MarketWithCandles,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { MarketMarkPrice } from '../market-mark-price';
import { Last24hPriceChange } from '../last-24h-price-change';
import { MarketTradingModeComponent } from '../market-trading-mode';
import { Last24hVolume } from '../last-24h-volume';
type Market = MarketWithData & MarketWithCandles; type Market = MarketWithData & MarketWithCandles;
export const cellClassNames = 'py-1 first:text-left text-right'; export const cellClassNames = 'py-1 first:text-left text-right';
const TradingMode = ({ market }: { market: Market }) => {
return (
<Tooltip
description={
market && (
<TradingModeTooltip
tradingMode={market.tradingMode}
trigger={market.data?.trigger || null}
/>
)
}
>
<span>
{market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
market.data?.trigger &&
market.data.trigger !==
Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
? `${MarketTradingModeMapping[market.tradingMode]}
- ${AuctionTriggerMapping[market.data.trigger]}`
: MarketTradingModeMapping[market.tradingMode]}
</span>
</Tooltip>
);
};
const FeesInfo = () => { const FeesInfo = () => {
return ( return (
<Tooltip <Tooltip
@ -205,7 +170,8 @@ export type OnCellClickHandler = (
export const columns = ( export const columns = (
market: Market, market: Market,
onSelect: (id: string) => void, onSelect: (id: string) => void,
onCellClick: OnCellClickHandler onCellClick: OnCellClickHandler,
activeMarketId?: string | null
) => { ) => {
const candlesClose = market.candles const candlesClose = market.candles
?.map((candle) => candle?.close) ?.map((candle) => candle?.close)
@ -221,6 +187,7 @@ export const columns = (
return onSelect(id); return onSelect(id);
} }
}; };
const noUpdate = !activeMarketId || market.id !== activeMarketId;
const selectMarketColumns: Column[] = [ const selectMarketColumns: Column[] = [
{ {
kind: ColumnKind.Market, kind: ColumnKind.Market,
@ -248,27 +215,25 @@ export const columns = (
}, },
{ {
kind: ColumnKind.LastPrice, kind: ColumnKind.LastPrice,
value: market.data?.markPrice ? ( value: (
<PriceCell <MarketMarkPrice
value={Number(market.data?.markPrice)} marketId={market.id}
valueFormatted={addDecimalsFormatNumber( decimalPlaces={market?.decimalPlaces}
market.data?.markPrice.toString(), initialValue={market.data?.markPrice.toString()}
market.decimalPlaces, noUpdate={noUpdate}
2
)}
/> />
) : (
'-'
), ),
className: cellClassNames, className: cellClassNames,
onlyOnDetailed: false, onlyOnDetailed: false,
}, },
{ {
kind: ColumnKind.Change24, kind: ColumnKind.Change24,
value: candlesClose && ( value: (
<PriceCellChange <Last24hPriceChange
candles={candlesClose} marketId={market.id}
decimalPlaces={market.decimalPlaces} decimalPlaces={market?.decimalPlaces}
noUpdate={noUpdate}
initialValue={candlesClose}
/> />
), ),
className: cellClassNames, className: cellClassNames,
@ -345,20 +310,28 @@ export const columns = (
}, },
{ {
kind: ColumnKind.Volume, kind: ColumnKind.Volume,
value: candleVolume value: (
? addDecimalsFormatNumber( <Last24hVolume
candleVolume.toString(), marketId={market.id}
market.positionDecimalPlaces, positionDecimalPlaces={market.positionDecimalPlaces}
2 initialValue={candleVolume}
) noUpdate={noUpdate}
: '-', />
),
className: `${cellClassNames} hidden lg:table-cell font-mono`, className: `${cellClassNames} hidden lg:table-cell font-mono`,
onlyOnDetailed: true, onlyOnDetailed: true,
dataTestId: 'market-volume', dataTestId: 'market-volume',
}, },
{ {
kind: ColumnKind.TradingMode, kind: ColumnKind.TradingMode,
value: <TradingMode market={market} />, value: (
<MarketTradingModeComponent
marketId={market?.id}
noUpdate={noUpdate}
initialMode={market.tradingMode}
initialTrigger={market.data?.trigger}
/>
),
className: `${cellClassNames} hidden lg:table-cell`, className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: true, onlyOnDetailed: true,
dataTestId: 'trading-mode-col', dataTestId: 'trading-mode-col',
@ -385,7 +358,8 @@ export const columnsPositionMarkets = (
market: Market, market: Market,
onSelect: (id: string) => void, onSelect: (id: string) => void,
openVolume?: string, openVolume?: string,
onCellClick?: OnCellClickHandler onCellClick?: OnCellClickHandler,
activeMarketId?: string | null
) => { ) => {
const candlesClose = market.candles const candlesClose = market.candles
?.map((candle) => candle?.close) ?.map((candle) => candle?.close)
@ -401,6 +375,7 @@ export const columnsPositionMarkets = (
} }
}; };
const candleVolume = market.candles && calcCandleVolume(market.candles); const candleVolume = market.candles && calcCandleVolume(market.candles);
const noUpdate = !activeMarketId || market.id !== activeMarketId;
const selectMarketColumns: Column[] = [ const selectMarketColumns: Column[] = [
{ {
kind: ColumnKind.Market, kind: ColumnKind.Market,
@ -428,27 +403,25 @@ export const columnsPositionMarkets = (
}, },
{ {
kind: ColumnKind.LastPrice, kind: ColumnKind.LastPrice,
value: market.data?.markPrice ? ( value: (
<PriceCell <MarketMarkPrice
value={Number(market.data.markPrice)} marketId={market.id}
valueFormatted={addDecimalsFormatNumber( decimalPlaces={market?.decimalPlaces}
market.data.markPrice.toString(), initialValue={market.data?.markPrice.toString()}
market.decimalPlaces, noUpdate={noUpdate}
2
)}
/> />
) : (
'-'
), ),
className: cellClassNames, className: cellClassNames,
onlyOnDetailed: false, onlyOnDetailed: false,
}, },
{ {
kind: ColumnKind.Change24, kind: ColumnKind.Change24,
value: candlesClose && ( value: (
<PriceCellChange <Last24hPriceChange
candles={candlesClose} marketId={market.id}
decimalPlaces={market.decimalPlaces} decimalPlaces={market?.decimalPlaces}
noUpdate={noUpdate}
initialValue={candlesClose}
/> />
), ),
className: cellClassNames, className: cellClassNames,
@ -525,20 +498,28 @@ export const columnsPositionMarkets = (
}, },
{ {
kind: ColumnKind.Volume, kind: ColumnKind.Volume,
value: candleVolume value: (
? addDecimalsFormatNumber( <Last24hVolume
candleVolume.toString(), marketId={market.id}
market.positionDecimalPlaces, positionDecimalPlaces={market.positionDecimalPlaces}
2 initialValue={candleVolume}
) noUpdate={noUpdate}
: '-', />
),
className: `${cellClassNames} hidden lg:table-cell font-mono`, className: `${cellClassNames} hidden lg:table-cell font-mono`,
onlyOnDetailed: true, onlyOnDetailed: true,
dataTestId: 'market-volume', dataTestId: 'market-volume',
}, },
{ {
kind: ColumnKind.TradingMode, kind: ColumnKind.TradingMode,
value: <TradingMode market={market} />, value: (
<MarketTradingModeComponent
marketId={market?.id}
noUpdate={noUpdate}
initialMode={market.tradingMode}
initialTrigger={market.data?.trigger}
/>
),
className: `${cellClassNames} hidden lg:table-cell`, className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: true, onlyOnDetailed: true,
dataTestId: 'trading-mode-col', dataTestId: 'trading-mode-col',

View File

@ -12,6 +12,7 @@ import type {
MarketData, MarketData,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
type Market = MarketWithCandles & MarketWithData; type Market = MarketWithCandles & MarketWithData;
type PartialMarket = Partial< type PartialMarket = Partial<
@ -91,6 +92,7 @@ const MARKET_B: PartialMarket = {
__typename: 'Market', __typename: 'Market',
id: '2', id: '2',
decimalPlaces: 2, decimalPlaces: 2,
positionDecimalPlaces: 0,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS, tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
tradableInstrument: { tradableInstrument: {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
@ -158,7 +160,8 @@ describe('SelectMarket', () => {
onCellClick={onCellClick} onCellClick={onCellClick}
onSelect={onSelect} onSelect={onSelect}
/> />
</MemoryRouter> </MemoryRouter>,
{ wrapper: MockedProvider }
); );
expect(screen.getByText('ABCDEF')).toBeTruthy(); // name expect(screen.getByText('ABCDEF')).toBeTruthy(); // name
expect(screen.getByText('25.00%')).toBeTruthy(); // price change expect(screen.getByText('25.00%')).toBeTruthy(); // price change
@ -178,7 +181,8 @@ describe('SelectMarket', () => {
onCellClick={onCellClick} onCellClick={onCellClick}
onSelect={onSelect} onSelect={onSelect}
/> />
</MemoryRouter> </MemoryRouter>,
{ wrapper: MockedProvider }
); );
fireEvent.click(screen.getAllByTestId(`market-link-1`)[0]); fireEvent.click(screen.getAllByTestId(`market-link-1`)[0]);
expect(onSelect).toHaveBeenCalledWith('1'); expect(onSelect).toHaveBeenCalledWith('1');

View File

@ -11,7 +11,7 @@ import {
Popover, Popover,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { import {
columnHeaders, columnHeaders,
@ -38,6 +38,7 @@ import {
TOKEN_NEW_MARKET_PROPOSAL, TOKEN_NEW_MARKET_PROPOSAL,
useLinks, useLinks,
} from '@vegaprotocol/environment'; } from '@vegaprotocol/environment';
import { useGlobalStore } from '../../stores';
type Market = MarketWithCandles & MarketWithData; type Market = MarketWithCandles & MarketWithData;
@ -87,14 +88,17 @@ export const SelectAllMarketsTableBody = ({
positions, positions,
onSelect, onSelect,
onCellClick, onCellClick,
activeMarketId,
headers = columnHeaders, headers = columnHeaders,
tableColumns = (market) => columns(market, onSelect, onCellClick), tableColumns = (market) =>
columns(market, onSelect, onCellClick, activeMarketId),
}: { }: {
markets?: Market[] | null; markets?: Market[] | null;
positions?: PositionFieldsFragment[]; positions?: PositionFieldsFragment[];
title?: string; title?: string;
onSelect: (id: string) => void; onSelect: (id: string) => void;
onCellClick: OnCellClickHandler; onCellClick: OnCellClickHandler;
activeMarketId?: string | null;
headers?: Column[]; headers?: Column[];
tableColumns?: (market: Market, openVolume?: string) => Column[]; tableColumns?: (market: Market, openVolume?: string) => Column[];
}) => { }) => {
@ -112,7 +116,7 @@ export const SelectAllMarketsTableBody = ({
<SelectMarketTableRow <SelectMarketTableRow
marketId={market.id} marketId={market.id}
key={i} key={i}
detailed={true} detailed
onSelect={onSelect} onSelect={onSelect}
columns={tableColumns( columns={tableColumns(
market, market,
@ -143,23 +147,35 @@ export const SelectMarketPopover = ({
onSelect: (id: string) => void; onSelect: (id: string) => void;
onCellClick: OnCellClickHandler; onCellClick: OnCellClickHandler;
}) => { }) => {
const { activeMarketId } = useGlobalStore((store) => ({
activeMarketId: store.marketId,
}));
const triggerClasses = const triggerClasses =
'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-2 whitespace-nowrap hover:text-neutral-500 dark:hover:text-neutral-300 mt-1'; 'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-2 whitespace-nowrap hover:text-neutral-500 dark:hover:text-neutral-300 mt-1';
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const { data, loading: marketsLoading } = useMarketList(); const {
data,
loading: marketsLoading,
reload: marketListReload,
} = useMarketList();
const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]); const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]);
const { data: party, loading: positionsLoading } = useDataProvider({ const {
data: party,
loading: positionsLoading,
reload,
} = useDataProvider({
dataProvider: positionsDataProvider, dataProvider: positionsDataProvider,
skipUpdates: true,
variables, variables,
skip: !pubKey, skip: !pubKey,
}); });
const onSelectMarket = useCallback(
const onSelectMarket = (marketId: string) => { (marketId: string) => {
onSelect(marketId); onSelect(marketId);
setOpen(false); setOpen(false);
}; },
[onSelect]
);
const iconClass = open ? 'rotate-180' : ''; const iconClass = open ? 'rotate-180' : '';
const markets = useMemo( const markets = useMemo(
@ -172,6 +188,13 @@ export const SelectMarketPopover = ({
[data, party] [data, party]
); );
useEffect(() => {
if (open) {
reload();
marketListReload();
}
}, [open, marketListReload, reload]);
return ( return (
<Popover <Popover
open={open} open={open}
@ -210,7 +233,8 @@ export const SelectMarketPopover = ({
market, market,
onSelectMarket, onSelectMarket,
openVolume, openVolume,
onCellClick onCellClick,
activeMarketId
) )
} }
/> />
@ -221,6 +245,7 @@ export const SelectMarketPopover = ({
markets={data} markets={data}
onSelect={onSelectMarket} onSelect={onSelectMarket}
onCellClick={onCellClick} onCellClick={onCellClick}
activeMarketId={activeMarketId}
/> />
</table> </table>
)} )}

View File

@ -5,7 +5,6 @@ import { LedgerTable } from './ledger-table';
// '3ac37999796c2be3546e0c1d87daa8ec7e99d8c423969be44c2f63256c415004' // '3ac37999796c2be3546e0c1d87daa8ec7e99d8c423969be44c2f63256c415004'
type LedgerManagerProps = { partyId: string }; type LedgerManagerProps = { partyId: string };
export const LedgerManager = ({ partyId }: LedgerManagerProps) => { export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
console.log('partyId', partyId);
const { data, error, loading } = useLedgerEntriesDataProvider(partyId); const { data, error, loading } = useLedgerEntriesDataProvider(partyId);
return ( return (

View File

@ -98,15 +98,15 @@ export const useMarketList = () => {
interval: Schema.Interval.INTERVAL_I1H, interval: Schema.Interval.INTERVAL_I1H,
}; };
}, [yesterday]); }, [yesterday]);
const { data, loading, error } = useDataProvider({ const { data, loading, error, reload } = useDataProvider({
dataProvider: marketListProvider, dataProvider: marketListProvider,
variables, variables,
skipUpdates: true,
}); });
return { return {
data, data,
loading, loading,
error, error,
reload,
}; };
}; };