diff --git a/frontend/src/components/DataGrid.ddl.test.tsx b/frontend/src/components/DataGrid.ddl.test.tsx
index 39ff6d53..cabda244 100644
--- a/frontend/src/components/DataGrid.ddl.test.tsx
+++ b/frontend/src/components/DataGrid.ddl.test.tsx
@@ -1036,6 +1036,54 @@ describe('DataGrid DDL interactions', () => {
},
);
+ it('selects every editable cell in a column when its header is clicked in cell edit mode', async () => {
+ messageApi.info.mockResolvedValue(undefined);
+ let renderer: ReactTestRenderer;
+ await act(async () => {
+ renderer = create(
+ ,
+ );
+ });
+ await waitForEffects();
+
+ await act(async () => {
+ renderer!.root.findByType(DataGridToolbarFrame).props.onToggleCellEditMode();
+ });
+ await waitForEffects();
+
+ const nameColumn = testRenderState.latestColumns.find((column) => column.key === 'name');
+ expect(nameColumn?.editable).toBe(true);
+ const headerProps = nameColumn.onHeaderCell(nameColumn);
+ const event = {
+ target: { closest: vi.fn(() => null) },
+ currentTarget: { querySelector: vi.fn(() => null) },
+ preventDefault: vi.fn(),
+ stopPropagation: vi.fn(),
+ };
+
+ await act(async () => {
+ headerProps.onClickCapture(event);
+ });
+
+ const toolbar = renderer!.root.findByType(DataGridToolbarFrame);
+ expect(event.preventDefault).toHaveBeenCalledOnce();
+ expect(event.stopPropagation).toHaveBeenCalledOnce();
+ expect(toolbar.props.cellEditMode).toBe(true);
+ expect(toolbar.props.selectedCellsSize).toBe(2);
+ renderer!.unmount();
+ });
+
it('opens the v2 column header context menu from table headers', async () => {
setCurrentLanguage('en-US');
storeState.appearance.uiVersion = 'v2';
diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx
index 098403a0..35003026 100644
--- a/frontend/src/components/DataGrid.tsx
+++ b/frontend/src/components/DataGrid.tsx
@@ -1599,6 +1599,27 @@ const DataGrid: React.FC = ({
resetCellSelection();
}, [resetCellSelection]);
+ const selectEditableColumnCells = useCallback((columnName: string) => {
+ if (
+ !cellEditModeRef.current
+ || !canModifyData
+ || !isWritableResultColumn(columnName, effectiveEditLocator)
+ ) {
+ return;
+ }
+
+ resetCellSelection(false);
+ const nextSelection = new Set();
+ displayDataRef.current.forEach((row) => {
+ const rowKey = row?.[GONAVI_ROW_KEY];
+ if (rowKey === undefined || rowKey === null) return;
+ nextSelection.add(makeCellKey(rowKeyStr(rowKey), columnName));
+ });
+ currentSelectionRef.current = nextSelection;
+ setSelectedCells(nextSelection);
+ updateCellSelection(nextSelection);
+ }, [canModifyData, effectiveEditLocator, makeCellKey, resetCellSelection, rowKeyStr, updateCellSelection]);
+
useEffect(() => {
closeCellEditModeRef.current = closeCellEditMode;
}, [closeCellEditMode]);
@@ -2548,12 +2569,19 @@ const DataGrid: React.FC = ({
showColumnHeaderContextMenu(event, key);
},
onClickCapture: (event: React.MouseEvent) => {
- if (!onSort) return;
const eventTarget = event.target as HTMLElement | null;
if (eventTarget?.closest?.('[data-grid-fk-jump="true"]')) return;
if (eventTarget?.closest?.('[data-grid-column-filter-trigger="true"]')) return;
if (eventTarget?.closest?.('[data-grid-column-filter-popover="true"]')) return;
if (eventTarget?.closest?.('.ant-select-dropdown')) return;
+ if (eventTarget?.closest?.('.react-resizable-handle')) return;
+ if (cellEditMode && canModifyData && isWritableResultColumn(key, effectiveEditLocator)) {
+ event.preventDefault();
+ event.stopPropagation();
+ selectEditableColumnCells(key);
+ return;
+ }
+ if (!onSort) return;
const headerCell = event.currentTarget as HTMLElement;
const upArrow = headerCell.querySelector('.ant-table-column-sorter-up') as HTMLElement | null;
const downArrow = headerCell.querySelector('.ant-table-column-sorter-down') as HTMLElement | null;
@@ -2574,7 +2602,7 @@ const DataGrid: React.FC = ({
},
}),
}));
- }, [canModifyData, columnWidths, currentConnConfig, dataTableDensity, displayColumnNames, displayColumnTypeMap, enableVirtual, handleResizeAutoFit, handleResizeStart, isV2Ui, language, normalizedPageFindText, onSort, pinnedLeftColumnSet, renderColumnTitle, showColumnComment, showColumnHeaderContextMenu, showColumnType, sortInfo]);
+ }, [canModifyData, cellEditMode, columnWidths, currentConnConfig, dataTableDensity, displayColumnNames, displayColumnTypeMap, effectiveEditLocator, enableVirtual, handleResizeAutoFit, handleResizeStart, isV2Ui, language, normalizedPageFindText, onSort, pinnedLeftColumnSet, renderColumnTitle, selectEditableColumnCells, showColumnComment, showColumnHeaderContextMenu, showColumnType, sortInfo]);
const mergedColumns = useMemo(() => columns.map((col): ColumnType => {
const dataIndex = String(col.dataIndex);