prevent positions table if not party id provided, handle no data in async renderer

This commit is contained in:
Matthew Russell 2022-03-29 17:01:34 -07:00
parent 3394050f76
commit 858bd372d2
5 changed files with 82 additions and 76 deletions

View File

@ -1,69 +1,17 @@
import { useRef, useCallback, useMemo } from 'react';
import { produce } from 'immer';
import merge from 'lodash/merge';
import { useRouter } from 'next/router';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { PositionSubscribe_positions } from './__generated__/PositionSubscribe';
import { Positions_party_positions } from './__generated__/Positions';
import type { AgGridReact } from 'ag-grid-react';
import PositionsTable, { getRowNodeId } from './positions-table';
import { positionsDataProvider } from './positions-data-provider';
import { PositionsManager } from './positions-manager';
export const PositionsContainer = () => {
const { pathname, push } = useRouter();
const gridRef = useRef<AgGridReact | null>(null);
const { keypair } = useVegaWallet();
const variables = useMemo(() => ({ partyId: keypair?.pub }), [keypair]);
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<Positions_party_positions>(
rowNode.data,
(draft: Positions_party_positions) => {
merge(draft, delta);
}
);
if (updatedData !== rowNode.data) {
update.push(updatedData);
}
} 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, variables);
return (
<AsyncRenderer loading={loading} error={error} data={data}>
{(data) => (
<PositionsTable
ref={gridRef}
data={data}
onRowClicked={(id) =>
push(`${pathname}/${id}?portfolio=orders&trade=orderbook`)
}
/>
)}
</AsyncRenderer>
);
if (!keypair) {
return (
<Splash>
<p>Please connect Vega wallet</p>
</Splash>
);
}
return <PositionsManager partyId={keypair.pub} />;
};

View File

@ -0,0 +1,61 @@
import { useRef, useCallback, useMemo } from 'react';
import { produce } from 'immer';
import merge from 'lodash/merge';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { PositionSubscribe_positions } from './__generated__/PositionSubscribe';
import { Positions_party_positions } from './__generated__/Positions';
import type { AgGridReact } from 'ag-grid-react';
import PositionsTable, { getRowNodeId } from './positions-table';
import { positionsDataProvider } from './positions-data-provider';
interface PositionsManagerProps {
partyId: string;
}
export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
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<Positions_party_positions>(
rowNode.data,
(draft: Positions_party_positions) => {
merge(draft, delta);
}
);
if (updatedData !== rowNode.data) {
update.push(updatedData);
}
} 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, variables);
return (
<AsyncRenderer loading={loading} error={error} data={data}>
{(data) => <PositionsTable ref={gridRef} data={data} />}
</AsyncRenderer>
);
};

View File

@ -54,19 +54,16 @@ const singleRow: Positions_party_positions = {
__typename: 'Position',
};
const singleRowData = [singleRow];
const onRowClicked = jest.fn;
test('should render successfully', async () => {
await act(async () => {
const { baseElement } = render(
<PositionsTable data={[]} onRowClicked={onRowClicked} />
);
const { baseElement } = render(<PositionsTable data={[]} />);
expect(baseElement).toBeTruthy();
});
});
test('Render correct columns', async () => {
await act(async () => {
render(<PositionsTable data={singleRowData} onRowClicked={onRowClicked} />);
render(<PositionsTable data={singleRowData} />);
});
const headers = screen.getAllByRole('columnheader');
@ -82,7 +79,7 @@ test('Render correct columns', async () => {
test('Correct formatting applied', async () => {
await act(async () => {
render(<PositionsTable data={singleRowData} onRowClicked={onRowClicked} />);
render(<PositionsTable data={singleRowData} />);
});
const cells = screen.getAllByRole('gridcell');
const expectedValues = [

View File

@ -15,7 +15,6 @@ import { MarketTradingMode } from '@vegaprotocol/types';
interface PositionsTableProps {
data: Positions_party_positions[] | null;
onRowClicked: (marketId: string) => void;
}
export const getRowNodeId = (data: { market: { id: string } }) =>
@ -47,7 +46,7 @@ interface PositionsTableValueFormatterParams extends ValueFormatterParams {
}
export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
({ data, onRowClicked }, ref) => {
({ data }, ref) => {
const sortedData = useMemo(() => {
return compact(data).sort(sortByName);
}, [data]);
@ -62,9 +61,6 @@ export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
flex: 1,
resizable: true,
}}
onRowClicked={({ data }: { data: Positions_party_positions }) =>
onRowClicked(getRowNodeId(data))
}
components={{ PriceCell }}
>
<AgGridColumn

View File

@ -19,9 +19,13 @@ export function AsyncRenderer<T = any>({
return <Splash>Something went wrong: {error.message}</Splash>;
}
if (loading || !data) {
if (loading) {
return <Splash>Loading...</Splash>;
}
if (!data) {
return <Splash>No data</Splash>;
}
return <>{children(data)}</>;
}