mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Notebook Views (#13465)
* Add notebook editor Introduce notebook editor component to allow for separate notebook displays in order to accomodate notebook views * Localize notebook views configuration title * Refactor view mode and remove the views configuration while it is unused * Only fire view mode changed event when the value has been changed * Remove notebook views contribution
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { nb } from 'azdata';
|
import { nb } from 'azdata';
|
||||||
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, OnDestroy, ViewChildren, QueryList } from '@angular/core';
|
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, OnDestroy, ViewChildren, QueryList, Input } from '@angular/core';
|
||||||
|
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import * as themeColors from 'vs/workbench/common/theme';
|
import * as themeColors from 'vs/workbench/common/theme';
|
||||||
@@ -22,21 +22,17 @@ import * as DOM from 'vs/base/browser/dom';
|
|||||||
|
|
||||||
import { AngularDisposable } from 'sql/base/browser/lifecycle';
|
import { AngularDisposable } from 'sql/base/browser/lifecycle';
|
||||||
import { CellTypes, CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts';
|
import { CellTypes, CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts';
|
||||||
import { ICellModel, IModelFactory, INotebookModel, NotebookContentChange } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
import { ICellModel, INotebookModel, NotebookContentChange } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||||
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||||
import { INotebookService, INotebookParams, INotebookManager, INotebookEditor, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER, INotebookSection, INavigationProvider, ICellEditorProvider, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
import { INotebookService, INotebookParams, INotebookEditor, INotebookSection, INavigationProvider, ICellEditorProvider, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||||
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
||||||
import { ModelFactory } from 'sql/workbench/services/notebook/browser/models/modelFactory';
|
|
||||||
import * as notebookUtils from 'sql/workbench/services/notebook/browser/models/notebookUtils';
|
|
||||||
import { Deferred } from 'sql/base/common/promise';
|
import { Deferred } from 'sql/base/common/promise';
|
||||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
|
||||||
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
import { AddCellAction, KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
|
import { AddCellAction, KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
|
||||||
import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu';
|
import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu';
|
||||||
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
||||||
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
||||||
import { CellMagicMapper } from 'sql/workbench/contrib/notebook/browser/models/cellMagicMapper';
|
|
||||||
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
|
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
|
||||||
import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||||
import { isValidBasename } from 'vs/base/common/extpath';
|
import { isValidBasename } from 'vs/base/common/extpath';
|
||||||
@@ -54,7 +50,6 @@ import { CodeCellComponent } from 'sql/workbench/contrib/notebook/browser/cellVi
|
|||||||
import { TextCellComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/textCell.component';
|
import { TextCellComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/textCell.component';
|
||||||
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
||||||
import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||||
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
|
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
|
||||||
|
|
||||||
@@ -73,12 +68,11 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
@ViewChildren(TextCellComponent) private textCells: QueryList<TextCellComponent>;
|
@ViewChildren(TextCellComponent) private textCells: QueryList<TextCellComponent>;
|
||||||
@ViewChildren(CellToolbarComponent) private cellToolbar: QueryList<CellToolbarComponent>;
|
@ViewChildren(CellToolbarComponent) private cellToolbar: QueryList<CellToolbarComponent>;
|
||||||
|
|
||||||
private _model: NotebookModel;
|
@Input() _model: NotebookModel;
|
||||||
|
|
||||||
protected _actionBar: Taskbar;
|
protected _actionBar: Taskbar;
|
||||||
protected isLoading: boolean;
|
protected isLoading: boolean;
|
||||||
private notebookManagers: INotebookManager[] = [];
|
|
||||||
private _modelReadyDeferred = new Deferred<NotebookModel>();
|
private _modelReadyDeferred = new Deferred<NotebookModel>();
|
||||||
private profile: IConnectionProfile;
|
|
||||||
private _trustedAction: TrustedAction;
|
private _trustedAction: TrustedAction;
|
||||||
private _runAllCellsAction: RunAllCellsAction;
|
private _runAllCellsAction: RunAllCellsAction;
|
||||||
private _providerRelatedActions: IAction[] = [];
|
private _providerRelatedActions: IAction[] = [];
|
||||||
@@ -106,11 +100,9 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService,
|
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService,
|
||||||
@Inject(ITextFileService) private textFileService: ITextFileService,
|
@Inject(ITextFileService) private textFileService: ITextFileService,
|
||||||
@Inject(ILogService) private readonly logService: ILogService,
|
@Inject(ILogService) private readonly logService: ILogService,
|
||||||
@Inject(IAdsTelemetryService) private adstelemetryService: IAdsTelemetryService,
|
|
||||||
@Inject(IConfigurationService) private _configurationService: IConfigurationService
|
@Inject(IConfigurationService) private _configurationService: IConfigurationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.updateProfile();
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.doubleClickEditEnabled = this._configurationService.getValue('notebook.enableDoubleClickEdit');
|
this.doubleClickEditEnabled = this._configurationService.getValue('notebook.enableDoubleClickEdit');
|
||||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
@@ -121,15 +113,12 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateProfile(): void {
|
|
||||||
this.profile = this.notebookParams ? this.notebookParams.profile : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
|
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
|
||||||
this.updateTheme(this.themeService.getColorTheme());
|
this.updateTheme(this.themeService.getColorTheme());
|
||||||
this.initActionBar();
|
this.initActionBar();
|
||||||
this.setScrollPosition();
|
this.setScrollPosition();
|
||||||
|
|
||||||
this.doLoad().catch(e => onUnexpectedError(e));
|
this.doLoad().catch(e => onUnexpectedError(e));
|
||||||
this.initNavSection();
|
this.initNavSection();
|
||||||
}
|
}
|
||||||
@@ -260,11 +249,11 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
|
|
||||||
private async doLoad(): Promise<void> {
|
private async doLoad(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.createModelAndLoadContents();
|
await this.registerModel();
|
||||||
this._modelReadyDeferred.resolve(this._model);
|
this._modelReadyDeferred.resolve(this._model);
|
||||||
this.notebookService.addNotebookEditor(this);
|
this.notebookService.addNotebookEditor(this);
|
||||||
await this.setNotebookManager();
|
await this._model.onClientSessionReady;
|
||||||
await this.loadModel();
|
this.detectChanges();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
// Offer to create a file from the error if we have a file not found and the name is valid
|
// Offer to create a file from the error if we have a file not found and the name is valid
|
||||||
@@ -305,41 +294,14 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadModel(): Promise<void> {
|
private async registerModel(): Promise<void> {
|
||||||
// Wait on provider information to be available before loading kernel and other information
|
this._register(this._model.onError((errInfo: INotification) => this.handleModelError(errInfo)));
|
||||||
await this.awaitNonDefaultProvider();
|
this._register(this._model.contentChanged((change) => this.handleContentChanged(change)));
|
||||||
await this._model.requestModelLoad();
|
this._register(this._model.onProviderIdChange((provider) => this.handleProviderIdChanged(provider)));
|
||||||
this.detectChanges();
|
this._register(this._model.kernelChanged((kernelArgs) => this.handleKernelChanged(kernelArgs)));
|
||||||
this.setContextKeyServiceWithProviderId(this._model.providerId);
|
this._register(this._model.onCellTypeChanged(() => this.detectChanges()));
|
||||||
await this._model.startSession(this._model.notebookManager, undefined, true);
|
this._register(this._model.layoutChanged(() => this.detectChanges()));
|
||||||
this.fillInActionsForCurrentContext();
|
|
||||||
this.detectChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createModelAndLoadContents(): Promise<void> {
|
|
||||||
let model = new NotebookModel({
|
|
||||||
factory: this.modelFactory,
|
|
||||||
notebookUri: this._notebookParams.notebookUri,
|
|
||||||
connectionService: this.connectionManagementService,
|
|
||||||
notificationService: this.notificationService,
|
|
||||||
notebookManagers: this.notebookManagers,
|
|
||||||
contentManager: this._notebookParams.input.contentManager,
|
|
||||||
cellMagicMapper: new CellMagicMapper(this.notebookService.languageMagics),
|
|
||||||
providerId: 'sql',
|
|
||||||
defaultKernel: this._notebookParams.input.defaultKernel,
|
|
||||||
layoutChanged: this._notebookParams.input.layoutChanged,
|
|
||||||
capabilitiesService: this.capabilitiesService,
|
|
||||||
editorLoadedTimestamp: this._notebookParams.input.editorOpenedTimestamp
|
|
||||||
}, this.profile, this.logService, this.notificationService, this.adstelemetryService, this.connectionManagementService, this._configurationService, this.capabilitiesService);
|
|
||||||
let trusted = await this.notebookService.isNotebookTrustCached(this._notebookParams.notebookUri, this.isDirty());
|
|
||||||
this._register(model.onError((errInfo: INotification) => this.handleModelError(errInfo)));
|
|
||||||
this._register(model.contentChanged((change) => this.handleContentChanged(change)));
|
|
||||||
this._register(model.onProviderIdChange((provider) => this.handleProviderIdChanged(provider)));
|
|
||||||
this._register(model.kernelChanged((kernelArgs) => this.handleKernelChanged(kernelArgs)));
|
|
||||||
this._register(model.onCellTypeChanged(() => this.detectChanges()));
|
|
||||||
this._register(model.layoutChanged(() => this.detectChanges()));
|
|
||||||
this._model = this._register(model);
|
|
||||||
await this._model.loadContents(trusted);
|
|
||||||
this.setLoading(false);
|
this.setLoading(false);
|
||||||
// Check if URI fragment is present; if it is, navigate to section by default
|
// Check if URI fragment is present; if it is, navigate to section by default
|
||||||
this.navigateToSectionIfURIFragmentExists();
|
this.navigateToSectionIfURIFragmentExists();
|
||||||
@@ -347,28 +309,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setNotebookManager(): Promise<void> {
|
|
||||||
let providerInfo = await this._notebookParams.providerInfo;
|
|
||||||
for (let providerId of providerInfo.providers) {
|
|
||||||
let notebookManager = await this.notebookService.getOrCreateNotebookManager(providerId, this._notebookParams.notebookUri);
|
|
||||||
this.notebookManagers.push(notebookManager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async awaitNonDefaultProvider(): Promise<void> {
|
|
||||||
// Wait on registration for now. Long-term would be good to cache and refresh
|
|
||||||
await this.notebookService.registrationComplete;
|
|
||||||
this.model.standardKernels = this._notebookParams.input.standardKernels;
|
|
||||||
// Refresh the provider if we had been using default
|
|
||||||
let providerInfo = await this._notebookParams.providerInfo;
|
|
||||||
|
|
||||||
if (DEFAULT_NOTEBOOK_PROVIDER === providerInfo.providerId) {
|
|
||||||
let providers = notebookUtils.getProvidersForFileName(this._notebookParams.notebookUri.fsPath, this.notebookService);
|
|
||||||
let tsqlProvider = providers.find(provider => provider === SQL_NOTEBOOK_PROVIDER);
|
|
||||||
providerInfo.providerId = tsqlProvider ? SQL_NOTEBOOK_PROVIDER : providers[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateToolbarComponents() {
|
private updateToolbarComponents() {
|
||||||
this._trustedAction.enabled = true;
|
this._trustedAction.enabled = true;
|
||||||
if (this.model.trustedMode) {
|
if (this.model.trustedMode) {
|
||||||
@@ -376,13 +316,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private get modelFactory(): IModelFactory {
|
|
||||||
if (!this._notebookParams.modelFactory) {
|
|
||||||
this._notebookParams.modelFactory = new ModelFactory(this.instantiationService);
|
|
||||||
}
|
|
||||||
return this._notebookParams.modelFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleModelError(notification: INotification): void {
|
private handleModelError(notification: INotification): void {
|
||||||
this.notificationService.notify(notification);
|
this.notificationService.notify(notification);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { ICellComponentRegistry, Extensions as OutputComponentExtensions } from
|
|||||||
import { CollapseComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/collapse.component';
|
import { CollapseComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/collapse.component';
|
||||||
import { MarkdownToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component';
|
import { MarkdownToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component';
|
||||||
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
|
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
|
||||||
|
import { NotebookEditorComponent } from 'sql/workbench/contrib/notebook/browser/notebookEditor.component';
|
||||||
|
|
||||||
const outputComponentRegistry = Registry.as<ICellComponentRegistry>(OutputComponentExtensions.CellComponentContributions);
|
const outputComponentRegistry = Registry.as<ICellComponentRegistry>(OutputComponentExtensions.CellComponentContributions);
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ export const NotebookModule = (params, selector: string, instantiationService: I
|
|||||||
MarkdownToolbarComponent,
|
MarkdownToolbarComponent,
|
||||||
PlaceholderCellComponent,
|
PlaceholderCellComponent,
|
||||||
NotebookComponent,
|
NotebookComponent,
|
||||||
|
NotebookEditorComponent,
|
||||||
ComponentHostDirective,
|
ComponentHostDirective,
|
||||||
OutputAreaComponent,
|
OutputAreaComponent,
|
||||||
OutputComponent,
|
OutputComponent,
|
||||||
@@ -62,6 +64,7 @@ export const NotebookModule = (params, selector: string, instantiationService: I
|
|||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
NotebookComponent,
|
NotebookComponent,
|
||||||
|
NotebookEditorComponent,
|
||||||
...outputComponents
|
...outputComponents
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
@@ -86,7 +89,7 @@ export const NotebookModule = (params, selector: string, instantiationService: I
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factoryWrapper: any = this._resolver.resolveComponentFactory(NotebookComponent);
|
const factoryWrapper: any = this._resolver.resolveComponentFactory(NotebookEditorComponent);
|
||||||
factoryWrapper.factory.selector = this.selector;
|
factoryWrapper.factory.selector = this.selector;
|
||||||
appRef.bootstrap(factoryWrapper);
|
appRef.bootstrap(factoryWrapper);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<!--
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
-->
|
||||||
|
<!-- Notebook View -->
|
||||||
|
<notebook-component *ngIf="viewMode === 0" [_model]="model"></notebook-component>
|
||||||
|
<!-- Dashboard View: To be implemented-->
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import { Component, Inject, ChangeDetectorRef, forwardRef } from '@angular/core';
|
||||||
|
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
||||||
|
import * as notebookUtils from 'sql/workbench/services/notebook/browser/models/notebookUtils';
|
||||||
|
import { AngularDisposable } from 'sql/base/browser/lifecycle';
|
||||||
|
import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
|
||||||
|
import { INotebookParams, INotebookService, INotebookManager, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||||
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||||
|
import { CellMagicMapper } from 'sql/workbench/contrib/notebook/browser/models/cellMagicMapper';
|
||||||
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
|
import { IModelFactory, ViewMode, NotebookContentChange } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||||
|
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { ModelFactory } from 'sql/workbench/services/notebook/browser/models/modelFactory';
|
||||||
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
|
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { IAction } from 'vs/base/common/actions';
|
||||||
|
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||||
|
import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
|
||||||
|
export const NOTEBOOKEDITOR_SELECTOR: string = 'notebookeditor-component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: NOTEBOOKEDITOR_SELECTOR,
|
||||||
|
templateUrl: decodeURI(require.toUrl('./notebookEditor.component.html'))
|
||||||
|
})
|
||||||
|
export class NotebookEditorComponent extends AngularDisposable {
|
||||||
|
private profile: IConnectionProfile;
|
||||||
|
private notebookManagers: INotebookManager[] = [];
|
||||||
|
private _model: NotebookModel;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(ILogService) private readonly logService: ILogService,
|
||||||
|
@Inject(IBootstrapParams) private _notebookParams: INotebookParams,
|
||||||
|
@Inject(INotebookService) private notebookService: INotebookService,
|
||||||
|
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService,
|
||||||
|
@Inject(IContextKeyService) private contextKeyService: IContextKeyService,
|
||||||
|
@Inject(IMenuService) private menuService: IMenuService,
|
||||||
|
@Inject(INotificationService) private notificationService: INotificationService,
|
||||||
|
@Inject(IAdsTelemetryService) private adstelemetryService: IAdsTelemetryService,
|
||||||
|
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
||||||
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
|
||||||
|
@Inject(IConfigurationService) private _configurationService: IConfigurationService,
|
||||||
|
@Inject(IConnectionManagementService) private connectionManagementService: IConnectionManagementService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.updateProfile();
|
||||||
|
}
|
||||||
|
ngOnInit() {
|
||||||
|
this.doLoad().catch(e => onUnexpectedError(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateProfile(): void {
|
||||||
|
this.profile = this._notebookParams ? this._notebookParams.profile : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private detectChanges(): void {
|
||||||
|
if (!(this._changeRef['destroyed'])) {
|
||||||
|
this._changeRef.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async doLoad(): Promise<void> {
|
||||||
|
await this.createModelAndLoadContents();
|
||||||
|
await this.setNotebookManager();
|
||||||
|
await this.loadModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async loadModel(): Promise<void> {
|
||||||
|
// Wait on provider information to be available before loading kernel and other information
|
||||||
|
await this.awaitNonDefaultProvider();
|
||||||
|
await this.model.requestModelLoad();
|
||||||
|
this.detectChanges();
|
||||||
|
this.setContextKeyServiceWithProviderId(this.model.providerId);
|
||||||
|
await this.model.startSession(this.model.notebookManager, undefined, true);
|
||||||
|
this.fillInActionsForCurrentContext();
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createModelAndLoadContents(): Promise<void> {
|
||||||
|
let model = new NotebookModel({
|
||||||
|
factory: this.modelFactory,
|
||||||
|
notebookUri: this._notebookParams.notebookUri,
|
||||||
|
connectionService: this.connectionManagementService,
|
||||||
|
notificationService: this.notificationService,
|
||||||
|
notebookManagers: this.notebookManagers,
|
||||||
|
contentManager: this._notebookParams.input.contentManager,
|
||||||
|
cellMagicMapper: new CellMagicMapper(this.notebookService.languageMagics),
|
||||||
|
providerId: 'sql',
|
||||||
|
defaultKernel: this._notebookParams.input.defaultKernel,
|
||||||
|
layoutChanged: this._notebookParams.input.layoutChanged,
|
||||||
|
capabilitiesService: this.capabilitiesService,
|
||||||
|
editorLoadedTimestamp: this._notebookParams.input.editorOpenedTimestamp
|
||||||
|
}, this.profile, this.logService, this.notificationService, this.adstelemetryService, this.connectionManagementService, this._configurationService, this.capabilitiesService);
|
||||||
|
|
||||||
|
let trusted = await this.notebookService.isNotebookTrustCached(this._notebookParams.notebookUri, this.isDirty());
|
||||||
|
this._model = this._register(model);
|
||||||
|
await this.model.loadContents(trusted);
|
||||||
|
|
||||||
|
this._register(model.viewModeChanged((mode) => this.onViewModeChanged()));
|
||||||
|
this._register(model.contentChanged((change) => this.handleContentChanged(change)));
|
||||||
|
this._register(model.onCellTypeChanged(() => this.detectChanges()));
|
||||||
|
this._register(model.layoutChanged(() => this.detectChanges()));
|
||||||
|
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setNotebookManager(): Promise<void> {
|
||||||
|
let providerInfo = await this._notebookParams.providerInfo;
|
||||||
|
for (let providerId of providerInfo.providers) {
|
||||||
|
let notebookManager = await this.notebookService.getOrCreateNotebookManager(providerId, this._notebookParams.notebookUri);
|
||||||
|
this.notebookManagers.push(notebookManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setContextKeyServiceWithProviderId(providerId: string) {
|
||||||
|
let provider = new RawContextKey<string>('providerId', providerId);
|
||||||
|
provider.bindTo(this.contextKeyService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async awaitNonDefaultProvider(): Promise<void> {
|
||||||
|
// Wait on registration for now. Long-term would be good to cache and refresh
|
||||||
|
await this.notebookService.registrationComplete;
|
||||||
|
this.model.standardKernels = this._notebookParams.input.standardKernels;
|
||||||
|
// Refresh the provider if we had been using default
|
||||||
|
let providerInfo = await this._notebookParams.providerInfo;
|
||||||
|
|
||||||
|
if (DEFAULT_NOTEBOOK_PROVIDER === providerInfo.providerId) {
|
||||||
|
let providers = notebookUtils.getProvidersForFileName(this._notebookParams.notebookUri.fsPath, this.notebookService);
|
||||||
|
let tsqlProvider = providers.find(provider => provider === SQL_NOTEBOOK_PROVIDER);
|
||||||
|
providerInfo.providerId = tsqlProvider ? SQL_NOTEBOOK_PROVIDER : providers[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the menu contributions that use the ID 'notebook/toolbar'.
|
||||||
|
* Then, find all groups (currently we don't leverage the contributed
|
||||||
|
* groups functionality for the notebook toolbar), and fill in the 'primary'
|
||||||
|
* array with items that don't list a group. Finally, add any actions from
|
||||||
|
* the primary array to the end of the toolbar.
|
||||||
|
*/
|
||||||
|
private fillInActionsForCurrentContext(): void {
|
||||||
|
let primary: IAction[] = [];
|
||||||
|
let secondary: IAction[] = [];
|
||||||
|
let notebookBarMenu = this.menuService.createMenu(MenuId.NotebookToolbar, this.contextKeyService);
|
||||||
|
let groups = notebookBarMenu.getActions({ arg: null, shouldForwardArgs: true });
|
||||||
|
fillInActions(groups, { primary, secondary }, false, (group: string) => group === undefined || group === '');
|
||||||
|
//this.addPrimaryContributedActions(primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get modelFactory(): IModelFactory {
|
||||||
|
if (!this._notebookParams.modelFactory) {
|
||||||
|
this._notebookParams.modelFactory = new ModelFactory(this.instantiationService);
|
||||||
|
}
|
||||||
|
return this._notebookParams.modelFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get model(): NotebookModel | null {
|
||||||
|
return this._model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get viewMode(): ViewMode {
|
||||||
|
return this.model?.viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isDirty(): boolean {
|
||||||
|
return this._notebookParams.input.isDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleContentChanged(change: NotebookContentChange) {
|
||||||
|
// Note: for now we just need to set dirty state and refresh the UI.
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public onViewModeChanged(): void {
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
||||||
import { NotebookModule } from 'sql/workbench/contrib/notebook/browser/notebook.module';
|
import { NotebookModule } from 'sql/workbench/contrib/notebook/browser/notebook.module';
|
||||||
import { NOTEBOOK_SELECTOR } from 'sql/workbench/contrib/notebook/browser/notebook.component';
|
import { NOTEBOOKEDITOR_SELECTOR } from 'sql/workbench/contrib/notebook/browser/notebookEditor.component';
|
||||||
import { INotebookParams, INotebookService, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
import { INotebookParams, INotebookService, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
import { ACTION_IDS, NOTEBOOK_MAX_MATCHES, IFindNotebookController, FindWidget, IConfigurationChangedEvent } from 'sql/workbench/contrib/notebook/browser/find/notebookFindWidget';
|
import { ACTION_IDS, NOTEBOOK_MAX_MATCHES, IFindNotebookController, FindWidget, IConfigurationChangedEvent } from 'sql/workbench/contrib/notebook/browser/find/notebookFindWidget';
|
||||||
@@ -235,7 +235,7 @@ export class NotebookEditor extends EditorPane implements IFindNotebookControlle
|
|||||||
this._instantiationService.invokeFunction(bootstrapAngular,
|
this._instantiationService.invokeFunction(bootstrapAngular,
|
||||||
NotebookModule,
|
NotebookModule,
|
||||||
this._notebookContainer,
|
this._notebookContainer,
|
||||||
NOTEBOOK_SELECTOR,
|
NOTEBOOKEDITOR_SELECTOR,
|
||||||
params,
|
params,
|
||||||
input
|
input
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { nb, IConnectionProfile } from 'azdata';
|
import { nb, IConnectionProfile } from 'azdata';
|
||||||
import * as vsEvent from 'vs/base/common/event';
|
import * as vsEvent from 'vs/base/common/event';
|
||||||
import { INotebookModel, ICellModel, IClientSession, NotebookContentChange, ISingleNotebookEditOperation, MoveDirection } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
import { INotebookModel, ICellModel, IClientSession, NotebookContentChange, ISingleNotebookEditOperation, MoveDirection, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||||
import { INotebookFindModel } from 'sql/workbench/contrib/notebook/browser/models/notebookFindModel';
|
import { INotebookFindModel } from 'sql/workbench/contrib/notebook/browser/models/notebookFindModel';
|
||||||
import { NotebookChangeType, CellType } from 'sql/workbench/services/notebook/common/contracts';
|
import { NotebookChangeType, CellType } from 'sql/workbench/services/notebook/common/contracts';
|
||||||
import { INotebookManager, INotebookService, INotebookEditor, ILanguageMagic, INotebookProvider, INavigationProvider, INotebookParams, INotebookSection, ICellEditorProvider, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
import { INotebookManager, INotebookService, INotebookEditor, ILanguageMagic, INotebookProvider, INavigationProvider, INotebookParams, INotebookSection, ICellEditorProvider, NotebookRange } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||||
@@ -94,6 +94,12 @@ export class NotebookModelStub implements INotebookModel {
|
|||||||
findCellIndex(cellModel: ICellModel): number {
|
findCellIndex(cellModel: ICellModel): number {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
get viewMode() {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
set viewMode(mode: ViewMode) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
addCell(cellType: CellType, index?: number): void {
|
addCell(cellType: CellType, index?: number): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
@@ -439,6 +445,7 @@ export class FutureStub implements nb.IFuture {
|
|||||||
|
|
||||||
export class NotebookComponentStub implements INotebookEditor {
|
export class NotebookComponentStub implements INotebookEditor {
|
||||||
cellEditors: ICellEditorProvider[];
|
cellEditors: ICellEditorProvider[];
|
||||||
|
viewMode: string;
|
||||||
deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void {
|
deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
@@ -651,6 +658,7 @@ export class NotebookEditorStub implements INotebookEditor {
|
|||||||
cellEditors: CellEditorProviderStub[];
|
cellEditors: CellEditorProviderStub[];
|
||||||
modelReady: Promise<INotebookModel>;
|
modelReady: Promise<INotebookModel>;
|
||||||
model: INotebookModel;
|
model: INotebookModel;
|
||||||
|
viewMode: string;
|
||||||
isDirty(): boolean {
|
isDirty(): boolean {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ import type { FutureInternal } from 'sql/workbench/services/notebook/browser/int
|
|||||||
import { ICellValue, ResultSetSummary } from 'sql/workbench/services/query/common/query';
|
import { ICellValue, ResultSetSummary } from 'sql/workbench/services/query/common/query';
|
||||||
import { QueryResultId } from 'sql/workbench/services/notebook/browser/models/cell';
|
import { QueryResultId } from 'sql/workbench/services/notebook/browser/models/cell';
|
||||||
|
|
||||||
|
export enum ViewMode {
|
||||||
|
Notebook,
|
||||||
|
Views,
|
||||||
|
}
|
||||||
|
|
||||||
export interface ICellRange {
|
export interface ICellRange {
|
||||||
readonly start: number;
|
readonly start: number;
|
||||||
readonly end: number;
|
readonly end: number;
|
||||||
@@ -334,6 +339,12 @@ export interface INotebookModel {
|
|||||||
*/
|
*/
|
||||||
providerId: string;
|
providerId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View mode for this model. It determines what editor mode
|
||||||
|
* will be displayed.
|
||||||
|
*/
|
||||||
|
viewMode: ViewMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the current kernel from the Kernel dropdown
|
* Change the current kernel from the Kernel dropdown
|
||||||
* @param displayName kernel name (as displayed in Kernel dropdown)
|
* @param displayName kernel name (as displayed in Kernel dropdown)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { localize } from 'vs/nls';
|
|||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
import { IClientSession, INotebookModel, INotebookModelOptions, ICellModel, NotebookContentChange, MoveDirection } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
import { IClientSession, INotebookModel, INotebookModelOptions, ICellModel, NotebookContentChange, MoveDirection, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||||
import { NotebookChangeType, CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
import { NotebookChangeType, CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
||||||
import { nbversion } from 'sql/workbench/services/notebook/common/notebookConstants';
|
import { nbversion } from 'sql/workbench/services/notebook/common/notebookConstants';
|
||||||
import * as notebookUtils from 'sql/workbench/services/notebook/browser/models/notebookUtils';
|
import * as notebookUtils from 'sql/workbench/services/notebook/browser/models/notebookUtils';
|
||||||
@@ -56,6 +56,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
|||||||
private _contentChangedEmitter = new Emitter<NotebookContentChange>();
|
private _contentChangedEmitter = new Emitter<NotebookContentChange>();
|
||||||
private _kernelsChangedEmitter = new Emitter<nb.IKernel>();
|
private _kernelsChangedEmitter = new Emitter<nb.IKernel>();
|
||||||
private _kernelChangedEmitter = new Emitter<nb.IKernelChangedArgs>();
|
private _kernelChangedEmitter = new Emitter<nb.IKernelChangedArgs>();
|
||||||
|
private _viewModeChangedEmitter = new Emitter<ViewMode>();
|
||||||
private _layoutChanged = new Emitter<void>();
|
private _layoutChanged = new Emitter<void>();
|
||||||
private _inErrorState: boolean = false;
|
private _inErrorState: boolean = false;
|
||||||
private _activeClientSession: IClientSession | undefined;
|
private _activeClientSession: IClientSession | undefined;
|
||||||
@@ -71,6 +72,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
|||||||
private _tags: string[] | undefined;
|
private _tags: string[] | undefined;
|
||||||
private _existingMetadata: nb.INotebookMetadata = {};
|
private _existingMetadata: nb.INotebookMetadata = {};
|
||||||
private _language: string = '';
|
private _language: string = '';
|
||||||
|
private _viewMode: ViewMode = ViewMode.Notebook;
|
||||||
private _onErrorEmitter = new Emitter<INotification>();
|
private _onErrorEmitter = new Emitter<INotification>();
|
||||||
private _savedKernelInfo: nb.IKernelSpec | undefined;
|
private _savedKernelInfo: nb.IKernelSpec | undefined;
|
||||||
private _savedConnectionName: string | undefined;
|
private _savedConnectionName: string | undefined;
|
||||||
@@ -274,6 +276,21 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get viewModeChanged(): Event<ViewMode> {
|
||||||
|
return this._viewModeChangedEmitter.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get viewMode() {
|
||||||
|
return this._viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set viewMode(mode: ViewMode) {
|
||||||
|
if (mode !== this._viewMode) {
|
||||||
|
this._viewMode = mode;
|
||||||
|
this._viewModeChangedEmitter.fire(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the server has finished loading. It may have failed to load in
|
* Indicates the server has finished loading. It may have failed to load in
|
||||||
* which case the view will be in an error state.
|
* which case the view will be in an error state.
|
||||||
|
|||||||
Reference in New Issue
Block a user