Skip to content

Commit

Permalink
Merge branch 'feat/sort-columns' into alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
mguellsegarra committed Aug 28, 2024
2 parents 933e560 + 0965d90 commit bfaa036
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 23 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dependencies": {
"ag-grid-community": "^31.2.1",
"ag-grid-react": "^31.2.1",
"dequal": "^2.0.3",
"lodash.debounce": "^4.0.8",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
43 changes: 23 additions & 20 deletions src/components/InfiniteTable/InfiniteTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import { TableProps } from "@/types";
import { useDeepArrayMemo } from "@/hooks/useDeepArrayMemo";
import { HeaderCheckbox } from "./HeaderCheckbox";
import { useRowSelection } from "./useRowSelection";
import { useColumnState } from "./useColumnState";
import { areStatesEqual, useColumnState } from "./useColumnState";
import { CHECKBOX_COLUMN, STATUS_COLUMN } from "./columnStateHelper";

const DEBOUNCE_TIME = 50;
const DEFAULT_TOTAL_ROWS_VALUE = Number.MAX_SAFE_INTEGER;

export type InfiniteTableProps = Omit<
TableProps,
Expand All @@ -42,14 +43,14 @@ export type InfiniteTableProps = Omit<
startRow: number;
endRow: number;
sortFields?: Record<string, SortDirection>;
}) => Promise<any[]>;
}) => Promise<any[] | undefined>;
height?: number;
onColumnChanged?: (columnsState: ColumnState[]) => void;
onGetColumnsState?: () => ColumnState[] | undefined;
onGetFirstVisibleRowIndex?: () => number | undefined;
onChangeFirstVisibleRowIndex?: (index: number) => void;
onGetSelectedRowKeys?: () => any[] | undefined;
totalRows: number;
totalRows?: number;
allRowSelectedMode?: boolean;
onAllRowSelectedModeChange?: (allRowSelectedMode: boolean) => void;
footer?: React.ReactNode;
Expand Down Expand Up @@ -78,7 +79,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
onChangeFirstVisibleRowIndex,
onGetFirstVisibleRowIndex,
onGetSelectedRowKeys,
totalRows,
totalRows = DEFAULT_TOTAL_ROWS_VALUE,
onAllRowSelectedModeChange,
allRowSelectedMode: allRowSelectedModeProps,
footer,
Expand All @@ -92,7 +93,6 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
const firstTimeOnBodyScroll = useRef(true);
const allRowSelectedModeRef = useRef<boolean>(false);
const containerRef = useRef<HTMLDivElement>(null);
const columnChangeListenerReady = useRef(false);
const totalHeight = footer ? heightProps + footerHeight : heightProps;
const tableHeight = footer ? heightProps - footerHeight : heightProps;

Expand Down Expand Up @@ -128,7 +128,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
const columns = useDeepArrayMemo(columnsProps, "key");

const {
applyColumnState,
loadPersistedColumnState,
columnsPersistedStateRef,
applyAndUpdateNewState,
} = useColumnState({
Expand All @@ -141,16 +141,19 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(

const onColumnChanged = useCallback(() => {
const state = gridRef?.current?.api.getColumnState();
if (!columnChangeListenerReady.current) {
columnChangeListenerReady.current = true;
if (!state) {
return;
}
if (!state) {
if (areStatesEqual(state, columnsPersistedStateRef.current)) {
return;
}
applyAndUpdateNewState(state);
onColumnsChangedProps?.(state);
}, [applyAndUpdateNewState, onColumnsChangedProps]);
}, [
applyAndUpdateNewState,
columnsPersistedStateRef,
onColumnsChangedProps,
]);

const onColumnMoved = useCallback(() => {
onColumnChanged();
Expand All @@ -166,10 +169,6 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
[onColumnChanged],
);

const onSortChanged = useCallback(() => {
gridRef.current?.api?.purgeInfiniteCache();
}, []);

const getSortedFields = useCallback(():
| Record<string, SortDirection>
| undefined => {
Expand Down Expand Up @@ -217,7 +216,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
const storedState = columnsPersistedStateRef.current;
const storedStateKeys = storedState?.map((col: any) => col.colId);

const restOfColumns = columns.map((column) => ({
const restOfColumns: ColDef[] = columns.map((column) => ({
field: column.key,
sortable: column.isSortable,
headerName: column.title,
Expand All @@ -228,6 +227,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(

// restOfColumns should be sorted by the order of the storedState
storedState &&
storedStateKeys &&
restOfColumns.sort((a, b) => {
const aIndex = storedStateKeys.indexOf(a.field);
const bIndex = storedStateKeys.indexOf(b.field);
Expand Down Expand Up @@ -274,6 +274,10 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
endRow,
sortFields: getSortedFields(),
});
if (!data) {
params.failCallback();
return;
}
let lastRow = -1;
if (data.length < endRow - startRow) {
lastRow = startRow + data.length;
Expand Down Expand Up @@ -317,10 +321,8 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
}
}
gridRef.current?.api.hideOverlay();
applyColumnState();
},
[
applyColumnState,
getSortedFields,
hasStatusColumn,
onGetSelectedRowKeys,
Expand All @@ -333,11 +335,12 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(

const onGridReady = useCallback(
(params: GridReadyEvent) => {
loadPersistedColumnState();
params.api.setGridOption("datasource", {
getRows,
});
},
[getRows],
[getRows, loadPersistedColumnState],
);

const onRowDoubleClicked = useCallback(
Expand Down Expand Up @@ -397,7 +400,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
onDragStopped={onColumnMoved}
onColumnResized={onColumnResized}
rowModelType={"infinite"}
cacheBlockSize={20}
cacheBlockSize={200}
onSelectionChanged={onSelectionChangedDebounced}
cacheOverflowSize={2}
maxConcurrentDatasourceRequests={1}
Expand All @@ -408,7 +411,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
onBodyScroll={onBodyScroll}
blockLoadDebounceMillis={DEBOUNCE_TIME}
suppressDragLeaveHidesColumns={true}
onSortChanged={onSortChanged}
onSortChanged={onColumnChanged}
/>
</div>
{footer && <div style={{ height: footerHeight }}>{footer}</div>}
Expand Down
31 changes: 28 additions & 3 deletions src/components/InfiniteTable/useColumnState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "./columnStateHelper";
import { TableColumn } from "@/types";
import { useDeepCompareCallback } from "use-deep-compare";
import { dequal } from "dequal";

const DEBOUNCE_DELAY = 50;

Expand All @@ -25,7 +26,7 @@ export const useColumnState = ({
onGetColumnsState?: () => ColumnState[] | undefined;
}) => {
const firstTimeResized = useRef(false);
const columnsPersistedStateRef = useRef<any>();
const columnsPersistedStateRef = useRef<ColumnState[]>();

const columnsToIgnore = FIXED_COLUMNS_TO_IGNORE;
if (hasStatusColumn) {
Expand Down Expand Up @@ -92,7 +93,7 @@ export const useColumnState = ({
});
}, [columnsToIgnore, gridRef, remainingBlankSpace, runDeferredCallback]);

const applyColumnState = useDeepCompareCallback(() => {
const loadPersistedColumnState = useDeepCompareCallback(() => {
columnsPersistedStateRef.current = getPersistedColumnState({
actualColumnKeys: columns.map((column) => column.key),
persistedColumnState: onGetColumnsState?.(),
Expand All @@ -110,8 +111,32 @@ export const useColumnState = ({
}, [applyAutoFitState, applyPersistedState, columns, onGetColumnsState]);

return {
applyColumnState,
loadPersistedColumnState,
columnsPersistedStateRef,
applyAndUpdateNewState,
};
};

const removeNullsFromState = (state: ColumnState): Partial<ColumnState> => {
return Object.entries(state).reduce<Partial<ColumnState>>(
(acc, [key, value]) => {
if (value != null) {
acc[key as keyof ColumnState] = value;
}
return acc;
},
{},
);
};

export const areStatesEqual = (
a?: ColumnState[],
b?: ColumnState[],
): boolean => {
if (!a || !b) {
return false;
}
const cleanA = a.map(removeNullsFromState);
const cleanB = b.map(removeNullsFromState);
return dequal(cleanA, cleanB);
};

0 comments on commit bfaa036

Please sign in to comment.