@deephaven/js-plugin-ag-grid
Version:
Deephaven AG Grid plugin
103 lines • 5.5 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useApi } from '@deephaven/jsapi-bootstrap';
import Log from '@deephaven/log';
import { createFormatterFromSettings } from '@deephaven/jsapi-utils';
import { AgGridReact } from 'ag-grid-react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { AgGridFormatter, getAutoGroupColumnDef, getColumnDefs, getSideBar, isPivotTable, isTable, toGroupKeyString, TREE_NODE_KEY, } from '../utils';
import { DeephavenViewportDatasource } from '../datasources';
const log = Log.module('@deephaven/js-plugin-ag-grid/AgGridView');
/**
* AgGrid view that uses the Server-Side Row Model and a Deephaven table as a data source to display
* in AG Grid, with support for value formatting, sorting, and basic filtering operations.
*/
export function AgGridView({ table, settings, agGridProps, }) {
const dh = useApi();
const gridApiRef = useRef(null);
const autoSizedColumnsRef = useRef(new Set());
const [isVisible, setIsVisible] = useState(false);
const [isFirstDataRendered, setIsFirstDataRendered] = useState(false);
log.debug('AgGridView rendering', table);
/** Map from Deephaven Table Columns to AG Grid ColDefs */
const colDefs = useMemo(() => getColumnDefs(table), [table]);
/** Create the ViewportDatasource to pass in to AG Grid based on the Deephaven Table */
const datasource = useMemo(() => new DeephavenViewportDatasource(dh, table), [dh, table]);
// Create the formatter used to format cell values, currently just a
// wrapper around jsapi-utils Formatter, but more functionality could be added.
const formatter = useMemo(() => new AgGridFormatter(createFormatterFromSettings(dh, settings)), [dh, settings]);
const autoGroupColumnDef = useMemo(() => getAutoGroupColumnDef(datasource), [datasource]);
const sideBar = useMemo(() => getSideBar(table), [table]);
// Workaround to auto-size columns based on their contents, as ag-grid ignores virtual columns
// that are not visible in the viewport
const autoSizeAllColumns = () => {
var _a, _b;
const gridApi = gridApiRef.current;
if (!gridApi)
return;
const allColumnIds = [
...((_a = gridApi.getColumns()) !== null && _a !== void 0 ? _a : []),
...((_b = gridApi.getPivotResultColumns()) !== null && _b !== void 0 ? _b : []),
].map(c => c.getColId());
// Only auto-size columns that haven't been auto-sized yet
const columnsToAutoSize = allColumnIds.filter(colId => !autoSizedColumnsRef.current.has(colId));
log.debug2('autoSizeAllColumns resizing', columnsToAutoSize);
if (columnsToAutoSize.length > 0) {
gridApi.autoSizeColumns(columnsToAutoSize);
columnsToAutoSize.forEach(colId => autoSizedColumnsRef.current.add(colId));
}
// Remove any columns that are no longer present in the grid from the auto-sized set
autoSizedColumnsRef.current.forEach(colId => {
if (!allColumnIds.includes(colId)) {
autoSizedColumnsRef.current.delete(colId);
}
});
};
const handleGridReady = useCallback((event) => {
log.debug('handleGridReady', event);
datasource.setGridApi(event.api);
gridApiRef.current = event.api;
}, [datasource]);
const handleFirstDataRendered = (event) => {
log.debug('handleFirstDataRendered', event);
setIsFirstDataRendered(true);
};
const handleGridSizeChanged = (event) => {
log.debug('handleGridSizeChanged', event);
setIsVisible(event.clientHeight > 0 && event.clientWidth > 0);
};
useEffect(() => {
if (isVisible && isFirstDataRendered) {
autoSizeAllColumns();
}
}, [isVisible, isFirstDataRendered]);
const getRowId = useCallback((params) => {
const { data } = params;
if (data == null) {
log.error('getRowId called with null data', params);
throw new Error('getRowId called with null data');
}
if (isPivotTable(table)) {
const groupKeys = [];
for (let i = 0; i < table.rowSources.length; i += 1) {
const rowSource = table.rowSources[i];
if (data[rowSource.name] != null) {
groupKeys.push(String(data[rowSource.name]));
}
}
return toGroupKeyString(groupKeys);
}
const treeNode = data === null || data === void 0 ? void 0 : data[TREE_NODE_KEY];
if (treeNode == null) {
log.error('getRowId called with missing tree node info', params);
throw new Error('Tree node info missing from row data');
}
return `${treeNode.index}`;
}, [table]);
return (_jsx(AgGridReact
// eslint-disable-next-line react/jsx-props-no-spreading
, Object.assign({}, agGridProps, { onGridReady: handleGridReady, onFirstDataRendered: handleFirstDataRendered, onGridSizeChanged: handleGridSizeChanged, autoGroupColumnDef: autoGroupColumnDef, columnDefs: colDefs, dataTypeDefinitions: formatter.cellDataTypeDefinitions, viewportDatasource: datasource, rowModelType: "viewport",
// With a regular table, the row IDs are just the row indices, so we don't need to specify getRowId
getRowId: isTable(table) ? undefined : getRowId, sideBar: sideBar })));
}
export default AgGridView;
//# sourceMappingURL=AgGridView.js.map