From 2ead555fcbad73f0b91ea64b5f37772eb7a53a3b Mon Sep 17 00:00:00 2001 From: Wroud Date: Thu, 11 Jun 2020 12:25:24 +0300 Subject: [PATCH 1/2] fix(data-viewer-plugin): table refresh --- .../src/AgGridTable/AgGridTableController.ts | 24 +------- .../src/AgGridTable/IAgGridModel.ts | 2 - .../TableDataModel/TableDataModel.ts | 2 +- .../TableViewer/TableFooter/TableFooter.tsx | 32 ++++------- .../src/TableViewer/TableViewerModel.ts | 55 ++++++------------- .../SqlResultPanelController.ts | 44 +++++---------- 6 files changed, 49 insertions(+), 110 deletions(-) diff --git a/webapp/packages/ag-grid-plugin/src/AgGridTable/AgGridTableController.ts b/webapp/packages/ag-grid-plugin/src/AgGridTable/AgGridTableController.ts index 2de4ebdab3..25a0491534 100644 --- a/webapp/packages/ag-grid-plugin/src/AgGridTable/AgGridTableController.ts +++ b/webapp/packages/ag-grid-plugin/src/AgGridTable/AgGridTableController.ts @@ -18,7 +18,6 @@ import { CellEditingStoppedEvent, } from 'ag-grid-community'; import { SortChangedEvent } from 'ag-grid-community/dist/lib/events'; -import { RowDataTransaction } from 'ag-grid-community/dist/lib/interfaces/rowDataTransaction'; import { computed, observable } from 'mobx'; import { injectable, IInitializableController, IDestructibleController } from '@dbeaver/core/di'; @@ -59,6 +58,7 @@ export class AgGridTableController implements IInitializableController, IDestruc rowHeight: 24, headerHeight: 28, rowModelType: 'infinite', + infiniteInitialRowCount: 0, cacheBlockSize: undefined, // to be set during init phase datasource: this.datasource, @@ -104,9 +104,6 @@ export class AgGridTableController implements IInitializableController, IDestruc gridModel.actions = this.actions; this.gridModel = gridModel; this.gridOptions.cacheBlockSize = gridModel.chunkSize; - if (gridModel.initialColumns?.length) { - this.columns = mapDataToColumns(gridModel.initialColumns); - } } destruct(): void { @@ -197,7 +194,6 @@ export class AgGridTableController implements IInitializableController, IDestruc private handleGridReady(params: GridReadyEvent) { this.api = params.api; this.columnApi = params.columnApi; - this.setInitialRow(this.gridModel.initialRows); } private handleSortChanged(event: SortChangedEvent) { @@ -209,28 +205,14 @@ export class AgGridTableController implements IInitializableController, IDestruc /* Actions */ - private resetData(columns?: IAgGridCol[], rows?: AgGridRow[]): void { + private resetData(): void { this.selection.clear(); if (this.api) { + this.api.setInfiniteRowCount(0, false); this.api.purgeInfiniteCache(); // it will reset internal state - if (columns) { - this.columns = mapDataToColumns(columns); - } - this.setInitialRow(rows); } } - private setInitialRow(initialRows?: AgGridRow[]): void { - if (!initialRows || !initialRows.length) { - return; - } - const transaction: RowDataTransaction = { - addIndex: 0, - add: initialRows || [], - }; - this.api!.applyTransaction(transaction); - } - private updateCellValue(rowNumber: number, colNumber: number, value: any): void { if (this.api) { this.api diff --git a/webapp/packages/ag-grid-plugin/src/AgGridTable/IAgGridModel.ts b/webapp/packages/ag-grid-plugin/src/AgGridTable/IAgGridModel.ts index acc8524da0..bd8333452f 100644 --- a/webapp/packages/ag-grid-plugin/src/AgGridTable/IAgGridModel.ts +++ b/webapp/packages/ag-grid-plugin/src/AgGridTable/IAgGridModel.ts @@ -24,8 +24,6 @@ export interface IRequestDataOptions { export interface IAgGridModel { - initialRows: AgGridRow[]; - initialColumns: IAgGridCol[]; chunkSize: number; enableRangeSelection?: boolean; diff --git a/webapp/packages/data-viewer-plugin/src/TableViewer/TableDataModel/TableDataModel.ts b/webapp/packages/data-viewer-plugin/src/TableViewer/TableDataModel/TableDataModel.ts index 44864925d8..fd3bb7c560 100644 --- a/webapp/packages/data-viewer-plugin/src/TableViewer/TableDataModel/TableDataModel.ts +++ b/webapp/packages/data-viewer-plugin/src/TableViewer/TableDataModel/TableDataModel.ts @@ -101,7 +101,7 @@ export class TableDataModel { } @action - overWrite(columns: TableColumn[]) { + setColumns(columns: TableColumn[]) { this.columns = [...columns]; } } diff --git a/webapp/packages/data-viewer-plugin/src/TableViewer/TableFooter/TableFooter.tsx b/webapp/packages/data-viewer-plugin/src/TableViewer/TableFooter/TableFooter.tsx index 2e66a0adca..f1829ff4cd 100644 --- a/webapp/packages/data-viewer-plugin/src/TableViewer/TableFooter/TableFooter.tsx +++ b/webapp/packages/data-viewer-plugin/src/TableViewer/TableFooter/TableFooter.tsx @@ -10,7 +10,7 @@ import { observer } from 'mobx-react'; import { useCallback } from 'react'; import styled, { css, use } from 'reshadow'; -import { Icon } from '@dbeaver/core/blocks'; +import { IconButton } from '@dbeaver/core/blocks'; import { composes, useStyles } from '@dbeaver/core/theming'; import { TableViewerModel } from '../TableViewerModel'; @@ -21,7 +21,7 @@ const tableFooterStyles = composes( table-footer { composes: theme-background-secondary theme-text-on-secondary from global; } - button { + reload { composes: theme-text-primary theme-ripple from global; } `, @@ -32,19 +32,6 @@ const tableFooterStyles = composes( display: flex; align-items: center; } - button { - outline: none; - padding: 0 8px; - display: flex; - cursor: pointer; - background: transparent; - - & Icon, - & placeholder { - height: 24px; - width: 24px; - } - } count input, count placeholder { height: 26px; @@ -55,9 +42,16 @@ const tableFooterStyles = composes( font-size: 13px; line-height: 24px; } - reload, - reload button { + reload { height: 100%; + display: flex; + align-items: center; + } + IconButton { + position: relative; + height: 24px; + width: 24px; + display: block; } reload, count, @@ -87,9 +81,7 @@ export const TableFooter = observer(function TableFooter({ return styled(useStyles(tableFooterStyles))( - + diff --git a/webapp/packages/data-viewer-plugin/src/TableViewer/TableViewerModel.ts b/webapp/packages/data-viewer-plugin/src/TableViewer/TableViewerModel.ts index d7410b822d..29d47e4a31 100644 --- a/webapp/packages/data-viewer-plugin/src/TableViewer/TableViewerModel.ts +++ b/webapp/packages/data-viewer-plugin/src/TableViewer/TableViewerModel.ts @@ -42,7 +42,6 @@ export interface ITableViewerModelOptions { resultId?: string | null; // will be filled after fist data fetch executionContext?: IExecutionContext | null; // will be filled before fist data fetch sourceName?: string; // TODO: refactor it, used for showing sql query for export - initialState?: IRequestDataResult; noLoaderWhileRequestingDataAsync?: boolean; requestDataAsync( model: TableViewerModel, @@ -67,7 +66,6 @@ export class TableViewerModel implements ITableViewerModelOptions { resultId: string | null; executionContext: IExecutionContext | null; sourceName?: string; - initialState?: IRequestDataResult; noLoaderWhileRequestingDataAsync?: boolean; requestDataAsync: ( model: TableViewerModel, @@ -77,8 +75,6 @@ export class TableViewerModel implements ITableViewerModelOptions { saveChanges: (model: TableViewerModel, diffs: RowDiff[]) => Promise; agGridModel: IAgGridModel = { - initialRows: [], - initialColumns: [], chunkSize: this.getDefaultRowsCount(), enableRangeSelection: true, onRequestData: this.onRequestData.bind(this), @@ -127,12 +123,9 @@ export class TableViewerModel implements ITableViewerModelOptions { this.resultId = options.resultId || null; this.executionContext = options.executionContext || null; this.sourceName = options.sourceName; - this.initialState = options.initialState; this.noLoaderWhileRequestingDataAsync = options.noLoaderWhileRequestingDataAsync; this.requestDataAsync = options.requestDataAsync; this.saveChanges = options.saveChanges; - - this.init(); } cancelFetch = () => { @@ -144,14 +137,22 @@ export class TableViewerModel implements ITableViewerModelOptions { } } - private init() { - if (this.initialState) { - this.insertRows(0, this.initialState.rows, !this.initialState.isFullyLoaded); - this.tableDataModel.overWrite(this.initialState.columns); - this.updateInfo(this.initialState.statusMessage, this.initialState.duration); - this.agGridModel.initialRows = this.tableDataModel.getRows(); - this.agGridModel.initialColumns = this.tableDataModel.getColumns(); - } + @action + insertRows(position: number, rows: TableRow[], hasMore: boolean) { + const isRowsAddition = this.tableDataModel.getRows().length < position + rows.length; + this.tableDataModel.insertRows(position, rows); + this._hasMoreRows = isRowsAddition ? hasMore : this._hasMoreRows; + } + + @action + setColumns(columns: TableColumn[]) { + this.tableDataModel.setColumns(columns); + } + + @action + updateInfo(status: string, duration?: number) { + this.queryDuration = duration || 0; + this.requestStatusMessage = status; } private async onCellEditingStopped(rowNumber: number, colNumber: number, value: any): Promise { @@ -176,7 +177,7 @@ export class TableViewerModel implements ITableViewerModelOptions { this.insertRows(rowOffset, response.rows, !response.isFullyLoaded); if (!this.tableDataModel.getColumns().length) { - this.tableDataModel.overWrite(response.columns); + this.tableDataModel.setColumns(response.columns); } this.clearErrors(); this.updateInfo(response.statusMessage, response.duration); @@ -211,25 +212,6 @@ export class TableViewerModel implements ITableViewerModelOptions { this.errorMessage = ''; } - @action - private updateInfo(status: string, duration?: number) { - this.queryDuration = duration || 0; - this.requestStatusMessage = status; - } - - @action - private pushRows(rows: TableRow[], hasMore: boolean) { - this.tableDataModel.pushRows(rows); - this._hasMoreRows = hasMore; - } - - @action - private insertRows(position: number, rows: TableRow[], hasMore: boolean) { - const isRowsAddition = this.tableDataModel.getRows().length < position + rows.length; - this.tableDataModel.insertRows(position, rows); - this._hasMoreRows = isRowsAddition ? hasMore : this._hasMoreRows; - } - private updateAgGridRows(rows: SomeTableRows) { rows.forEach((row, rowNumber) => { this.agGridModel.actions?.updateRowValue(rowNumber, row); @@ -280,8 +262,7 @@ export class TableViewerModel implements ITableViewerModelOptions { } private onSortChanged() { - this.tableDataModel.resetData(); - this._hasMoreRows = true; + this.resetData(); } private async trySaveChanges(diffs: RowDiff[]) { diff --git a/webapp/packages/sql-editor/src/SqlResultTabs/SqlResultPanel/SqlResultPanelController.ts b/webapp/packages/sql-editor/src/SqlResultTabs/SqlResultPanel/SqlResultPanelController.ts index b2fd539ffb..91e8a5f2e4 100644 --- a/webapp/packages/sql-editor/src/SqlResultTabs/SqlResultPanel/SqlResultPanelController.ts +++ b/webapp/packages/sql-editor/src/SqlResultTabs/SqlResultPanel/SqlResultPanelController.ts @@ -72,14 +72,21 @@ implements IInitializableController, IDestructibleController { this.state = EPanelState.TABLE_RESULT; const initialState = this.sqlResultService .sqlExecuteInfoToData(response, this.panelInit.indexInResultSet, fetchingSettings.fetchDefault); - this.createTableModel( - panelInit.sqlQueryParams.query, - panelInit.sqlQueryParams, - initialState, - panelInit.sqlQueryParams.connectionId, - dataSet.resultSet.id, - panelInit.sqlExecutionState - ); + + const tableModel = this.tableViewerStorageService.create({ + tableId: this.getTableId(), + connectionId: panelInit.sqlQueryParams.connectionId, + executionContext: panelInit.sqlQueryParams, + resultId: dataSet.resultSet.id, + sourceName: panelInit.sqlQueryParams.query, + requestDataAsync: this.requestDataAsync.bind(this, panelInit.sqlExecutionState), + noLoaderWhileRequestingDataAsync: true, + saveChanges: this.saveChanges.bind(this), + }); + + tableModel.insertRows(0, initialState.rows, !initialState.isFullyLoaded); + tableModel.setColumns(initialState.columns); + tableModel.updateInfo(initialState.statusMessage, initialState.duration); } } catch (exception) { @@ -130,27 +137,6 @@ implements IInitializableController, IDestructibleController { } } - private createTableModel( - sourceName: string, - executionContext: IExecutionContext, - initialState: IRequestDataResult, - connectionId: string, - resultId: string, - sqlExecutingState: SqlExecutionState - ) { - return this.tableViewerStorageService.create({ - tableId: this.getTableId(), - connectionId, - executionContext, - resultId, - sourceName, - initialState, - requestDataAsync: this.requestDataAsync.bind(this, sqlExecutingState), - noLoaderWhileRequestingDataAsync: true, - saveChanges: this.saveChanges.bind(this), - }); - } - private async requestDataAsync( sqlExecutingState: SqlExecutionState, model: TableViewerModel, From aa985a01a3be0ec91d8eb478dcfdaf893ca32be6 Mon Sep 17 00:00:00 2001 From: Wroud Date: Thu, 11 Jun 2020 17:48:22 +0300 Subject: [PATCH 2/2] feat(core): make MetadataMap iterable fix(core): fix first returned value MetadataMap --- webapp/packages/core/src/utils/MetadataMap.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/webapp/packages/core/src/utils/MetadataMap.ts b/webapp/packages/core/src/utils/MetadataMap.ts index 4a2b30a9e4..e952895721 100644 --- a/webapp/packages/core/src/utils/MetadataMap.ts +++ b/webapp/packages/core/src/utils/MetadataMap.ts @@ -12,9 +12,31 @@ export type DefaultValueGetter = (key: TKey, metadata: MetadataMap export class MetadataMap { private data: Map; + private length: number; constructor(private defaultValueGetter: DefaultValueGetter) { this.data = observable(new Map()); + this.length = 0; + } + + [Symbol.iterator]() { + return this.data[Symbol.iterator](); + } + + entries() { + return this.data.entries(); + } + + keys() { + return this.data.keys(); + } + + values() { + return this.data.values(); + } + + count() { + return this.length; } get(key: TKey): TValue { @@ -23,10 +45,19 @@ export class MetadataMap { } const value = this.defaultValueGetter(key, this); this.data.set(key, value); - return value; + this.length++; + return this.data.get(key)!; } delete(key: TKey) { - this.data.delete(key); + if (this.data.has(key)) { + this.data.delete(key); + this.length--; + } + } + + clear() { + this.data.clear(); + this.length = 0; } }