Custom Summary Page for NotebookWizard and notebook Cell with wizard variables (#10297)

* save not yet tested work

* Merge from master.

* Screeens Shared for Feeedback

* Code complete

* remove unneeded changes

* remove unnecessary comma

* remov wss

* remove dead code

* PR feedback

* checkpoint fixes

* PR & minor fixes

* minor fix for feature of  resourceType options being optional.

* reverting experimental change

* separating out changes for future featurework.

* revert unneeded change

* review feedback fixes

* review feedback

* rename InputFieldComponent to InputComponent

* working version of custom summary page

* add option to align items in a flex- container.

* changes to support labelColor

* save work , still pending issue with labelCSSStyles

* Summary page and setting variabless in notebook.

* minor fixes.

* pr feedbck

* fix formatting issues

* pr feedback

* pr feedback

* pr feedback

* fixing docs

* summary page value setting fix

* rename children of RowInfo to items

* rename a method

* rename summary_text to evaluated_text

* rename properties of fieldInfo

* revert inadvertent change

* rename linked_texttext to hyperlinked_text and removing linking facility from readonly_text

* pr feedback

* fix setting tools variables in env and notebook

* removing saving of originalValues for EvaluatedText

* await on launchNotebookWithEdits

* await on launchNotebookWithContent

* merge RadioOptions & Options into 1

* merge ReadOnlyText, links  & evaluatedText

* Samples for new generic wizard features

* fix comment

* fix assertions

* return type and comment for getClusterContext

* fix inadvertent change

* increase minimum required azdata version

* remove unneeded environment variable settings

* not leaking passwords in notebooks
This commit is contained in:
Arvind Ranasaria
2020-06-01 11:14:59 -07:00
committed by GitHub
parent 84492049e8
commit 678bbe3142
23 changed files with 1190 additions and 473 deletions

View File

@@ -9,7 +9,7 @@ import * as path from 'path';
import { isString } from 'util';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { NotebookInfo } from '../interfaces';
import { NotebookPathInfo } from '../interfaces';
import { getDateTimeString, getErrorMessage } from '../utils';
import { IPlatformService } from './platformService';
const localize = nls.loadMessageBundle();
@@ -33,11 +33,13 @@ export interface NotebookExecutionResult {
}
export interface INotebookService {
launchNotebook(notebook: string | NotebookInfo): Thenable<azdata.nb.NotebookEditor>;
launchNotebookWithContent(title: string, content: string): Thenable<azdata.nb.NotebookEditor>;
getNotebook(notebook: string | NotebookInfo): Promise<Notebook>;
launchNotebook(notebook: string | NotebookPathInfo): Promise<azdata.nb.NotebookEditor>;
launchNotebookWithEdits(notebook: string | NotebookPathInfo, cellStatements: string[], insertionPosition?: number): Promise<void>;
launchNotebookWithContent(title: string, content: string): Promise<azdata.nb.NotebookEditor>;
getNotebook(notebook: string | NotebookPathInfo): Promise<Notebook>;
getNotebookPath(notebook: string | NotebookPathInfo): string;
executeNotebook(notebook: any, env?: NodeJS.ProcessEnv): Promise<NotebookExecutionResult>;
backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookInfo, tempNoteBookPrefix: string, platformService: IPlatformService): void;
backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookPathInfo | Notebook, tempNotebookPrefix: string, platformService: IPlatformService, env?: NodeJS.ProcessEnv): void;
}
export class NotebookService implements INotebookService {
@@ -48,9 +50,26 @@ export class NotebookService implements INotebookService {
* Launch notebook with file path
* @param notebook the path of the notebook
*/
launchNotebook(notebook: string | NotebookInfo): Thenable<azdata.nb.NotebookEditor> {
return this.getNotebookFullPath(notebook).then(notebookPath => {
return this.showNotebookAsUntitled(notebookPath);
async launchNotebook(notebook: string | NotebookPathInfo): Promise<azdata.nb.NotebookEditor> {
const notebookPath = await this.getNotebookFullPath(notebook);
return await this.showNotebookAsUntitled(notebookPath);
}
/**
* Inserts cell code given by {@param cellStatements} in an existing notebook given by {@param notebook} file path at the location
* {@param insertionPosition} and then launches the edited notebook.
*
* @param notebook - the path to notebook that needs to be launched
* @param cellStatements - array of statements to be inserted in a cell
* @param insertionPosition - the position at which cells are inserted. Default is a new cell at the beginning of the notebook.
*/
async launchNotebookWithEdits(notebook: string, cellStatements: string[], insertionPosition: number = 0): Promise<void> {
const openedNotebook = await this.launchNotebook(notebook);
await openedNotebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
editBuilder.insertCell({
cell_type: 'code',
source: cellStatements
}, insertionPosition);
});
}
@@ -59,9 +78,9 @@ export class NotebookService implements INotebookService {
* @param title the title of the notebook
* @param content the notebook content
*/
launchNotebookWithContent(title: string, content: string): Thenable<azdata.nb.NotebookEditor> {
async launchNotebookWithContent(title: string, content: string): Promise<azdata.nb.NotebookEditor> {
const uri: vscode.Uri = vscode.Uri.parse(`untitled:${title}`);
return azdata.nb.showNotebookDocument(uri, {
return await azdata.nb.showNotebookDocument(uri, {
connectionProfile: undefined,
preview: false,
initialContent: content,
@@ -70,7 +89,7 @@ export class NotebookService implements INotebookService {
}
async getNotebook(notebook: string | NotebookInfo): Promise<Notebook> {
async getNotebook(notebook: string | NotebookPathInfo): Promise<Notebook> {
const notebookPath = await this.getNotebookFullPath(notebook);
return <Notebook>JSON.parse(await this.platformService.readTextFile(notebookPath));
}
@@ -83,7 +102,7 @@ export class NotebookService implements INotebookService {
const outputFullPath = path.join(workingDirectory, `output-${fileName}`);
const additionalEnvironmentVariables: NodeJS.ProcessEnv = env || {};
// Set the azdata eula
// Scenarios using the executeNotebook feature already have the EULA acceptted by the user before executing this.
// Scenarios using the executeNotebook feature already have the EULA accepted by the user before executing this.
additionalEnvironmentVariables['ACCEPT_EULA'] = 'yes';
try {
await this.platformService.saveTextFile(content, notebookFullPath);
@@ -109,15 +128,17 @@ export class NotebookService implements INotebookService {
}
}
public backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookInfo, tempNotebookPrefix: string, platformService: IPlatformService): void {
backgroundExecuteNotebook(taskName: string = 'Executing notebook', notebookInfo: string | NotebookPathInfo | Notebook, tempNotebookPrefix: string, platformService: IPlatformService, env?: NodeJS.ProcessEnv): void {
azdata.tasks.startBackgroundOperation({
displayName: taskName!,
description: taskName!,
displayName: taskName,
description: taskName,
isCancelable: false,
operation: async op => {
op.updateStatus(azdata.TaskStatus.InProgress);
const notebook = await this.getNotebook(notebookInfo);
const result = await this.executeNotebook(notebook);
const notebook = (typeof notebookInfo === 'object' && 'cells' in notebookInfo)
? <Notebook>notebookInfo
: await this.getNotebook(notebookInfo);
const result = await this.executeNotebook(notebook, env);
if (result.succeeded) {
op.updateStatus(azdata.TaskStatus.Succeeded);
} else {
@@ -129,7 +150,7 @@ export class NotebookService implements INotebookService {
platformService.logToOutputChannel(taskFailedMessage);
if (selectedOption === viewErrorDetail) {
try {
this.launchNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook);
await this.launchNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook);
} catch (error) {
const launchNotebookError = localize('resourceDeployment.FailedToOpenNotebook', "An error occurred launching the output notebook. {1}{2}.", EOL, getErrorMessage(error));
platformService.logToOutputChannel(launchNotebookError);
@@ -146,7 +167,7 @@ export class NotebookService implements INotebookService {
});
}
async getNotebookFullPath(notebook: string | NotebookInfo): Promise<string> {
async getNotebookFullPath(notebook: string | NotebookPathInfo): Promise<string> {
const notebookPath = this.getNotebookPath(notebook);
let notebookExists = await this.platformService.fileExists(notebookPath);
if (notebookExists) {
@@ -168,7 +189,7 @@ export class NotebookService implements INotebookService {
* get the notebook path for current platform
* @param notebook the notebook path
*/
getNotebookPath(notebook: string | NotebookInfo): string {
getNotebookPath(notebook: string | NotebookPathInfo): string {
let notebookPath;
if (notebook && !isString(notebook)) {
const platform = this.platformService.platform();
@@ -199,17 +220,16 @@ export class NotebookService implements INotebookService {
return title;
}
showNotebookAsUntitled(notebookPath: string): Thenable<azdata.nb.NotebookEditor> {
async showNotebookAsUntitled(notebookPath: string): Promise<azdata.nb.NotebookEditor> {
let targetFileName: string = this.findNextUntitledEditorName(notebookPath);
const untitledFileName: vscode.Uri = vscode.Uri.parse(`untitled:${targetFileName}`);
return vscode.workspace.openTextDocument(notebookPath).then((document) => {
let initialContent = document.getText();
return azdata.nb.showNotebookDocument(untitledFileName, {
connectionProfile: undefined,
preview: false,
initialContent: initialContent,
initialDirtyState: false
});
const document = await vscode.workspace.openTextDocument(notebookPath);
let initialContent = document.getText();
return await azdata.nb.showNotebookDocument(untitledFileName, {
connectionProfile: undefined,
preview: false,
initialContent: initialContent,
initialDirtyState: false
});
}
}

View File

@@ -13,7 +13,7 @@ import * as nls from 'vscode-nls';
import { INotebookService } from './notebookService';
import { IPlatformService } from './platformService';
import { IToolsService } from './toolsService';
import { ResourceType, ResourceTypeOption, NotebookInfo, DeploymentProvider, instanceOfWizardDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfNotebookDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookWizardDeploymentProvider } from '../interfaces';
import { ResourceType, ResourceTypeOption, NotebookPathInfo, DeploymentProvider, instanceOfWizardDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfNotebookDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookWizardDeploymentProvider } from '../interfaces';
import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard';
import { DeploymentInputDialog } from '../ui/deploymentInputDialog';
@@ -77,7 +77,7 @@ export class ResourceTypeService implements IResourceTypeService {
});
}
private updateNotebookPath(objWithNotebookProperty: { notebook: string | NotebookInfo } | undefined, extensionPath: string): void {
private updateNotebookPath(objWithNotebookProperty: { notebook: string | NotebookPathInfo } | undefined, extensionPath: string): void {
if (objWithNotebookProperty && objWithNotebookProperty.notebook) {
if (typeof objWithNotebookProperty.notebook === 'string') {
objWithNotebookProperty.notebook = path.join(extensionPath, objWithNotebookProperty.notebook);
@@ -239,10 +239,10 @@ export class ResourceTypeService implements IResourceTypeService {
public startDeployment(provider: DeploymentProvider): void {
const self = this;
if (instanceOfWizardDeploymentProvider(provider)) {
const wizard = new DeployClusterWizard(provider.bdcWizard, new KubeService(), new AzdataService(this.platformService), this.notebookService);
const wizard = new DeployClusterWizard(provider.bdcWizard, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService);
wizard.open();
} else if (instanceOfNotebookWizardDeploymentProvider(provider)) {
const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService);
const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService, this.toolsService);
wizard.open();
} else if (instanceOfDialogDeploymentProvider(provider)) {
const dialog = new DeploymentInputDialog(this.notebookService, this.platformService, provider.dialog);

View File

@@ -11,10 +11,12 @@ import { IPlatformService } from './platformService';
export interface IToolsService {
getToolByName(toolName: string): ITool | undefined;
toolsForCurrentProvider: ITool[];
}
export class ToolsService implements IToolsService {
private supportedTools: Map<string, ITool>;
private currentTools: ITool[] = [];
constructor(private _platformService: IPlatformService) {
this.supportedTools = new Map<string, ITool>(
@@ -30,4 +32,12 @@ export class ToolsService implements IToolsService {
getToolByName(toolName: string): ITool | undefined {
return this.supportedTools.get(toolName);
}
get toolsForCurrentProvider(): ITool[] {
return this.currentTools;
}
set toolsForCurrentProvider(tools: ITool[]) {
this.currentTools = tools;
}
}