Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
Expand All @@ -26,6 +26,7 @@ import { useGridReactiveValue } from './useGridReactiveValue.js';
import { mapCellContentRenderer } from './mapCellContentRenderer.js';
import { mapRenderHeaderCell } from './mapRenderHeaderCell.js';
import { mapEditCellRenderer } from './mapEditCellRenderer.js';
import { mapSummaryCellRenderer } from './mapSummaryCellRenderer.js';
import { DataGridRowContext, type IDataGridRowContext } from './DataGridRowContext.js';
import './DataGrid.css';
import { HeaderDnDContext, isColumn, useHeaderDnD } from './useHeaderDnD.js';
Expand Down Expand Up @@ -71,6 +72,7 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
getHeaderResizable,
columnSortable,
getHeaderHeight,
getSummaryRowHeight,
getHeaderPinned,
columnSortingState,
getHeaderDnD,
Expand All @@ -87,6 +89,8 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
getRowId,
getRowHeight,
getRowClass,
getRowPinnedTop,
getRowPinnedBottom,
onHeaderReorder,
onScroll,
onScrollToBottom,
Expand Down Expand Up @@ -121,6 +125,7 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
renderHeaderCell: mapRenderHeaderCell(i),
renderCell: mapCellContentRenderer(i),
renderEditCell: mapEditCellRenderer(i),
renderSummaryCell: mapSummaryCellRenderer(i),
};
});

Expand Down Expand Up @@ -180,13 +185,31 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
}
}

const rows = useMemo(
() =>
new Array<IInnerRow>(rowsCount).fill({ idx: 0 }).map((_, i) => ({
idx: i,
})),
[rowsCount],
);
const { rows, topPinnedRows, bottomPinnedRows } = useMemo(() => {
const allRows = new Array<IInnerRow>(rowsCount).fill({ idx: 0 }).map((_, i) => ({
idx: i,
}));

const topPinned: IInnerRow[] = [];
const bottomPinned: IInnerRow[] = [];

for (const row of allRows) {
const isPinnedTop = getRowPinnedTop?.(row.idx) ?? false;
const isPinnedBottom = getRowPinnedBottom?.(row.idx) ?? false;

if (isPinnedTop) {
topPinned.push(row);
} else if (isPinnedBottom) {
bottomPinned.push(row);
}
}

return {
rows: allRows,
topPinnedRows: topPinned,
bottomPinnedRows: bottomPinned,
};
}, [rowsCount, getRowPinnedTop, getRowPinnedBottom]);

function handleCellFocus(args: CellSelectArgs<IInnerRow, unknown>) {
onFocus?.({ colIdx: dndHeaderContext.getDataColIdxByKey(args.column.key), rowIdx: args.rowIdx });
Expand Down Expand Up @@ -215,7 +238,7 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid

return (
<HeaderDnDContext value={dndHeaderContext}>
<DataGridRowContext value={{ rowElement, rowCount, onScrollToBottom }}>
<DataGridRowContext value={{ rowElement, rowCount, onScrollToBottom, getRowPinnedTop, getRowPinnedBottom }}>
<DataGridCellContext value={{ cell, cellText, cellElement, cellTooltip, onCellChange }}>
<DataGridCellHeaderContext
value={{
Expand All @@ -235,6 +258,7 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
rows={rows}
className={className}
headerRowHeight={getHeaderHeight?.()}
summaryRowHeight={getSummaryRowHeight?.()}
rowHeight={getRowHeight ? row => getRowHeight(row.idx) : undefined}
rowKeyGetter={getRowId ? row => getRowId(row.idx) : undefined}
rowClass={getRowClass ? row => getRowClass(row.idx) : undefined}
Expand All @@ -244,6 +268,8 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
renderCell: cellRenderer,
noRowsFallback: children,
}}
topSummaryRows={topPinnedRows}
bottomSummaryRows={bottomPinnedRows}
onScroll={onScroll}
onSelectedCellChange={handleCellFocus}
onCellKeyDown={handleCellKeyDown}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@ export interface IDataGridHeaderCellContext {
getHeaderWidth?: (colIdx: number) => number | string | null;
getHeaderResizable?: (colIdx: number) => boolean;
getHeaderHeight?: () => number;
getSummaryRowHeight?: () => number;
getHeaderPinned?: (colIdx: number) => boolean;
getHeaderDnD?: (colIdx: number) => boolean;
onHeaderReorder?: (from: number, to: number) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
Expand All @@ -12,13 +12,15 @@
export interface IDataGridRowProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {}

export interface IDataGridRowRenderer {
(propsOverride: Partial<IDataGridRowProps>): React.ReactNode;

Check warning on line 15 in webapp/common-react/@dbeaver/react-data-grid/src/DataGridRowContext.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Interface only has a call signature, you should use a function type instead
}

export interface IDataGridRowContext {
rowElement?: IGridReactiveValue<React.ReactNode, [rowIdx: number, props: IDataGridRowProps, renderDefaultRow: IDataGridRowRenderer]>;
rowCount: IGridReactiveValue<number, []>;
onScrollToBottom?: () => void;
getRowPinnedTop?: (rowIdx: number) => boolean;
getRowPinnedBottom?: (rowIdx: number) => boolean;
}

export const DataGridRowContext = createContext<IDataGridRowContext | null>(null);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

import type { RenderSummaryCellProps } from 'react-data-grid';
import type { IInnerRow } from './IInnerRow.js';
import { SummaryCellRenderer } from './renderers/SummaryCellRenderer.js';

export function mapSummaryCellRenderer(colIdx: number) {

Check warning on line 13 in webapp/common-react/@dbeaver/react-data-grid/src/mapSummaryCellRenderer.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

'colIdx' is defined but never used
return function RenderSummaryCell({ row, column }: RenderSummaryCellProps<unknown, IInnerRow>) {

Check warning on line 14 in webapp/common-react/@dbeaver/react-data-grid/src/mapSummaryCellRenderer.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
const rowIdx = (row as IInnerRow).idx;
return <SummaryCellRenderer rowIdx={rowIdx} column={column} />;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

import { use, useMemo } from 'react';
import { HeaderDnDContext } from '../useHeaderDnD.js';
import { DataGridCellContext, type IDataGridCellRenderer, type IDataGridCellProps } from '../DataGridCellContext.js';
import { useGridReactiveValue } from '../useGridReactiveValue.js';
import type { CalculatedColumn } from 'react-data-grid';
import type { IInnerRow } from '../IInnerRow.js';
import { CellContentRenderer } from './CellContentRenderer.js';

export interface Props {
rowIdx: number;
column: CalculatedColumn<IInnerRow, unknown>;
}

export function SummaryCellRenderer({ rowIdx, column }: Props): React.ReactNode {
const cellContext = use(DataGridCellContext);
const dndContext = use(HeaderDnDContext)!;
const dataColIdx = dndContext.getDataColIdxByKey(column.key);

const mappedProps = useMemo<IDataGridCellProps>(
() => ({
isFocused: false,
}),
[],
);

const renderDefaultCell = useMemo<IDataGridCellRenderer>(
() => () => <CellContentRenderer rowIdx={rowIdx} colIdx={dataColIdx} />,
[rowIdx, dataColIdx],
);

return useGridReactiveValue(cellContext?.cellElement, rowIdx, dataColIdx, mappedProps, renderDefaultCell);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createAction } from '@cloudbeaver/core-view';

export const ACTION_DATA_GRID_PIN_ROW_BOTTOM = createAction('data-grid-pin-row-bottom', {
label: 'plugin_data_spreadsheet_new_pin_row_bottom',
icon: 'pin-row-bottom',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createAction } from '@cloudbeaver/core-view';

export const ACTION_DATA_GRID_PIN_ROW_TOP = createAction('data-grid-pin-row-top', {
label: 'plugin_data_spreadsheet_new_pin_row_top',
icon: 'pin-row-top',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createAction } from '@cloudbeaver/core-view';

export const ACTION_DATA_GRID_UNPIN_ALL_ROWS = createAction('data-grid-unpin-all-rows', {
label: 'plugin_data_spreadsheet_new_unpin_all_rows',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createAction } from '@cloudbeaver/core-view';

export const ACTION_DATA_GRID_UNPIN_ROW = createAction('data-grid-unpin-row', {
label: 'plugin_data_spreadsheet_new_unpin_row',
icon: 'unpin-row',
});
Loading
Loading