[#128] add <Positions/> component to trade-grid, add useDataProvider hook
This commit is contained in:
parent
7f1632d44d
commit
aec5d54820
66
apps/trading/pages/markets/positions.tsx
Normal file
66
apps/trading/pages/markets/positions.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import { useRef, useCallback } from 'react';
|
||||
import { produce } from 'immer';
|
||||
import assign from 'assign-deep';
|
||||
import { useRouter } from 'next/router';
|
||||
import { AsyncRenderer } from '../../components/async-renderer';
|
||||
import { PositionsTable, getRowNodeId } from '@vegaprotocol/positions';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
positions_party_positions,
|
||||
positionSubscribe_positions,
|
||||
positionsDataProvider,
|
||||
} from '@vegaprotocol/graphql';
|
||||
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
|
||||
export const Positions = () => {
|
||||
const { pathname, push } = useRouter();
|
||||
const gridRef = useRef<AgGridReact>();
|
||||
const update = useCallback(
|
||||
(delta: positionSubscribe_positions) => {
|
||||
const update: positions_party_positions[] = [];
|
||||
const add: positions_party_positions[] = [];
|
||||
if (!gridRef.current) {
|
||||
return false;
|
||||
}
|
||||
const rowNode = gridRef.current.api.getRowNode(getRowNodeId(delta));
|
||||
if (rowNode) {
|
||||
const updatedData = produce(
|
||||
rowNode.data,
|
||||
(draft: positions_party_positions) => assign(draft, delta)
|
||||
);
|
||||
if (updatedData !== rowNode.data) {
|
||||
update.push(delta);
|
||||
}
|
||||
} else {
|
||||
add.push(delta);
|
||||
}
|
||||
if (update.length || add.length) {
|
||||
gridRef.current.api.applyTransactionAsync({
|
||||
update,
|
||||
add,
|
||||
addIndex: 0,
|
||||
});
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
positions_party_positions,
|
||||
positionSubscribe_positions
|
||||
>(positionsDataProvider, update);
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
{(data) => (
|
||||
<PositionsTable
|
||||
ref={gridRef}
|
||||
data={data}
|
||||
onRowClicked={(id) =>
|
||||
push(`${pathname}/${id}?portfolio=orders&trade=orderbook`)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
@ -6,6 +6,7 @@ import { GridTab, GridTabs } from './grid-tabs';
|
||||
import { DealTicketContainer } from '../../components/deal-ticket-container';
|
||||
import { OrderListContainer } from '../..//components/order-list-container';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { Positions } from './positions';
|
||||
|
||||
const Chart = () => (
|
||||
<Splash>
|
||||
@ -17,11 +18,6 @@ const Orderbook = () => (
|
||||
<p>Orderbook</p>
|
||||
</Splash>
|
||||
);
|
||||
const Positions = () => (
|
||||
<Splash>
|
||||
<p>Positions</p>
|
||||
</Splash>
|
||||
);
|
||||
const Collateral = () => (
|
||||
<Splash>
|
||||
<p>Collateral</p>
|
||||
|
@ -7,19 +7,19 @@ import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
|
||||
interface MarketListTableProps {
|
||||
markets: Markets_markets[] | null;
|
||||
data: Markets_markets[];
|
||||
onRowClicked: (marketId: string) => void;
|
||||
}
|
||||
|
||||
export const getRowNodeId = (data: { id: string }) => data.id;
|
||||
|
||||
export const MarketListTable = forwardRef<AgGridReact, MarketListTableProps>(
|
||||
({ markets, onRowClicked }, ref) => {
|
||||
({ data, onRowClicked }, ref) => {
|
||||
return (
|
||||
<AgGrid
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
overlayNoRowsTemplate="No markets"
|
||||
rowData={markets}
|
||||
rowData={data}
|
||||
getRowNodeId={getRowNodeId}
|
||||
ref={ref}
|
||||
defaultColDef={{
|
||||
|
3
libs/react-helpers/src/hooks/index.ts
Normal file
3
libs/react-helpers/src/hooks/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './use-apply-grid-transaction';
|
||||
export * from './use-data-provider';
|
||||
export * from './use-theme-switcher';
|
35
libs/react-helpers/src/hooks/use-data-provider.ts
Normal file
35
libs/react-helpers/src/hooks/use-data-provider.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import type { ApolloClient } from '@apollo/client';
|
||||
|
||||
export function useDataProvider<Data, Delta>(
|
||||
dataProvider: (
|
||||
client: ApolloClient<object>,
|
||||
callback: (arg: {
|
||||
data: Data[] | null;
|
||||
error?: Error;
|
||||
loading: boolean;
|
||||
delta?: Delta;
|
||||
}) => void
|
||||
) => () => void,
|
||||
update: (delta: Delta) => boolean = () => false
|
||||
) {
|
||||
const client = useApolloClient();
|
||||
const [data, setData] = useState<Data[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<Error | undefined>(undefined);
|
||||
const initialized = useRef<boolean>(false);
|
||||
useEffect(() => {
|
||||
return dataProvider(client, ({ data, error, loading, delta }) => {
|
||||
setError(error);
|
||||
setLoading(loading);
|
||||
if (!error && !loading) {
|
||||
if (!initialized.current || !delta || !update(delta)) {
|
||||
initialized.current = true;
|
||||
setData(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [client, initialized, dataProvider, update]);
|
||||
return { data, loading, error };
|
||||
}
|
@ -5,5 +5,4 @@ export * from './lib/format';
|
||||
export * from './lib/grid-cells';
|
||||
export * from './lib/storage';
|
||||
|
||||
export * from './hooks/use-apply-grid-transaction';
|
||||
export * from './hooks/use-theme-switcher';
|
||||
export * from './hooks';
|
||||
|
Loading…
Reference in New Issue
Block a user