mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Adding back save api (#4407)
* #4339: Kernel change event occurs after model load * #4347: Code cleanup - Notebooks Save * Remove save method from sqlops * Adding save method to api's * Adding save method to ext host * Misc change
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>save_inverse</title><path class="cls-1" d="M14,1a1,1,0,0,1,.39.08,1,1,0,0,1,.53.53A1,1,0,0,1,15,2V15H2.79L1,13.2V2a1,1,0,0,1,.08-.39,1,1,0,0,1,.53-.53A1,1,0,0,1,2,1Zm0,1H13V8H3V2H2V12.79L3.2,14H4V10h7v4h3ZM4,7h8V2H4Zm6,4H5v3H6V12H7v2h3Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 391 B |
@@ -1 +0,0 @@
|
|||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>save</title><path d="M14,1a1,1,0,0,1,.39.08,1,1,0,0,1,.53.53A1,1,0,0,1,15,2V15H2.79L1,13.2V2a1,1,0,0,1,.08-.39,1,1,0,0,1,.53-.53A1,1,0,0,1,2,1Zm0,1H13V8H3V2H2V12.79L3.2,14H4V10h7v4h3ZM4,7h8V2H4Zm6,4H5v3H6V12H7v2h3Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 323 B |
@@ -370,12 +370,6 @@ export interface INotebookModel {
|
|||||||
*/
|
*/
|
||||||
deleteCell(cellModel: ICellModel): void;
|
deleteCell(cellModel: ICellModel): void;
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the model to its backing content manager.
|
|
||||||
* Serializes the model and then calls through to save it
|
|
||||||
*/
|
|
||||||
saveModel(): Promise<boolean>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize notebook cell content to JSON
|
* Serialize notebook cell content to JSON
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -766,20 +766,6 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async saveModel(): Promise<boolean> {
|
|
||||||
let notebook = this.toJSON();
|
|
||||||
if (!notebook) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// TODO: refactor ContentManager out from NotebookManager
|
|
||||||
await this.notebookManagers[0].contentManager.save(this._notebookOptions.notebookUri, notebook);
|
|
||||||
this._contentChangedEmitter.fire({
|
|
||||||
changeType: NotebookChangeType.DirtyStateChanged,
|
|
||||||
isDirty: false
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async updateKernelInfo(kernel: nb.IKernel): Promise<void> {
|
private async updateKernelInfo(kernel: nb.IKernel): Promise<void> {
|
||||||
if (kernel) {
|
if (kernel) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -18,12 +18,6 @@ import { IAction, Action, IActionItem } from 'vs/base/common/actions';
|
|||||||
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { fillInActions, LabeledMenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem';
|
import { fillInActions, LabeledMenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||||
import { Schemas } from 'vs/base/common/network';
|
|
||||||
import { URI } from 'vs/base/common/uri';
|
|
||||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
|
||||||
import * as paths from 'vs/base/common/paths';
|
|
||||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||||
import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions';
|
import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions';
|
||||||
|
|
||||||
@@ -32,7 +26,7 @@ import { AngularDisposable } from 'sql/base/node/lifecycle';
|
|||||||
import { CellTypes, CellType } from 'sql/parts/notebook/models/contracts';
|
import { CellTypes, CellType } from 'sql/parts/notebook/models/contracts';
|
||||||
import { ICellModel, IModelFactory, INotebookModel, NotebookContentChange, notebookConstants } from 'sql/parts/notebook/models/modelInterfaces';
|
import { ICellModel, IModelFactory, INotebookModel, NotebookContentChange, notebookConstants } from 'sql/parts/notebook/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_FILETYPE, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/common/notebookService';
|
import { INotebookService, INotebookParams, INotebookManager, INotebookEditor, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/common/notebookService';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
||||||
import { ModelFactory } from 'sql/parts/notebook/models/modelFactory';
|
import { ModelFactory } from 'sql/parts/notebook/models/modelFactory';
|
||||||
@@ -40,11 +34,10 @@ import * as notebookUtils from 'sql/parts/notebook/notebookUtils';
|
|||||||
import { Deferred } from 'sql/base/common/promise';
|
import { Deferred } from 'sql/base/common/promise';
|
||||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
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 { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, SaveNotebookAction } from 'sql/parts/notebook/notebookActions';
|
import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction } from 'sql/parts/notebook/notebookActions';
|
||||||
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/common/objectExplorerService';
|
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/common/objectExplorerService';
|
||||||
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
import { IResourceInput } from 'vs/platform/editor/common/editor';
|
|
||||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||||
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
||||||
@@ -90,11 +83,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
@Inject(IContextKeyService) private contextKeyService: IContextKeyService,
|
@Inject(IContextKeyService) private contextKeyService: IContextKeyService,
|
||||||
@Inject(IMenuService) private menuService: IMenuService,
|
@Inject(IMenuService) private menuService: IMenuService,
|
||||||
@Inject(IKeybindingService) private keybindingService: IKeybindingService,
|
@Inject(IKeybindingService) private keybindingService: IKeybindingService,
|
||||||
@Inject(IHistoryService) private historyService: IHistoryService,
|
|
||||||
@Inject(IWindowService) private windowService: IWindowService,
|
|
||||||
@Inject(IViewletService) private viewletService: IViewletService,
|
@Inject(IViewletService) private viewletService: IViewletService,
|
||||||
@Inject(IUntitledEditorService) private untitledEditorService: IUntitledEditorService,
|
|
||||||
@Inject(IEditorGroupsService) private editorGroupService: IEditorGroupsService,
|
|
||||||
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService
|
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -316,6 +305,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
}
|
}
|
||||||
return this._notebookParams.modelFactory;
|
return this._notebookParams.modelFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleModelError(notification: INotification): void {
|
private handleModelError(notification: INotification): void {
|
||||||
this.notificationService.notify(notification);
|
this.notificationService.notify(notification);
|
||||||
}
|
}
|
||||||
@@ -367,8 +357,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted');
|
this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted');
|
||||||
this._trustedAction.enabled = false;
|
this._trustedAction.enabled = false;
|
||||||
|
|
||||||
let saveNotebookButton = this.instantiationService.createInstance(SaveNotebookAction, 'notebook.SaveNotebook', localize('save', 'Save'), 'notebook-button icon-save');
|
|
||||||
|
|
||||||
let taskbar = <HTMLElement>this.toolbar.nativeElement;
|
let taskbar = <HTMLElement>this.toolbar.nativeElement;
|
||||||
this._actionBar = new Taskbar(taskbar, this.contextMenuService, { actionItemProvider: action => this.actionItemProvider(action as Action) });
|
this._actionBar = new Taskbar(taskbar, this.contextMenuService, { actionItemProvider: action => this.actionItemProvider(action as Action) });
|
||||||
this._actionBar.context = this;
|
this._actionBar.context = this;
|
||||||
@@ -377,101 +365,11 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
{ element: attachToContainer },
|
{ element: attachToContainer },
|
||||||
{ action: addCodeCellButton },
|
{ action: addCodeCellButton },
|
||||||
{ action: addTextCellButton },
|
{ action: addTextCellButton },
|
||||||
{ action: saveNotebookButton },
|
|
||||||
{ action: this._trustedAction }
|
{ action: this._trustedAction }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets file path from recent workspace in local
|
|
||||||
private getLastActiveFilePath(untitledResource: URI): string {
|
|
||||||
let fileName = untitledResource.path + '.' + DEFAULT_NOTEBOOK_FILETYPE.toLocaleLowerCase();
|
|
||||||
|
|
||||||
let lastActiveFile = this.historyService.getLastActiveFile(Schemas.file);
|
|
||||||
if (lastActiveFile) {
|
|
||||||
return URI.file(paths.join(paths.dirname(lastActiveFile.fsPath), fileName)).fsPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastActiveFolder = this.historyService.getLastActiveWorkspaceRoot('file');
|
|
||||||
if (lastActiveFolder) {
|
|
||||||
return URI.file(paths.join(lastActiveFolder.fsPath, fileName)).fsPath;
|
|
||||||
}
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
promptForPath(defaultPath: string): TPromise<string> {
|
|
||||||
return this.windowService.showSaveDialog({
|
|
||||||
defaultPath: defaultPath,
|
|
||||||
filters: [{ name: localize('notebookFile', 'Notebook'), extensions: ['ipynb'] }]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry point to save notebook
|
|
||||||
public async save(): Promise<boolean> {
|
|
||||||
let self = this;
|
|
||||||
let notebookUri = this.notebookParams.notebookUri;
|
|
||||||
if (notebookUri.scheme === Schemas.untitled) {
|
|
||||||
let dialogPath = this.getLastActiveFilePath(notebookUri);
|
|
||||||
return this.promptForPath(dialogPath).then(path => {
|
|
||||||
if (path) {
|
|
||||||
let target = URI.file(path);
|
|
||||||
let resource = self._model.notebookUri;
|
|
||||||
self._model.notebookUri = target;
|
|
||||||
this.saveNotebook().then(result => {
|
|
||||||
if (result) {
|
|
||||||
return this.replaceUntitledNotebookEditor(resource, target);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false; // User clicks cancel
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return await this.saveNotebook();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replaces untitled notebook editor with the saved file name
|
|
||||||
private async replaceUntitledNotebookEditor(resource: URI, target: URI): Promise<boolean> {
|
|
||||||
let encodingOfSource = this.untitledEditorService.getEncoding(resource);
|
|
||||||
const replacement: IResourceInput = {
|
|
||||||
resource: target,
|
|
||||||
encoding: encodingOfSource,
|
|
||||||
options: {
|
|
||||||
pinned: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return TPromise.join(this.editorGroupService.groups.map(g =>
|
|
||||||
this.editorService.replaceEditors([{
|
|
||||||
editor: { resource },
|
|
||||||
replacement
|
|
||||||
}], g))).then(() => {
|
|
||||||
this.notebookService.renameNotebookEditor(resource, target, this);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async saveNotebook(): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
let saved = await this._model.saveModel();
|
|
||||||
if (saved) {
|
|
||||||
this.setDirty(false);
|
|
||||||
}
|
|
||||||
return saved;
|
|
||||||
} catch (err) {
|
|
||||||
this.notificationService.error(localize('saveFailed', 'Failed to save notebook: {0}', notebookUtils.getErrorMessage(err)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private setDirty(isDirty: boolean): void {
|
|
||||||
if (this._notebookParams.input) {
|
|
||||||
this._notebookParams.input.setDirty(isDirty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private actionItemProvider(action: Action): IActionItem {
|
private actionItemProvider(action: Action): IActionItem {
|
||||||
// Check extensions to create ActionItem; otherwise, return undefined
|
// Check extensions to create ActionItem; otherwise, return undefined
|
||||||
// This is similar behavior that exists in MenuItemActionItem
|
// This is similar behavior that exists in MenuItemActionItem
|
||||||
|
|||||||
@@ -68,19 +68,11 @@
|
|||||||
background-image: url("./media/dark/nottrusted_inverse.svg");
|
background-image: url("./media/dark/nottrusted_inverse.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.notebookEditor .notebook-button.icon-save{
|
|
||||||
background-image: url("./media/light/save.svg");
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs-dark .notebookEditor .notebook-button.icon-save,
|
|
||||||
.hc-black .notebookEditor .notebook-button.icon-save{
|
|
||||||
background-image: url("./media/dark/save_inverse.svg");
|
|
||||||
}
|
|
||||||
|
|
||||||
.moreActions .action-label.icon.toggle-more {
|
.moreActions .action-label.icon.toggle-more {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.moreActions.actionhidden {
|
.moreActions.actionhidden {
|
||||||
visibility: hidden
|
visibility: hidden
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,26 +53,6 @@ export class AddCellAction extends Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SaveNotebookAction extends Action {
|
|
||||||
private static readonly notebookSavedMsg = localize('notebookSavedMsg', 'Notebook saved successfully.');
|
|
||||||
private static readonly notebookFailedSaveMsg = localize('notebookFailedSaveMsg', 'Failed to save Notebook.');
|
|
||||||
constructor(
|
|
||||||
id: string, label: string, cssClass: string,
|
|
||||||
@INotificationService private _notificationService: INotificationService
|
|
||||||
) {
|
|
||||||
super(id, label, cssClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async run(context: NotebookComponent): TPromise<boolean> {
|
|
||||||
const actions: INotificationActions = { primary: [] };
|
|
||||||
let saved = await context.save();
|
|
||||||
if (saved) {
|
|
||||||
this._notificationService.notify({ severity: Severity.Info, message: SaveNotebookAction.notebookSavedMsg, actions });
|
|
||||||
}
|
|
||||||
return saved;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IToggleableState {
|
export interface IToggleableState {
|
||||||
baseClass?: string;
|
baseClass?: string;
|
||||||
shouldToggleTooltip?: boolean;
|
shouldToggleTooltip?: boolean;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class MainThreadNotebookEditor extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public save(): Thenable<boolean> {
|
public save(): Thenable<boolean> {
|
||||||
return this.editor.save();
|
return this.editor.notebookParams.input.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public matches(input: NotebookInput): boolean {
|
public matches(input: NotebookInput): boolean {
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ export interface INotebookEditor {
|
|||||||
isDirty(): boolean;
|
isDirty(): boolean;
|
||||||
isActive(): boolean;
|
isActive(): boolean;
|
||||||
isVisible(): boolean;
|
isVisible(): boolean;
|
||||||
save(): Promise<boolean>;
|
|
||||||
executeEdits(edits: ISingleNotebookEditOperation[]): boolean;
|
executeEdits(edits: ISingleNotebookEditOperation[]): boolean;
|
||||||
runCell(cell: ICellModel): Promise<boolean>;
|
runCell(cell: ICellModel): Promise<boolean>;
|
||||||
}
|
}
|
||||||
@@ -89,9 +89,6 @@ export class NotebookModelStub implements INotebookModel {
|
|||||||
deleteCell(cellModel: ICellModel): void {
|
deleteCell(cellModel: ICellModel): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
saveModel(): Promise<boolean> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
pushEditOperations(edits: ISingleNotebookEditOperation[]): void {
|
pushEditOperations(edits: ISingleNotebookEditOperation[]): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user