Add grid streaming support for notebooks (#12175)

* add onResultUpdate handler in gridoutput

* convert rows to mimetype and html

* wait for data conversion to finish before saving

* detach changeRef after output is created

* fix save grid action

* move data conversion check to each cell

* move conversion logic to dataprovider

* notify data converting when user saves

* add comments and remove unused methods

* fix method return type

* fix tests

* fix convertData method header

* move azdata changes to azdata proposed

* address PR comments

* display top rows message

* fix messages/table ordering and query 100 rows

* add missing escape import

* set default max rows to 5000

* add undefined check to updateResultSet

* change gridDataConversionComplete return type
This commit is contained in:
Lucy Zhang
2020-09-10 13:31:40 -07:00
committed by GitHub
parent 1528c642d1
commit e3ec6bf9c5
20 changed files with 400 additions and 132 deletions

View File

@@ -64,6 +64,7 @@ export class CellModel extends Disposable implements ICellModel {
private _showPreview: boolean = true;
private _onCellPreviewChanged = new Emitter<boolean>();
private _isCommandExecutionSettingEnabled: boolean = false;
private _gridDataConversionComplete: Promise<void>[] = [];
constructor(cellData: nb.ICellContents,
private _options: ICellModelOptions,
@@ -338,6 +339,8 @@ export class CellModel extends Disposable implements ICellModel {
public async runCell(notificationService?: INotificationService, connectionManagementService?: IConnectionManagementService): Promise<boolean> {
try {
// Clear grid data conversion promises from previous execution results
this._gridDataConversionComplete = [];
if (!this.active && this !== this.notebookModel.activeCell) {
this.notebookModel.updateActiveCell(this);
this.active = true;
@@ -523,6 +526,25 @@ export class CellModel extends Disposable implements ICellModel {
return this._outputs;
}
public updateOutputData(batchId: number, id: number, data: any) {
for (let i = 0; i < this._outputs.length; i++) {
if (this._outputs[i].output_type === 'execute_result'
&& (<nb.IExecuteResult>this._outputs[i]).batchId === batchId
&& (<nb.IExecuteResult>this._outputs[i]).id === id) {
(<nb.IExecuteResult>this._outputs[i]).data = data;
break;
}
}
}
public get gridDataConversionComplete(): Promise<void> {
return Promise.all(this._gridDataConversionComplete).then();
}
public addGridDataConversionPromise(complete: Promise<void>): void {
this._gridDataConversionComplete.push(complete);
}
public get renderedOutputTextContent(): string[] {
return this._renderedOutputTextContent;
}
@@ -579,7 +601,22 @@ export class CellModel extends Disposable implements ICellModel {
if (output) {
// deletes transient node in the serialized JSON
delete output['transient'];
this._outputs.push(this.rewriteOutputUrls(output));
// display message outputs before grid outputs
if (output.output_type === 'display_data' && this._outputs.length > 0) {
let added = false;
for (let i = 0; i < this._outputs.length; i++) {
if (this._outputs[i].output_type === 'execute_result') {
this._outputs.splice(i, 0, this.rewriteOutputUrls(output));
added = true;
break;
}
}
if (!added) {
this._outputs.push(this.rewriteOutputUrls(output));
}
} else {
this._outputs.push(this.rewriteOutputUrls(output));
}
// Only scroll on 1st output being added
let shouldScroll = this._outputs.length === 1;
this.fireOutputsChanged(shouldScroll);

View File

@@ -237,6 +237,10 @@ export interface INotebookModel {
* Promise indicating when client session is ready to use.
*/
readonly sessionLoadFinished: Promise<void>;
/**
* Promise indicating when output grid data is converted to mimeType and html.
*/
gridDataConversionComplete: Promise<any>;
/**
* LanguageInfo saved in the notebook
*/
@@ -480,6 +484,9 @@ export interface ICellModel {
showPreview: boolean;
readonly onCellPreviewChanged: Event<boolean>;
sendChangeToNotebook(change: NotebookChangeType): void;
gridDataConversionComplete: Promise<void>;
addGridDataConversionPromise(complete: Promise<void>): void;
updateOutputData(batchId: number, id: number, data: any): void;
}
export interface IModelFactory {

View File

@@ -271,6 +271,17 @@ export class NotebookModel extends Disposable implements INotebookModel {
return this._sessionLoadFinished;
}
/**
* Indicates all result grid output has been converted to mimeType and html.
*/
public get gridDataConversionComplete(): Promise<any> {
let promises = [];
for (let cell of this._cells) {
promises.push(cell.gridDataConversionComplete);
}
return Promise.all(promises);
}
/**
* Notifies when the client session is ready for use
*/