Adding help text for resourceTypes (#14166)

* Adding help text to arc resource deployment.

* Fixing null help text and agreement logic

* Made some types optional
Fixed a language specific link
This commit is contained in:
Aasim Khan
2021-02-04 23:45:29 -08:00
committed by GitHub
parent 71d9c91551
commit 1944813c4a
7 changed files with 81 additions and 14 deletions

View File

@@ -1100,6 +1100,16 @@
} }
], ],
"when": "mi-type=arc-mi" "when": "mi-type=arc-mi"
},
"helpText": {
"template": "%arc.agreement.sql.help.text%",
"links": [
{
"text": "%arc.agreement.sql.help.text.learn.more%",
"url": "https://go.microsoft.com/fwlink/?linkid=2141849"
}
],
"when": "mi-type=arc-mi"
} }
} }
] ]

View File

@@ -153,5 +153,7 @@
"requested.cores.less.than.or.equal.to.cores.limit": "Requested cores must be less than or equal to cores limit", "requested.cores.less.than.or.equal.to.cores.limit": "Requested cores must be less than or equal to cores limit",
"cores.limit.greater.than.or.equal.to.requested.cores": "Cores limit must be greater than or equal to requested cores", "cores.limit.greater.than.or.equal.to.requested.cores": "Cores limit must be greater than or equal to requested cores",
"requested.memory.less.than.or.equal.to.memory.limit": "Requested memory must be less than or equal to memory limit", "requested.memory.less.than.or.equal.to.memory.limit": "Requested memory must be less than or equal to memory limit",
"memory.limit.greater.than.or.equal.to.requested.memory": "Memory limit must be greater than or equal to requested memory" "memory.limit.greater.than.or.equal.to.requested.memory": "Memory limit must be greater than or equal to requested memory",
"arc.agreement.sql.help.text": "Azure Arc enabled Managed Instance provides SQL Server access and feature compatibility that can be deployed on the infrastructure of your choice. While this service is in preview, it has some feature limitations compared to SQL Managed Instance on Azure. {0}",
"arc.agreement.sql.help.text.learn.more": "Learn more"
} }

View File

@@ -587,6 +587,18 @@
], ],
"when": "mi-type=azure-sql-mi" "when": "mi-type=azure-sql-mi"
} }
],
"helpTexts": [
{
"template": "%azure-sql-mi-help-text%",
"links": [
{
"text": "%azure-sql-mi-help-text-learn-more%",
"url": "https://docs.microsoft.com/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview"
}
],
"when": "mi-type=azure-sql-mi"
}
] ]
} }
] ]

View File

@@ -82,9 +82,11 @@
"azure-sqldb-agreement-sqldb-eula": "Azure SQL DB License Terms", "azure-sqldb-agreement-sqldb-eula": "Azure SQL DB License Terms",
"azure-sqldb-agreement-azdata-eula": "azdata License Terms", "azure-sqldb-agreement-azdata-eula": "azdata License Terms",
"azure-sql-mi-display-name": "Azure SQL managed instance", "azure-sql-mi-display-name": "Azure SQL managed instance",
"azure-sql-mi-display-description": "Create a SQL Managed Instance. Best for most migrations to the cloud.", "azure-sql-mi-display-description": "Create a SQL Managed Instance in either Azure or a customer-managed environment",
"azure-sql-mi-okButton-text": "Open in Portal", "azure-sql-mi-okButton-text": "Open in Portal",
"azure-sql-mi-resource-type-option-label": "Resource Type", "azure-sql-mi-resource-type-option-label": "Resource Type",
"azure-sql-mi-agreement": "I accept {0} and {1}.", "azure-sql-mi-agreement": "I accept {0} and {1}.",
"azure-sql-mi-agreement-eula": "Azure SQL MI License Terms" "azure-sql-mi-agreement-eula": "Azure SQL MI License Terms",
"azure-sql-mi-help-text": "Azure SQL Managed Instance provides full SQL Server access and feature compatibility for migrating SQL Servers to Azure, or developing new applications. {0}.",
"azure-sql-mi-help-text-learn-more" : "Learn More"
} }

View File

@@ -21,10 +21,11 @@ export interface ResourceType {
agreements?: AgreementInfo[]; agreements?: AgreementInfo[];
displayIndex?: number; displayIndex?: number;
okButtonText?: OkButtonTextValue[]; okButtonText?: OkButtonTextValue[];
helpTexts: HelpText[];
getOkButtonText(selectedOptions: { option: string, value: string }[]): string | undefined; getOkButtonText(selectedOptions: { option: string, value: string }[]): string | undefined;
getProvider(selectedOptions: { option: string, value: string }[]): DeploymentProvider | undefined; getProvider(selectedOptions: { option: string, value: string }[]): DeploymentProvider | undefined;
getAgreementInfo(selectedOptions: { option: string, value: string }[]): AgreementInfo | undefined; getAgreementInfo(selectedOptions: { option: string, value: string }[]): AgreementInfo | undefined;
getHelpText(selectedOption: { option: string, value: string }[]): string | undefined; getHelpText(selectedOption: { option: string, value: string }[]): HelpText | undefined;
tags?: string[]; tags?: string[];
} }
@@ -41,12 +42,19 @@ export interface ResourceSubType {
provider: DeploymentProvider; provider: DeploymentProvider;
okButtonText?: OkButtonTextValue; okButtonText?: OkButtonTextValue;
agreement?: AgreementInfo; agreement?: AgreementInfo;
helpText?: HelpText;
}
export interface HelpText {
template: string;
links?: azdata.LinkArea[];
when?: string;
} }
export interface AgreementInfo { export interface AgreementInfo {
template: string; template: string;
links: azdata.LinkArea[]; links?: azdata.LinkArea[];
when: string; when?: string;
} }
export interface ResourceTypeOption { export interface ResourceTypeOption {

View File

@@ -9,7 +9,7 @@ import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption, ResourceSubType, AgreementInfo } from '../interfaces'; import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption, ResourceSubType, AgreementInfo, HelpText } from '../interfaces';
import { AzdataService } from './azdataService'; import { AzdataService } from './azdataService';
import { KubeService } from './kubeService'; import { KubeService } from './kubeService';
import { INotebookService } from './notebookService'; import { INotebookService } from './notebookService';
@@ -56,6 +56,7 @@ export class ResourceTypeService implements IResourceTypeService {
resourceType.getProvider = (selectedOptions) => { return this.getProvider(resourceType, selectedOptions); }; resourceType.getProvider = (selectedOptions) => { return this.getProvider(resourceType, selectedOptions); };
resourceType.getOkButtonText = (selectedOptions) => { return this.getOkButtonText(resourceType, selectedOptions); }; resourceType.getOkButtonText = (selectedOptions) => { return this.getOkButtonText(resourceType, selectedOptions); };
resourceType.getAgreementInfo = (selectedOptions) => { return this.getAgreementInfo(resourceType, selectedOptions); }; resourceType.getAgreementInfo = (selectedOptions) => { return this.getAgreementInfo(resourceType, selectedOptions); };
resourceType.getHelpText = (selectedOptions) => { return this.getHelpText(resourceType, selectedOptions); };
this.getResourceSubTypes(resourceType); this.getResourceSubTypes(resourceType);
this._resourceTypes.push(resourceType); this._resourceTypes.push(resourceType);
}); });
@@ -153,6 +154,9 @@ export class ResourceTypeService implements IResourceTypeService {
if (resourceSubType.agreement) { if (resourceSubType.agreement) {
resourceType.agreements?.push(resourceSubType.agreement!); resourceType.agreements?.push(resourceSubType.agreement!);
} }
if (resourceSubType.helpText) {
resourceType.helpTexts.push(resourceSubType.helpText);
}
} }
}); });
}); });
@@ -307,6 +311,17 @@ export class ResourceTypeService implements IResourceTypeService {
return undefined; return undefined;
} }
private getHelpText(resourceType: ResourceType, selectedOptions: { option: string, value: string }[]): HelpText | undefined {
if (resourceType.helpTexts) {
for (const possibleOption of resourceType.helpTexts) {
if (processWhenClause(possibleOption.when, selectedOptions)) {
return possibleOption;
}
}
}
return undefined;
}
public startDeployment(resourceType: ResourceType, optionValuesFilter?: OptionValuesFilter): void { public startDeployment(resourceType: ResourceType, optionValuesFilter?: OptionValuesFilter): void {
const wizard = new ResourceTypeWizard(resourceType, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService, this, optionValuesFilter); const wizard = new ResourceTypeWizard(resourceType, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService, this, optionValuesFilter);
wizard.open(); wizard.open();

View File

@@ -6,7 +6,7 @@
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import { EOL } from 'os'; import { EOL } from 'os';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { AgreementInfo, DeploymentProvider, ITool, ResourceType, ResourceTypeOptionValue, ToolRequirementInfo, ToolStatus } from '../interfaces'; import { AgreementInfo, DeploymentProvider, HelpText, ITool, ResourceType, ResourceTypeOptionValue, ToolRequirementInfo, ToolStatus } from '../interfaces';
import { createFlexContainer } from './modelViewUtils'; import { createFlexContainer } from './modelViewUtils';
import * as loc from '../localizedConstants'; import * as loc from '../localizedConstants';
import { IToolsService } from '../services/toolsService'; import { IToolsService } from '../services/toolsService';
@@ -26,6 +26,7 @@ export class ToolsAndEulaPage extends ResourceTypePage {
private _optionDropDownMap: Map<string, azdata.DropDownComponent> = new Map(); private _optionDropDownMap: Map<string, azdata.DropDownComponent> = new Map();
private _toolsLoadingComponent!: azdata.LoadingComponent; private _toolsLoadingComponent!: azdata.LoadingComponent;
private _agreementContainer!: azdata.DivContainer; private _agreementContainer!: azdata.DivContainer;
private _helpTextContainer!: azdata.DivContainer;
private _agreementCheckBox!: azdata.CheckBoxComponent; private _agreementCheckBox!: azdata.CheckBoxComponent;
private _installToolButton!: azdata.ButtonComponent; private _installToolButton!: azdata.ButtonComponent;
private _installationInProgress: boolean = false; private _installationInProgress: boolean = false;
@@ -94,6 +95,7 @@ export class ToolsAndEulaPage extends ResourceTypePage {
const tableWidth = 1060; const tableWidth = 1060;
this._optionsContainer = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component(); this._optionsContainer = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
this._agreementContainer = view.modelBuilder.divContainer().component(); this._agreementContainer = view.modelBuilder.divContainer().component();
this._helpTextContainer = view.modelBuilder.divContainer().component();
const toolColumn: azdata.TableColumn = { const toolColumn: azdata.TableColumn = {
value: loc.toolText, value: loc.toolText,
width: 105 width: 105
@@ -149,6 +151,8 @@ export class ToolsAndEulaPage extends ResourceTypePage {
this.form = view.modelBuilder.formContainer().withFormItems( this.form = view.modelBuilder.formContainer().withFormItems(
[ [
{ {
component: this._helpTextContainer,
}, {
component: this._optionsContainer, component: this._optionsContainer,
}, { }, {
component: this._agreementContainer, component: this._agreementContainer,
@@ -234,9 +238,16 @@ export class ToolsAndEulaPage extends ResourceTypePage {
}); });
} }
if (this._resourceType.agreements) { const agreementInfo = this._resourceType.getAgreementInfo(this.getSelectedOptions());
this._agreementContainer.addItem(this.createAgreementCheckbox()); if (agreementInfo) {
this._agreementContainer.addItem(this.createAgreementCheckbox(agreementInfo));
} }
const helpText = this._resourceType.getHelpText(this.getSelectedOptions());
if (helpText) {
this._helpTextContainer.addItem(this.createHelpText(helpText));
}
this.updateOkButtonText(); this.updateOkButtonText();
this.updateToolsDisplayTable(); this.updateToolsDisplayTable();
}); });
@@ -245,8 +256,7 @@ export class ToolsAndEulaPage extends ResourceTypePage {
} }
private createAgreementCheckbox(): azdata.FlexContainer { private createAgreementCheckbox(agreementInfo: AgreementInfo): azdata.FlexContainer {
const agreementInfo = this._resourceType.getAgreementInfo(this.getSelectedOptions())!;
this._agreementCheckBox = this.view.modelBuilder.checkBox().withProperties<azdata.CheckBoxProperties>({ this._agreementCheckBox = this.view.modelBuilder.checkBox().withProperties<azdata.CheckBoxProperties>({
ariaLabel: this.getAgreementDisplayText(agreementInfo), ariaLabel: this.getAgreementDisplayText(agreementInfo),
required: true required: true
@@ -259,12 +269,20 @@ export class ToolsAndEulaPage extends ResourceTypePage {
return createFlexContainer(this.view, [this._agreementCheckBox, text]); return createFlexContainer(this.view, [this._agreementCheckBox, text]);
} }
private createHelpText(helpText: HelpText): azdata.FlexContainer {
const helpTextComponent = this.view.modelBuilder.text().withProps({
value: helpText.template,
links: helpText.links,
}).component();
return createFlexContainer(this.view, [helpTextComponent]);
}
private getAgreementDisplayText(agreementInfo: AgreementInfo): string { private getAgreementDisplayText(agreementInfo: AgreementInfo): string {
// the agreement template will have {index} as placeholder for hyperlinks // the agreement template will have {index} as placeholder for hyperlinks
// this method will get the display text after replacing the placeholders // this method will get the display text after replacing the placeholders
let text = agreementInfo.template; let text = agreementInfo.template;
for (let i: number = 0; i < agreementInfo.links.length; i++) { for (let i: number = 0; i < agreementInfo.links!.length; i++) {
text = text.replace(`{${i}}`, agreementInfo.links[i].text); text = text.replace(`{${i}}`, agreementInfo.links![i].text);
} }
return text; return text;
} }