mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-05 17:23:51 -05:00
dialog assisted notebooks (#6564)
This commit is contained in:
135
extensions/resource-deployment/src/ui/deploymentDialog.ts
Normal file
135
extensions/resource-deployment/src/ui/deploymentDialog.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as vscode from 'vscode';
|
||||
import { DialogBase } from './dialogBase';
|
||||
import { INotebookService } from '../services/notebookService';
|
||||
import { DeploymentProvider, DialogFieldInfo, FieldType } from '../interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class DeploymentDialog extends DialogBase {
|
||||
|
||||
private variables: { [s: string]: string | undefined; } = {};
|
||||
|
||||
constructor(context: vscode.ExtensionContext,
|
||||
private notebookService: INotebookService,
|
||||
private deploymentProvider: DeploymentProvider) {
|
||||
super(context, deploymentProvider.dialog.title, deploymentProvider.dialog.name, false);
|
||||
this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Open Notebook');
|
||||
this._dialogObject.okButton.onClick(() => this.onComplete());
|
||||
}
|
||||
|
||||
protected initializeDialog() {
|
||||
const tabs: azdata.window.DialogTab[] = [];
|
||||
this.deploymentProvider.dialog.tabs.forEach(tabInfo => {
|
||||
const tab = azdata.window.createTab(tabInfo.title);
|
||||
tab.registerContent((view: azdata.ModelView) => {
|
||||
const sections: azdata.FormComponentGroup[] = [];
|
||||
tabInfo.sections.forEach(sectionInfo => {
|
||||
const fields: azdata.FormComponent[] = [];
|
||||
sectionInfo.fields.forEach(fieldInfo => {
|
||||
this.addField(view, fields, fieldInfo);
|
||||
});
|
||||
sections.push({ title: sectionInfo.title, components: fields });
|
||||
});
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
sections,
|
||||
{
|
||||
horizontal: false
|
||||
}
|
||||
);
|
||||
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
tabs.push(tab);
|
||||
});
|
||||
this._dialogObject.content = tabs;
|
||||
}
|
||||
|
||||
private addField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void {
|
||||
switch (fieldInfo.type) {
|
||||
case FieldType.Options:
|
||||
this.addOptionsTypeField(view, fields, fieldInfo);
|
||||
break;
|
||||
case FieldType.DateTimeText:
|
||||
case FieldType.Number:
|
||||
case FieldType.Password:
|
||||
case FieldType.Text:
|
||||
this.addInputTypeField(view, fields, fieldInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private addOptionsTypeField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void {
|
||||
const component = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({ values: fieldInfo.options, value: fieldInfo.defaultValue }).component();
|
||||
this.variables[fieldInfo.variableName] = fieldInfo.defaultValue;
|
||||
this._toDispose.push(component.onValueChanged(() => { this.variables[fieldInfo.variableName] = <string>component.value; }));
|
||||
fields.push({ title: fieldInfo.label, component: component });
|
||||
}
|
||||
|
||||
private addInputTypeField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void {
|
||||
let inputType: azdata.InputBoxInputType = 'text';
|
||||
let defaultValue: string | undefined = fieldInfo.defaultValue;
|
||||
|
||||
switch (fieldInfo.type) {
|
||||
case FieldType.Number:
|
||||
inputType = 'number';
|
||||
break;
|
||||
case FieldType.Password:
|
||||
inputType = 'password';
|
||||
break;
|
||||
case FieldType.DateTimeText:
|
||||
defaultValue = fieldInfo.defaultValue + new Date().toISOString().slice(0, 19).replace(/[^0-9]/g, '');
|
||||
break;
|
||||
}
|
||||
const component = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
value: defaultValue, ariaLabel: fieldInfo.label, inputType: inputType, min: fieldInfo.min, max: fieldInfo.max, required: fieldInfo.required, placeHolder: fieldInfo.placeHolder
|
||||
}).component();
|
||||
this.variables[fieldInfo.variableName] = defaultValue;
|
||||
this._toDispose.push(component.onTextChanged(() => { this.variables[fieldInfo.variableName] = component.value; }));
|
||||
fields.push({ title: fieldInfo.label, component: component });
|
||||
|
||||
if (fieldInfo.type === FieldType.Password && fieldInfo.confirmationRequired) {
|
||||
const confirmPasswordComponent = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ ariaLabel: fieldInfo.confirmationLabel, inputType: inputType, required: true }).component();
|
||||
fields.push({ title: fieldInfo.confirmationLabel, component: confirmPasswordComponent });
|
||||
|
||||
this._dialogObject.registerCloseValidator((): boolean => {
|
||||
const passwordMatches = component.value === confirmPasswordComponent.value;
|
||||
if (!passwordMatches) {
|
||||
this._dialogObject.message = { level: azdata.window.MessageLevel.Error, text: localize('passwordNotMatch', "{0} doesn't match the confirmation password", fieldInfo.label) };
|
||||
}
|
||||
return passwordMatches;
|
||||
});
|
||||
|
||||
const checkPassword = (): void => {
|
||||
const passwordMatches = component.value === confirmPasswordComponent.value;
|
||||
if (passwordMatches) {
|
||||
this._dialogObject.message = { text: '' };
|
||||
}
|
||||
};
|
||||
|
||||
this._toDispose.push(component.onTextChanged(() => {
|
||||
checkPassword();
|
||||
}));
|
||||
this._toDispose.push(confirmPasswordComponent.onTextChanged(() => {
|
||||
checkPassword();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private onComplete(): void {
|
||||
Object.keys(this.variables).forEach(key => {
|
||||
process.env[key] = this.variables[key];
|
||||
});
|
||||
this.notebookService.launchNotebook(this.deploymentProvider.notebook);
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
33
extensions/resource-deployment/src/ui/dialogBase.ts
Normal file
33
extensions/resource-deployment/src/ui/dialogBase.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export abstract class DialogBase {
|
||||
protected _toDispose: vscode.Disposable[] = [];
|
||||
protected _dialogObject: azdata.window.Dialog;
|
||||
|
||||
constructor(protected extensionContext: vscode.ExtensionContext, dialogTitle: string, dialogName: string, isWide: boolean = false) {
|
||||
this._dialogObject = azdata.window.createModelViewDialog(dialogTitle, dialogName, isWide);
|
||||
this._dialogObject.cancelButton.onClick(() => this.onCancel());
|
||||
}
|
||||
|
||||
protected abstract initializeDialog(): void;
|
||||
|
||||
public open(): void {
|
||||
this.initializeDialog();
|
||||
azdata.window.openDialog(this._dialogObject);
|
||||
}
|
||||
|
||||
protected onCancel(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
protected dispose(): void {
|
||||
this._toDispose.forEach(disposable => disposable.dispose());
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,13 @@ import * as vscode from 'vscode';
|
||||
import { ResourceType, DeploymentProvider } from '../interfaces';
|
||||
import { IToolsService } from '../services/toolsService';
|
||||
import { INotebookService } from '../services/notebookService';
|
||||
import { DialogBase } from './dialogBase';
|
||||
import { DeploymentDialog } from './deploymentDialog';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class ResourceDeploymentDialog {
|
||||
export class ResourceTypePickerDialog extends DialogBase {
|
||||
private _selectedResourceType: ResourceType;
|
||||
private _toDispose: vscode.Disposable[] = [];
|
||||
private _dialogObject: azdata.window.Dialog;
|
||||
private _resourceTypeCards: azdata.CardComponent[] = [];
|
||||
private _view!: azdata.ModelView;
|
||||
private _resourceDescriptionLabel!: azdata.TextComponent;
|
||||
@@ -26,19 +26,18 @@ export class ResourceDeploymentDialog {
|
||||
private _cardResourceTypeMap: Map<string, azdata.CardComponent> = new Map();
|
||||
private _optionDropDownMap: Map<string, azdata.DropDownComponent> = new Map();
|
||||
|
||||
constructor(private context: vscode.ExtensionContext,
|
||||
constructor(context: vscode.ExtensionContext,
|
||||
private notebookService: INotebookService,
|
||||
private toolsService: IToolsService,
|
||||
private resourceTypeService: IResourceTypeService,
|
||||
resourceType: ResourceType) {
|
||||
super(context, localize('resourceTypePickerDialog.title', "Select the deployment options"), 'ResourceTypePickerDialog', true);
|
||||
this._selectedResourceType = resourceType;
|
||||
this._dialogObject = azdata.window.createModelViewDialog(localize('deploymentDialog.title', 'Select the deployment options'), 'resourceDeploymentDialog', true);
|
||||
this._dialogObject.cancelButton.onClick(() => this.onCancel());
|
||||
this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Open Notebook');
|
||||
this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Select');
|
||||
this._dialogObject.okButton.onClick(() => this.onComplete());
|
||||
}
|
||||
|
||||
private initializeDialog() {
|
||||
initializeDialog() {
|
||||
let tab = azdata.window.createTab('');
|
||||
tab.registerContent((view: azdata.ModelView) => {
|
||||
const tableWidth = 1126;
|
||||
@@ -98,17 +97,12 @@ export class ResourceDeploymentDialog {
|
||||
this._dialogObject.content = [tab];
|
||||
}
|
||||
|
||||
public open(): void {
|
||||
this.initializeDialog();
|
||||
azdata.window.openDialog(this._dialogObject);
|
||||
}
|
||||
|
||||
private addCard(resourceType: ResourceType): void {
|
||||
const card = this._view.modelBuilder.card().withProperties<azdata.CardProperties>({
|
||||
cardType: azdata.CardType.VerticalButton,
|
||||
iconPath: {
|
||||
dark: this.context.asAbsolutePath(resourceType.icon.dark),
|
||||
light: this.context.asAbsolutePath(resourceType.icon.light)
|
||||
dark: this.extensionContext.asAbsolutePath(resourceType.icon.dark),
|
||||
light: this.extensionContext.asAbsolutePath(resourceType.icon.light)
|
||||
},
|
||||
label: resourceType.displayName,
|
||||
selected: (this._selectedResourceType && this._selectedResourceType.name === resourceType.name)
|
||||
@@ -180,17 +174,14 @@ export class ResourceDeploymentDialog {
|
||||
return this._selectedResourceType.getProvider(options)!;
|
||||
}
|
||||
|
||||
private onCancel(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
private onComplete(): void {
|
||||
const provider = this.getCurrentProvider();
|
||||
this.notebookService.launchNotebook(provider.notebook);
|
||||
if (provider.dialog) {
|
||||
const dialog = new DeploymentDialog(this.extensionContext, this.notebookService, provider);
|
||||
dialog.open();
|
||||
} else {
|
||||
this.notebookService.launchNotebook(provider.notebook);
|
||||
}
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
private dispose(): void {
|
||||
this._toDispose.forEach(disposable => disposable.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user