feat(trading): add liquidity provision link to orders table (#3432)
This commit is contained in:
parent
2346b2f1a0
commit
045dace274
@ -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 ? (
|
||||
<ResizableGrid proportionalLayout minSize={200}>
|
||||
@ -94,6 +98,7 @@ const MarketBottomPanel = memo(
|
||||
<TradingViews.Orders
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
onOrderTypeClick={onOrderTypeClick}
|
||||
enforceBottomPlaceholder
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
@ -150,6 +155,7 @@ const MarketBottomPanel = memo(
|
||||
<TradingViews.Orders
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
onOrderTypeClick={onOrderTypeClick}
|
||||
enforceBottomPlaceholder
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
@ -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<TradingView>('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}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -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 = () => {
|
||||
</Tab>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<VegaWalletContainer>
|
||||
<OrderListContainer onMarketClick={onMarketClick} />
|
||||
<OrderListContainer
|
||||
onMarketClick={onMarketClick}
|
||||
onOrderTypeClick={onOrderTypeClick}
|
||||
/>
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
|
@ -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]
|
||||
);
|
||||
};
|
||||
|
@ -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: <LazyLiquidity />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <LazyLiquidity />,
|
||||
},
|
||||
{
|
||||
path: ':marketId',
|
||||
element: <LazyLiquidity />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.PORTFOLIO,
|
||||
|
@ -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';
|
||||
|
52
libs/datagrid/src/lib/cells/order-type-cell.tsx
Normal file
52
libs/datagrid/src/lib/cells/order-type-cell.tsx
Normal file
@ -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<HTMLButtonElement>) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
if (onClick) {
|
||||
onClick(id, ev.metaKey || ev.ctrlKey);
|
||||
}
|
||||
},
|
||||
[id, onClick]
|
||||
);
|
||||
if (!order) return null;
|
||||
return order?.liquidityProvision ? (
|
||||
<button onClick={handleOnClick} tabIndex={0} className="underline">
|
||||
{label}
|
||||
</button>
|
||||
) : (
|
||||
<span>{label}</span>
|
||||
);
|
||||
};
|
@ -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}
|
||||
/>
|
||||
|
@ -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
|
||||
|
@ -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<AgGridReact, OrderListTableProps>(
|
||||
({ cancel, setEditOrder, onMarketClick, ...props }, ref) => {
|
||||
(
|
||||
{ cancel, setEditOrder, onMarketClick, onOrderTypeClick, ...props },
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<AgGrid
|
||||
ref={ref}
|
||||
@ -51,7 +56,7 @@ export const OrderListTable = memo(
|
||||
height: '100%',
|
||||
}}
|
||||
getRowId={({ data }) => data.id}
|
||||
components={{ MarketNameCell }}
|
||||
components={{ MarketNameCell, OrderTypeCell }}
|
||||
{...props}
|
||||
>
|
||||
<AgGridColumn
|
||||
@ -103,17 +108,9 @@ export const OrderListTable = memo(
|
||||
filterParams={{
|
||||
set: Schema.OrderTypeMapping,
|
||||
}}
|
||||
valueFormatter={({
|
||||
data: order,
|
||||
value,
|
||||
}: VegaValueFormatterParams<Order, 'type'>) => {
|
||||
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}
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user