mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Move New Notebook command to core (#21247)
This commit is contained in:
@@ -98,14 +98,6 @@
|
|||||||
"command": "notebook.command.analyzeNotebook",
|
"command": "notebook.command.analyzeNotebook",
|
||||||
"title": "%notebook.analyzeJupyterNotebook%"
|
"title": "%notebook.analyzeJupyterNotebook%"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "_notebook.command.new",
|
|
||||||
"title": "%notebook.command.new%",
|
|
||||||
"icon": {
|
|
||||||
"dark": "resources/dark/new_notebook_inverse.svg",
|
|
||||||
"light": "resources/light/new_notebook.svg"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "notebook.command.open",
|
"command": "notebook.command.open",
|
||||||
"title": "%notebook.command.open%"
|
"title": "%notebook.command.open%"
|
||||||
@@ -346,10 +338,6 @@
|
|||||||
"command": "notebook.command.analyzeNotebook",
|
"command": "notebook.command.analyzeNotebook",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "_notebook.command.new",
|
|
||||||
"when": "false"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "notebook.command.open"
|
"command": "notebook.command.open"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ export class NotebookUtils {
|
|||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
public async newNotebook(options?: azdata.nb.NotebookShowOptions): Promise<azdata.nb.NotebookEditor> {
|
|
||||||
return azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }), options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async openNotebook(): Promise<void> {
|
public async openNotebook(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
let filter: { [key: string]: Array<string> } = {};
|
let filter: { [key: string]: Array<string> } = {};
|
||||||
|
|||||||
@@ -85,9 +85,6 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
|
|||||||
return dialog.createDialog();
|
return dialog.createDialog();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
extensionContext.subscriptions.push(vscode.commands.registerCommand('_notebook.command.new', async (options?: azdata.nb.NotebookShowOptions) => {
|
|
||||||
return appContext.notebookUtils.newNotebook(options);
|
|
||||||
}));
|
|
||||||
extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.open', async () => {
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.open', async () => {
|
||||||
await appContext.notebookUtils.openNotebook();
|
await appContext.notebookUtils.openNotebook();
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -906,7 +906,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
|||||||
nbformat_minor: constants.NBFORMAT_MINOR
|
nbformat_minor: constants.NBFORMAT_MINOR
|
||||||
};
|
};
|
||||||
|
|
||||||
await vscode.commands.executeCommand('_notebook.command.new', {
|
await vscode.commands.executeCommand('notebook.command.new', {
|
||||||
initialContent: JSON.stringify(initialContent),
|
initialContent: JSON.stringify(initialContent),
|
||||||
defaultKernel: 'Python 3'
|
defaultKernel: 'Python 3'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
describe('newNotebook', function (): void {
|
describe('newNotebook', function (): void {
|
||||||
it('Should open a new notebook successfully', async function (): Promise<void> {
|
it('Should open a new notebook successfully', async function (): Promise<void> {
|
||||||
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
||||||
await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
||||||
@@ -48,12 +48,12 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
|
|
||||||
it('Opening an untitled editor after closing should re-use previous untitled name', async function (): Promise<void> {
|
it('Opening an untitled editor after closing should re-use previous untitled name', async function (): Promise<void> {
|
||||||
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
||||||
await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
||||||
should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1');
|
should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1');
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
||||||
await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document after second opening');
|
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document after second opening');
|
||||||
should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1 after closing first Untitled Notebook');
|
should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1 after closing first Untitled Notebook');
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
@@ -61,10 +61,11 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
|
|
||||||
it('Untitled Name index should increase', async function (): Promise<void> {
|
it('Untitled Name index should increase', async function (): Promise<void> {
|
||||||
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents');
|
||||||
await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document');
|
||||||
const secondNotebook = await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
should(azdata.nb.notebookDocuments.length).equal(2, 'There should be exactly 2 open Notebook documents');
|
should(azdata.nb.notebookDocuments.length).equal(2, 'There should be exactly 2 open Notebook documents');
|
||||||
|
let secondNotebook = azdata.nb.activeNotebookEditor;
|
||||||
should(secondNotebook.document.fileName).equal('Notebook-2', 'The second Untitled Notebook should have an index of 2');
|
should(secondNotebook.document.fileName).equal('Notebook-2', 'The second Untitled Notebook should have an index of 2');
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
@@ -94,9 +95,9 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('closing and opening an untitled notebook shows correct contents', async function (): Promise<void> {
|
it('closing and opening an untitled notebook shows correct contents', async function (): Promise<void> {
|
||||||
await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||||
await notebookUtils.newNotebook({
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }), {
|
||||||
initialContent: {
|
initialContent: {
|
||||||
cells: [{
|
cells: [{
|
||||||
source: 'test content',
|
source: 'test content',
|
||||||
@@ -183,7 +184,8 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not show error when notebook visible for code cell', async function (): Promise<void> {
|
it('does not show error when notebook visible for code cell', async function (): Promise<void> {
|
||||||
const notebookEditor = await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebookEditor = azdata.nb.activeNotebookEditor;
|
||||||
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
||||||
await notebookUtils.addCell('code');
|
await notebookUtils.addCell('code');
|
||||||
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called');
|
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called');
|
||||||
@@ -192,7 +194,8 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not show error when notebook visible for markdown cell', async function (): Promise<void> {
|
it('does not show error when notebook visible for markdown cell', async function (): Promise<void> {
|
||||||
const notebookEditor = await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebookEditor = azdata.nb.activeNotebookEditor;
|
||||||
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
||||||
await notebookUtils.addCell('markdown');
|
await notebookUtils.addCell('markdown');
|
||||||
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called');
|
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called');
|
||||||
@@ -203,7 +206,8 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
|
|
||||||
describe('analyzeNotebook', function () {
|
describe('analyzeNotebook', function () {
|
||||||
it('creates cell when oeContext exists', async function (): Promise<void> {
|
it('creates cell when oeContext exists', async function (): Promise<void> {
|
||||||
const notebookEditor = await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebookEditor = azdata.nb.activeNotebookEditor;
|
||||||
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
||||||
sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor));
|
sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor));
|
||||||
const oeContext: azdata.ObjectExplorerContext = {
|
const oeContext: azdata.ObjectExplorerContext = {
|
||||||
@@ -226,7 +230,8 @@ describe('notebookUtils Tests', function (): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not create new cell when oeContext does not exist', async function (): Promise<void> {
|
it('does not create new cell when oeContext does not exist', async function (): Promise<void> {
|
||||||
const notebookEditor = await notebookUtils.newNotebook(undefined);
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebookEditor = azdata.nb.activeNotebookEditor;
|
||||||
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor);
|
||||||
sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor));
|
sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor));
|
||||||
await notebookUtils.analyzeNotebook();
|
await notebookUtils.analyzeNotebook();
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ describe('Completion Item Provider', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not provide items when session does not exist in notebook provider', async () => {
|
it('should not provide items when session does not exist in notebook provider', async () => {
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
await notebookUtils.addCell('code');
|
await notebookUtils.addCell('code');
|
||||||
let document = await tryFindTextDocument(notebook);
|
let document = await tryFindTextDocument(notebook);
|
||||||
should(document).not.equal(undefined, 'Could not find text document that matched cell uri path');
|
should(document).not.equal(undefined, 'Could not find text document that matched cell uri path');
|
||||||
@@ -75,7 +76,8 @@ describe('Completion Item Provider', function () {
|
|||||||
it('should not provide items when session list throws exception', async () => {
|
it('should not provide items when session list throws exception', async () => {
|
||||||
mockSessionManager.setup(m => m.listRunning()).throws(new Error('Test Error'));
|
mockSessionManager.setup(m => m.listRunning()).throws(new Error('Test Error'));
|
||||||
|
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
await notebookUtils.addCell('code');
|
await notebookUtils.addCell('code');
|
||||||
let document = await tryFindTextDocument(notebook);
|
let document = await tryFindTextDocument(notebook);
|
||||||
|
|
||||||
@@ -86,7 +88,8 @@ describe('Completion Item Provider', function () {
|
|||||||
it('should not provide items when kernel does not exist in notebook provider', async () => {
|
it('should not provide items when kernel does not exist in notebook provider', async () => {
|
||||||
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
||||||
|
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
await notebookUtils.addCell('code');
|
await notebookUtils.addCell('code');
|
||||||
let document = await tryFindTextDocument(notebook);
|
let document = await tryFindTextDocument(notebook);
|
||||||
|
|
||||||
@@ -102,7 +105,8 @@ describe('Completion Item Provider', function () {
|
|||||||
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
||||||
mockJupyterSession.setup(s => s.path).returns(() => notebook.document.uri.path);
|
mockJupyterSession.setup(s => s.path).returns(() => notebook.document.uri.path);
|
||||||
|
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
await notebookUtils.addCell('code');
|
await notebookUtils.addCell('code');
|
||||||
let document = await tryFindTextDocument(notebook);
|
let document = await tryFindTextDocument(notebook);
|
||||||
|
|
||||||
@@ -145,7 +149,8 @@ describe('Completion Item Provider', function () {
|
|||||||
mockJupyterSession.setup(s => s.kernel).returns(() => kernel);
|
mockJupyterSession.setup(s => s.kernel).returns(() => kernel);
|
||||||
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
||||||
|
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
||||||
editBuilder.insertCell({
|
editBuilder.insertCell({
|
||||||
cell_type: 'code',
|
cell_type: 'code',
|
||||||
@@ -182,7 +187,8 @@ describe('Completion Item Provider', function () {
|
|||||||
mockJupyterSession.setup(s => s.kernel).returns(() => kernel);
|
mockJupyterSession.setup(s => s.kernel).returns(() => kernel);
|
||||||
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]);
|
||||||
|
|
||||||
let notebook = await notebookUtils.newNotebook();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
|
const notebook = azdata.nb.activeNotebookEditor;
|
||||||
if (source) {
|
if (source) {
|
||||||
await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
||||||
editBuilder.insertCell({
|
editBuilder.insertCell({
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { AppContext } from '../../common/appContext';
|
|||||||
import { JupyterController } from '../../jupyter/jupyterController';
|
import { JupyterController } from '../../jupyter/jupyterController';
|
||||||
import { LocalPipPackageManageProvider } from '../../jupyter/localPipPackageManageProvider';
|
import { LocalPipPackageManageProvider } from '../../jupyter/localPipPackageManageProvider';
|
||||||
import { MockExtensionContext } from '../common/stubs';
|
import { MockExtensionContext } from '../common/stubs';
|
||||||
import { NotebookUtils } from '../../common/notebookUtils';
|
|
||||||
|
|
||||||
describe('Jupyter Controller', function () {
|
describe('Jupyter Controller', function () {
|
||||||
let mockExtensionContext: vscode.ExtensionContext = new MockExtensionContext();
|
let mockExtensionContext: vscode.ExtensionContext = new MockExtensionContext();
|
||||||
@@ -74,7 +73,7 @@ describe('Jupyter Controller', function () {
|
|||||||
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not be called');
|
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not be called');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Returns expected values from notebook provider', async () => {
|
it('Returns expected values from notebook provider', async () => {
|
||||||
await controller.activate();
|
await controller.activate();
|
||||||
should(controller.executeProvider.providerId).equal('jupyter', 'Notebook provider should be jupyter');
|
should(controller.executeProvider.providerId).equal('jupyter', 'Notebook provider should be jupyter');
|
||||||
await should(controller.executeProvider.getExecuteManager(undefined)).be.rejected();
|
await should(controller.executeProvider.getExecuteManager(undefined)).be.rejected();
|
||||||
@@ -82,10 +81,10 @@ describe('Jupyter Controller', function () {
|
|||||||
controller.executeProvider.handleNotebookClosed(undefined);
|
controller.executeProvider.handleNotebookClosed(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Returns execute manager for real notebook editor', async () => {
|
it('Returns execute manager for real notebook editor', async () => {
|
||||||
await controller.activate();
|
await controller.activate();
|
||||||
let notebookUtils = new NotebookUtils();
|
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||||
const notebookEditor = await notebookUtils.newNotebook(undefined);
|
const notebookEditor = azdata.nb.activeNotebookEditor;
|
||||||
let notebookManager = await controller.executeProvider.getExecuteManager(notebookEditor.document.uri);
|
let notebookManager = await controller.executeProvider.getExecuteManager(notebookEditor.document.uri);
|
||||||
should(controller.executeProvider.executeManagerCount).equal(1);
|
should(controller.executeProvider.executeManagerCount).equal(1);
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ import { NotebookChangeType, CellTypes } from 'sql/workbench/services/notebook/c
|
|||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { IFileService } from 'vs/platform/files/common/files';
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||||
import { NotebookEditor } from 'sql/workbench/contrib/notebook/browser/notebookEditor';
|
|
||||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||||
import { SqlExtHostContext, SqlMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
import { SqlExtHostContext, SqlMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
import { NotebookEditor } from 'sql/workbench/contrib/notebook/browser/notebookEditor';
|
||||||
|
|
||||||
class MainThreadNotebookEditor extends Disposable {
|
class MainThreadNotebookEditor extends Disposable {
|
||||||
private _contentChangedEmitter = new Emitter<NotebookContentChange>();
|
private _contentChangedEmitter = new Emitter<NotebookContentChange>();
|
||||||
@@ -323,7 +322,6 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
|
|||||||
@INotebookService private readonly _notebookService: INotebookService,
|
@INotebookService private readonly _notebookService: INotebookService,
|
||||||
@IFileService private readonly _fileService: IFileService,
|
@IFileService private readonly _fileService: IFileService,
|
||||||
@ITextFileService private readonly _textFileService: ITextFileService,
|
@ITextFileService private readonly _textFileService: ITextFileService,
|
||||||
@IUntitledTextEditorService private readonly _untitledEditorService: IUntitledTextEditorService,
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
if (extHostContext) {
|
if (extHostContext) {
|
||||||
@@ -346,38 +344,9 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise<string> {
|
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise<string> {
|
||||||
// Append a numbered suffix if an untitled notebook is already open with the same path
|
|
||||||
if (resource.scheme === Schemas.untitled) {
|
|
||||||
if (!resource.path || this.untitledEditorTitleExists(resource.path)) {
|
|
||||||
resource.path = this.createPrefixedNotebookFilePath(resource.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Promise.resolve(this.doOpenEditor(resource, options));
|
return Promise.resolve(this.doOpenEditor(resource, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
private untitledEditorTitleExists(filePath: string): boolean {
|
|
||||||
return !!this._untitledEditorService.get(URI.from({ scheme: Schemas.untitled, path: filePath }));
|
|
||||||
}
|
|
||||||
|
|
||||||
private createPrefixedNotebookFilePath(prefix?: string): string {
|
|
||||||
if (!prefix) {
|
|
||||||
prefix = 'Notebook';
|
|
||||||
}
|
|
||||||
let prefixFileName = (counter: number): string => {
|
|
||||||
return `${prefix}-${counter}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
let counter = 1;
|
|
||||||
// Get document name and check if it exists
|
|
||||||
let filePath = prefixFileName(counter);
|
|
||||||
while (this.untitledEditorTitleExists(filePath)) {
|
|
||||||
counter++;
|
|
||||||
filePath = prefixFileName(counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
$trySetTrusted(uriComponent: UriComponents, isTrusted: boolean): Promise<boolean> {
|
$trySetTrusted(uriComponent: UriComponents, isTrusted: boolean): Promise<boolean> {
|
||||||
let uri = URI.revive(uriComponent);
|
let uri = URI.revive(uriComponent);
|
||||||
return this._notebookService.setTrusted(uri, isTrusted);
|
return this._notebookService.setTrusted(uri, isTrusted);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilit
|
|||||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||||
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
||||||
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
|
||||||
import { CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts';
|
import { CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts';
|
||||||
import { getErrorMessage } from 'vs/base/common/errors';
|
import { getErrorMessage } from 'vs/base/common/errors';
|
||||||
import { IEditorAction } from 'vs/editor/common/editorCommon';
|
import { IEditorAction } from 'vs/editor/common/editorCommon';
|
||||||
@@ -839,13 +838,12 @@ export class NewNotebookAction extends Action {
|
|||||||
public static readonly ID = 'notebook.command.new';
|
public static readonly ID = 'notebook.command.new';
|
||||||
public static readonly LABEL = localize('newNotebookAction', "New Notebook");
|
public static readonly LABEL = localize('newNotebookAction', "New Notebook");
|
||||||
|
|
||||||
public static readonly INTERNAL_NEW_NOTEBOOK_CMD_ID = '_notebook.command.new';
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
@ICommandService private commandService: ICommandService,
|
|
||||||
@IObjectExplorerService private objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private objectExplorerService: IObjectExplorerService,
|
||||||
@IAdsTelemetryService private _telemetryService: IAdsTelemetryService,
|
@IAdsTelemetryService private _telemetryService: IAdsTelemetryService,
|
||||||
|
@INotebookService private _notebookService: INotebookService,
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
this.class = 'notebook-action new-notebook';
|
this.class = 'notebook-action new-notebook';
|
||||||
@@ -862,7 +860,7 @@ export class NewNotebookAction extends Action {
|
|||||||
} else if (context && context.connectionProfile) {
|
} else if (context && context.connectionProfile) {
|
||||||
connProfile = context.connectionProfile;
|
connProfile = context.connectionProfile;
|
||||||
}
|
}
|
||||||
return this.commandService.executeCommand(NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID, { connectionProfile: connProfile });
|
await this._notebookService.openNotebook(URI.from({ scheme: 'untitled' }), { connectionProfile: connProfile });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as assert from 'assert';
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService';
|
import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService';
|
||||||
import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, CreateNotebookViewAction, DashboardViewAction, kernelNotSupported, KernelsDropdown, msgChanging, NewNotebookAction, noKernelName, noParameterCell, noParametersInCell, NotebookViewAction, NotebookViewsActionProvider, RunAllCellsAction, RunParametersAction, TrustedAction, untitledNotSupported } from 'sql/workbench/contrib/notebook/browser/notebookActions';
|
import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, CreateNotebookViewAction, DashboardViewAction, kernelNotSupported, KernelsDropdown, msgChanging, noKernelName, noParameterCell, noParametersInCell, NotebookViewAction, NotebookViewsActionProvider, RunAllCellsAction, RunParametersAction, TrustedAction, untitledNotSupported } from 'sql/workbench/contrib/notebook/browser/notebookActions';
|
||||||
import { ClientSessionStub, ContextViewProviderStub, NotebookComponentStub, NotebookModelStub, NotebookServiceStub, NotebookViewsStub, NotebookViewStub } from 'sql/workbench/contrib/notebook/test/stubs';
|
import { ClientSessionStub, ContextViewProviderStub, NotebookComponentStub, NotebookModelStub, NotebookServiceStub, NotebookViewsStub, NotebookViewStub } from 'sql/workbench/contrib/notebook/test/stubs';
|
||||||
import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testCommon';
|
import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testCommon';
|
||||||
import { ICellModel, INotebookModel, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
import { ICellModel, INotebookModel, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||||
@@ -16,15 +16,12 @@ import { INotebookEditor, INotebookService } from 'sql/workbench/services/notebo
|
|||||||
import { CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
import { CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
||||||
import * as TypeMoq from 'typemoq';
|
import * as TypeMoq from 'typemoq';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
|
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
|
||||||
import { IConfigurationChangeEvent, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationChangeEvent, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||||
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService';
|
|
||||||
import { MockQuickInputService } from 'sql/workbench/contrib/notebook/test/common/quickInputServiceMock';
|
import { MockQuickInputService } from 'sql/workbench/contrib/notebook/test/common/quickInputServiceMock';
|
||||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||||
import { Separator } from 'vs/base/common/actions';
|
import { Separator } from 'vs/base/common/actions';
|
||||||
@@ -251,22 +248,6 @@ suite('Notebook Actions', function (): void {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('New Notebook Action', async function (): Promise<void> {
|
|
||||||
let actualCmdId: string;
|
|
||||||
|
|
||||||
let mockCommandService = TypeMoq.Mock.ofType<ICommandService>(TestCommandService);
|
|
||||||
mockCommandService.setup(s => s.executeCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
|
||||||
.returns((commandId) => {
|
|
||||||
actualCmdId = commandId;
|
|
||||||
return Promise.resolve(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
let action = new NewNotebookAction('TestId', 'TestLabel', mockCommandService.object, undefined, new NullAdsTelemetryService());
|
|
||||||
await action.run(undefined);
|
|
||||||
|
|
||||||
assert.strictEqual(actualCmdId, NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should Run with Parameters Action', async function (): Promise<void> {
|
test('Should Run with Parameters Action', async function (): Promise<void> {
|
||||||
const testContents: azdata.nb.INotebookContents = {
|
const testContents: azdata.nb.INotebookContents = {
|
||||||
cells: [{
|
cells: [{
|
||||||
|
|||||||
@@ -339,12 +339,42 @@ export class NotebookService extends Disposable implements INotebookService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async openNotebook(resource: UriComponents, options: INotebookShowOptions): Promise<IEditorPane | undefined> {
|
public async openNotebook(resource: UriComponents, options: INotebookShowOptions): Promise<IEditorPane | undefined> {
|
||||||
|
// Append a numbered suffix if an untitled notebook is already open with the same path
|
||||||
|
if (resource.scheme === Schemas.untitled) {
|
||||||
|
if (!resource.path || this.untitledEditorTitleExists(resource.path)) {
|
||||||
|
resource.path = this.createPrefixedNotebookFilePath(resource.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const editorOptions: ITextEditorOptions = {
|
const editorOptions: ITextEditorOptions = {
|
||||||
preserveFocus: options.preserveFocus,
|
preserveFocus: options.preserveFocus,
|
||||||
pinned: !options.preview
|
pinned: !options.preview
|
||||||
};
|
};
|
||||||
let input = await this.createNotebookInput(options, resource);
|
let input = await this.createNotebookInput(options, resource);
|
||||||
return await this._editorService.openEditor(input, editorOptions, viewColumnToEditorGroup(this._editorGroupService, options.position));
|
return this._editorService.openEditor(input, editorOptions, viewColumnToEditorGroup(this._editorGroupService, options.position));
|
||||||
|
}
|
||||||
|
|
||||||
|
private untitledEditorTitleExists(filePath: string): boolean {
|
||||||
|
return !!this._untitledEditorService.get(URI.from({ scheme: Schemas.untitled, path: filePath }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private createPrefixedNotebookFilePath(prefix?: string): string {
|
||||||
|
if (!prefix) {
|
||||||
|
prefix = 'Notebook';
|
||||||
|
}
|
||||||
|
let prefixFileName = (counter: number): string => {
|
||||||
|
return `${prefix}-${counter}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
let counter = 1;
|
||||||
|
// Get document name and check if it exists
|
||||||
|
let filePath = prefixFileName(counter);
|
||||||
|
while (this.untitledEditorTitleExists(filePath)) {
|
||||||
|
counter++;
|
||||||
|
filePath = prefixFileName(counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user