From 045dace2749ce1a8dcf4c82be4f20a39a59a1e09 Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Tue, 18 Apr 2023 08:55:11 -0400 Subject: [PATCH] feat(trading): add liquidity provision link to orders table (#3432) --- .../client-pages/market/trade-grid.tsx | 15 +++++- .../client-pages/portfolio/portfolio.tsx | 11 +++- .../lib/hooks/use-market-click-handler.ts | 18 +++++++ apps/trading/pages/client-router.tsx | 18 +++++-- libs/datagrid/src/index.ts | 1 + .../src/lib/cells/order-type-cell.tsx | 52 +++++++++++++++++++ .../lib/components/order-list-container.tsx | 3 ++ .../order-list-manager/order-list-manager.tsx | 3 ++ .../lib/components/order-list/order-list.tsx | 23 ++++---- 9 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 libs/datagrid/src/lib/cells/order-type-cell.tsx diff --git a/apps/trading/client-pages/market/trade-grid.tsx b/apps/trading/client-pages/market/trade-grid.tsx index 580fb6518..7fc750c27 100644 --- a/apps/trading/client-pages/market/trade-grid.tsx +++ b/apps/trading/client-pages/market/trade-grid.tsx @@ -29,7 +29,10 @@ import { LiquidityContainer } from '../liquidity/liquidity'; import { useNavigate } from 'react-router-dom'; import type { PinnedAsset } from '@vegaprotocol/accounts'; import { useScreenDimensions } from '@vegaprotocol/react-helpers'; -import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler'; +import { + useMarketClickHandler, + useMarketLiquidityClickHandler, +} from '../../lib/hooks/use-market-click-handler'; type MarketDependantView = | typeof CandlesChartContainer @@ -79,6 +82,7 @@ const MarketBottomPanel = memo( ({ marketId, pinnedAsset }: BottomPanelProps) => { const { screenSize } = useScreenDimensions(); const onMarketClick = useMarketClickHandler(true); + const onOrderTypeClick = useMarketLiquidityClickHandler(true); return 'xxxl' === screenSize ? ( @@ -94,6 +98,7 @@ const MarketBottomPanel = memo( @@ -150,6 +155,7 @@ const MarketBottomPanel = memo( @@ -293,6 +299,7 @@ interface TradePanelsProps { market: Market | null; onSelect: (marketId: string, metaKey?: boolean) => void; onMarketClick?: (marketId: string) => void; + onOrderTypeClick?: (marketId: string) => void; onClickCollateral: () => void; pinnedAsset?: PinnedAsset; } @@ -303,12 +310,16 @@ export const TradePanels = ({ onClickCollateral, pinnedAsset, }: TradePanelsProps) => { + const onMarketClick = useMarketClickHandler(true); + const onOrderTypeClick = useMarketLiquidityClickHandler(true); + const [view, setView] = useState('Candles'); const renderView = () => { const Component = memo<{ marketId: string; onSelect: (marketId: string, metaKey?: boolean) => void; onMarketClick?: (marketId: string) => void; + onOrderTypeClick?: (marketId: string) => void; onClickCollateral: () => void; pinnedAsset?: PinnedAsset; }>(TradingViews[view]); @@ -325,6 +336,8 @@ export const TradePanels = ({ onSelect={onSelect} onClickCollateral={onClickCollateral} pinnedAsset={pinnedAsset} + onMarketClick={onMarketClick} + onOrderTypeClick={onOrderTypeClick} /> ); }; diff --git a/apps/trading/client-pages/portfolio/portfolio.tsx b/apps/trading/client-pages/portfolio/portfolio.tsx index a8e9bcf8c..efb93d449 100644 --- a/apps/trading/client-pages/portfolio/portfolio.tsx +++ b/apps/trading/client-pages/portfolio/portfolio.tsx @@ -19,7 +19,10 @@ import { usePageTitleStore } from '../../stores'; import { LedgerContainer } from '@vegaprotocol/ledger'; import { AccountsContainer } from '../../components/accounts-container'; import { AccountHistoryContainer } from './account-history-container'; -import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler'; +import { + useMarketClickHandler, + useMarketLiquidityClickHandler, +} from '../../lib/hooks/use-market-click-handler'; export const Portfolio = () => { const { updateTitle } = usePageTitleStore((store) => ({ @@ -31,6 +34,7 @@ export const Portfolio = () => { }, [updateTitle]); const onMarketClick = useMarketClickHandler(true); + const onOrderTypeClick = useMarketLiquidityClickHandler(true); const wrapperClasses = 'h-full max-h-full flex flex-col'; return ( @@ -54,7 +58,10 @@ export const Portfolio = () => { - + diff --git a/apps/trading/lib/hooks/use-market-click-handler.ts b/apps/trading/lib/hooks/use-market-click-handler.ts index 946a27889..23a51a3db 100644 --- a/apps/trading/lib/hooks/use-market-click-handler.ts +++ b/apps/trading/lib/hooks/use-market-click-handler.ts @@ -19,3 +19,21 @@ export const useMarketClickHandler = (replace = false) => { [navigate, marketId, replace, isMarketPage] ); }; + +export const useMarketLiquidityClickHandler = (replace = false) => { + const navigate = useNavigate(); + const { marketId } = useParams(); + const { pathname } = useLocation(); + const isLiquidityPage = pathname.match(/^\/liquidity\/(.+)/); + return useCallback( + (selectedId: string, metaKey?: boolean) => { + const link = Links[Routes.LIQUIDITY](selectedId); + if (metaKey) { + window.open(`/#${link}`, '_blank'); + } else if (selectedId !== marketId || !isLiquidityPage) { + navigate(link, { replace }); + } + }, + [navigate, marketId, replace, isLiquidityPage] + ); +}; diff --git a/apps/trading/pages/client-router.tsx b/apps/trading/pages/client-router.tsx index 8a569bfd7..e5a4659b6 100644 --- a/apps/trading/pages/client-router.tsx +++ b/apps/trading/pages/client-router.tsx @@ -31,7 +31,7 @@ export enum Routes { MARKET = '/markets', MARKETS = '/markets/all', PORTFOLIO = '/portfolio', - LIQUIDITY = 'liquidity/:marketId', + LIQUIDITY = '/liquidity', } type ConsoleLinks = { [r in Routes]: (...args: string[]) => string }; @@ -41,8 +41,10 @@ export const Links: ConsoleLinks = { marketId ? trimEnd(`${Routes.MARKET}/${marketId}`, '/') : Routes.MARKET, [Routes.MARKETS]: () => Routes.MARKETS, [Routes.PORTFOLIO]: () => Routes.PORTFOLIO, - [Routes.LIQUIDITY]: (marketId: string) => - Routes.LIQUIDITY.replace(':marketId', marketId), + [Routes.LIQUIDITY]: (marketId: string | null | undefined) => + marketId + ? trimEnd(`${Routes.LIQUIDITY}/${marketId}`, '/') + : Routes.LIQUIDITY, }; const routerConfig: RouteObject[] = [ @@ -70,6 +72,16 @@ const routerConfig: RouteObject[] = [ { path: Routes.LIQUIDITY, element: , + children: [ + { + index: true, + element: , + }, + { + path: ':marketId', + element: , + }, + ], }, { path: Routes.PORTFOLIO, diff --git a/libs/datagrid/src/index.ts b/libs/datagrid/src/index.ts index f84344412..7a827234a 100644 --- a/libs/datagrid/src/index.ts +++ b/libs/datagrid/src/index.ts @@ -10,6 +10,7 @@ export * from './lib/cells/price-flash-cell'; export * from './lib/cells/vol-cell'; export * from './lib/cells/centered-grid-cell'; export * from './lib/cells/market-name-cell'; +export * from './lib/cells/order-type-cell'; export * from './lib/filters/date-range-filter'; export * from './lib/filters/set-filter'; diff --git a/libs/datagrid/src/lib/cells/order-type-cell.tsx b/libs/datagrid/src/lib/cells/order-type-cell.tsx new file mode 100644 index 000000000..cb42b7884 --- /dev/null +++ b/libs/datagrid/src/lib/cells/order-type-cell.tsx @@ -0,0 +1,52 @@ +import type { MouseEvent } from 'react'; +import { useMemo } from 'react'; +import { useCallback } from 'react'; +import { t } from '@vegaprotocol/i18n'; +import * as Schema from '@vegaprotocol/types'; + +interface OrderTypeCellProps { + value?: Schema.OrderType; + data?: Schema.Order; + onClick?: (marketId: string, metaKey?: boolean) => void; +} + +export const OrderTypeCell = ({ + value, + data: order, + onClick, +}: OrderTypeCellProps) => { + const id = order ? order.market.id : ''; + + const label = useMemo(() => { + if (!order) { + return undefined; + } + if (!value) return '-'; + if (order?.peggedOrder) { + return t('Pegged'); + } + if (order?.liquidityProvision) { + return t('Liquidity provision'); + } + return Schema.OrderTypeMapping[value]; + }, [order, value]); + + const handleOnClick = useCallback( + (ev: MouseEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + if (onClick) { + onClick(id, ev.metaKey || ev.ctrlKey); + } + }, + [id, onClick] + ); + if (!order) return null; + return order?.liquidityProvision ? ( + + ) : ( + {label} + ); +}; diff --git a/libs/orders/src/lib/components/order-list-container.tsx b/libs/orders/src/lib/components/order-list-container.tsx index 86689da45..9620a6924 100644 --- a/libs/orders/src/lib/components/order-list-container.tsx +++ b/libs/orders/src/lib/components/order-list-container.tsx @@ -6,10 +6,12 @@ import { OrderListManager } from './order-list-manager'; export const OrderListContainer = ({ marketId, onMarketClick, + onOrderTypeClick, enforceBottomPlaceholder, }: { marketId?: string; onMarketClick?: (marketId: string, metaKey?: boolean) => void; + onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void; enforceBottomPlaceholder?: boolean; }) => { const { pubKey, isReadOnly } = useVegaWallet(); @@ -23,6 +25,7 @@ export const OrderListContainer = ({ partyId={pubKey} marketId={marketId} onMarketClick={onMarketClick} + onOrderTypeClick={onOrderTypeClick} isReadOnly={isReadOnly} enforceBottomPlaceholder={enforceBottomPlaceholder} /> diff --git a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx index f662a2b07..310664539 100644 --- a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx +++ b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx @@ -25,6 +25,7 @@ export interface OrderListManagerProps { partyId: string; marketId?: string; onMarketClick?: (marketId: string, metaKey?: boolean) => void; + onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void; isReadOnly: boolean; enforceBottomPlaceholder?: boolean; } @@ -52,6 +53,7 @@ export const OrderListManager = ({ partyId, marketId, onMarketClick, + onOrderTypeClick, isReadOnly, enforceBottomPlaceholder, }: OrderListManagerProps) => { @@ -165,6 +167,7 @@ export const OrderListManager = ({ cancel={cancel} setEditOrder={setEditOrder} onMarketClick={onMarketClick} + onOrderTypeClick={onOrderTypeClick} isReadOnly={isReadOnly} blockLoadDebounceMillis={100} suppressLoadingOverlay diff --git a/libs/orders/src/lib/components/order-list/order-list.tsx b/libs/orders/src/lib/components/order-list/order-list.tsx index 3d484e15d..30c22d4a5 100644 --- a/libs/orders/src/lib/components/order-list/order-list.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.tsx @@ -16,6 +16,7 @@ import { negativeClassNames, positiveClassNames, MarketNameCell, + OrderTypeCell, } from '@vegaprotocol/datagrid'; import type { TypedDataAgGrid, @@ -31,12 +32,16 @@ export type OrderListTableProps = OrderListProps & { cancel: (order: Order) => void; setEditOrder: (order: Order) => void; onMarketClick?: (marketId: string, metaKey?: boolean) => void; + onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void; isReadOnly: boolean; }; export const OrderListTable = memo( forwardRef( - ({ cancel, setEditOrder, onMarketClick, ...props }, ref) => { + ( + { cancel, setEditOrder, onMarketClick, onOrderTypeClick, ...props }, + ref + ) => { return ( data.id} - components={{ MarketNameCell }} + components={{ MarketNameCell, OrderTypeCell }} {...props} > ) => { - if (!order) { - return undefined; - } - if (!value) return '-'; - if (order?.peggedOrder) return t('Pegged'); - if (order?.liquidityProvision) return t('Liquidity provision'); - return Schema.OrderTypeMapping[value]; + cellRenderer="OrderTypeCell" + cellRendererParams={{ + onClick: onOrderTypeClick, }} minWidth={80} />