Remove inputValueTransformer and getInputComponentValue (#13502)

This commit is contained in:
Charles Gagnon
2020-11-20 10:51:00 -08:00
committed by GitHub
parent 2a81a0a70f
commit 172a044ba7
2 changed files with 124 additions and 170 deletions

View File

@@ -6,7 +6,7 @@ import * as azdata from 'azdata';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { FieldType, SectionInfo } from '../../../interfaces'; import { FieldType, SectionInfo } from '../../../interfaces';
import { createFlexContainer, createGroupContainer, createLabel, createNumberInput, createSection, createInputBox, getCheckboxComponent, getDropdownComponent, getInputBoxComponent, InputComponentInfo, InputComponents, setModelValues, Validator, InputComponent } from '../../modelViewUtils'; import { createFlexContainer, createGroupContainer, createLabel, createNumberInputBoxInputInfo, createSection, createInputBoxInputInfo, getCheckboxComponent, getDropdownComponent, getInputBoxComponent, InputComponentInfo, InputComponents, setModelValues, Validator, InputComponent } from '../../modelViewUtils';
import { ResourceTypePage } from '../../resourceTypePage'; import { ResourceTypePage } from '../../resourceTypePage';
import * as VariableNames from '../constants'; import * as VariableNames from '../constants';
import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel'; import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel';
@@ -175,54 +175,54 @@ export class ServiceSettingsPage extends ResourceTypePage {
this.endpointHeaderRow = createFlexContainer(view, [this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]); this.endpointHeaderRow = createFlexContainer(view, [this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]);
this.controllerNameLabel = createLabel(view, { text: localize('deployCluster.ControllerText', "Controller"), width: labelWidth, required: true }); this.controllerNameLabel = createLabel(view, { text: localize('deployCluster.ControllerText', "Controller"), width: labelWidth, required: true });
const controllerDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.ControllerDNSName', "Controller DNS name"), required: false, width: inputWidth }); const controllerDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ControllerDNSName', "Controller DNS name"), required: false, width: inputWidth });
this.controllerDNSInput = controllerDNSInput.component; this.controllerDNSInput = controllerDNSInput.component;
const controllerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ControllerPortName', "Controller port"), required: true, width: NumberInputWidth, min: 1 }); const controllerPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ControllerPortName', "Controller port"), required: true, width: NumberInputWidth, min: 1 });
this.controllerPortInput = controllerPortInput.component; this.controllerPortInput = controllerPortInput.component;
this.controllerEndpointRow = createFlexContainer(view, [this.controllerNameLabel, this.controllerDNSInput, this.controllerPortInput]); this.controllerEndpointRow = createFlexContainer(view, [this.controllerNameLabel, this.controllerDNSInput, this.controllerPortInput]);
this.onNewInputComponentCreated(VariableNames.ControllerDNSName_VariableName, controllerDNSInput); this.onNewInputComponentCreated(VariableNames.ControllerDNSName_VariableName, controllerDNSInput);
this.onNewInputComponentCreated(VariableNames.ControllerPort_VariableName, controllerPortInput); this.onNewInputComponentCreated(VariableNames.ControllerPort_VariableName, controllerPortInput);
this.SqlServerNameLabel = createLabel(view, { text: localize('deployCluster.MasterSqlText', "SQL Server Master"), width: labelWidth, required: true }); this.SqlServerNameLabel = createLabel(view, { text: localize('deployCluster.MasterSqlText', "SQL Server Master"), width: labelWidth, required: true });
const sqlServerDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.MasterSQLServerDNSName', "SQL Server Master DNS name"), required: false, width: inputWidth }); const sqlServerDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.MasterSQLServerDNSName', "SQL Server Master DNS name"), required: false, width: inputWidth });
this.sqlServerDNSInput = sqlServerDNSInput.component; this.sqlServerDNSInput = sqlServerDNSInput.component;
const sqlServerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.MasterSQLServerPortName', "SQL Server Master port"), required: true, width: NumberInputWidth, min: 1 }); const sqlServerPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.MasterSQLServerPortName', "SQL Server Master port"), required: true, width: NumberInputWidth, min: 1 });
this.sqlServerPortInput = sqlServerPortInput.component; this.sqlServerPortInput = sqlServerPortInput.component;
this.sqlServerEndpointRow = createFlexContainer(view, [this.SqlServerNameLabel, this.sqlServerDNSInput, this.sqlServerPortInput]); this.sqlServerEndpointRow = createFlexContainer(view, [this.SqlServerNameLabel, this.sqlServerDNSInput, this.sqlServerPortInput]);
this.onNewInputComponentCreated(VariableNames.SQLServerDNSName_VariableName, sqlServerDNSInput); this.onNewInputComponentCreated(VariableNames.SQLServerDNSName_VariableName, sqlServerDNSInput);
this.onNewInputComponentCreated(VariableNames.SQLServerPort_VariableName, sqlServerPortInput); this.onNewInputComponentCreated(VariableNames.SQLServerPort_VariableName, sqlServerPortInput);
this.gatewayNameLabel = createLabel(view, { text: localize('deployCluster.GatewayText', "Gateway"), width: labelWidth, required: true }); this.gatewayNameLabel = createLabel(view, { text: localize('deployCluster.GatewayText', "Gateway"), width: labelWidth, required: true });
const gatewayDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.GatewayDNSName', "Gateway DNS name"), required: false, width: inputWidth }); const gatewayDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.GatewayDNSName', "Gateway DNS name"), required: false, width: inputWidth });
this.gatewayDNSInput = gatewayDNSInput.component; this.gatewayDNSInput = gatewayDNSInput.component;
const gatewayPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.GatewayPortName', "Gateway port"), required: true, width: NumberInputWidth, min: 1 }); const gatewayPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.GatewayPortName', "Gateway port"), required: true, width: NumberInputWidth, min: 1 });
this.gatewayPortInput = gatewayPortInput.component; this.gatewayPortInput = gatewayPortInput.component;
this.gatewayEndpointRow = createFlexContainer(view, [this.gatewayNameLabel, this.gatewayDNSInput, this.gatewayPortInput]); this.gatewayEndpointRow = createFlexContainer(view, [this.gatewayNameLabel, this.gatewayDNSInput, this.gatewayPortInput]);
this.onNewInputComponentCreated(VariableNames.GatewayDNSName_VariableName, gatewayDNSInput); this.onNewInputComponentCreated(VariableNames.GatewayDNSName_VariableName, gatewayDNSInput);
this.onNewInputComponentCreated(VariableNames.GateWayPort_VariableName, gatewayPortInput); this.onNewInputComponentCreated(VariableNames.GateWayPort_VariableName, gatewayPortInput);
this.serviceProxyNameLabel = createLabel(view, { text: localize('deployCluster.ServiceProxyText', "Management proxy"), width: labelWidth, required: true }); this.serviceProxyNameLabel = createLabel(view, { text: localize('deployCluster.ServiceProxyText', "Management proxy"), width: labelWidth, required: true });
const serviceProxyDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.ServiceProxyDNSName', "Management proxy DNS name"), required: false, width: inputWidth }); const serviceProxyDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ServiceProxyDNSName', "Management proxy DNS name"), required: false, width: inputWidth });
this.serviceProxyDNSInput = serviceProxyDNSInput.component; this.serviceProxyDNSInput = serviceProxyDNSInput.component;
const serviceProxyPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ServiceProxyPortName', "Management proxy port"), required: true, width: NumberInputWidth, min: 1 }); const serviceProxyPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ServiceProxyPortName', "Management proxy port"), required: true, width: NumberInputWidth, min: 1 });
this.serviceProxyPortInput = serviceProxyPortInput.component; this.serviceProxyPortInput = serviceProxyPortInput.component;
this.serviceProxyEndpointRow = createFlexContainer(view, [this.serviceProxyNameLabel, this.serviceProxyDNSInput, this.serviceProxyPortInput]); this.serviceProxyEndpointRow = createFlexContainer(view, [this.serviceProxyNameLabel, this.serviceProxyDNSInput, this.serviceProxyPortInput]);
this.onNewInputComponentCreated(VariableNames.ServiceProxyDNSName_VariableName, serviceProxyDNSInput); this.onNewInputComponentCreated(VariableNames.ServiceProxyDNSName_VariableName, serviceProxyDNSInput);
this.onNewInputComponentCreated(VariableNames.ServiceProxyPort_VariableName, serviceProxyPortInput); this.onNewInputComponentCreated(VariableNames.ServiceProxyPort_VariableName, serviceProxyPortInput);
this.appServiceProxyNameLabel = createLabel(view, { text: localize('deployCluster.AppServiceProxyText', "Application proxy"), width: labelWidth, required: true }); this.appServiceProxyNameLabel = createLabel(view, { text: localize('deployCluster.AppServiceProxyText', "Application proxy"), width: labelWidth, required: true });
const appServiceProxyDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.AppServiceProxyDNSName', "Application proxy DNS name"), required: false, width: inputWidth }); const appServiceProxyDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.AppServiceProxyDNSName', "Application proxy DNS name"), required: false, width: inputWidth });
this.appServiceProxyDNSInput = appServiceProxyDNSInput.component; this.appServiceProxyDNSInput = appServiceProxyDNSInput.component;
const appServiceProxyPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.AppServiceProxyPortName', "Application proxy port"), required: true, width: NumberInputWidth, min: 1 }); const appServiceProxyPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.AppServiceProxyPortName', "Application proxy port"), required: true, width: NumberInputWidth, min: 1 });
this.appServiceProxyPortInput = appServiceProxyPortInput.component; this.appServiceProxyPortInput = appServiceProxyPortInput.component;
this.appServiceProxyEndpointRow = createFlexContainer(view, [this.appServiceProxyNameLabel, this.appServiceProxyDNSInput, this.appServiceProxyPortInput]); this.appServiceProxyEndpointRow = createFlexContainer(view, [this.appServiceProxyNameLabel, this.appServiceProxyDNSInput, this.appServiceProxyPortInput]);
this.onNewInputComponentCreated(VariableNames.AppServiceProxyDNSName_VariableName, appServiceProxyDNSInput); this.onNewInputComponentCreated(VariableNames.AppServiceProxyDNSName_VariableName, appServiceProxyDNSInput);
this.onNewInputComponentCreated(VariableNames.AppServiceProxyPort_VariableName, appServiceProxyPortInput); this.onNewInputComponentCreated(VariableNames.AppServiceProxyPort_VariableName, appServiceProxyPortInput);
this.readableSecondaryNameLabel = createLabel(view, { text: localize('deployCluster.ReadableSecondaryText', "Readable secondary"), width: labelWidth, required: true }); this.readableSecondaryNameLabel = createLabel(view, { text: localize('deployCluster.ReadableSecondaryText', "Readable secondary"), width: labelWidth, required: true });
const readableSecondaryDNSInput = createInputBox(view, { ariaLabel: localize('deployCluster.ReadableSecondaryDNSName', "Readable secondary DNS name"), required: false, width: inputWidth }); const readableSecondaryDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ReadableSecondaryDNSName', "Readable secondary DNS name"), required: false, width: inputWidth });
this.readableSecondaryDNSInput = readableSecondaryDNSInput.component; this.readableSecondaryDNSInput = readableSecondaryDNSInput.component;
const readableSecondaryPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ReadableSecondaryPortName', "Readable secondary port"), required: false, width: NumberInputWidth, min: 1 }); const readableSecondaryPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ReadableSecondaryPortName', "Readable secondary port"), required: false, width: NumberInputWidth, min: 1 });
this.readableSecondaryPortInput = readableSecondaryPortInput.component; this.readableSecondaryPortInput = readableSecondaryPortInput.component;
this.readableSecondaryEndpointRow = createFlexContainer(view, [this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput]); this.readableSecondaryEndpointRow = createFlexContainer(view, [this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput]);
this.onNewInputComponentCreated(VariableNames.ReadableSecondaryDNSName_VariableName, readableSecondaryDNSInput); this.onNewInputComponentCreated(VariableNames.ReadableSecondaryDNSName_VariableName, readableSecondaryDNSInput);
@@ -243,10 +243,10 @@ export class ServiceSettingsPage extends ResourceTypePage {
required: true, required: true,
description: localize('deployCluster.AdvancedStorageDescription', "By default Controller storage settings will be applied to other services as well, you can expand the advanced storage settings to configure storage for other services.") description: localize('deployCluster.AdvancedStorageDescription', "By default Controller storage settings will be applied to other services as well, you can expand the advanced storage settings to configure storage for other services.")
}); });
const controllerDataStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.controllerDataStorageClass', "Controller's data storage class"), width: inputWidth, required: true }); const controllerDataStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerDataStorageClass', "Controller's data storage class"), width: inputWidth, required: true });
const controllerDataStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.controllerDataStorageClaimSize', "Controller's data storage claim size"), width: inputWidth, required: true, min: 1 }); const controllerDataStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerDataStorageClaimSize', "Controller's data storage claim size"), width: inputWidth, required: true, min: 1 });
const controllerLogsStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClass', "Controller's logs storage class"), width: inputWidth, required: true }); const controllerLogsStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClass', "Controller's logs storage class"), width: inputWidth, required: true });
const controllerLogsStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClaimSize', "Controller's logs storage claim size"), width: inputWidth, required: true, min: 1 }); const controllerLogsStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClaimSize', "Controller's logs storage claim size"), width: inputWidth, required: true, min: 1 });
const storagePoolLabel = createLabel(view, const storagePoolLabel = createLabel(view,
{ {
@@ -254,10 +254,10 @@ export class ServiceSettingsPage extends ResourceTypePage {
width: inputWidth, width: inputWidth,
required: false required: false
}); });
const storagePoolDataStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClass', "Storage pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const storagePoolDataStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClass', "Storage pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const storagePoolDataStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClaimSize', "Storage pool's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const storagePoolDataStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClaimSize', "Storage pool's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const storagePoolLogsStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClass', "Storage pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const storagePoolLogsStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClass', "Storage pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const storagePoolLogsStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClaimSize', "Storage pool's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const storagePoolLogsStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClaimSize', "Storage pool's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const dataPoolLabel = createLabel(view, const dataPoolLabel = createLabel(view,
{ {
@@ -265,10 +265,10 @@ export class ServiceSettingsPage extends ResourceTypePage {
width: inputWidth, width: inputWidth,
required: false required: false
}); });
const dataPoolDataStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClass', "Data pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const dataPoolDataStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClass', "Data pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const dataPoolDataStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClaimSize', "Data pool's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const dataPoolDataStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClaimSize', "Data pool's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const dataPoolLogsStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClass', "Data pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const dataPoolLogsStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClass', "Data pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const dataPoolLogsStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClaimSize', "Data pool's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const dataPoolLogsStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClaimSize', "Data pool's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const sqlServerMasterLabel = createLabel(view, const sqlServerMasterLabel = createLabel(view,
@@ -277,10 +277,10 @@ export class ServiceSettingsPage extends ResourceTypePage {
width: inputWidth, width: inputWidth,
required: false required: false
}); });
const sqlServerMasterDataStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClass', "SQL Server master's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const sqlServerMasterDataStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClass', "SQL Server master's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const sqlServerMasterDataStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClaimSize', "SQL Server master's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const sqlServerMasterDataStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClaimSize', "SQL Server master's data storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const sqlServerMasterLogsStorageClassInput = createInputBox(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClass', "SQL Server master's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields }); const sqlServerMasterLogsStorageClassInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClass', "SQL Server master's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const sqlServerMasterLogsStorageClaimSizeInput = createNumberInput(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClaimSize', "SQL Server master's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields }); const sqlServerMasterLogsStorageClaimSizeInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClaimSize', "SQL Server master's logs storage claim size"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
this.onNewInputComponentCreated(VariableNames.ControllerDataStorageClassName_VariableName, controllerDataStorageClassInput); this.onNewInputComponentCreated(VariableNames.ControllerDataStorageClassName_VariableName, controllerDataStorageClassInput);
this.onNewInputComponentCreated(VariableNames.ControllerDataStorageSize_VariableName, controllerDataStorageClaimSizeInput); this.onNewInputComponentCreated(VariableNames.ControllerDataStorageSize_VariableName, controllerDataStorageClaimSizeInput);

View File

@@ -33,13 +33,11 @@ const localize = nls.loadMessageBundle();
export type Validator = () => { valid: boolean, message: string }; export type Validator = () => { valid: boolean, message: string };
export type InputValueType = string | number | undefined; export type InputValueType = string | number | undefined;
export type InputValueTransformer = (inputValue: string) => InputValueType | Promise<InputValueType>;
export type InputComponent = azdata.TextComponent | azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent | RadioGroupLoadingComponentBuilder; export type InputComponent = azdata.TextComponent | azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent | RadioGroupLoadingComponentBuilder;
export type InputComponentInfo<T extends InputComponent> = { export type InputComponentInfo<T extends InputComponent> = {
component: T; component: T;
getValue: () => Promise<InputValueType>; getValue: () => Promise<InputValueType>;
onValueChanged: vscode.Event<void>; onValueChanged: vscode.Event<void>;
inputValueTransformer?: InputValueTransformer;
isPassword?: boolean isPassword?: boolean
}; };
@@ -168,7 +166,7 @@ interface InputBoxInfo {
*/ */
function createInputBoxField({ context, inputBoxType = 'text' }: { context: FieldContext; inputBoxType?: azdata.InputBoxInputType; }) { function createInputBoxField({ context, inputBoxType = 'text' }: { context: FieldContext; inputBoxType?: azdata.InputBoxInputType; }) {
const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles });
const input = createInputBox(context.view, { const input = createInputBoxInputInfo(context.view, {
type: inputBoxType, type: inputBoxType,
defaultValue: context.fieldInfo.defaultValue, defaultValue: context.fieldInfo.defaultValue,
ariaLabel: context.fieldInfo.label, ariaLabel: context.fieldInfo.label,
@@ -184,7 +182,7 @@ function createInputBoxField({ context, inputBoxType = 'text' }: { context: Fiel
return input; return input;
} }
export function createInputBox(view: azdata.ModelView, inputInfo: InputBoxInfo): InputComponentInfo<azdata.InputBoxComponent> { export function createInputBoxInputInfo(view: azdata.ModelView, inputInfo: InputBoxInfo): InputComponentInfo<azdata.InputBoxComponent> {
const component = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ const component = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
value: inputInfo.defaultValue, value: inputInfo.defaultValue,
ariaLabel: inputInfo.ariaLabel, ariaLabel: inputInfo.ariaLabel,
@@ -198,7 +196,7 @@ export function createInputBox(view: azdata.ModelView, inputInfo: InputBoxInfo):
}).withValidation(async (component) => await validateInputBoxComponent(component, inputInfo.validations)).component(); }).withValidation(async (component) => await validateInputBoxComponent(component, inputInfo.validations)).component();
return { return {
component: component, component: component,
getValue: async (): Promise<InputValueType> => component.value || '', getValue: async (): Promise<InputValueType> => component.value,
onValueChanged: component.onTextChanged onValueChanged: component.onTextChanged
}; };
} }
@@ -229,11 +227,19 @@ export function createLabel(view: azdata.ModelView, info: { text: string, descri
* @param view - the ModelView object used to create the inputBox * @param view - the ModelView object used to create the inputBox
* @param info - an object to define the properties of the 'number' inputBox component. If the type property is set then it is overridden with 'number' type. * @param info - an object to define the properties of the 'number' inputBox component. If the type property is set then it is overridden with 'number' type.
*/ */
export function createNumberInput(view: azdata.ModelView, info: InputBoxInfo): InputComponentInfo<azdata.InputBoxComponent> { export function createNumberInputBoxInputInfo(view: azdata.ModelView, info: InputBoxInfo): InputComponentInfo<azdata.InputBoxComponent> {
info.type = 'number'; // for the type to be 'number' info.type = 'number'; // for the type to be 'number'
return createInputBox(view, info); return createInputBoxInputInfo(view, info);
} }
export function createCheckboxInputInfo(view: azdata.ModelView, info: { initialValue: boolean, label: string, required?: boolean }): InputComponentInfo<azdata.CheckBoxComponent> {
const checkbox = createCheckbox(view, info);
return {
component: checkbox,
getValue: async () => checkbox.checked ? 'true' : 'false',
onValueChanged: checkbox.onChanged
};
}
export function createCheckbox(view: azdata.ModelView, info: { initialValue: boolean, label: string, required?: boolean }): azdata.CheckBoxComponent { export function createCheckbox(view: azdata.ModelView, info: { initialValue: boolean, label: string, required?: boolean }): azdata.CheckBoxComponent {
return view.modelBuilder.checkBox().withProperties<azdata.CheckBoxProperties>({ return view.modelBuilder.checkBox().withProperties<azdata.CheckBoxProperties>({
checked: info.initialValue, checked: info.initialValue,
@@ -242,8 +248,8 @@ export function createCheckbox(view: azdata.ModelView, info: { initialValue: boo
}).component(); }).component();
} }
export function createDropdown(view: azdata.ModelView, info: { defaultValue?: string | azdata.CategoryValue, values?: string[] | azdata.CategoryValue[], width?: string, editable?: boolean, required?: boolean, label: string }): azdata.DropDownComponent { export function createDropdownInputInfo(view: azdata.ModelView, info: { defaultValue?: string | azdata.CategoryValue, values?: string[] | azdata.CategoryValue[], width?: string, editable?: boolean, required?: boolean, label: string }): InputComponentInfo<azdata.DropDownComponent> {
return view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({ const dropdown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({
values: info.values, values: info.values,
value: info.defaultValue, value: info.defaultValue,
width: info.width, width: info.width,
@@ -252,6 +258,12 @@ export function createDropdown(view: azdata.ModelView, info: { defaultValue?: st
required: info.required, required: info.required,
ariaLabel: info.label ariaLabel: info.label
}).component(); }).component();
return {
component: dropdown,
getValue: async (): Promise<InputValueType> => typeof dropdown.value === 'string' ? dropdown.value : dropdown.value?.name,
onValueChanged: dropdown.onValueChanged,
};
} }
export function initializeDialog(dialogContext: DialogContext): void { export function initializeDialog(dialogContext: DialogContext): void {
@@ -451,7 +463,7 @@ export function createGroupContainer(view: azdata.ModelView, items: azdata.Compo
return view.modelBuilder.groupContainer().withItems(items).withLayout(layout).component(); return view.modelBuilder.groupContainer().withItems(items).withLayout(layout).component();
} }
function addLabelInputPairToContainer(view: azdata.ModelView, components: azdata.Component[], label: azdata.Component, input: azdata.Component | undefined, fieldInfo: FieldInfo, additionalComponents?: azdata.Component[]) { function addLabelInputPairToContainer(view: azdata.ModelView, components: azdata.Component[], label: azdata.Component, input: azdata.Component | undefined, fieldInfo: FieldInfo, additionalComponents?: azdata.Component[]): void {
const inputs: azdata.Component[] = [label]; const inputs: azdata.Component[] = [label];
if (input !== undefined) { if (input !== undefined) {
inputs.push(input); inputs.push(input);
@@ -479,7 +491,7 @@ async function processField(context: FieldContext): Promise<void> {
} }
}, },
() => context.inputComponents[context.fieldInfo.variableName || context.fieldInfo.label].getValue(), // callback to fetch the value of this field, and return the default value if the field value is undefined () => context.inputComponents[context.fieldInfo.variableName || context.fieldInfo.label].getValue(), // callback to fetch the value of this field, and return the default value if the field value is undefined
(variable: string) => getInputComponentValue(context.inputComponents[variable]), // callback to fetch the value of a variable corresponding to any field already defined. (variable: string) => context.inputComponents[variable].getValue(), // callback to fetch the value of a variable corresponding to any field already defined.
(targetVariable: string) => (<azdata.InputBoxComponent>context.inputComponents[targetVariable].component).onValidityChanged, (targetVariable: string) => (<azdata.InputBoxComponent>context.inputComponents[targetVariable].component).onValidityChanged,
(disposable: vscode.Disposable) => context.onNewDisposableCreated(disposable) (disposable: vscode.Disposable) => context.onNewDisposableCreated(disposable)
))); )));
@@ -581,16 +593,18 @@ async function processOptionsTypeField(context: FieldContext): Promise<void> {
} }
} }
async function configureOptionsSourceSubfields(context: FieldContext, optionsSource: IOptionsSource, variableKey: string, optionsComponent: RadioGroupLoadingComponentBuilder | azdata.DropDownComponent, optionsSourceProvider: IOptionsSourceProvider) { async function configureOptionsSourceSubfields(context: FieldContext, optionsSource: IOptionsSource, variableKey: string, optionsComponent: RadioGroupLoadingComponentBuilder | azdata.DropDownComponent, optionsSourceProvider: IOptionsSourceProvider): Promise<void> {
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: context.fieldInfo.label, label: context.fieldInfo.label,
variableName: optionsSource.variableNames![variableKey] variableName: optionsSource.variableNames![variableKey]
}); });
context.onNewInputComponentCreated(optionsSource.variableNames![variableKey], { context.onNewInputComponentCreated(optionsSource.variableNames![variableKey], {
component: optionsComponent, component: optionsComponent,
inputValueTransformer: async (optionValue: string) => { isPassword: await optionsSourceProvider.getIsPassword!(variableKey),
getValue: async (): Promise<InputValueType> => {
const value = (typeof optionsComponent.value === 'string' ? optionsComponent.value : optionsComponent.value?.name) || '';
try { try {
return await optionsSourceProvider.getVariableValue!(variableKey, optionValue); return await optionsSourceProvider.getVariableValue!(variableKey, value);
} catch (e) { } catch (e) {
disableControlButtons(context.container); disableControlButtons(context.container);
context.container.message = { context.container.message = {
@@ -601,8 +615,6 @@ async function configureOptionsSourceSubfields(context: FieldContext, optionsSou
throw e; throw e;
} }
}, },
isPassword: await optionsSourceProvider.getIsPassword!(variableKey),
getValue: async (): Promise<InputValueType> => (typeof optionsComponent.value === 'string' ? optionsComponent.value : optionsComponent.value?.displayName) || '',
onValueChanged: optionsComponent.onValueChanged onValueChanged: optionsComponent.onValueChanged
}); });
} }
@@ -610,7 +622,7 @@ async function configureOptionsSourceSubfields(context: FieldContext, optionsSou
function processDropdownOptionsTypeField(context: FieldContext): azdata.DropDownComponent { function processDropdownOptionsTypeField(context: FieldContext): azdata.DropDownComponent {
const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles });
const options = context.fieldInfo.options as OptionsInfo; const options = context.fieldInfo.options as OptionsInfo;
const dropdown = createDropdown(context.view, { const dropdown = createDropdownInputInfo(context.view, {
values: options.values, values: options.values,
defaultValue: options.defaultValue, defaultValue: options.defaultValue,
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
@@ -618,33 +630,27 @@ function processDropdownOptionsTypeField(context: FieldContext): azdata.DropDown
required: context.fieldInfo.required, required: context.fieldInfo.required,
label: context.fieldInfo.label label: context.fieldInfo.label
}); });
dropdown.fireOnTextChange = true; dropdown.component.fireOnTextChange = true;
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, dropdown);
getValue: async (): Promise<InputValueType> => typeof dropdown.value === 'string' ? dropdown.value : dropdown.value?.displayName || '', addLabelInputPairToContainer(context.view, context.components, label, dropdown.component, context.fieldInfo);
onValueChanged: dropdown.onValueChanged, return dropdown.component;
component: dropdown
});
addLabelInputPairToContainer(context.view, context.components, label, dropdown, context.fieldInfo);
return dropdown;
} }
function processDateTimeTextField(context: FieldContext): void { function processDateTimeTextField(context: FieldContext): void {
context.fieldInfo.defaultValue = context.fieldInfo.defaultValue + getDateTimeString(); context.fieldInfo.defaultValue = context.fieldInfo.defaultValue + getDateTimeString();
const input = createInputBoxField({ context }); const input = createInputBoxField({ context });
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, input);
component: input.component,
getValue: async (): Promise<InputValueType> => input.component.value || '',
onValueChanged: input.component.onTextChanged
});
} }
function processNumberField(context: FieldContext): void { function processNumberField(context: FieldContext): void {
const input = createInputBoxField({ context, inputBoxType: 'number' }); const input = createInputBoxField({ context, inputBoxType: 'number' });
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, {
component: input.component, component: input.component,
getValue: input.getValue, getValue: async (): Promise<InputValueType> => {
onValueChanged: input.onValueChanged, const value = await input.getValue();
inputValueTransformer: (value: string | number | undefined) => (typeof value === 'string') && value.length > 0 ? parseFloat(value) : value return typeof value === 'string' && value.length > 0 ? parseFloat(value) : value;
},
onValueChanged: input.onValueChanged
}); });
} }
@@ -655,8 +661,8 @@ function processTextField(context: FieldContext): InputComponentInfo<azdata.Inpu
input.isPassword = isPasswordField; input.isPassword = isPasswordField;
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, input); context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, input);
return input; return input;
} }
function processPasswordField(context: FieldContext): void { function processPasswordField(context: FieldContext): void {
const passwordInput = processTextField(context); const passwordInput = processTextField(context);
@@ -732,16 +738,15 @@ function processHyperlinkedTextField(context: FieldContext): ReadOnlyFieldInputs
function processEvaluatedTextField(context: FieldContext): ReadOnlyFieldInputs { function processEvaluatedTextField(context: FieldContext): ReadOnlyFieldInputs {
const readOnlyField = processReadonlyTextField(context, false /*allowEvaluation*/); const readOnlyField = processReadonlyTextField(context, false /*allowEvaluation*/);
const onChangedEmitter = new vscode.EventEmitter<void>(); // Stub event since we don't currently supp const onChangedEmitter = new vscode.EventEmitter<void>(); // Stub event since we don't currently support updating this when the dependent fields change
context.onNewDisposableCreated(onChangedEmitter); context.onNewDisposableCreated(onChangedEmitter);
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, {
component: readOnlyField.text!, component: readOnlyField.text!,
getValue: async (): Promise<InputValueType> => readOnlyField.text?.value || '', getValue: async (): Promise<InputValueType> => {
onValueChanged: onChangedEmitter.event,
inputValueTransformer: async () => {
readOnlyField.text!.value = await substituteVariableValues(context.inputComponents, context.fieldInfo.defaultValue); readOnlyField.text!.value = await substituteVariableValues(context.inputComponents, context.fieldInfo.defaultValue);
return readOnlyField.text?.value!; return readOnlyField.text!.value;
} },
onValueChanged: onChangedEmitter.event,
}); });
return readOnlyField; return readOnlyField;
} }
@@ -759,7 +764,7 @@ async function substituteVariableValues(inputComponents: InputComponents, inputV
await Promise.all(Object.keys(inputComponents) await Promise.all(Object.keys(inputComponents)
.filter(key => key.startsWith(NoteBookEnvironmentVariablePrefix)) .filter(key => key.startsWith(NoteBookEnvironmentVariablePrefix))
.map(async key => { .map(async key => {
const value = (await getInputComponentValue(inputComponents[key])) ?? '<undefined>'; const value = (await inputComponents[key].getValue()) ?? '<undefined>';
const re: RegExp = new RegExp(`\\\$\\\(${key}\\\)`, 'gi'); const re: RegExp = new RegExp(`\\\$\\\(${key}\\\)`, 'gi');
inputValue = inputValue?.replace(re, value.toString()); inputValue = inputValue?.replace(re, value.toString());
}) })
@@ -768,17 +773,9 @@ async function substituteVariableValues(inputComponents: InputComponents, inputV
} }
function processCheckboxField(context: FieldContext): void { function processCheckboxField(context: FieldContext): void {
const checkbox = createCheckbox(context.view, { initialValue: context.fieldInfo.defaultValue! === 'true', label: context.fieldInfo.label, required: context.fieldInfo.required }); const checkbox = createCheckboxInputInfo(context.view, { initialValue: context.fieldInfo.defaultValue! === 'true', label: context.fieldInfo.label, required: context.fieldInfo.required });
context.components.push(checkbox); context.components.push(checkbox.component);
const onChangedEmitter = new vscode.EventEmitter<void>(); context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, checkbox);
context.onNewDisposableCreated(onChangedEmitter);
const onChangedEvent = checkbox.onChanged(() => onChangedEmitter.fire());
context.onNewDisposableCreated(onChangedEvent);
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, {
getValue: async (): Promise<InputValueType> => checkbox.checked?.toString() || '',
onValueChanged: onChangedEmitter.event,
component: checkbox
});
} }
/** /**
@@ -790,7 +787,7 @@ function processFilePickerField(context: FieldContext): FilePickerInputs {
const buttonWidth = 100; const buttonWidth = 100;
const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles });
const input = createInputBox(context.view, { const input = createInputBoxInputInfo(context.view, {
defaultValue: context.fieldInfo.defaultValue || '', defaultValue: context.fieldInfo.defaultValue || '',
ariaLabel: context.fieldInfo.label, ariaLabel: context.fieldInfo.label,
required: context.fieldInfo.required, required: context.fieldInfo.required,
@@ -929,7 +926,7 @@ async function createRadioOptions(context: FieldContext, getRadioButtonInfo?: ((
context.fieldInfo.labelPosition = LabelPosition.Left; context.fieldInfo.labelPosition = LabelPosition.Left;
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, {
component: radioGroupLoadingComponentBuilder, component: radioGroupLoadingComponentBuilder,
getValue: async (): Promise<InputValueType> => radioGroupLoadingComponentBuilder.value || '', getValue: async (): Promise<InputValueType> => radioGroupLoadingComponentBuilder.value,
onValueChanged: radioGroupLoadingComponentBuilder.onValueChanged, onValueChanged: radioGroupLoadingComponentBuilder.onValueChanged,
}); });
addLabelInputPairToContainer(context.view, context.components, label, radioGroupLoadingComponentBuilder.component(), context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, radioGroupLoadingComponentBuilder.component(), context.fieldInfo);
@@ -965,15 +962,11 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
const subscriptionDropdown = createAzureSubscriptionDropdown(context, subscriptionValueToSubscriptionMap); const subscriptionDropdown = createAzureSubscriptionDropdown(context, subscriptionValueToSubscriptionMap);
const resourceGroupDropdown = createAzureResourceGroupsDropdown(context, accountDropdown, accountValueToAccountMap, subscriptionDropdown, subscriptionValueToSubscriptionMap); const resourceGroupDropdown = createAzureResourceGroupsDropdown(context, accountDropdown, accountValueToAccountMap, subscriptionDropdown, subscriptionValueToSubscriptionMap);
if (context.fieldInfo.allowNewResourceGroup) { if (context.fieldInfo.allowNewResourceGroup) {
const newRGCheckbox = createCheckbox(context.view, { initialValue: false, label: loc.createNewResourceGroup }); const newRGCheckbox = createCheckboxInputInfo(context.view, { initialValue: false, label: loc.createNewResourceGroup });
context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupFlagVariableName!, { context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupFlagVariableName!, newRGCheckbox);
component: newRGCheckbox, const newRGNameInput = createInputBoxInputInfo(context.view, { ariaLabel: loc.NewResourceGroupAriaLabel });
getValue: async (): Promise<InputValueType> => newRGCheckbox.checked?.toString() || '',
onValueChanged: newRGCheckbox.onChanged
});
const newRGNameInput = createInputBox(context.view, { ariaLabel: loc.NewResourceGroupAriaLabel });
context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupNameVariableName!, newRGNameInput); context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupNameVariableName!, newRGNameInput);
context.components.push(newRGCheckbox); context.components.push(newRGCheckbox.component);
context.components.push(newRGNameInput.component); context.components.push(newRGNameInput.component);
const setRGStatus = (newRG: boolean) => { const setRGStatus = (newRG: boolean) => {
resourceGroupDropdown.required = !newRG; resourceGroupDropdown.required = !newRG;
@@ -984,8 +977,8 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
newRGNameInput.component.value = ''; newRGNameInput.component.value = '';
} }
}; };
context.onNewDisposableCreated(newRGCheckbox.onChanged(() => { context.onNewDisposableCreated(newRGCheckbox.onValueChanged(() => {
setRGStatus(newRGCheckbox.checked!); setRGStatus(newRGCheckbox.component.checked!);
})); }));
setRGStatus(false); setRGStatus(false);
} }
@@ -1049,7 +1042,7 @@ async function processKubeStorageClassField(context: FieldContext): Promise<void
vscode.window.showErrorMessage(localize('resourceDeployment.errorFetchingStorageClasses', "Unexpected error fetching available kubectl storage classes : {0}", err.message ?? err)); vscode.window.showErrorMessage(localize('resourceDeployment.errorFetchingStorageClasses', "Unexpected error fetching available kubectl storage classes : {0}", err.message ?? err));
} }
const storageClassDropdown = createDropdown(context.view, { const storageClassDropdown = createDropdownInputInfo(context.view, {
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
editable: true, editable: true,
required: context.fieldInfo.required, required: context.fieldInfo.required,
@@ -1057,13 +1050,9 @@ async function processKubeStorageClassField(context: FieldContext): Promise<void
values: storageClasses, values: storageClasses,
defaultValue: defaultStorageClass defaultValue: defaultStorageClass
}); });
storageClassDropdown.fireOnTextChange = true; storageClassDropdown.component.fireOnTextChange = true;
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, storageClassDropdown);
component: storageClassDropdown, addLabelInputPairToContainer(context.view, context.components, label, storageClassDropdown.component, context.fieldInfo);
getValue: async (): Promise<InputValueType> => (typeof storageClassDropdown.value === 'string' ? storageClassDropdown.value : storageClassDropdown.value?.displayName) || '',
onValueChanged: storageClassDropdown.onValueChanged
});
addLabelInputPairToContainer(context.view, context.components, label, storageClassDropdown, context.fieldInfo);
} }
@@ -1079,26 +1068,22 @@ function createAzureAccountDropdown(context: AzureAccountFieldContext): AzureAcc
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const accountDropdown = createDropdown(context.view, { const accountDropdown = createDropdownInputInfo(context.view, {
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
editable: false, editable: false,
required: context.fieldInfo.required, required: context.fieldInfo.required,
label: loc.account label: loc.account
}); });
accountDropdown.fireOnTextChange = true; accountDropdown.component.fireOnTextChange = true;
context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, accountDropdown);
component: accountDropdown,
getValue: async (): Promise<InputValueType> => (typeof accountDropdown.value === 'string' ? accountDropdown.value : accountDropdown.value?.displayName) || '',
onValueChanged: accountDropdown.onValueChanged
});
const signInButton = context.view!.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.signIn, width: '100px' }).component(); const signInButton = context.view!.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.signIn, width: '100px' }).component();
const refreshButton = context.view!.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.refresh, width: '100px' }).component(); const refreshButton = context.view!.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.refresh, width: '100px' }).component();
addLabelInputPairToContainer(context.view, context.components, label, accountDropdown, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, accountDropdown.component, context.fieldInfo);
const buttons = createFlexContainer(context.view!, [signInButton, refreshButton], true, undefined, undefined, undefined, { 'margin-right': '10px' }); const buttons = createFlexContainer(context.view!, [signInButton, refreshButton], true, undefined, undefined, undefined, { 'margin-right': '10px' });
context.components.push(buttons); context.components.push(buttons);
return { return {
accountDropdown: accountDropdown, accountDropdown: accountDropdown.component,
signInButton: signInButton, signInButton: signInButton,
refreshAccountsButton: refreshButton refreshAccountsButton: refreshButton
}; };
@@ -1115,39 +1100,35 @@ function createAzureSubscriptionDropdown(
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const subscriptionDropdown = createDropdown(context.view, { const subscriptionDropdown = createDropdownInputInfo(context.view, {
defaultValue: (context.fieldInfo.required) ? undefined : '', defaultValue: (context.fieldInfo.required) ? undefined : '',
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
editable: false, editable: false,
required: context.fieldInfo.required, required: context.fieldInfo.required,
label: loc.subscription label: loc.subscription
}); });
subscriptionDropdown.fireOnTextChange = true; subscriptionDropdown.component.fireOnTextChange = true;
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value!,
variableName: context.fieldInfo.subscriptionVariableName variableName: context.fieldInfo.subscriptionVariableName
}); });
context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName || context.fieldInfo.label, {
component: subscriptionDropdown, component: subscriptionDropdown.component,
getValue: async (): Promise<InputValueType> => (typeof subscriptionDropdown.value === 'string' ? subscriptionDropdown.value : subscriptionDropdown.value?.displayName) || '', getValue: async (): Promise<InputValueType> => {
onValueChanged: subscriptionDropdown.onValueChanged, const inputValue = (await subscriptionDropdown.getValue())?.toString() || '';
inputValueTransformer: (inputValue: string) => {
return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue; return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue;
} },
onValueChanged: subscriptionDropdown.onValueChanged
}); });
if (context.fieldInfo.displaySubscriptionVariableName) { if (context.fieldInfo.displaySubscriptionVariableName) {
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value!,
variableName: context.fieldInfo.displaySubscriptionVariableName variableName: context.fieldInfo.displaySubscriptionVariableName
}); });
context.onNewInputComponentCreated(context.fieldInfo.displaySubscriptionVariableName!, { context.onNewInputComponentCreated(context.fieldInfo.displaySubscriptionVariableName!, subscriptionDropdown);
component: subscriptionDropdown,
getValue: async (): Promise<InputValueType> => (typeof subscriptionDropdown.value === 'string' ? subscriptionDropdown.value : subscriptionDropdown.value?.displayName) || '',
onValueChanged: subscriptionDropdown.onValueChanged,
});
} }
addLabelInputPairToContainer(context.view, context.components, label, subscriptionDropdown, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, subscriptionDropdown.component, context.fieldInfo);
return subscriptionDropdown; return subscriptionDropdown.component;
} }
async function handleSelectedAccountChanged( async function handleSelectedAccountChanged(
@@ -1259,33 +1240,29 @@ function createAzureResourceGroupsDropdown(
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const resourceGroupDropdown = createDropdown(context.view, { const resourceGroupDropdown = createDropdownInputInfo(context.view, {
defaultValue: (context.fieldInfo.required) ? undefined : '', defaultValue: (context.fieldInfo.required) ? undefined : '',
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
editable: false, editable: false,
required: context.fieldInfo.required, required: context.fieldInfo.required,
label: loc.resourceGroup label: loc.resourceGroup
}); });
resourceGroupDropdown.fireOnTextChange = true; resourceGroupDropdown.component.fireOnTextChange = true;
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value!,
variableName: context.fieldInfo.resourceGroupVariableName variableName: context.fieldInfo.resourceGroupVariableName
}); });
const rgValueChangedEmitter = new vscode.EventEmitter<void>(); const rgValueChangedEmitter = new vscode.EventEmitter<void>();
resourceGroupDropdown.onValueChanged(() => rgValueChangedEmitter.fire()); resourceGroupDropdown.onValueChanged(() => rgValueChangedEmitter.fire());
context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName || context.fieldInfo.label, resourceGroupDropdown);
component: resourceGroupDropdown, addLabelInputPairToContainer(context.view, context.components, label, resourceGroupDropdown.component, context.fieldInfo);
getValue: async (): Promise<InputValueType> => (typeof resourceGroupDropdown.value === 'string' ? resourceGroupDropdown.value : resourceGroupDropdown.value?.displayName) || '',
onValueChanged: resourceGroupDropdown.onValueChanged,
});
addLabelInputPairToContainer(context.view, context.components, label, resourceGroupDropdown, context.fieldInfo);
subscriptionDropdown.onValueChanged(async selectedItem => { subscriptionDropdown.onValueChanged(async selectedItem => {
const selectedAccount = !accountDropdown || !accountDropdown.value ? undefined : accountValueToAccountMap.get(accountDropdown.value.toString()); const selectedAccount = !accountDropdown || !accountDropdown.value ? undefined : accountValueToAccountMap.get(accountDropdown.value.toString());
const selectedSubscription = subscriptionValueToSubscriptionMap.get(selectedItem.selected); const selectedSubscription = subscriptionValueToSubscriptionMap.get(selectedItem.selected);
await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown.component);
rgValueChangedEmitter.fire(); rgValueChangedEmitter.fire();
}); });
return resourceGroupDropdown; return resourceGroupDropdown.component;
} }
async function handleSelectedSubscriptionChanged(context: AzureAccountFieldContext, selectedAccount: azdata.Account | undefined, selectedSubscription: azureResource.AzureResourceSubscription | undefined, resourceGroupDropdown: azdata.DropDownComponent): Promise<void> { async function handleSelectedSubscriptionChanged(context: AzureAccountFieldContext, selectedAccount: azdata.Account | undefined, selectedSubscription: azureResource.AzureResourceSubscription | undefined, resourceGroupDropdown: azdata.DropDownComponent): Promise<void> {
@@ -1347,7 +1324,7 @@ async function processAzureLocationsField(context: AzureLocationsFieldContext):
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const locationValues = context.fieldInfo.locations?.map(l => { return { name: l, displayName: apiService.azurecoreApi.getRegionDisplayName(l) }; }); const locationValues = context.fieldInfo.locations?.map(l => { return { name: l, displayName: apiService.azurecoreApi.getRegionDisplayName(l) }; });
const locationDropdown = createDropdown(context.view, { const locationDropdown = createDropdownInputInfo(context.view, {
defaultValue: locationValues?.find(l => l.name === context.fieldInfo.defaultValue), defaultValue: locationValues?.find(l => l.name === context.fieldInfo.defaultValue),
width: context.fieldInfo.inputWidth, width: context.fieldInfo.inputWidth,
editable: false, editable: false,
@@ -1355,33 +1332,33 @@ async function processAzureLocationsField(context: AzureLocationsFieldContext):
label: loc.location, label: loc.location,
values: locationValues values: locationValues
}); });
locationDropdown.fireOnTextChange = true; locationDropdown.component.fireOnTextChange = true;
context.fieldInfo.subFields = context.fieldInfo.subFields || []; context.fieldInfo.subFields = context.fieldInfo.subFields || [];
if (context.fieldInfo.locationVariableName) { if (context.fieldInfo.locationVariableName) {
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value!,
variableName: context.fieldInfo.locationVariableName variableName: context.fieldInfo.locationVariableName
}); });
context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, { context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, locationDropdown);
component: locationDropdown,
getValue: async (): Promise<InputValueType> => (typeof locationDropdown.value === 'string' ? locationDropdown.value : locationDropdown.value?.displayName) || '',
onValueChanged: locationDropdown.onValueChanged,
});
} }
if (context.fieldInfo.displayLocationVariableName) { if (context.fieldInfo.displayLocationVariableName) {
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value!,
variableName: context.fieldInfo.displayLocationVariableName variableName: context.fieldInfo.displayLocationVariableName
}); });
// Create a special input component that maps the dropdown to the display name for the location
// so that we have two variables - one for the value and one for the display name
context.onNewInputComponentCreated(context.fieldInfo.displayLocationVariableName, { context.onNewInputComponentCreated(context.fieldInfo.displayLocationVariableName, {
component: locationDropdown, component: locationDropdown.component,
inputValueTransformer: (value => apiService.azurecoreApi.getRegionDisplayName(value)), getValue: async (): Promise<InputValueType> => {
getValue: async (): Promise<InputValueType> => (typeof locationDropdown.value === 'string' ? locationDropdown.value : locationDropdown.value?.displayName) || '', const inputValue = (await locationDropdown.getValue())?.toString();
return apiService.azurecoreApi.getRegionDisplayName(inputValue);
},
onValueChanged: locationDropdown.onValueChanged, onValueChanged: locationDropdown.onValueChanged,
}); });
} }
addLabelInputPairToContainer(context.view, context.components, label, locationDropdown, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, locationDropdown.component, context.fieldInfo);
return locationDropdown; return locationDropdown.component;
} }
export function isValidSQLPassword(password: string, userName: string = 'sa'): boolean { export function isValidSQLPassword(password: string, userName: string = 'sa'): boolean {
@@ -1413,34 +1390,11 @@ export function getPasswordMismatchMessage(fieldName: string): string {
export async function setModelValues(inputComponents: InputComponents, model: Model): Promise<void> { export async function setModelValues(inputComponents: InputComponents, model: Model): Promise<void> {
await Promise.all(Object.keys(inputComponents).map(async key => { await Promise.all(Object.keys(inputComponents).map(async key => {
const value = await getInputComponentValue(inputComponents[key]); const value = await inputComponents[key].getValue();
model.setPropertyValue(key, value); model.setPropertyValue(key, value);
})); }));
} }
async function getInputComponentValue(inputComponentInfo: InputComponentInfo<InputComponent>): Promise<InputValueType> {
const input = inputComponentInfo.component;
if (input === undefined) {
return undefined;
}
let value: string | number | undefined;
if (input instanceof RadioGroupLoadingComponentBuilder) {
value = input.value;
} else if ('checked' in input) { // CheckBoxComponent
value = input.checked ? 'true' : 'false';
} else if ('value' in input) { // InputBoxComponent or DropDownComponent
const inputValue = input.value;
if (typeof inputValue === 'string' || typeof inputValue === 'undefined' || typeof inputValue === 'number') {
value = inputValue;
} else {
value = inputValue.name;
}
} else {
throw new Error(`Unknown input type with ID ${input.id}`);
}
return inputComponentInfo.inputValueTransformer ? await inputComponentInfo.inputValueTransformer(value ?? '') : value;
}
export function isInputBoxEmpty(input: azdata.InputBoxComponent): boolean { export function isInputBoxEmpty(input: azdata.InputBoxComponent): boolean {
return input.value === undefined || input.value === ''; return input.value === undefined || input.value === '';
} }