Adding lists support in text component (#17065)

* Adding lists support in text component

* Fixing get textType

* Code cleanup

* Combining values into value
This commit is contained in:
Aasim Khan
2021-09-14 12:43:14 -07:00
committed by GitHub
parent 32e6a24115
commit 95e82d53e6
10 changed files with 79 additions and 37 deletions

View File

@@ -68,7 +68,7 @@ export class AddEditLanguageTab extends LanguageViewBase {
public get updatedData(): LanguageUpdateModel { public get updatedData(): LanguageUpdateModel {
return { return {
language: { language: {
name: this.languageName?.value || '', name: this.languageName?.value as string || '',
contents: this._languageUpdateModel.language.contents contents: this._languageUpdateModel.language.contents
}, },
content: this.languageView?.updatedContent || this._languageUpdateModel.content, content: this.languageView?.updatedContent || this._languageUpdateModel.content,

View File

@@ -146,10 +146,10 @@ export class LanguageContentView extends LanguageViewBase {
public get updatedContent(): mssql.ExternalLanguageContent { public get updatedContent(): mssql.ExternalLanguageContent {
return { return {
pathToExtension: this.extensionFile.value || '', pathToExtension: this.extensionFile.value as string || '',
extensionFileName: this.extensionFileName.value || '', extensionFileName: this.extensionFileName.value as string || '',
parameters: this.parameters.value || '', parameters: this.parameters.value as string || '',
environmentVariables: this.envVariables.value || '', environmentVariables: this.envVariables.value as string || '',
isLocalFile: this._isLocalPath || false, isLocalFile: this._isLocalPath || false,
platform: this._languageContent?.platform platform: this._languageContent?.platform
}; };

View File

@@ -183,7 +183,7 @@ export class AddNewPackageTab {
private async doPackageInstall(): Promise<void> { private async doPackageInstall(): Promise<void> {
let packageName = this.newPackagesName.value; let packageName = this.newPackagesName.value as string;
let packageVersion = this.newPackagesVersions.value as string; let packageVersion = this.newPackagesVersions.value as string;
if (!packageName || packageName.length === 0 || if (!packageName || packageName.length === 0 ||
!packageVersion || packageVersion.length === 0) { !packageVersion || packageVersion.length === 0) {

View File

@@ -1252,7 +1252,7 @@ function createAzureSubscriptionComponent(
} }
subscriptionInputInfo.labelComponent = label; subscriptionInputInfo.labelComponent = label;
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value! as string,
variableName: context.fieldInfo.subscriptionVariableName variableName: context.fieldInfo.subscriptionVariableName
}); });
context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName || context.fieldInfo.label, { context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName || context.fieldInfo.label, {
@@ -1407,7 +1407,7 @@ function createAzureResourceGroupsComponent(
} }
resourceGroupInputInfo.labelComponent = label; resourceGroupInputInfo.labelComponent = label;
context.fieldInfo.subFields!.push({ context.fieldInfo.subFields!.push({
label: label.value!, label: label.value! as string,
variableName: context.fieldInfo.resourceGroupVariableName variableName: context.fieldInfo.resourceGroupVariableName
}); });
const rgValueChangedEmitter = new vscode.EventEmitter<void>(); const rgValueChangedEmitter = new vscode.EventEmitter<void>();
@@ -1517,7 +1517,7 @@ async function processAzureLocationsField(context: AzureLocationsFieldContext):
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! as string,
variableName: context.fieldInfo.locationVariableName variableName: context.fieldInfo.locationVariableName
}); });
context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, locationInputInfo); context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, locationInputInfo);

View File

@@ -170,14 +170,14 @@ export class DashboardWidget {
const migrateButton = this.createTaskButton(view, migrateButtonMetadata); const migrateButton = this.createTaskButton(view, migrateButtonMetadata);
const points = `${loc.PRE_REQ_1}
${loc.PRE_REQ_2}
${loc.PRE_REQ_3}`;
const preRequisiteListElement = view.modelBuilder.text().withProps({ const preRequisiteListElement = view.modelBuilder.text().withProps({
value: points, value: [
loc.PRE_REQ_1,
loc.PRE_REQ_2,
loc.PRE_REQ_3
],
CSSStyles: { CSSStyles: {
'padding-left': '15px', 'padding-left': '30px',
'margin-bottom': '5px', 'margin-bottom': '5px',
'margin-top': '10px' 'margin-top': '10px'
} }

5
src/sql/azdata.d.ts vendored
View File

@@ -3434,7 +3434,10 @@ declare module 'azdata' {
} }
export interface TextComponentProperties extends ComponentProperties, TitledComponentProperties { export interface TextComponentProperties extends ComponentProperties, TitledComponentProperties {
value?: string | undefined; /**
* Provide value to be displayed in the text component. An array of value will be displayed as an unordered list.
*/
value?: string | string[] | undefined;
links?: LinkArea[] | undefined; links?: LinkArea[] | undefined;
description?: string | undefined; description?: string | undefined;
requiredIndicator?: boolean | undefined; requiredIndicator?: boolean | undefined;

View File

@@ -585,7 +585,9 @@ declare module 'azdata' {
*/ */
export enum TextType { export enum TextType {
Normal = 'Normal', Normal = 'Normal',
Error = 'Error' Error = 'Error',
UnorderedList = 'UnorderedList',
OrderedList = 'OrderedList'
} }
export interface TextComponentProperties { export interface TextComponentProperties {
@@ -595,7 +597,7 @@ declare module 'azdata' {
*/ */
headingLevel?: HeadingLevel; headingLevel?: HeadingLevel;
/** /**
* The type to display the text as - used to determine the color of the text. Default is Normal. * Sets the type of text box to be displayed
*/ */
textType?: TextType; textType?: TextType;
} }

View File

@@ -1350,10 +1350,10 @@ class TextComponentWrapper extends ComponentWrapper implements azdata.TextCompon
this.properties = {}; this.properties = {};
} }
public get value(): string { public get value(): string | string[] {
return this.properties['value']; return this.properties['value'];
} }
public set value(v: string) { public set value(v: string | string[]) {
this.setProperty('value', v); this.setProperty('value', v);
} }

View File

@@ -897,5 +897,7 @@ export enum ButtonType {
export enum TextType { export enum TextType {
Normal = 'Normal', Normal = 'Normal',
Error = 'Error' Error = 'Error',
UnorderedList = 'UnorderedList',
OrderedList = 'OrderedList'
} }

View File

@@ -22,7 +22,9 @@ import { errorForeground } from 'vs/platform/theme/common/colorRegistry';
export enum TextType { export enum TextType {
Normal = 'Normal', Normal = 'Normal',
Error = 'Error' Error = 'Error',
UnorderedList = 'UnorderedList',
OrderedList = 'OrderedList'
} }
const errorTextClass = 'error-text'; const errorTextClass = 'error-text';
@@ -30,6 +32,19 @@ const errorTextClass = 'error-text';
@Component({ @Component({
selector: 'modelview-text', selector: 'modelview-text',
template: ` template: `
<div *ngIf="showList;else noList" [style.display]="display" [style.width]="getWidth()" [style.height]="getHeight()" [title]="title" [attr.role]="ariaRole" [attr.aria-hidden]="ariaHidden" [ngStyle]="this.CSSStyles">
<div *ngIf="isUnOrderedList;else orderedlist">
<ul style="padding-left:0px">
<li *ngFor="let v of value">{{v}}</li>
</ul>
</div>
<ng-template #orderedlist>
<ol style="padding-left:0px">
<li *ngFor="let v of value">{{v}}</li>
</ol>
</ng-template>
</div>
<ng-template #noList>
<div *ngIf="showDiv;else noDiv" style="display:flex;flex-flow:row;align-items:center;" [style.width]="getWidth()" [style.height]="getHeight()"> <div *ngIf="showDiv;else noDiv" style="display:flex;flex-flow:row;align-items:center;" [style.width]="getWidth()" [style.height]="getHeight()">
<p [title]="title" [ngStyle]="this.CSSStyles" [attr.role]="ariaRole" [attr.aria-hidden]="ariaHidden"></p> <p [title]="title" [ngStyle]="this.CSSStyles" [attr.role]="ariaRole" [attr.aria-hidden]="ariaHidden"></p>
<div #textContainer id="textContainer"></div> <div #textContainer id="textContainer"></div>
@@ -40,6 +55,7 @@ const errorTextClass = 'error-text';
</div> </div>
<ng-template #noDiv> <ng-template #noDiv>
<div #textContainer id="textContainer" [style.display]="display" [style.width]="getWidth()" [style.height]="getHeight()" [title]="title" [attr.role]="ariaRole" [attr.aria-hidden]="ariaHidden" [ngStyle]="this.CSSStyles"></div> <div #textContainer id="textContainer" [style.display]="display" [style.width]="getWidth()" [style.height]="getHeight()" [title]="title" [attr.role]="ariaRole" [attr.aria-hidden]="ariaHidden" [ngStyle]="this.CSSStyles"></div>
</ng-template>
</ng-template>` </ng-template>`
}) })
export default class TextComponent extends TitledComponent<azdata.TextComponentProperties> implements IComponent, OnDestroy, AfterViewInit { export default class TextComponent extends TitledComponent<azdata.TextComponentProperties> implements IComponent, OnDestroy, AfterViewInit {
@@ -71,12 +87,12 @@ export default class TextComponent extends TitledComponent<azdata.TextComponentP
this.layout(); this.layout();
} }
public set value(newValue: string) { public set value(newValue: string | string[]) {
this.setPropertyFromUI<string>((properties, value) => { properties.value = value; }, newValue); this.setPropertyFromUI<string | string[]>((properties, value) => { properties.value = value; }, newValue);
} }
public get value(): string { public get value(): string | string[] {
return this.getPropertyOrDefault<string>((props) => props.value, ''); return this.getPropertyOrDefault<string | string[]>((props) => props.value, undefined);
} }
public set description(newValue: string) { public set description(newValue: string) {
@@ -104,13 +120,29 @@ export default class TextComponent extends TitledComponent<azdata.TextComponentP
} }
public get textType(): azdata.TextType | undefined { public get textType(): azdata.TextType | undefined {
return this.getPropertyOrDefault<azdata.TextType | undefined>(props => props.textType, undefined); let textType = this.getPropertyOrDefault<azdata.TextType | undefined>(props => props.textType, undefined);
if (!textType && typeof this.value !== 'string') {
textType = (this.value) ? TextType.UnorderedList : undefined;
}
// Throwing an error when a string value is provided for list.
if ((textType === TextType.OrderedList || textType === TextType.UnorderedList) && typeof this.value === 'string') {
throw new Error(`Invalid type of value provided for the textType ${textType}`);
}
return textType;
} }
public set textType(newValue: azdata.TextType | undefined) { public set textType(newValue: azdata.TextType | undefined) {
this.setPropertyFromUI<azdata.TextType | undefined>((properties, value) => { properties.textType = value; }, newValue); this.setPropertyFromUI<azdata.TextType | undefined>((properties, value) => { properties.textType = value; }, newValue);
} }
public get isUnOrderedList(): boolean | undefined {
return this.textType === TextType.UnorderedList;
}
public get showList(): boolean | undefined {
return (this.textType === TextType.UnorderedList || this.textType === TextType.OrderedList);
}
public override setProperties(properties: { [key: string]: any; }): void { public override setProperties(properties: { [key: string]: any; }): void {
super.setProperties(properties); super.setProperties(properties);
this.updateText(); this.updateText();
@@ -123,6 +155,9 @@ export default class TextComponent extends TitledComponent<azdata.TextComponentP
} }
public updateText(): void { public updateText(): void {
if (typeof this.value !== 'string') {
return;
}
DOM.clearNode((<HTMLElement>this.textContainer.nativeElement)); DOM.clearNode((<HTMLElement>this.textContainer.nativeElement));
const links = this.getPropertyOrDefault<azdata.LinkArea[]>((props) => props.links, []); const links = this.getPropertyOrDefault<azdata.LinkArea[]>((props) => props.links, []);
// The text may contain link placeholders so go through and create those and insert them as needed now // The text may contain link placeholders so go through and create those and insert them as needed now
@@ -137,7 +172,7 @@ export default class TextComponent extends TitledComponent<azdata.TextComponentP
// First insert any text from the start of the current string fragment up to the placeholder // First insert any text from the start of the current string fragment up to the placeholder
let curText = text.slice(0, placeholderIndex); let curText = text.slice(0, placeholderIndex);
if (curText) { if (curText && typeof text === 'string') {
const textElement = this.createTextElement(); const textElement = this.createTextElement();
textElement.innerText = text.slice(0, placeholderIndex); textElement.innerText = text.slice(0, placeholderIndex);
(<HTMLElement>this.textContainer.nativeElement).appendChild(textElement); (<HTMLElement>this.textContainer.nativeElement).appendChild(textElement);
@@ -163,7 +198,7 @@ export default class TextComponent extends TitledComponent<azdata.TextComponentP
} }
// If we have any text left over now insert that in directly // If we have any text left over now insert that in directly
if (text) { if (text && typeof text === 'string') {
const textElement = this.createTextElement(); const textElement = this.createTextElement();
textElement.innerText = text; textElement.innerText = text;
(<HTMLElement>this.textContainer.nativeElement).appendChild(textElement); (<HTMLElement>this.textContainer.nativeElement).appendChild(textElement);