mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-10 10:12:34 -05:00
GenerateToNotebook and Deploy buttons for Notebook Wizards (#12656)
* enable userChooses how to run notebook * arc ext changes * nb fixes * working version * revert unneeded changes * fix comments * Update interfaces.ts * fix comments * fix comments * fix comments * runAllCells instead of background execute * pr feedback * PR feedback * pr feedback * arc ext changes for new WizardInfo syntax * fix doc comments * pr feedback
This commit is contained in:
@@ -56,7 +56,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### **Setup and Check Prerequisites**"
|
||||
"### **Setup**"
|
||||
],
|
||||
"metadata": {
|
||||
"azdata_cell_guid": "e3dd8e75-e15f-44b4-81fc-1f54d6f0b1e2"
|
||||
|
||||
@@ -144,9 +144,13 @@
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.arc.data.controller.ipynb",
|
||||
"type": "new-arc-control-plane",
|
||||
"runNotebook": false,
|
||||
"doneAction": {
|
||||
"label": "%deploy.done.action%"
|
||||
},
|
||||
"scriptAction": {
|
||||
"label": "%deploy.script.action%"
|
||||
},
|
||||
"codeCellInsertionPosition": 5,
|
||||
"actionText": "%deploy.script.to.notebook.action%",
|
||||
"title": "%arc.data.controller.new.wizard.title%",
|
||||
"name": "arc.data.controller.new.wizard",
|
||||
"labelPosition": "left",
|
||||
@@ -521,9 +525,13 @@
|
||||
{
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.sql.existing.arc.ipynb",
|
||||
"runNotebook": false,
|
||||
"doneAction": {
|
||||
"label": "%deploy.done.action%"
|
||||
},
|
||||
"scriptAction": {
|
||||
"label": "%deploy.script.action%"
|
||||
},
|
||||
"codeCellInsertionPosition": 5,
|
||||
"actionText": "%deploy.script.to.notebook.action%",
|
||||
"title": "%arc.sql.wizard.title%",
|
||||
"name": "arc.sql.wizard",
|
||||
"labelPosition": "left",
|
||||
@@ -682,9 +690,13 @@
|
||||
{
|
||||
"notebookWizard": {
|
||||
"notebook": "./notebooks/arcDeployment/deploy.postgres.existing.arc.ipynb",
|
||||
"runNotebook": false,
|
||||
"doneAction": {
|
||||
"label": "%deploy.done.action%"
|
||||
},
|
||||
"scriptAction": {
|
||||
"label": "%deploy.script.action%"
|
||||
},
|
||||
"codeCellInsertionPosition": 5,
|
||||
"actionText": "%deploy.script.to.notebook.action%",
|
||||
"title": "%arc.postgres.wizard.title%",
|
||||
"name": "arc.postgres.wizard",
|
||||
"labelPosition": "left",
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
"arc.data.controller.summary.location": "Location",
|
||||
"arc.data.controller.arc.data.controller.agreement": "I accept {0} and {1}.",
|
||||
"microsoft.agreement.privacy.statement":"Microsoft Privacy Statement",
|
||||
"deploy.script.to.notebook.action":"Script to notebook",
|
||||
|
||||
"deploy.script.action":"Script to notebook",
|
||||
"deploy.done.action":"Deploy",
|
||||
|
||||
"resource.type.arc.sql.display.name": "Azure SQL managed instance - Azure Arc (preview)",
|
||||
"resource.type.arc.postgres.display.name": "PostgreSQL Hyperscale server groups - Azure Arc (preview)",
|
||||
|
||||
@@ -114,21 +114,53 @@ export interface BdcWizardInfo {
|
||||
notebook: string | NotebookPathInfo;
|
||||
type: BdcDeploymentType;
|
||||
}
|
||||
/**
|
||||
* An object that configures Script and Done buttons of the wizard.
|
||||
*/
|
||||
export interface WizardAction {
|
||||
label?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* This object defines the shape, form and behavior of a Notebook Wizard.
|
||||
*/
|
||||
export interface NotebookWizardInfo extends WizardInfoBase {
|
||||
/**
|
||||
* path to the template python notebook that is modified with variables collected in the wizard. A copy of this modified notebook is executed at the end of the wizard either from commonadline of from notebook editor in ADS.
|
||||
*/
|
||||
notebook: string | NotebookPathInfo;
|
||||
runNotebook?: boolean;
|
||||
/**
|
||||
* 0 based position number where the variables values are inserted into the notebook as python statements.
|
||||
*/
|
||||
codeCellInsertionPosition?: number;
|
||||
/**
|
||||
* This array defines the json for the pages of this wizard.
|
||||
*/
|
||||
pages: NotebookWizardPageInfo[]
|
||||
}
|
||||
|
||||
export interface WizardInfoBase extends FieldInfoBase {
|
||||
taskName?: string;
|
||||
type?: DeploymentType;
|
||||
actionText?: string;
|
||||
/**
|
||||
* done button attributes.
|
||||
*/
|
||||
doneAction: WizardAction;
|
||||
/**
|
||||
* script button attributes.
|
||||
*/
|
||||
scriptAction?: WizardAction;
|
||||
/**
|
||||
* title displayed on every page of the wizard
|
||||
*/
|
||||
title: string;
|
||||
name?: string;
|
||||
/**
|
||||
* This array defines the json for the pages of this wizard.
|
||||
*/
|
||||
pages: PageInfoBase[];
|
||||
/**
|
||||
* if true an auto generated summary page is inserted at the end of the wizard
|
||||
*/
|
||||
isSummaryPageAutoGenerated?: boolean
|
||||
}
|
||||
|
||||
@@ -401,11 +433,7 @@ export const enum BdcDeploymentType {
|
||||
ExistingOpenShift = 'existing-openshift'
|
||||
}
|
||||
|
||||
export const enum ArcDeploymentType {
|
||||
NewControlPlane = 'new-control-plane'
|
||||
}
|
||||
|
||||
export type DeploymentType = ArcDeploymentType | BdcDeploymentType;
|
||||
export type DeploymentType = BdcDeploymentType;
|
||||
|
||||
export interface Command {
|
||||
command: string;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { FieldType, OptionsType } from './interfaces';
|
||||
import { OptionsSourceType } from './helpers/optionSources';
|
||||
import { FieldType, OptionsType } from './interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -37,3 +37,5 @@ export const optionsTypeRadioOrDropdown = localize('optionsTypeRadioOrDropdown',
|
||||
export const azdataEulaNotAccepted = localize('azdataEulaNotAccepted', "Deployment cannot continue. Azure Data CLI license terms have not yet been accepted. Please accept the EULA to enable the features that requires Azure Data CLI.");
|
||||
export const azdataEulaDeclined = localize('azdataEulaDeclined', "Deployment cannot continue. Azure Data CLI license terms were declined.You can either Accept EULA to continue or Cancel this operation");
|
||||
export const acceptEulaAndSelect = localize('deploymentDialog.RecheckEulaButton', "Accept EULA & Select");
|
||||
export const scriptToNotebook = localize('ui.ScriptToNotebookButton', "Script");
|
||||
export const deployNotebook = localize('ui.DeployButton', "Run");
|
||||
|
||||
@@ -33,9 +33,9 @@ export interface NotebookExecutionResult {
|
||||
}
|
||||
|
||||
export interface INotebookService {
|
||||
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>;
|
||||
openNotebook(notebook: string | NotebookPathInfo): Promise<azdata.nb.NotebookEditor>;
|
||||
openNotebookWithEdits(notebook: string | NotebookPathInfo, cellStatements: string[], insertionPosition?: number): Promise<azdata.nb.NotebookEditor>;
|
||||
openNotebookWithContent(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>;
|
||||
@@ -47,38 +47,39 @@ export class NotebookService implements INotebookService {
|
||||
constructor(private platformService: IPlatformService, private extensionPath: string) { }
|
||||
|
||||
/**
|
||||
* Launch notebook with file path
|
||||
* Open notebook with file path
|
||||
* @param notebook the path of the notebook
|
||||
*/
|
||||
async launchNotebook(notebook: string | NotebookPathInfo): Promise<azdata.nb.NotebookEditor> {
|
||||
async openNotebook(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 insertionPosition} and then opens the edited notebook.
|
||||
*
|
||||
* @param notebook - the path to notebook that needs to be launched
|
||||
* @param notebook - the path to notebook that needs to be opened
|
||||
* @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);
|
||||
async openNotebookWithEdits(notebook: string, cellStatements: string[], insertionPosition: number = 0): Promise<azdata.nb.NotebookEditor> {
|
||||
const openedNotebook = await this.openNotebook(notebook);
|
||||
await openedNotebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
||||
editBuilder.insertCell({
|
||||
cell_type: 'code',
|
||||
source: cellStatements
|
||||
}, insertionPosition);
|
||||
});
|
||||
return openedNotebook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch notebook with file path
|
||||
* Open notebook with given contents
|
||||
* @param title the title of the notebook
|
||||
* @param content the notebook content
|
||||
*/
|
||||
async launchNotebookWithContent(title: string, content: string): Promise<azdata.nb.NotebookEditor> {
|
||||
async openNotebookWithContent(title: string, content: string): Promise<azdata.nb.NotebookEditor> {
|
||||
const uri: vscode.Uri = vscode.Uri.parse(`untitled:${this.findNextUntitledEditorName(title)}`);
|
||||
return await azdata.nb.showNotebookDocument(uri, {
|
||||
connectionProfile: undefined,
|
||||
@@ -150,11 +151,11 @@ export class NotebookService implements INotebookService {
|
||||
platformService.logToOutputChannel(taskFailedMessage);
|
||||
if (selectedOption === viewErrorDetail) {
|
||||
try {
|
||||
await this.launchNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook);
|
||||
await this.openNotebookWithContent(`${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);
|
||||
vscode.window.showErrorMessage(launchNotebookError);
|
||||
const openNotebookError = localize('resourceDeployment.FailedToOpenNotebook', "An error occurred opening the output notebook. {1}{2}.", EOL, getErrorMessage(error));
|
||||
platformService.logToOutputChannel(openNotebookError);
|
||||
vscode.window.showErrorMessage(openNotebookError);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -10,17 +10,17 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption } from '../interfaces';
|
||||
import { DeployAzureSQLVMWizard } from '../ui/deployAzureSQLVMWizard/deployAzureSQLVMWizard';
|
||||
import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard';
|
||||
import { DeploymentInputDialog } from '../ui/deploymentInputDialog';
|
||||
import { NotebookWizard } from '../ui/notebookWizard/notebookWizard';
|
||||
import { AzdataService } from './azdataService';
|
||||
import { KubeService } from './kubeService';
|
||||
import { INotebookService } from './notebookService';
|
||||
import { IPlatformService } from './platformService';
|
||||
import { IToolsService } from './toolsService';
|
||||
import { ResourceType, ResourceTypeOption, NotebookPathInfo, DeploymentProvider, instanceOfWizardDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfNotebookDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookWizardDeploymentProvider, NotebookInfo, instanceOfAzureSQLVMDeploymentProvider } from '../interfaces';
|
||||
import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard';
|
||||
import { DeploymentInputDialog } from '../ui/deploymentInputDialog';
|
||||
|
||||
import { KubeService } from './kubeService';
|
||||
import { AzdataService } from './azdataService';
|
||||
import { NotebookWizard } from '../ui/notebookWizard/notebookWizard';
|
||||
import { DeployAzureSQLVMWizard } from '../ui/deployAzureSQLVMWizard/deployAzureSQLVMWizard';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export interface IResourceTypeService {
|
||||
@@ -257,7 +257,7 @@ export class ResourceTypeService implements IResourceTypeService {
|
||||
const dialog = new DeploymentInputDialog(this.notebookService, this.platformService, this.toolsService, provider.dialog);
|
||||
dialog.open();
|
||||
} else if (instanceOfNotebookDeploymentProvider(provider)) {
|
||||
this.notebookService.launchNotebook(provider.notebook);
|
||||
this.notebookService.openNotebook(provider.notebook);
|
||||
} else if (instanceOfDownloadDeploymentProvider(provider)) {
|
||||
const taskName = localize('resourceDeployment.DownloadAndLaunchTaskName', "Download and launch installer, URL: {0}", provider.downloadUrl);
|
||||
azdata.tasks.startBackgroundOperation({
|
||||
|
||||
@@ -73,7 +73,7 @@ export class DeployAzureSQLVMWizard extends WizardBase<DeployAzureSQLVMWizard, W
|
||||
const variableValueStatements = this.model.getCodeCellContentForNotebook();
|
||||
const insertionPosition = 2; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook.
|
||||
try {
|
||||
await this.notebookService.launchNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);
|
||||
await this.notebookService.openNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, WizardP
|
||||
const variableValueStatements = this.model.getCodeCellContentForNotebook(this.toolsService.toolsForCurrentProvider);
|
||||
const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook.
|
||||
try {
|
||||
await this.notebookService.launchNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);
|
||||
await this.notebookService.openNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(getErrorMessage(error));
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export class DeploymentInputDialog extends DialogBase {
|
||||
const notebook = Array.isArray(this.dialogInfo.notebook) ?
|
||||
this.dialogInfo.notebook.find(nb => nb.type === model.getStringValue(NotebookTypeVariableName))?.path :
|
||||
this.dialogInfo.notebook;
|
||||
this.notebookService.launchNotebook(notebook!).catch(error => {
|
||||
this.notebookService.openNotebook(notebook!).catch(error => {
|
||||
vscode.window.showErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import { INotebookService, Notebook } from '../../services/notebookService';
|
||||
import { IToolsService } from '../../services/toolsService';
|
||||
import { Model } from '../model';
|
||||
@@ -14,8 +14,6 @@ import { IPlatformService } from './../../services/platformService';
|
||||
import { NotebookWizardAutoSummaryPage } from './notebookWizardAutoSummaryPage';
|
||||
import { NotebookWizardPage } from './notebookWizardPage';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPage, Model> {
|
||||
private _inputComponents: InputComponents = {};
|
||||
|
||||
@@ -40,7 +38,8 @@ export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPag
|
||||
if (this._wizardInfo.codeCellInsertionPosition === undefined) {
|
||||
this._wizardInfo.codeCellInsertionPosition = 0;
|
||||
}
|
||||
this.wizardObject.doneButton.label = _wizardInfo.actionText || this.wizardObject.doneButton.label;
|
||||
this.wizardObject.doneButton.label = _wizardInfo.doneAction?.label || loc.deployNotebook;
|
||||
this.wizardObject.generateScriptButton.label = _wizardInfo.scriptAction?.label || loc.scriptToNotebook;
|
||||
}
|
||||
|
||||
public get deploymentType(): DeploymentType | undefined {
|
||||
@@ -49,17 +48,37 @@ export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPag
|
||||
|
||||
protected initialize(): void {
|
||||
this.setPages(this.getPages());
|
||||
this.wizardObject.generateScriptButton.hidden = true;
|
||||
this.wizardInfo.actionText = this.wizardInfo.actionText || localize('notebookWizard.ScriptToNotebook', "Script to Notebook");
|
||||
this.wizardObject.doneButton.label = this.wizardInfo.actionText;
|
||||
}
|
||||
|
||||
protected onCancel(): void {
|
||||
}
|
||||
|
||||
protected async onGenerateScript(): Promise<void> {
|
||||
try {
|
||||
const notebook = await this.prepareNotebookAndEnvironment();
|
||||
await this.openNotebook(notebook);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error);
|
||||
}
|
||||
}
|
||||
protected async onOk(): Promise<void> {
|
||||
try {
|
||||
const notebook = await this.prepareNotebookAndEnvironment();
|
||||
const openedNotebook = await this.openNotebook(notebook);
|
||||
openedNotebook.runAllCells();
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async openNotebook(notebook: Notebook) {
|
||||
const notebookPath = this.notebookService.getNotebookPath(this.wizardInfo.notebook);
|
||||
return await this.notebookService.openNotebookWithContent(notebookPath, JSON.stringify(notebook, undefined, 4));
|
||||
}
|
||||
|
||||
private async prepareNotebookAndEnvironment() {
|
||||
await setModelValues(this.inputComponents, this.model);
|
||||
const env: NodeJS.ProcessEnv = {};
|
||||
const env: NodeJS.ProcessEnv = process.env;
|
||||
this.model.setEnvironmentVariables(env, (varName) => {
|
||||
const isPassword = !!this.inputComponents[varName]?.isPassword;
|
||||
return isPassword;
|
||||
@@ -85,17 +104,7 @@ export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPag
|
||||
execution_count: 0
|
||||
}
|
||||
);
|
||||
try {
|
||||
if (this.wizardInfo.runNotebook) {
|
||||
this.notebookService.backgroundExecuteNotebook(this.wizardInfo.taskName, notebook, 'deploy', this.platformService, env);
|
||||
} else {
|
||||
Object.assign(process.env, env);
|
||||
const notebookPath = this.notebookService.getNotebookPath(this.wizardInfo.notebook);
|
||||
await this.notebookService.launchNotebookWithContent(notebookPath, JSON.stringify(notebook, undefined, 4));
|
||||
}
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error);
|
||||
}
|
||||
return notebook;
|
||||
}
|
||||
|
||||
private getPages(): NotebookWizardPage[] {
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as nls from 'vscode-nls';
|
||||
import { NotebookWizardPageInfo } from '../../interfaces';
|
||||
import { initializeWizardPage, InputComponentInfo, setModelValues, Validator } from '../modelViewUtils';
|
||||
import { WizardPageBase } from '../wizardPageBase';
|
||||
import { WizardPageInfo } from '../wizardPageInfo';
|
||||
import { NotebookWizard } from './notebookWizard';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -32,6 +33,20 @@ export class NotebookWizardPage extends WizardPageBase<NotebookWizard> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the return value is true then done button should be visible to the user
|
||||
*/
|
||||
private get isDoneButtonVisible(): boolean {
|
||||
return !!this.wizard.wizardInfo.doneAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the return value is true then generateScript button should be visible to the user
|
||||
*/
|
||||
private get isGenerateScriptButtonVisible(): boolean {
|
||||
return !!this.wizard.wizardInfo.scriptAction;
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
initializeWizardPage({
|
||||
container: this.wizard.wizardObject,
|
||||
@@ -64,7 +79,17 @@ export class NotebookWizardPage extends WizardPageBase<NotebookWizard> {
|
||||
});
|
||||
}
|
||||
|
||||
public async onEnter(): Promise<void> {
|
||||
public async onEnter(pageInfo: WizardPageInfo): Promise<void> {
|
||||
if (pageInfo.isLastPage) {
|
||||
// on the last page either one or both of done button and generateScript button are visible depending on configuration of 'runNotebook' in wizard info
|
||||
this.wizard.wizardObject.doneButton.hidden = !this.isDoneButtonVisible;
|
||||
this.wizard.wizardObject.generateScriptButton.hidden = !this.isGenerateScriptButtonVisible;
|
||||
} else {
|
||||
//on any page but the last page doneButton and generateScriptButton are hidden
|
||||
this.wizard.wizardObject.doneButton.hidden = true;
|
||||
this.wizard.wizardObject.generateScriptButton.hidden = true;
|
||||
}
|
||||
|
||||
if (this.pageInfo.isSummaryPage) {
|
||||
await setModelValues(this.wizard.inputComponents, this.wizard.model);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { WizardPageBase } from './wizardPageBase';
|
||||
import { Model } from './model';
|
||||
import { IToolsService } from '../services/toolsService';
|
||||
import { Model } from './model';
|
||||
import { WizardPageBase } from './wizardPageBase';
|
||||
import { WizardPageInfo } from './wizardPageInfo';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model> {
|
||||
@@ -21,37 +22,55 @@ export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model
|
||||
return this._model;
|
||||
}
|
||||
|
||||
constructor(private title: string, name: string, private _model: M, public toolsService: IToolsService) {
|
||||
protected get useGenerateScriptButton(): boolean {
|
||||
return this._useGenerateScriptButton;
|
||||
}
|
||||
|
||||
constructor(private title: string, name: string, private _model: M, public toolsService: IToolsService, private _useGenerateScriptButton: boolean = false) {
|
||||
this.wizardObject = azdata.window.createWizard(title, name);
|
||||
}
|
||||
|
||||
public async open(): Promise<void> {
|
||||
this.initialize();
|
||||
this.wizardObject.generateScriptButton.hidden = true; // by default generateScriptButton stays hidden.
|
||||
this.wizardObject.customButtons = this.customButtons;
|
||||
this.toDispose.push(this.wizardObject.onPageChanged(async (e) => {
|
||||
let previousPage = this.pages[e.lastPage];
|
||||
let newPage = this.pages[e.newPage];
|
||||
await previousPage.onLeave();
|
||||
await newPage.onEnter();
|
||||
//if we are changing to the first page from no page before, essentially when we load the wizard for the first time, e.lastPage is -1 and previousPage is undefined.
|
||||
await previousPage?.onLeave(new WizardPageInfo(e.lastPage, this.pages.length));
|
||||
if (this.useGenerateScriptButton) {
|
||||
if (newPage === this.pages.slice(-1)[0]) {
|
||||
// if newPage is the last page
|
||||
this.wizardObject.generateScriptButton.hidden = false; //un-hide generateScriptButton on last page
|
||||
} else {
|
||||
// if newPage is not the last page
|
||||
this.wizardObject.generateScriptButton.hidden = true; //hide generateScriptButton if it is not the last page
|
||||
}
|
||||
}
|
||||
await newPage.onEnter(new WizardPageInfo(e.newPage, this.pages.length));
|
||||
}));
|
||||
|
||||
this.toDispose.push(this.wizardObject.doneButton.onClick(async () => {
|
||||
await this.onOk();
|
||||
this.dispose();
|
||||
}));
|
||||
this.toDispose.push(this.wizardObject.generateScriptButton.onClick(async () => {
|
||||
await this.onGenerateScript();
|
||||
this.dispose();
|
||||
this.wizardObject.close(); // close the wizard. This is already hooked up into doneButton, so it is not needed for that button above.
|
||||
}));
|
||||
this.toDispose.push(this.wizardObject.cancelButton.onClick(() => {
|
||||
this.onCancel();
|
||||
this.dispose();
|
||||
}));
|
||||
|
||||
await this.wizardObject.open();
|
||||
if (this.pages && this.pages.length > 0) {
|
||||
await this.pages[0].onEnter();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract initialize(): void;
|
||||
protected abstract async onOk(): Promise<void>;
|
||||
protected async onGenerateScript(): Promise<void> { }
|
||||
protected abstract onCancel(): void;
|
||||
|
||||
public addButton(button: azdata.window.Button) {
|
||||
@@ -62,11 +81,15 @@ export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model
|
||||
this.wizardObject!.pages = pages.map(p => p.pageObject);
|
||||
this.pages = pages;
|
||||
this.pages.forEach((page) => {
|
||||
page.pageObject.onValidityChanged((isValid: boolean) => {
|
||||
// generateScriptButton is enabled only when the page is valid.
|
||||
this.wizardObject.generateScriptButton.enabled = isValid;
|
||||
});
|
||||
page.initialize();
|
||||
});
|
||||
}
|
||||
|
||||
private dispose() {
|
||||
protected dispose() {
|
||||
let errorOccurred = false;
|
||||
this.toDispose.forEach((disposable: vscode.Disposable) => {
|
||||
try {
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { Validator } from './modelViewUtils';
|
||||
import { WizardPageInfo } from './wizardPageInfo';
|
||||
|
||||
export abstract class WizardPageBase<T> {
|
||||
|
||||
private _page: azdata.window.WizardPage;
|
||||
private _validators: Validator[] = [];
|
||||
|
||||
@@ -23,9 +25,9 @@ export abstract class WizardPageBase<T> {
|
||||
return this._wizard;
|
||||
}
|
||||
|
||||
public async onEnter(): Promise<void> { }
|
||||
public async onEnter(_pageInfo?: WizardPageInfo): Promise<void> { }
|
||||
|
||||
public async onLeave(): Promise<void> { }
|
||||
public async onLeave(_pageInfo?: WizardPageInfo): Promise<void> { }
|
||||
|
||||
public abstract initialize(): void;
|
||||
|
||||
|
||||
26
extensions/resource-deployment/src/ui/wizardPageInfo.ts
Normal file
26
extensions/resource-deployment/src/ui/wizardPageInfo.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class WizardPageInfo {
|
||||
public get pageCount(): number {
|
||||
return this._pageCount;
|
||||
}
|
||||
|
||||
public get currentPageId(): number {
|
||||
return this._currentPageId;
|
||||
}
|
||||
|
||||
public get isFirstPage(): boolean {
|
||||
return this._currentPageId === 0;
|
||||
}
|
||||
|
||||
public get isLastPage(): boolean {
|
||||
return this._currentPageId === this._pageCount - 1;
|
||||
}
|
||||
|
||||
constructor(private _currentPageId: number, private _pageCount: number) {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user