diff --git a/webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx b/webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx index 03afecd9ff..540b66a4f3 100644 --- a/webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx +++ b/webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx @@ -1,5 +1,20 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2025 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 { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react'; -import { DataGrid as DataGridBase, type ColumnOrColumnGroup, type CellSelectArgs, type DataGridHandle, type ColumnWidth, type ColumnWidths } from 'react-data-grid'; +import { + DataGrid as DataGridBase, + type ColumnOrColumnGroup, + type CellSelectArgs, + type DataGridHandle, + type ColumnWidth, + type ColumnWidths, +} from 'react-data-grid'; import { rowRenderer } from './renderers/rowRenderer.js'; import { cellRenderer } from './renderers/cellRenderer.js'; import { DataGridCellHeaderContext, type IDataGridHeaderCellContext } from './DataGridHeaderCellContext.js'; @@ -111,9 +126,12 @@ export const DataGrid = forwardRef(function DataGrid innerGridRef.current?.scrollToCell({ idx: position.colIdx && dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx }); }, openEditor: (position: ICellPosition) => { - innerGridRef.current?.selectCell({ idx: dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx }, { - enableEditor: true, - }); + innerGridRef.current?.selectCell( + { idx: dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx }, + { + enableEditor: true, + }, + ); }, })); @@ -126,7 +144,7 @@ export const DataGrid = forwardRef(function DataGrid } } - let rows = useMemo( + const rows = useMemo( () => new Array(rowsCount).fill({ idx: 0 }).map((_, i) => ({ idx: i, @@ -142,21 +160,16 @@ export const DataGrid = forwardRef(function DataGrid onCellKeyDown?.({ colIdx: dndHeaderContext.getDataColIdx(args.column.idx), rowIdx: args.rowIdx }, event); } - const isMeasurementRender = columnWidths.size === 0 && columnCount.get() > 0; - - if (isMeasurementRender) { - rows = rows.slice(0, 100); - } - return ( - + ({ index: this.data.columns.indexOf(c) })); + return this.columnsOrder.map(index => ({ index })); } get rows(): IResultSetValue[][] { diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableViewer.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TableViewer.tsx index 6a3ecc1d11..cbefdce39b 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableViewer.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableViewer.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -197,7 +197,7 @@ export const TableViewer = observer( const isStatistics = result?.loadedFully && !result.data; const resultExist = dataModel.source.hasResult(resultIndex); - const overlay = dataModel.source.results.length > 0 && presentation.dataFormat === dataFormat; + const overlay = getComputed(() => dataModel.source.results.length > 0 && presentation.dataFormat === dataFormat); const valuePanelDisplayed = valuePresentation && (valuePresentation.dataFormat === undefined || valuePresentation.dataFormat === dataFormat) && diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts index 4c55206db6..a875fe5e52 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -15,9 +15,9 @@ export function navigationTreeDuplicateFilter(navNodeViewService: NavNodeViewSer const { nodes, duplicates } = navNodeViewService.filterDuplicates(children); untracked(() => { - navNodeViewService.logDuplicates(node.id, duplicates); + navNodeViewService.logDuplicates(node.id, Array.from(duplicates)); }); - return nodes; + return Array.from(nodes); }; } diff --git a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/NavNodeViewService.ts b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/NavNodeViewService.ts index af264cee2f..c6e7a1261b 100644 --- a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/NavNodeViewService.ts +++ b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/NavNodeViewService.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -13,8 +13,8 @@ import { NotificationService } from '@cloudbeaver/core-events'; import type { INavNodeFolderTransform, NavNodeFolderTransformFn, NavNodeTransformView } from './IFolderTransform.js'; export interface INodeDuplicateList { - nodes: string[]; - duplicates: string[]; + nodes: Set; + duplicates: Set; } export interface INodeLimitedList { @@ -59,10 +59,10 @@ export class NavNodeViewService { const { nodes, duplicates } = this.filterDuplicates(children); untracked(() => { - this.logDuplicates(nodeId, duplicates); + this.logDuplicates(nodeId, Array.from(duplicates)); }); - return nodes; + return Array.from(nodes); }, }); } @@ -80,25 +80,24 @@ export class NavNodeViewService { } filterDuplicates(nodes: string[]): INodeDuplicateList { + const seen = new Set(); + const duplicatesSet = new Set(); const nextChildren: string[] = []; - const duplicates: string[] = []; for (const child of nodes) { - const isDuplicate = duplicates.includes(child); - - if (nextChildren.includes(child) || isDuplicate) { - if (!isDuplicate) { - duplicates.push(child); - nextChildren.splice(nextChildren.indexOf(child), 1); - } + if (seen.has(child)) { + duplicatesSet.add(child); } else { + seen.add(child); nextChildren.push(child); } } + const uniqueChildren = new Set(nextChildren.filter(child => !duplicatesSet.has(child))); + return { - nodes: nextChildren, - duplicates, + nodes: uniqueChildren, + duplicates: duplicatesSet, }; } diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx index cdc9afd080..ef3f477544 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx @@ -35,12 +35,10 @@ export const VirtualFolderPanel: NavNodeTransformViewComponent = observer(functi const allData = dbObjectLoader.resource.get(pagination.allPages).filter(isDefined); const { nodes, duplicates } = navNodeViewService.filterDuplicates(allData.map(node => node?.id) || []); - const objects = allData.filter( - object => object && nodes.includes(object.id) && navNodeInfoResource.get(object.id)?.nodeType === nodeType, - ) as DBObject[]; + const objects = allData.filter(object => object && nodes.has(object.id) && navNodeInfoResource.get(object.id)?.nodeType === nodeType) as DBObject[]; useEffect(() => { - navNodeViewService.logDuplicates(nodeId, duplicates); + navNodeViewService.logDuplicates(nodeId, Array.from(duplicates)); }); return ( diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx index afd051eb92..1c0b97c493 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx @@ -38,15 +38,15 @@ export const ObjectPropertyTable = observer(function O const allData = dbObjectLoader.resource.get(pagination.allPages).filter(isDefined); const { nodes, duplicates } = navNodeViewService.filterDuplicates(allData.map(node => node?.id) || []); - const objects = allData.filter(node => nodes.includes(node.id)) as DBObject[]; + const objects = allData.filter(node => nodes.has(node.id)) as DBObject[]; useEffect(() => { - navNodeViewService.logDuplicates(objectId, duplicates); + navNodeViewService.logDuplicates(objectId, Array.from(duplicates)); }); return ( <> - {nodes.length === 0 ? ( + {nodes.size === 0 ? ( {translate('plugin_object_viewer_table_no_items')} ) : (