Add incremental grid loading option to notebooks (#16577)

* render grids incrementally

* add loading spinner

* fix loading animation

* move rendergrids to notebook editor component

* add setting for incremental grid loading

* check configuration

* just use setTimeout to queue grids

* remove extra line

* add setter/getter for isloading

* add comment
This commit is contained in:
Lucy Zhang
2021-08-05 13:44:26 -07:00
committed by GitHub
parent c6308b77df
commit 9f761c44c4
2 changed files with 39 additions and 5 deletions

View File

@@ -340,6 +340,11 @@ configurationRegistry.registerConfiguration({
'type': 'boolean',
'default': false,
'description': localize('notebook.useAbsoluteFilePaths', "Use absolute file paths when linking to other notebooks.")
},
'notebook.enableIncrementalGridRendering': {
'type': 'boolean',
'default': false,
'description': localize('notebook.enableIncrementalGridRendering', "Enable incremental grid rendering for notebooks. This will improve the initial rendering time for large notebooks. There may be performance issues when interacting with the notebook while the rest of the grids are rendering.")
}
}
});

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { OnInit, Component, Input, Inject, ViewChild, ElementRef } from '@angular/core';
import { OnInit, Component, Input, Inject, ViewChild, ElementRef, ChangeDetectorRef, forwardRef } from '@angular/core';
import * as azdata from 'azdata';
import { IGridDataProvider, getResultsString } from 'sql/workbench/services/query/common/gridDataProvider';
@@ -23,7 +23,7 @@ import { localize } from 'vs/nls';
import { IAction } from 'vs/base/common/actions';
import { AngularDisposable } from 'sql/base/browser/lifecycle';
import { IMimeComponent } from 'sql/workbench/contrib/notebook/browser/outputs/mimeRegistry';
import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { CellExecutionState, ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { MimeModel } from 'sql/workbench/services/notebook/browser/outputs/mimemodel';
import { GridTableState } from 'sql/workbench/common/editor/query/gridTableState';
import { GridTableBase } from 'sql/workbench/contrib/query/browser/gridPanel';
@@ -51,7 +51,9 @@ import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
@Component({
selector: GridOutputComponent.SELECTOR,
template: `<div #output class="notebook-cellTable"></div>`
template: `
<loading-spinner [loading]="loading"></loading-spinner>
<div #output class="notebook-cellTable"></div>`
})
export class GridOutputComponent extends AngularDisposable implements IMimeComponent, OnInit {
public static readonly SELECTOR: string = 'grid-output';
@@ -66,12 +68,17 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
private _batchId: number | undefined;
private _id: number | undefined;
private _layoutCalledOnce: boolean = false;
private _incrementalGridRenderingEnabled: boolean;
private _isLoading: boolean = false;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
@Inject(IThemeService) private readonly themeService: IThemeService
@Inject(IThemeService) private readonly themeService: IThemeService,
@Inject(IConfigurationService) private configurationService: IConfigurationService
) {
super();
this._incrementalGridRenderingEnabled = this.configurationService.getValue('notebook.enableIncrementalGridRendering');
}
@Input() set bundleOptions(value: MimeModel.IOptions) {
@@ -102,6 +109,17 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
this._cellOutput = value;
}
get loading(): boolean {
return this._isLoading;
}
@Input() set loading(isLoading: boolean) {
this._isLoading = isLoading;
if (!(this._changeRef['destroyed'])) {
this._changeRef.detectChanges();
}
}
async ngOnInit() {
if (this.cellModel) {
let outputId: QueryResultId = this.cellModel.getOutputId(this._cellOutput);
@@ -114,10 +132,21 @@ export class GridOutputComponent extends AngularDisposable implements IMimeCompo
this.updateResult(e.resultSet, e.rows);
}
}));
if (this._cellModel.executionState === CellExecutionState.Running || !this._incrementalGridRenderingEnabled) {
await this.renderGrid();
} else {
this.loading = true;
// setTimeout adds the renderGrid call to a queue that gets called after all current tasks get executed -
// this allows the rest of the notebook to render first before rendering grids incrementally.
setTimeout(async () => {
await this.renderGrid();
this.loading = false;
});
}
}
await this.renderGrid();
}
async renderGrid(): Promise<void> {
if (!this._bundleOptions || !this._cellModel || !this.mimeType) {
return;