fix(#2345): positions table link to markets (#2652)

This commit is contained in:
m.ray 2023-01-19 16:53:10 -05:00 committed by GitHub
parent 805e8fbee7
commit e4ada295e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 24 deletions

View File

@ -26,6 +26,8 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
import { TradeMarketHeader } from './trade-market-header'; 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 { Links, Routes } from '../../pages/client-router';
type MarketDependantView = type MarketDependantView =
| typeof CandlesChartContainer | typeof CandlesChartContainer
@ -72,6 +74,12 @@ const MainGrid = ({
marketId: string; marketId: string;
onSelect?: (marketId: string) => void; onSelect?: (marketId: string) => void;
}) => { }) => {
const navigate = useNavigate();
const onMarketClick = (marketId: string) => {
navigate(Links[Routes.MARKET](marketId), {
replace: true,
});
};
return ( return (
<ResizableGrid vertical> <ResizableGrid vertical>
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}> <ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
@ -143,17 +151,23 @@ const MainGrid = ({
<Tabs> <Tabs>
<Tab id="positions" name={t('Positions')}> <Tab id="positions" name={t('Positions')}>
<VegaWalletContainer> <VegaWalletContainer>
<TradingViews.Positions /> <TradingViews.Positions onMarketClick={onMarketClick} />
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="orders" name={t('Orders')}> <Tab id="orders" name={t('Orders')}>
<VegaWalletContainer> <VegaWalletContainer>
<TradingViews.Orders marketId={marketId} /> <TradingViews.Orders
marketId={marketId}
onMarketClick={onMarketClick}
/>
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="fills" name={t('Fills')}> <Tab id="fills" name={t('Fills')}>
<VegaWalletContainer> <VegaWalletContainer>
<TradingViews.Fills marketId={marketId} /> <TradingViews.Fills
marketId={marketId}
onMarketClick={onMarketClick}
/>
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="accounts" name={t('Collateral')}> <Tab id="accounts" name={t('Collateral')}>
@ -195,15 +209,16 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
interface TradePanelsProps { interface TradePanelsProps {
market: SingleMarketFieldsFragment | null; market: SingleMarketFieldsFragment | null;
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
onMarketClick?: (marketId: string) => void;
} }
export const TradePanels = ({ market, onSelect }: TradePanelsProps) => { export const TradePanels = ({ market, onSelect }: TradePanelsProps) => {
const [view, setView] = useState<TradingView>('Candles'); const [view, setView] = useState<TradingView>('Candles');
const renderView = () => { const renderView = () => {
const Component = memo<{ const Component = memo<{
marketId: string; marketId: string;
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
onMarketClick?: (marketId: string) => void;
}>(TradingViews[view]); }>(TradingViews[view]);
if (!Component) { if (!Component) {

View File

@ -14,16 +14,26 @@ 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 { 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) => {
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 (
<div className={wrapperClasses}> <div className={wrapperClasses}>
@ -38,17 +48,17 @@ export const Portfolio = () => {
</Tab> </Tab>
<Tab id="positions" name={t('Positions')}> <Tab id="positions" name={t('Positions')}>
<VegaWalletContainer> <VegaWalletContainer>
<PositionsContainer /> <PositionsContainer onMarketClick={onMarketClick} />
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="orders" name={t('Orders')}> <Tab id="orders" name={t('Orders')}>
<VegaWalletContainer> <VegaWalletContainer>
<OrderListContainer /> <OrderListContainer onMarketClick={onMarketClick} />
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="fills" name={t('Fills')}> <Tab id="fills" name={t('Fills')}>
<VegaWalletContainer> <VegaWalletContainer>
<FillsContainer /> <FillsContainer onMarketClick={onMarketClick} />
</VegaWalletContainer> </VegaWalletContainer>
</Tab> </Tab>
<Tab id="ledger-entries" name={t('Ledger entries')}> <Tab id="ledger-entries" name={t('Ledger entries')}>

View File

@ -3,7 +3,13 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { FillsManager } from './fills-manager'; import { FillsManager } from './fills-manager';
export const FillsContainer = ({ marketId }: { marketId?: string }) => { export const FillsContainer = ({
marketId,
onMarketClick,
}: {
marketId?: string;
onMarketClick?: (marketId: string) => void;
}) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
if (!pubKey) { if (!pubKey) {
@ -14,5 +20,11 @@ export const FillsContainer = ({ marketId }: { marketId?: string }) => {
); );
} }
return <FillsManager partyId={pubKey} marketId={marketId} />; return (
<FillsManager
partyId={pubKey}
marketId={marketId}
onMarketClick={onMarketClick}
/>
);
}; };

View File

@ -9,9 +9,14 @@ import { useFillsList } from './use-fills-list';
interface FillsManagerProps { interface FillsManagerProps {
partyId: string; partyId: string;
marketId?: string; marketId?: string;
onMarketClick?: (marketId: string) => void;
} }
export const FillsManager = ({ partyId, marketId }: FillsManagerProps) => { export const FillsManager = ({
partyId,
marketId,
onMarketClick,
}: FillsManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true); const scrolledToTop = useRef(true);
const { data, error, loading, addNewRows, getRows } = useFillsList({ const { data, error, loading, addNewRows, getRows } = useFillsList({
@ -41,6 +46,7 @@ export const FillsManager = ({ partyId, marketId }: FillsManagerProps) => {
onBodyScrollEnd={onBodyScrollEnd} onBodyScrollEnd={onBodyScrollEnd}
onBodyScroll={onBodyScroll} onBodyScroll={onBodyScroll}
noRowsOverlayComponent={() => null} noRowsOverlayComponent={() => null}
onMarketClick={onMarketClick}
/> />
<div className="pointer-events-none absolute inset-0"> <div className="pointer-events-none absolute inset-0">
<AsyncRenderer <AsyncRenderer

View File

@ -16,7 +16,11 @@ import {
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
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 type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit'; import type {
VegaICellRendererParams,
VegaValueFormatterParams,
} from '@vegaprotocol/ui-toolkit';
import { Link } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit'; import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { forwardRef } from 'react'; import { forwardRef } from 'react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
@ -24,10 +28,11 @@ import type { Trade } from './fills-data-provider';
export type Props = (AgGridReactProps | AgReactUiProps) & { export type Props = (AgGridReactProps | AgReactUiProps) & {
partyId: string; partyId: string;
onMarketClick?: (marketId: string) => void;
}; };
export const FillsTable = forwardRef<AgGridReact, Props>( export const FillsTable = forwardRef<AgGridReact, Props>(
({ partyId, ...props }, ref) => { ({ partyId, onMarketClick, ...props }, ref) => {
return ( return (
<AgGrid <AgGrid
ref={ref} ref={ref}
@ -42,6 +47,25 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
<AgGridColumn <AgGridColumn
headerName={t('Market')} headerName={t('Market')}
field="market.tradableInstrument.instrument.name" field="market.tradableInstrument.instrument.name"
cellRenderer={({
value,
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')}

View File

@ -3,12 +3,24 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { OrderListManager } from './order-list-manager'; import { OrderListManager } from './order-list-manager';
export const OrderListContainer = ({ marketId }: { marketId?: string }) => { export const OrderListContainer = ({
marketId,
onMarketClick,
}: {
marketId?: string;
onMarketClick?: (marketId: string) => void;
}) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
if (!pubKey) { if (!pubKey) {
return <Splash>{t('Please connect Vega wallet')}</Splash>; return <Splash>{t('Please connect Vega wallet')}</Splash>;
} }
return <OrderListManager partyId={pubKey} marketId={marketId} />; return (
<OrderListManager
partyId={pubKey}
marketId={marketId}
onMarketClick={onMarketClick}
/>
);
}; };

View File

@ -30,6 +30,7 @@ import type { Order } from '../order-data-provider';
export interface OrderListManagerProps { export interface OrderListManagerProps {
partyId: string; partyId: string;
marketId?: string; marketId?: string;
onMarketClick?: (marketId: string) => void;
} }
export const TransactionComplete = ({ export const TransactionComplete = ({
@ -70,6 +71,7 @@ export const TransactionComplete = ({
export const OrderListManager = ({ export const OrderListManager = ({
partyId, partyId,
marketId, marketId,
onMarketClick,
}: OrderListManagerProps) => { }: OrderListManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true); const scrolledToTop = useRef(true);
@ -143,6 +145,7 @@ export const OrderListManager = ({
}); });
}} }}
setEditOrder={setEditOrder} setEditOrder={setEditOrder}
onMarketClick={onMarketClick}
/> />
<div className="pointer-events-none absolute inset-0"> <div className="pointer-events-none absolute inset-0">
<AsyncRenderer <AsyncRenderer

View File

@ -31,10 +31,11 @@ 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;
}; };
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>( export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
({ cancel, setEditOrder, ...props }, ref) => { ({ cancel, setEditOrder, onMarketClick, ...props }, ref) => {
return ( return (
<AgGrid <AgGrid
ref={ref} ref={ref}
@ -58,8 +59,14 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
Order, Order,
'market.tradableInstrument.instrument.code' 'market.tradableInstrument.instrument.code'
>) => >) =>
data?.market?.id ? ( onMarketClick ? (
<Link href={`/#/markets/${data?.market?.id}`}>{value}</Link> <Link
onClick={() =>
data?.market?.id && onMarketClick(data?.market?.id)
}
>
{value}
</Link>
) : ( ) : (
value value
) )

View File

@ -3,7 +3,11 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { PositionsManager } from './positions-manager'; import { PositionsManager } from './positions-manager';
export const PositionsContainer = () => { export const PositionsContainer = ({
onMarketClick,
}: {
onMarketClick?: (marketId: string) => void;
}) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
if (!pubKey) { if (!pubKey) {
@ -13,6 +17,5 @@ export const PositionsContainer = () => {
</Splash> </Splash>
); );
} }
return <PositionsManager partyId={pubKey} onMarketClick={onMarketClick} />;
return <PositionsManager partyId={pubKey} />;
}; };

View File

@ -8,9 +8,13 @@ import { t } from '@vegaprotocol/react-helpers';
interface PositionsManagerProps { interface PositionsManagerProps {
partyId: string; partyId: string;
onMarketClick?: (marketId: string) => void;
} }
export const PositionsManager = ({ partyId }: PositionsManagerProps) => { export const PositionsManager = ({
partyId,
onMarketClick,
}: PositionsManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const { data, error, loading, getRows } = usePositionsData(partyId, gridRef); const { data, error, loading, getRows } = usePositionsData(partyId, gridRef);
const create = useVegaTransactionStore((store) => store.create); const create = useVegaTransactionStore((store) => store.create);
@ -21,6 +25,7 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
rowModelType="infinite" rowModelType="infinite"
ref={gridRef} ref={gridRef}
datasource={{ getRows }} datasource={{ getRows }}
onMarketClick={onMarketClick}
onClose={({ marketId, openVolume }) => onClose={({ marketId, openVolume }) =>
create({ create({
batchMarketInstructions: { batchMarketInstructions: {

View File

@ -20,7 +20,7 @@ import {
DateRangeFilter, DateRangeFilter,
addDecimalsFormatNumber, addDecimalsFormatNumber,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit'; import { AgGridDynamic as AgGrid, Link } from '@vegaprotocol/ui-toolkit';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import type { Position } from './positions-data-providers'; import type { Position } from './positions-data-providers';
@ -31,6 +31,7 @@ import type { VegaICellRendererParams } from '@vegaprotocol/ui-toolkit';
interface Props extends TypedDataAgGrid<Position> { interface Props extends TypedDataAgGrid<Position> {
onClose?: (data: Position) => void; onClose?: (data: Position) => void;
onMarketClick?: (id: string) => void;
style?: CSSProperties; style?: CSSProperties;
} }
@ -66,7 +67,7 @@ export const AmountCell = ({ valueFormatted }: AmountCellProps) => {
AmountCell.displayName = 'AmountCell'; AmountCell.displayName = 'AmountCell';
export const PositionsTable = forwardRef<AgGridReact, Props>( export const PositionsTable = forwardRef<AgGridReact, Props>(
({ onClose, ...props }, ref) => { ({ onClose, onMarketClick, ...props }, ref) => {
return ( return (
<AgGrid <AgGrid
style={{ width: '100%', height: '100%' }} style={{ width: '100%', height: '100%' }}
@ -85,7 +86,24 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
components={{ AmountCell, PriceFlashCell, ProgressBarCell }} components={{ AmountCell, PriceFlashCell, ProgressBarCell }}
{...props} {...props}
> >
<AgGridColumn headerName={t('Market')} field="marketName" /> <AgGridColumn
headerName={t('Market')}
field="marketName"
cellRenderer={({
value,
data,
}: VegaICellRendererParams<Position, 'marketName'>) =>
onMarketClick ? (
<Link
onClick={() => data?.marketId && onMarketClick(data?.marketId)}
>
{value}
</Link>
) : (
value
)
}
/>
<AgGridColumn <AgGridColumn
headerName={t('Notional')} headerName={t('Notional')}
headerTooltip={t('Mark price x open volume.')} headerTooltip={t('Mark price x open volume.')}