Added a dynamic Cost Summary section to SQL MIAA Deployment Wizard (#17420)

* Added valueprovider for pricing. Pushing this for troubleshooting help.

* Committing changes for troubleshooting help. Moved InputValueType to typings file.

* Add readonly inputs to list

* Fixed ordering of package.json merge items

* Estimated cost moved to input page, ValueProvider only takes in a triggerfields[] and not a single string, fixed pricing logic.

* Removed pricingModel.ts

* Reverted some comments and code changes that were used in debugging.

* Changed some values from localizedConstants to single-quote constants'

* Changed some values from localizedConstants to single-quote constants'

* Added copyright header to pricingUtils.ts

* Removed try catch in extension.ts valueproviders, made some values in PricingUtils.ts top-level instead of exporting.

* Minor changes, added some comments and localized USD.

* Changes pricingutils classes to be constants, and added disposable to Hookupvalueprovider

Co-authored-by: Candice Ye <canye@microsoft.com>
Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
Candice Ye
2021-10-21 16:51:31 -07:00
committed by GitHub
parent 5fe569e864
commit dc0651aef7
10 changed files with 321 additions and 21 deletions

View File

@@ -7,7 +7,7 @@ import { azureResource } from 'azureResource';
import * as fs from 'fs';
import { EOL } from 'os';
import * as path from 'path';
import { IOptionsSourceProvider } from 'resource-deployment';
import { InputValueType, IOptionsSourceProvider } from 'resource-deployment';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { getDateTimeString, getErrorMessage, isUserCancelledError, throwUnless } from '../common/utils';
@@ -33,7 +33,6 @@ const localize = nls.loadMessageBundle();
*/
export type Validator = () => { valid: boolean, message: string };
export type InputValueType = string | number | undefined;
export type InputComponent = azdata.TextComponent | azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent | RadioGroupLoadingComponentBuilder;
export type InputComponentInfo<T extends InputComponent> = {
component: T;
@@ -471,20 +470,35 @@ async function hookUpValueProviders(context: WizardPageContext): Promise<void> {
if (field.valueProvider) {
const fieldKey = field.variableName || field.label;
const fieldComponent = context.inputComponents[fieldKey];
const targetComponent = context.inputComponents[field.valueProvider.triggerField];
if (!targetComponent) {
console.error(`Could not find target component ${field.valueProvider.triggerField} when hooking up value providers for ${field.label}`);
return;
}
const provider = await valueProviderService.getValueProvider(field.valueProvider.providerId);
let targetComponentLabelToComponent: { [label: string]: InputComponentInfo<InputComponent>; } = {};
field.valueProvider.triggerFields.forEach((triggerField) => {
const targetComponent = context.inputComponents[triggerField];
if (!targetComponent) {
console.error(`Could not find target component ${triggerField} when hooking up value providers for ${field.label}`);
return;
}
targetComponentLabelToComponent[triggerField] = targetComponent;
});
// If one triggerfield changes value, update the new field value.
const updateFields = async () => {
const targetComponentValue = await targetComponent.getValue();
const newFieldValue = await provider.getValue(targetComponentValue?.toString() ?? '');
let targetComponentLabelToValue: { [label: string]: InputValueType; } = {};
for (let label in targetComponentLabelToComponent) {
targetComponentLabelToValue[label] = await targetComponentLabelToComponent[label].getValue();
}
let newFieldValue = await provider.getValue(targetComponentLabelToValue);
fieldComponent.setValue(newFieldValue);
};
targetComponent.onValueChanged(() => {
updateFields();
});
// Set the onValueChanged behavior for each component
for (let label in targetComponentLabelToComponent) {
context.onNewDisposableCreated(targetComponentLabelToComponent[label].onValueChanged(() => {
updateFields();
}));
}
await updateFields();
}
}));
@@ -863,6 +877,18 @@ function processReadonlyTextField(context: FieldContext, allowEvaluation: boolea
const text = context.fieldInfo.defaultValue !== undefined
? createLabel(context.view, { text: context.fieldInfo.defaultValue, description: '', required: false, width: context.fieldInfo.inputWidth })
: undefined;
if (text) {
// If we created the text component then add it to our list of inputs so other fields can utilize it
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.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, {
component: text,
getValue: async (): Promise<InputValueType> => typeof text.value === 'string' ? text.value : text.value?.join(EOL),
setValue: (value: InputValueType) => text.value = value?.toString(),
onValueChanged: onChangedEmitter.event,
});
}
addLabelInputPairToContainer(context.view, context.components, label, text, context.fieldInfo);
return { label: label, text: text };
}