Add support for initial values of Azure fields in resource deployment (#14458)

This commit is contained in:
Charles Gagnon
2021-02-26 09:33:34 -08:00
committed by GitHub
parent ab114376aa
commit 013ecc4ddc

View File

@@ -163,6 +163,8 @@ interface InputBoxInfo {
validations?: Validation[]; validations?: Validation[];
} }
type AzureComponent = azdata.InputBoxComponent | azdata.DropDownComponent;
/** /**
* Creates an inputBox using the properties defined in context.fieldInfo object * Creates an inputBox using the properties defined in context.fieldInfo object
* *
@@ -1055,10 +1057,19 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
context.fieldInfo.subFields = []; context.fieldInfo.subFields = [];
const accountValueToAccountMap = new Map<string, azdata.Account>(); const accountValueToAccountMap = new Map<string, azdata.Account>();
const subscriptionValueToSubscriptionMap = new Map<string, azureResource.AzureResourceSubscription>(); const subscriptionValueToSubscriptionMap = new Map<string, azureResource.AzureResourceSubscription>();
const accountComponents = createAzureAccountDropdown(context); let accountComponents: AzureAccountComponents | undefined;
const accountDropdown = accountComponents.accountDropdown; let accountDropdown: azdata.DropDownComponent | undefined;
const subscriptionDropdown = createAzureSubscriptionDropdown(context, subscriptionValueToSubscriptionMap);
const resourceGroupDropdown = createAzureResourceGroupsDropdown(context, accountDropdown, accountValueToAccountMap, subscriptionDropdown, subscriptionValueToSubscriptionMap); // Check if we have an initial subscription value - if we do then the user isn't going to be allowed to change any of the
// Azure values so we can skip adding the account picker
const hasInitialSubscriptionValue = !!context.initialVariableValues?.[context.fieldInfo.subscriptionVariableName || ''].toString();
if (!hasInitialSubscriptionValue) {
accountComponents = createAzureAccountDropdown(context);
accountDropdown = accountComponents.accountDropdown;
}
const subscriptionComponent = createAzureSubscriptionComponent(context, subscriptionValueToSubscriptionMap);
const resourceGroupComponent = createAzureResourceGroupsComponent(context, accountDropdown, accountValueToAccountMap, subscriptionComponent, subscriptionValueToSubscriptionMap);
if (context.fieldInfo.allowNewResourceGroup) { if (context.fieldInfo.allowNewResourceGroup) {
const newRGCheckbox = createCheckboxInputInfo(context.view, { initialValue: false, label: loc.createNewResourceGroup }); const newRGCheckbox = createCheckboxInputInfo(context.view, { initialValue: false, label: loc.createNewResourceGroup });
context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupFlagVariableName!, newRGCheckbox); context.onNewInputComponentCreated(context.fieldInfo.newResourceGroupFlagVariableName!, newRGCheckbox);
@@ -1067,8 +1078,8 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
context.components.push(newRGCheckbox.component); 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; resourceGroupComponent.required = !newRG;
resourceGroupDropdown.enabled = !newRG; resourceGroupComponent.enabled = !newRG;
newRGNameInput.component.required = newRG; newRGNameInput.component.required = newRG;
newRGNameInput.component.enabled = newRG; newRGNameInput.component.enabled = newRG;
if (!newRG) { if (!newRG) {
@@ -1080,42 +1091,45 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
})); }));
setRGStatus(false); setRGStatus(false);
} }
const locationDropdown = context.fieldInfo.locations && await processAzureLocationsField(context);
accountDropdown.onValueChanged(async selectedItem => {
const selectedAccount = accountValueToAccountMap.get(selectedItem.selected)!;
await handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown);
});
const populateAzureAccounts = async () => { const locationComponent = context.fieldInfo.locations && await processAzureLocationsField(context);
accountValueToAccountMap.clear(); if (!hasInitialSubscriptionValue) {
try { accountDropdown!.onValueChanged(async selectedItem => {
const accounts = await azdata.accounts.getAllAccounts(); const selectedAccount = accountValueToAccountMap.get(selectedItem.selected)!;
// Append a blank value for the "default" option if the field isn't required, context will clear all the dropdowns when selected await handleSelectedAccountChanged(context, selectedAccount, subscriptionComponent, subscriptionValueToSubscriptionMap, resourceGroupComponent, locationComponent);
const dropdownValues = context.fieldInfo.required ? [] : ['']; });
accountDropdown.values = dropdownValues.concat(accounts.map(account => {
const displayName = getAccountDisplayString(account);
accountValueToAccountMap.set(displayName, account);
return displayName;
}));
const selectedAccount = accountDropdown.value ? accountValueToAccountMap.get(accountDropdown.value.toString()) : undefined;
await handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown);
} catch (error) {
vscode.window.showErrorMessage(localize('azure.accounts.unexpectedAccountsError', 'Unexpected error fetching accounts: {0}', getErrorMessage(error)));
}
};
context.onNewDisposableCreated(accountComponents.refreshAccountsButton.onDidClick(async () => { const populateAzureAccounts = async () => {
await populateAzureAccounts(); accountValueToAccountMap.clear();
})); try {
context.onNewDisposableCreated(accountComponents.signInButton.onDidClick(async () => { const accounts = await azdata.accounts.getAllAccounts();
await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount'); // Append a blank value for the "default" option if the field isn't required, context will clear all the dropdowns when selected
await populateAzureAccounts(); const dropdownValues = context.fieldInfo.required ? [] : [''];
})); accountDropdown!.values = dropdownValues.concat(accounts.map(account => {
const displayName = getAccountDisplayString(account);
accountValueToAccountMap.set(displayName, account);
return displayName;
}));
const selectedAccount = accountDropdown!.value ? accountValueToAccountMap.get(accountDropdown!.value.toString()) : undefined;
await handleSelectedAccountChanged(context, selectedAccount, subscriptionComponent, subscriptionValueToSubscriptionMap, resourceGroupComponent, locationComponent);
} catch (error) {
vscode.window.showErrorMessage(localize('azure.accounts.unexpectedAccountsError', 'Unexpected error fetching accounts: {0}', getErrorMessage(error)));
}
};
// populate the values in a different batch as the initialization to avoid the issue that the account list is empty even though the values are correctly. context.onNewDisposableCreated(accountComponents!.refreshAccountsButton.onDidClick(async () => {
setTimeout(async () => { await populateAzureAccounts();
await populateAzureAccounts(); }));
}, 0); context.onNewDisposableCreated(accountComponents!.signInButton.onDidClick(async () => {
await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount');
await populateAzureAccounts();
}));
// populate the values in a different batch as the initialization to avoid the issue that the account list is empty even though the values are correctly.
setTimeout(async () => {
await populateAzureAccounts();
}, 0);
}
} }
async function processKubeStorageClassField(context: FieldContext): Promise<void> { async function processKubeStorageClassField(context: FieldContext): Promise<void> {
@@ -1190,9 +1204,9 @@ function createAzureAccountDropdown(context: AzureAccountFieldContext): AzureAcc
} }
function createAzureSubscriptionDropdown( function createAzureSubscriptionComponent(
context: AzureAccountFieldContext, context: AzureAccountFieldContext,
subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>): azdata.DropDownComponent { subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>): AzureComponent {
const label = createLabel(context.view, { const label = createLabel(context.view, {
text: loc.subscription, text: loc.subscription,
description: loc.subscriptionDescription, description: loc.subscriptionDescription,
@@ -1200,55 +1214,78 @@ function createAzureSubscriptionDropdown(
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const subscriptionDropdown = createDropdownInputInfo(context.view, {
defaultValue: (context.fieldInfo.required) ? undefined : '', const defaultValue = context.initialVariableValues?.[context.fieldInfo.subscriptionVariableName || ''].toString() ?? (context.fieldInfo.required ? undefined : '');
width: context.fieldInfo.inputWidth, let subscriptionInputInfo: InputComponentInfo<AzureComponent>;
editable: false, let setValueFunc: (value: InputValueType) => void;
required: context.fieldInfo.required, // If we have an default value then we don't allow users to modify it - so use a disabled text input box instead
label: loc.subscription if (defaultValue) {
}); subscriptionInputInfo = createInputBoxInputInfo(context.view, {
subscriptionDropdown.component.fireOnTextChange = true; type: 'text',
subscriptionDropdown.labelComponent = label; defaultValue: defaultValue,
ariaLabel: loc.subscription,
required: context.fieldInfo.required,
width: context.fieldInfo.inputWidth,
enabled: false
});
setValueFunc = (value) => { };
} else {
subscriptionInputInfo = createDropdownInputInfo(context.view, {
defaultValue: defaultValue,
width: context.fieldInfo.inputWidth,
editable: false,
required: context.fieldInfo.required,
label: loc.subscription
});
setValueFunc = value => setDropdownValue(<azdata.DropDownComponent>subscriptionInputInfo.component, value?.toString());
(<InputComponentInfo<azdata.DropDownComponent>>subscriptionInputInfo).component.fireOnTextChange = true;
}
subscriptionInputInfo.labelComponent = label;
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, component: subscriptionInputInfo.component,
getValue: async (): Promise<InputValueType> => { getValue: async (): Promise<InputValueType> => {
const inputValue = (await subscriptionDropdown.getValue())?.toString() || ''; const inputValue = (await subscriptionInputInfo.getValue())?.toString() || '';
return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue; return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue;
}, },
setValue: (value: InputValueType) => setDropdownValue(subscriptionDropdown.component, value?.toString()), setValue: (value: InputValueType) => setValueFunc,
getDisplayValue: subscriptionDropdown.getDisplayValue, getDisplayValue: subscriptionInputInfo.getDisplayValue,
onValueChanged: subscriptionDropdown.onValueChanged onValueChanged: subscriptionInputInfo.onValueChanged
}); });
addLabelInputPairToContainer(context.view, context.components, label, subscriptionDropdown.component, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, subscriptionInputInfo.component, context.fieldInfo);
return subscriptionDropdown.component; return subscriptionInputInfo.component;
} }
async function handleSelectedAccountChanged( async function handleSelectedAccountChanged(
context: AzureAccountFieldContext, context: AzureAccountFieldContext,
selectedAccount: azdata.Account | undefined, selectedAccount: azdata.Account | undefined,
subscriptionDropdown: azdata.DropDownComponent, subscriptionComponent: AzureComponent,
subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>, subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>,
resourceGroupDropdown: azdata.DropDownComponent, resourceGroupComponent: AzureComponent,
locationDropdown?: azdata.DropDownComponent locationComponent?: AzureComponent
): Promise<void> { ): Promise<void> {
// If the component isn't a dropdown then just return - we don't need to do anything for the static InputBox
if (!('values' in subscriptionComponent)) {
return;
}
subscriptionValueToSubscriptionMap.clear(); subscriptionValueToSubscriptionMap.clear();
subscriptionDropdown.values = []; subscriptionComponent.values = [];
await handleSelectedSubscriptionChanged(context, selectedAccount, undefined, resourceGroupDropdown); await handleSelectedSubscriptionChanged(context, selectedAccount, undefined, resourceGroupComponent);
if (!selectedAccount) { if (!selectedAccount) {
subscriptionDropdown.values = ['']; subscriptionComponent.values = [''];
if (locationDropdown) { if (locationComponent && 'values' in locationComponent) {
locationDropdown.values = ['']; locationComponent.values = [''];
} }
return; return;
} }
if (locationDropdown) { if (locationComponent && 'values' in locationComponent) {
if (locationDropdown.values && locationDropdown.values.length === 0) { if (locationComponent.values && locationComponent.values.length === 0) {
locationDropdown.values = context.fieldInfo.locations; locationComponent.values = context.fieldInfo.locations;
} }
} }
@@ -1285,13 +1322,13 @@ async function handleSelectedAccountChanged(
} }
} }
} }
subscriptionDropdown.values = response.subscriptions.map(subscription => { subscriptionComponent.values = response.subscriptions.map(subscription => {
const displayName = getSubscriptionDisplayString(subscription); const displayName = getSubscriptionDisplayString(subscription);
subscriptionValueToSubscriptionMap.set(displayName, subscription); subscriptionValueToSubscriptionMap.set(displayName, subscription);
return displayName; return displayName;
}).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())); }).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()));
const selectedSubscription = subscriptionDropdown.values.length > 0 ? subscriptionValueToSubscriptionMap.get(subscriptionDropdown.values[0]) : undefined; const selectedSubscription = subscriptionComponent.values.length > 0 ? subscriptionValueToSubscriptionMap.get(subscriptionComponent.values[0]) : undefined;
await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupComponent);
} catch (error) { } catch (error) {
await vscode.window.showErrorMessage(await getAzureAccessError({ selectedAccount, defaultErrorMessage: localize('azure.accounts.unexpectedSubscriptionsError', "Unexpected error fetching subscriptions for account {0}: {1}", getAccountDisplayString(selectedAccount), getErrorMessage(error)), error })); await vscode.window.showErrorMessage(await getAzureAccessError({ selectedAccount, defaultErrorMessage: localize('azure.accounts.unexpectedSubscriptionsError', "Unexpected error fetching subscriptions for account {0}: {1}", getAccountDisplayString(selectedAccount), getErrorMessage(error)), error }));
} }
@@ -1324,46 +1361,67 @@ async function getAzureAccessError({ selectedAccount, defaultErrorMessage = '',
} }
} }
function createAzureResourceGroupsDropdown( function createAzureResourceGroupsComponent(
context: AzureAccountFieldContext, context: AzureAccountFieldContext,
accountDropdown: azdata.DropDownComponent, accountDropdown: azdata.DropDownComponent | undefined,
accountValueToAccountMap: Map<string, azdata.Account>, accountValueToAccountMap: Map<string, azdata.Account>,
subscriptionDropdown: azdata.DropDownComponent, subscriptionComponent: AzureComponent,
subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>): azdata.DropDownComponent { subscriptionValueToSubscriptionMap: Map<string, azureResource.AzureResourceSubscription>): AzureComponent {
const label = createLabel(context.view, { const label = createLabel(context.view, {
text: loc.resourceGroup, text: loc.resourceGroup,
required: context.fieldInfo.required, required: context.fieldInfo.required,
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const resourceGroupDropdown = createDropdownInputInfo(context.view, { const defaultValue = context.initialVariableValues?.[context.fieldInfo.resourceGroupVariableName || ''].toString() ?? (context.fieldInfo.required ? undefined : '');
defaultValue: (context.fieldInfo.required) ? undefined : '', let resourceGroupInputInfo: InputComponentInfo<AzureComponent>;
width: context.fieldInfo.inputWidth, // If we have an default value then we don't allow users to modify it - so use a disabled text input box instead
editable: false, if (defaultValue) {
required: context.fieldInfo.required, resourceGroupInputInfo = createInputBoxInputInfo(context.view, {
label: loc.resourceGroup type: 'text',
}); defaultValue: defaultValue,
resourceGroupDropdown.component.fireOnTextChange = true; ariaLabel: loc.resourceGroup,
resourceGroupDropdown.labelComponent = label; required: context.fieldInfo.required,
width: context.fieldInfo.inputWidth,
enabled: false
});
} else {
resourceGroupInputInfo = createDropdownInputInfo(context.view, {
defaultValue: (context.fieldInfo.required) ? undefined : '',
width: context.fieldInfo.inputWidth,
editable: false,
required: context.fieldInfo.required,
label: loc.resourceGroup
});
(<InputComponentInfo<azdata.DropDownComponent>>resourceGroupInputInfo).component.fireOnTextChange = true;
}
resourceGroupInputInfo.labelComponent = label;
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()); resourceGroupInputInfo.onValueChanged(() => rgValueChangedEmitter.fire());
context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName || context.fieldInfo.label, resourceGroupDropdown); context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName || context.fieldInfo.label, resourceGroupInputInfo);
addLabelInputPairToContainer(context.view, context.components, label, resourceGroupDropdown.component, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, resourceGroupInputInfo.component, context.fieldInfo);
subscriptionDropdown.onValueChanged(async selectedItem => { if ('onValueChanged' in subscriptionComponent) {
const selectedAccount = !accountDropdown || !accountDropdown.value ? undefined : accountValueToAccountMap.get(accountDropdown.value.toString()); subscriptionComponent.onValueChanged(async selectedItem => {
const selectedSubscription = subscriptionValueToSubscriptionMap.get(selectedItem.selected); const selectedAccount = !accountDropdown || !accountDropdown.value ? undefined : accountValueToAccountMap.get(accountDropdown.value.toString());
await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown.component); const selectedSubscription = subscriptionValueToSubscriptionMap.get(selectedItem.selected);
rgValueChangedEmitter.fire(); await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupInputInfo.component);
}); rgValueChangedEmitter.fire();
return resourceGroupDropdown.component; });
}
return resourceGroupInputInfo.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, resourceGroupComponent: AzureComponent): Promise<void> {
resourceGroupDropdown.values = ['']; if (!('values' in resourceGroupComponent)) {
return;
}
resourceGroupComponent.values = [''];
if (!selectedAccount || !selectedSubscription) { if (!selectedAccount || !selectedSubscription) {
// Don't need to execute command if we don't have both an account and subscription selected // Don't need to execute command if we don't have both an account and subscription selected
return; return;
@@ -1401,7 +1459,7 @@ async function handleSelectedSubscriptionChanged(context: AzureAccountFieldConte
} }
} }
} }
resourceGroupDropdown.values = (response.resourceGroups.length !== 0) resourceGroupComponent.values = (response.resourceGroups.length !== 0)
? response.resourceGroups.map(resourceGroup => resourceGroup.name).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())) ? response.resourceGroups.map(resourceGroup => resourceGroup.name).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()))
: ['']; : [''];
} catch (error) { } catch (error) {
@@ -1413,34 +1471,49 @@ async function handleSelectedSubscriptionChanged(context: AzureAccountFieldConte
* An Azure Locations field consists of a dropdown field for azure locations * An Azure Locations field consists of a dropdown field for azure locations
* @param context The context to use to create the field * @param context The context to use to create the field
*/ */
async function processAzureLocationsField(context: AzureLocationsFieldContext): Promise<azdata.DropDownComponent> { async function processAzureLocationsField(context: AzureLocationsFieldContext): Promise<AzureComponent> {
const label = createLabel(context.view, { const label = createLabel(context.view, {
text: context.fieldInfo.label || loc.location, text: context.fieldInfo.label || loc.location,
required: context.fieldInfo.required, required: context.fieldInfo.required,
width: context.fieldInfo.labelWidth, width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles cssStyles: context.fieldInfo.labelCSSStyles
}); });
const locationValues = context.fieldInfo.locations?.map(l => { return { name: l, displayName: apiService.azurecoreApi.getRegionDisplayName(l) }; }); const defaultValue = context.initialVariableValues?.[context.fieldInfo.locationVariableName || ''].toString() ?? (context.fieldInfo.required ? undefined : '');
const locationDropdown = createDropdownInputInfo(context.view, { let locationInputInfo: InputComponentInfo<AzureComponent>;
defaultValue: locationValues?.find(l => l.name === context.fieldInfo.defaultValue), // If we have an default value then we don't allow users to modify it - so use a disabled text input box instead
width: context.fieldInfo.inputWidth, if (defaultValue) {
editable: false, locationInputInfo = createInputBoxInputInfo(context.view, {
required: context.fieldInfo.required, type: 'text',
label: loc.location, defaultValue: defaultValue,
values: locationValues ariaLabel: loc.location,
}); required: context.fieldInfo.required,
locationDropdown.component.fireOnTextChange = true; width: context.fieldInfo.inputWidth,
locationDropdown.labelComponent = label; enabled: false
});
} else {
const locationValues = context.fieldInfo.locations?.map(l => { return { name: l, displayName: apiService.azurecoreApi.getRegionDisplayName(l) }; });
locationInputInfo = createDropdownInputInfo(context.view, {
defaultValue: locationValues?.find(l => l.name === context.fieldInfo.defaultValue),
width: context.fieldInfo.inputWidth,
editable: false,
required: context.fieldInfo.required,
label: loc.location,
values: locationValues
});
(<InputComponentInfo<azdata.DropDownComponent>>locationInputInfo).component.fireOnTextChange = true;
}
locationInputInfo.labelComponent = label;
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, locationDropdown); context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, locationInputInfo);
} }
addLabelInputPairToContainer(context.view, context.components, label, locationDropdown.component, context.fieldInfo); addLabelInputPairToContainer(context.view, context.components, label, locationInputInfo.component, context.fieldInfo);
return locationDropdown.component; return locationInputInfo.component;
} }
export function isValidSQLPassword(password: string, userName: string = 'sa'): boolean { export function isValidSQLPassword(password: string, userName: string = 'sa'): boolean {