feat: make storing grid sizes opt in

This commit is contained in:
Matthew Russell
2023-05-04 18:52:44 -07:00
parent 7030b3c9cf
commit 0dbd96ef1f
6 changed files with 85 additions and 116 deletions
@@ -91,7 +91,7 @@ export const Portfolio = () => {
<Tabs storageKey="console-portfolio-bottom">
<Tab id="collateral" name={t('Collateral')}>
<VegaWalletContainer>
<AccountsContainer id="portfolioCollateral" />
<AccountsContainer />
</VegaWalletContainer>
</Tab>
<Tab id="deposits" name={t('Deposits')}>
@@ -13,12 +13,10 @@ export const AccountsContainer = ({
pinnedAsset,
hideButtons,
noBottomPlaceholder,
id,
}: {
pinnedAsset?: PinnedAsset;
hideButtons?: boolean;
noBottomPlaceholder?: boolean;
id?: string;
}) => {
const { pubKey, isReadOnly } = useVegaWallet();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
@@ -44,7 +42,6 @@ export const AccountsContainer = ({
return (
<div className="h-full relative">
<AccountManager
id={id}
partyId={pubKey}
onClickAsset={onClickAsset}
onClickWithdraw={openWithdrawalDialog}
@@ -19,7 +19,6 @@ interface AccountManagerProps {
isReadOnly: boolean;
pinnedAsset?: PinnedAsset;
noBottomPlaceholder?: boolean;
id?: string;
}
export const AccountManager = ({
@@ -30,7 +29,6 @@ export const AccountManager = ({
isReadOnly,
pinnedAsset,
noBottomPlaceholder,
id,
}: AccountManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
@@ -54,7 +52,6 @@ export const AccountManager = ({
return (
<div className="relative h-full">
<AccountTable
id={id}
ref={gridRef}
rowData={error ? [] : data}
onClickAsset={onClickAsset}
+11 -3
View File
@@ -1,4 +1,4 @@
import { forwardRef, useCallback, useMemo, useState } from 'react';
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react';
import {
addDecimalsFormatNumber,
isNumeric,
@@ -9,6 +9,7 @@ import type {
VegaICellRendererParams,
VegaValueFormatterParams,
} from '@vegaprotocol/datagrid';
import { useColumnSizes } from '@vegaprotocol/datagrid';
import {
Button,
ButtonLink,
@@ -105,6 +106,11 @@ export interface AccountTableProps extends AgGridReactProps {
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
const containerRef = useRef<HTMLDivElement | null>(null);
const { onGridReady, onColumnResized } = useColumnSizes({
id: 'accounts',
container: containerRef,
});
const [openBreakdown, setOpenBreakdown] = useState(false);
const [row, setRow] = useState<AccountFields>();
const pinnedAssetId = props.pinnedAsset?.id;
@@ -144,7 +150,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
);
return (
<>
<div className="w-full h-full" ref={containerRef}>
<AgGrid
{...props}
style={{ width: '100%', height: '100%' }}
@@ -155,6 +161,8 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
rowData={props.rowData?.filter(
(data) => data.asset.id !== pinnedAssetId
)}
onGridReady={onGridReady}
onColumnResized={onColumnResized}
defaultColDef={{
resizable: true,
tooltipComponent: TooltipCellComponent,
@@ -387,7 +395,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
/>
</div>
</Dialog>
</>
</div>
);
}
);
@@ -1,7 +1,7 @@
import React, { useCallback, useRef } from 'react';
import type { ReactNode } from 'react';
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import type { ColumnResizedEvent } from 'ag-grid-community';
import type { ColumnResizedEvent, GridReadyEvent } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { useColumnSizes } from './use-column-sizes';
@@ -19,35 +19,19 @@ export const AgGridThemed = ({
id?: string;
children?: ReactNode[];
}) => {
const containerRef = useRef<HTMLDivElement | null>(null);
const [setValues, reshapeChildren, reshapeProps] = useColumnSizes({
id,
container: containerRef,
});
const { theme } = useThemeSwitcher();
const defaultProps = {
rowHeight: 22,
headerHeight: 22,
enableCellTextSelection: true,
onColumnResized: useCallback(
(event: ColumnResizedEvent) => {
if (event.source === 'uiColumnDragged' && event.columns) {
setValues(event.columns);
}
},
[setValues]
),
};
children = reshapeChildren(children);
props = reshapeProps(props, children);
const wrapperClasses = classNames('vega-ag-grid', {
'ag-theme-balham': theme === 'light',
'ag-theme-balham-dark': theme === 'dark',
});
return (
<div className={wrapperClasses} style={style} ref={containerRef}>
<div className={wrapperClasses} style={style}>
<AgGridReact {...defaultProps} {...props} ref={gridRef}>
{children}
</AgGridReact>
@@ -1,7 +1,12 @@
import type { MutableRefObject, ReactElement } from 'react';
import { useCallback, useState } from 'react';
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import type { Column, ColDef } from 'ag-grid-community';
import type {
Column,
ColDef,
ColumnResizedEvent,
GridReadyEvent,
} from 'ag-grid-community';
import debounce from 'lodash/debounce';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
@@ -35,17 +40,7 @@ interface UseColumnSizesProps {
id?: string;
container?: MutableRefObject<HTMLDivElement | null>;
}
export const useColumnSizes = ({
id = '',
container,
}: UseColumnSizesProps): [
(columns: Column[]) => void,
(children?: ReactElement[]) => ReactElement[] | undefined,
(
props: AgGridReactProps | AgReactUiProps,
children?: ReactElement[]
) => AgGridReactProps | AgReactUiProps
] => {
export const useColumnSizes = ({ id = '', container }: UseColumnSizesProps) => {
const sizes = useColumnSizesStore((store) => store.sizes[id] || {});
const valueSetter = useColumnSizesStore((store) => store.valueSetter);
const getWidthOfAll = useCallback(
@@ -54,85 +49,73 @@ export const useColumnSizes = ({
0,
[container]
);
const recalculateSizes = useCallback(
(sizes: Record<string, number>) => {
const width = getWidthOfAll();
if (width && sizes['width'] && width !== sizes['width']) {
const oldWidth = sizes['width'];
const ratio = width / oldWidth;
return {
...Object.entries(sizes).reduce((agg, [key, value]) => {
agg[key] = value * ratio;
return agg;
}, {} as Record<string, number>),
width,
} as Record<string, number>;
}
return sizes;
},
[getWidthOfAll]
);
const [calculatedSizes, setCalculatedSizes] = useState(
recalculateSizes(sizes)
);
const onResize = useCallback(() => {
const width = getWidthOfAll();
if (width && sizes['width'] && width !== sizes['width']) {
setCalculatedSizes(recalculateSizes(sizes));
}
}, [getWidthOfAll, recalculateSizes, sizes]);
useResizeObserver(container?.current as Element, onResize);
// const recalculateSizes = useCallback(
// (sizes: Record<string, number>) => {
// const width = getWidthOfAll();
// if (width && sizes['width'] && width !== sizes['width']) {
// const oldWidth = sizes['width'];
// const ratio = width / oldWidth;
// return {
// ...Object.entries(sizes).reduce((agg, [key, value]) => {
// agg[key] = value * ratio;
// return agg;
// }, {} as Record<string, number>),
// width,
// } as Record<string, number>;
// }
// return sizes;
// },
// [getWidthOfAll]
// );
// const [calculatedSizes, setCalculatedSizes] = useState(
// recalculateSizes(sizes)
// );
// const onResize = useCallback(() => {
// const width = getWidthOfAll();
// if (width && sizes['width'] && width !== sizes['width']) {
// setCalculatedSizes(recalculateSizes(sizes));
// }
// }, [getWidthOfAll, recalculateSizes, sizes]);
// useResizeObserver(container?.current as Element, onResize);
// eslint-disable-next-line react-hooks/exhaustive-deps
const handleOnChange = useCallback(
debounce((columns: Column[]) => {
if (id && columns.length) {
const sizesObj = columns.reduce((aggr, column) => {
aggr[column.getColId()] = column.getActualWidth();
return aggr;
}, {} as Record<string, number>);
sizesObj['width'] = getWidthOfAll();
valueSetter(id, sizesObj);
const onColumnResized = useCallback(
(event: ColumnResizedEvent) => {
if (
event.finished &&
event.source === 'uiColumnDragged' &&
event.columns
) {
const colState = event.columnApi.getColumnState();
const store: { [colId: string]: number } = {};
colState.forEach((c) => {
if (c.width) {
store[c.colId] = c.width;
}
});
valueSetter(id, store);
}
}, COLUMNS_SET_DEBOUNCE_TIME),
},
[valueSetter, id]
);
const reshapeAgGridChildren = useCallback(
(children?: ReactElement[]) =>
id && children?.length && Object.keys(calculatedSizes).length
? children.map((child: ReactElement) => ({
...child,
props: {
...(child?.props ?? {}),
width:
(child?.props.colId && calculatedSizes[child?.props.colId]) ||
(child?.props.field && calculatedSizes[child?.props.field]) ||
undefined,
},
}))
: children,
[calculatedSizes, id]
const onGridReady = useCallback(
(event: GridReadyEvent) => {
console.log(event);
if (!Object.keys(sizes).length) {
event.columnApi.sizeColumnsToFit(getWidthOfAll());
} else {
const initialSizes = Object.entries(sizes).map(([key, newWidth]) => ({
key,
newWidth,
}));
event.columnApi.setColumnWidths(initialSizes);
}
},
[sizes, getWidthOfAll]
);
const reshapeAgGridProps = useCallback(
(props: AgGridReactProps | AgReactUiProps, children?: ReactElement[]) =>
id && props?.columnDefs && Object.keys(calculatedSizes).length
? ({
...props,
columnDefs: props.columnDefs.map((columnDef: ColDef) => ({
...columnDef,
width:
(columnDef.colId && calculatedSizes[columnDef.colId]) ||
(columnDef.field && calculatedSizes[columnDef.field]) ||
undefined,
})),
} as AgGridReactProps | AgReactUiProps)
: children?.length
? props
: ({
...props,
defaultColDef: { ...(props.defaultColDef || null), flex: 1 },
} as AgGridReactProps | AgReactUiProps),
[calculatedSizes, id]
);
return [handleOnChange, reshapeAgGridChildren, reshapeAgGridProps];
return {
onColumnResized,
onGridReady,
};
};