mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #79 from dbeaver/feat-data-filter
fix(data-viewer-plugin): table refresh
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -24,8 +24,6 @@ export interface IRequestDataOptions {
|
||||
|
||||
|
||||
export interface IAgGridModel {
|
||||
initialRows: AgGridRow[];
|
||||
initialColumns: IAgGridCol[];
|
||||
chunkSize: number;
|
||||
enableRangeSelection?: boolean;
|
||||
|
||||
|
||||
@@ -12,9 +12,31 @@ export type DefaultValueGetter<TKey, TValue> = (key: TKey, metadata: MetadataMap
|
||||
|
||||
export class MetadataMap<TKey, TValue> {
|
||||
private data: Map<TKey, TValue>;
|
||||
private length: number;
|
||||
|
||||
constructor(private defaultValueGetter: DefaultValueGetter<TKey, TValue>) {
|
||||
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<TKey, TValue> {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class TableDataModel {
|
||||
}
|
||||
|
||||
@action
|
||||
overWrite(columns: TableColumn[]) {
|
||||
setColumns(columns: TableColumn[]) {
|
||||
this.columns = [...columns];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))(
|
||||
<table-footer as="div">
|
||||
<reload as="div">
|
||||
<button type="button" onClick={model.handleRefresh}>
|
||||
<Icon name="reload" />
|
||||
</button>
|
||||
<IconButton type="button" name='reload' onClick={model.handleRefresh} viewBox=""/>
|
||||
</reload>
|
||||
<count as="div">
|
||||
<input type="number" value={model.getChunkSize()} onBlur={handleChange} {...use({ mod: 'surface' })} />
|
||||
|
||||
@@ -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<IRequestDataResult>;
|
||||
|
||||
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<void> {
|
||||
@@ -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[]) {
|
||||
|
||||
+15
-29
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user