aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2
diff options
context:
space:
mode:
authorArielk <Ariel.Kenan@amdocs.com>2018-10-03 14:06:13 +0300
committerAvi Gaffa <avi.gaffa@amdocs.com>2018-10-11 11:47:26 +0000
commit502b7b7839374680a494c1606798a8b4588daa2b (patch)
treefd8868b0d4c3e142f2a8921600c8cb8b986b7acd /catalog-ui/src/app/ng2
parent4d5da30c41326eeeb9344b31875e010b1a7507c1 (diff)
Operation screen changes.
1. [ATTASDC-7390] Output parameter support 2. VF Workflow context 3. [ATTASDC-7420] "Opening same operation displays invalid fields and values" Change-Id: I7bb94b50ad299af6080266076b5e0b632ef5e0e7 Issue-ID: SDC-1814 Signed-off-by: Arielk <Ariel.Kenan@amdocs.com>
Diffstat (limited to 'catalog-ui/src/app/ng2')
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html4
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts28
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html49
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less20
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts132
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html2
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less3
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts1
8 files changed, 181 insertions, 58 deletions
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
index e210534352..c9fdf94fe0 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
@@ -15,6 +15,8 @@
-->
<div class="interface-operation">
+ <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
+
<div
class="add-btn"
[ngClass]="{'disabled': readonly}"
@@ -25,8 +27,6 @@
<div class="operation-list">
- <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
-
<div
class="operation-row"
*ngFor="let operation of operationList"
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
index 21ac60981a..f23f66a5ff 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
@@ -1,5 +1,5 @@
import * as _ from "lodash";
-import {Component, Input, ComponentRef, Inject} from '@angular/core';
+import {Component, Input, Output, ComponentRef, Inject} from '@angular/core';
import {Component as IComponent} from 'app/models/components/component';
import {SdcConfigToken, ISdcConfig} from "app/ng2/config/sdc-config.config";
@@ -32,9 +32,12 @@ export class InterfaceOperationComponent {
@Input() component: IComponent;
@Input() readonly: boolean;
+ @Input() enableMenuItems: Function;
+ @Input() disableMenuItems: Function;
constructor(
- @Inject(SdcConfigToken) sdcConfig: ISdcConfig,
+ @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
+ @Inject("$state") private $state: ng.ui.IStateService,
private ComponentServiceNg2: ComponentServiceNg2,
private WorkflowServiceNg2: WorkflowServiceNg2,
private ModalServiceNg2: ModalService,
@@ -44,17 +47,24 @@ export class InterfaceOperationComponent {
ngOnInit(): void {
this.isLoading = true;
+ let gotOperations = false;
+ let gotInputs = false;
+
this.ComponentServiceNg2.getInterfaceOperations(this.component).subscribe((response: ComponentGenericResponse) => {
- if (this.inputs) {
+ if (gotInputs) {
this.isLoading = false;
+ } else {
+ gotOperations = true;
}
- let {interfaceOperations} = response;
- this.component.interfaceOperations = interfaceOperations;
- this.operationList = _.toArray(interfaceOperations).sort((a, b) => a.operationType.localeCompare(b.operationType));
+ this.component.interfaceOperations = response.interfaceOperations;
+ this.operationList = _.toArray(response.interfaceOperations).sort((a, b) => a.operationType.localeCompare(b.operationType));
});
+
this.ComponentServiceNg2.getComponentInputs(this.component).subscribe((response: ComponentGenericResponse) => {
- if (this.component.interfaceOperations) {
+ if (gotOperations) {
this.isLoading = false;
+ } else {
+ gotInputs = true;
}
this.inputs = response.inputs;
});
@@ -99,7 +109,7 @@ export class InterfaceOperationComponent {
modalData.saveBtnText,
'blue',
() => {
- this.modalInstance.instance.dynamicContent.instance.createInputParamList();
+ this.modalInstance.instance.dynamicContent.instance.createParamLists();
this.ModalServiceNg2.closeCurrentModal();
const {operation, isAssociateWorkflow} = this.modalInstance.instance.dynamicContent.instance;
@@ -180,6 +190,8 @@ export class InterfaceOperationComponent {
const versionId = response.workflowVersionId;
const artifactId = response.artifactUUID;
this.WorkflowServiceNg2.associateWorkflowArtifact(resourceId, operationId, workflowId, versionId, artifactId).subscribe();
+ } else {
+ this.$state.go('workspace.plugins', { path: 'workflowDesigner' });
}
});
}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
index d7d12d0585..5c511c15f3 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
@@ -31,7 +31,7 @@
[ngClass]="{'disabled':isEditMode}" />
</div>
- <div class="i-sdc-form-item" >
+ <div class="i-sdc-form-item">
<label class="i-sdc-form-label">Description</label>
<input
type="text"
@@ -43,17 +43,20 @@
</div>
</div>
- <div class="i-sdc-form-item" *ngIf="enableWorkflowAssociation">
- <checkbox
- [label]="'Assign Workflow'"
- [(checked)]="isAssociateWorkflow"
- (checkedChange)="toggleAssociateWorkflow()"
- [ngClass]="{'disabled': readonly}"
- data-tests-id="checkbox-assign-workflow">
- </checkbox>
+ <div class="side-by-side association-options">
+ <div class="i-sdc-form-item" *ngIf="enableWorkflowAssociation">
+ <label class="i-sdc-form-label">Workflow Assignment</label>
+ <ui-element-dropdown
+ [(value)]="workflowAssociationType"
+ [values]="associationOptions"
+ (valueChange)="toggleAssociateWorkflow()"
+ [readonly]="readonly">
+ </ui-element-dropdown>
+ </div>
+ <div></div>
</div>
- <div class="side-by-side" *ngIf="isAssociateWorkflow">
+ <div class="side-by-side" *ngIf="workflowAssociationType == WORKFLOW_ASSOCIATION_OPTIONS.EXISTING">
<div class="i-sdc-form-item">
<label class="i-sdc-form-label required">Workflow</label>
<ui-element-dropdown
@@ -78,35 +81,38 @@
</div>
<div class="separator-buttons">
- <span class="input-param-title">Input Parameters</span>
+ <tabs #propertyInputTabs tabStyle="round-tabs" (tabChanged)="tabChanged($event)" [hideIndicationOnTabChange]="true">
+ <tab tabTitle="Inputs"></tab>
+ <tab tabTitle="Outputs"></tab>
+ </tabs>
<a
class="add-param-link add-btn"
- *ngIf="!isAssociateWorkflow && !readonly"
+ *ngIf="workflowAssociationType != WORKFLOW_ASSOCIATION_OPTIONS.EXISTING && !readonly"
data-tests-id="addInputParameter"
[ngClass]="{'disabled':!isParamsValid()}"
- (click)="addParam()">Add Input Parameter</a>
+ (click)="addParam()">Add Parameter</a>
</div>
<div class="generic-table">
<div class="header-row table-row">
<span class="cell header-cell field-name">Name</span>
<span class="cell header-cell field-type">Type</span>
- <span class="cell header-cell field-property">
+ <span class="cell header-cell field-property" *ngIf="currentTab == TYPE_INPUT">
Property
<span
- *ngIf="!isAssociateWorkflow"
+ *ngIf="workflowAssociationType != WORKFLOW_ASSOCIATION_OPTIONS.EXISTING"
class="sprite-new info-icon"
tooltip="{{propertyTooltipText}}"
tooltipDelay="0">
</span>
</span>
- <span class="cell header-cell field-mandatory" *ngIf="!isAssociateWorkflow">Mandatory</span>
- <span class="cell header-cell remove" *ngIf="!isAssociateWorkflow && !readonly">●●●</span>
+ <span class="cell header-cell field-mandatory" *ngIf="workflowAssociationType != WORKFLOW_ASSOCIATION_OPTIONS.EXISTING">Mandatory</span>
+ <span class="cell header-cell remove" *ngIf="workflowAssociationType != WORKFLOW_ASSOCIATION_OPTIONS.EXISTING && !readonly">●●●</span>
</div>
- <div class="empty-msg data-row" *ngIf="inputParameters.length === 0">
+ <div class="empty-msg data-row" *ngIf="tableParameters.length === 0">
<div>NO PARAMETERS TO SHOW</div>
- <div *ngIf="isAssociateWorkflow && !operation.workflowVersionId">
+ <div *ngIf="workflowAssociationType == WORKFLOW_ASSOCIATION_OPTIONS.EXISTING && !operation.workflowVersionId">
<div *ngIf="workflows.length">
<span class="bold-message">Select Workflow and Workflow Version above</span>
<span>in order to see the parameters</span>
@@ -118,9 +124,10 @@
</div>
<param-row
- *ngFor="let param of inputParameters"
+ *ngFor="let param of tableParameters"
class="data-row"
- [isAssociateWorkflow]="isAssociateWorkflow"
+ [isInputParam]="currentTab == TYPE_INPUT"
+ [isAssociateWorkflow]="workflowAssociationType == WORKFLOW_ASSOCIATION_OPTIONS.EXISTING"
[param]="param"
[inputProps]="inputProperties"
[propTypes]="inputPropertyTypes"
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
index e2b53bee65..f64a087abc 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
@@ -17,6 +17,10 @@
.side-by-side {
display: flex;
+ &.association-options {
+ margin-top: 5px;
+ }
+
.i-sdc-form-item {
flex-basis: 100%;
@@ -33,9 +37,9 @@
}
.separator-buttons {
- margin: 10px 0;
display: flex;
justify-content: space-between;
+ margin-top: 10px;
.add-param-link {
&:not(.disabled):hover {
@@ -46,6 +50,8 @@
.generic-table {
max-height: 233px;
+ min-height: 91px;
+ background: @main_color_p;
.header-row .header-cell {
&.remove {
@@ -54,12 +60,9 @@
.info-icon {
float: right;
}
- .tooltip-inner {
- &.tooltip-inner {
- &.tooltip-inner {
- max-width: 230px;
- }
- }
+ /deep/ .tooltip-inner {
+ max-width: 280px;
+ font-size: 11px;
}
}
@@ -79,7 +82,7 @@
flex-direction: column;
justify-content: center;
align-items: center;
- padding: 11px 0;
+ padding: 14px;
}
}
@@ -101,6 +104,7 @@
&.remove {
min-width: 40px;
+ max-width: 40px;
}
}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
index d2bad5f02d..42f95d577c 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
@@ -1,12 +1,13 @@
import * as _ from "lodash";
-import {Component} from '@angular/core';
+import {Component, ViewChild} from '@angular/core';
import {Subscription} from "rxjs/Subscription";
import {TranslateService} from "app/ng2/shared/translator/translate.service";
import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
-import {OperationModel, OperationParameter, InputBEModel} from 'app/models';
+import {OperationModel, OperationParameter, InputBEModel, RadioButtonModel} from 'app/models';
+import {Tabs, Tab} from "app/ng2/components/ui/tabs/tabs.component";
import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
export interface OperationCreatorInput {
@@ -17,6 +18,7 @@ export interface OperationCreatorInput {
isService: boolean
}
+
@Component({
selector: 'operation-creator',
templateUrl: './operation-creator.component.html',
@@ -38,8 +40,16 @@ export class OperationCreatorComponent {
noAssignInputParameters: Array<OperationParameter> = [];
assignInputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
+ outputParameters: Array<OperationParameter> = [];
+ noAssignOutputParameters: Array<OperationParameter> = [];
+ assignOutputParameters: { [key: string]: { [key: string]: Array<OperationParameter>; }; } = {};
+
+ tableParameters: Array<OperationParameter> = [];
+
+ associationOptions: Array<DropdownValue>;
+ workflowAssociationType: String;
+
enableWorkflowAssociation: boolean;
- isAssociateWorkflow: boolean;
isEditMode: boolean = false;
isLoading: boolean = false;
readonly: boolean;
@@ -47,10 +57,30 @@ export class OperationCreatorComponent {
propertyTooltipText: String;
+ WORKFLOW_ASSOCIATION_OPTIONS = {
+ NONE: 'No Workflow',
+ NEW: 'New Workflow',
+ EXISTING: 'Existing Workflow'
+ }
+
+ TYPE_INPUT = 'Inputs';
+ TYPE_OUTPUT = 'Outputs';
+
+ @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
+ currentTab: String;
+
constructor(private workflowServiceNg2: WorkflowServiceNg2, private translateService: TranslateService) {
this.translateService.languageChangedObservable.subscribe(lang => {
this.propertyTooltipText = this.translateService.translate("OPERATION_PROPERTY_TOOLTIP_TEXT");
});
+ this.currentTab = this.TYPE_INPUT;
+
+ this.associationOptions = [
+ new DropdownValue(this.WORKFLOW_ASSOCIATION_OPTIONS.NONE, this.WORKFLOW_ASSOCIATION_OPTIONS.NONE),
+ new DropdownValue(this.WORKFLOW_ASSOCIATION_OPTIONS.NEW, this.WORKFLOW_ASSOCIATION_OPTIONS.NEW),
+ new DropdownValue(this.WORKFLOW_ASSOCIATION_OPTIONS.EXISTING, this.WORKFLOW_ASSOCIATION_OPTIONS.EXISTING)
+ ];
+ this.workflowAssociationType = this.WORKFLOW_ASSOCIATION_OPTIONS.NONE;
}
ngOnInit() {
@@ -91,20 +121,37 @@ export class OperationCreatorComponent {
if (inputOperation) {
if (!this.enableWorkflowAssociation || !inputOperation.workflowVersionId || this.isService) {
this.inputParameters = this.noAssignInputParameters;
- this.isAssociateWorkflow = false;
- this.buildInputParams();
+ this.outputParameters = this.noAssignOutputParameters;
+ this.buildParams();
+ this.updateTable();
} else {
- this.isAssociateWorkflow = true;
- this.onSelectWorkflow(inputOperation.workflowVersionId).add(this.buildInputParams);
+ this.workflowAssociationType = this.WORKFLOW_ASSOCIATION_OPTIONS.EXISTING;
+ this.onSelectWorkflow(inputOperation.workflowVersionId).add(() => {
+ this.buildParams();
+ this.updateTable();
+ });
}
if (inputOperation.uniqueId) {
this.isEditMode = true;
}
}
+ this.updateTable();
}
- buildInputParams = () => {
+ buildParams = () => {
+ if (this.input.operation.outputParams) {
+ this.currentTab = this.TYPE_OUTPUT;
+ this.updateTable();
+ _.forEach(
+ [...this.input.operation.outputParams.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
+ (output: OperationParameter) => {
+ this.addParam(output);
+ }
+ );
+ }
+ this.currentTab = this.TYPE_INPUT;
+ this.updateTable();
if (this.input.operation.inputParams) {
_.forEach(
[...this.input.operation.inputParams.listToscaDataDefinition].sort((a, b) => a.name.localeCompare(b.name)),
@@ -120,6 +167,7 @@ export class OperationCreatorComponent {
this.operation.workflowVersionId = selectedVersionId || null;
if (!this.assignInputParameters[this.operation.workflowId]) {
this.assignInputParameters[this.operation.workflowId] = {};
+ this.assignOutputParameters[this.operation.workflowId] = {};
}
this.isLoading = true;
@@ -141,6 +189,16 @@ export class OperationCreatorComponent {
});
})
.sort((a, b) => a.name.localeCompare(b.name));
+
+ this.assignOutputParameters[this.operation.workflowId][version.id] = _.map(version.outputs, (output: any) => {
+ return new OperationParameter({
+ name: output.name,
+ type: output.type && output.type.toLowerCase(),
+ property: null,
+ mandatory: output.mandatory,
+ });
+ })
+ .sort((a, b) => a.name.localeCompare(b.name));
}
return new DropdownValue(version.id, `V ${version.name}`);
}
@@ -156,30 +214,55 @@ export class OperationCreatorComponent {
changeWorkflowVersion() {
this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
+ this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
+ this.updateTable();
}
toggleAssociateWorkflow() {
- if (!this.isAssociateWorkflow) {
+ if (this.workflowAssociationType !== this.WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) {
this.inputParameters = this.noAssignInputParameters;
+ this.outputParameters = this.noAssignOutputParameters;
} else {
if (!this.operation.workflowId || !this.operation.workflowVersionId) {
this.inputParameters = [];
+ this.outputParameters = [];
} else {
this.inputParameters = this.assignInputParameters[this.operation.workflowId][this.operation.workflowVersionId];
+ this.outputParameters = this.assignOutputParameters[this.operation.workflowId][this.operation.workflowVersionId];
}
}
+ this.updateTable();
+
+ }
+
+ tabChanged = (event) => {
+ this.currentTab = event.title;
+ this.updateTable();
+ }
+
+ updateTable() {
+ switch (this.currentTab) {
+ case this.TYPE_INPUT:
+ this.tableParameters = this.inputParameters;
+ break;
+ case this.TYPE_OUTPUT:
+ this.tableParameters = this.outputParameters;
+ break;
+ }
}
addParam(param?: OperationParameter): void {
- this.inputParameters.push(new OperationParameter(param));
+ this.tableParameters.push(new OperationParameter(param));
}
isParamsValid(): boolean {
- for (let ctr=0; ctr<this.inputParameters.length; ctr++) {
- if (!this.inputParameters[ctr].name || !this.inputParameters[ctr].property) {
+ for (let ctr=0; ctr<this.tableParameters.length; ctr++) {
+ if (!this.tableParameters[ctr].name ||
+ (this.currentTab == this.TYPE_INPUT && !this.tableParameters[ctr].property)
+ ) {
return false;
}
}
@@ -188,17 +271,32 @@ export class OperationCreatorComponent {
}
onRemoveParam = (param: OperationParameter): void => {
- let index = _.indexOf(this.inputParameters, param);
- this.inputParameters.splice(index, 1);
+ let index = _.indexOf(this.tableParameters, param);
+ this.tableParameters.splice(index, 1);
}
- createInputParamList(): void {
- this.operation.createInputParamsList(this.inputParameters);
+ createParamLists(): void {
+ this.operation.createInputParamsList(_.map(this.inputParameters, input => {
+ return {
+ name: input.name,
+ type: input.type,
+ property: input.property,
+ mandatory: Boolean(input.mandatory)
+ }
+ }));
+ this.operation.createOutputParamsList(_.map(this.outputParameters, output => {
+ return {
+ name: output.name,
+ type: output.type,
+ property: output.property,
+ mandatory: Boolean(output.mandatory)
+ }
+ }));
}
checkFormValidForSubmit(): boolean {
return this.operation.operationType &&
- (!this.isAssociateWorkflow || this.operation.workflowVersionId) &&
+ (this.workflowAssociationType !== this.WORKFLOW_ASSOCIATION_OPTIONS.EXISTING || this.operation.workflowVersionId) &&
this.isParamsValid();
}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
index 33085b08f4..8382f1e842 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
@@ -36,7 +36,7 @@
<span *ngIf="isAssociateWorkflow">{{param.type}}</span>
</div>
-<div class="cell field-property">
+<div class="cell field-property" *ngIf="isInputParam">
<ui-element-dropdown
data-tests-id="paramProperty"
[values]="filteredInputProps"
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
index 8795d22e8d..81a1832c21 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
@@ -5,7 +5,7 @@
align-items: center;
justify-content: center;
- .delete-btn {
+ .delete-item-icon {
&:hover {
cursor: pointer;
}
@@ -14,6 +14,7 @@
.cell {
+ min-height: 50px;
padding: 10px;
display: flex;
align-items: center;
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
index 53dcffddd3..9f7f4230ee 100644
--- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
@@ -17,6 +17,7 @@ export class ParamRowComponent {
@Input() onRemoveParam: Function;
@Input() isAssociateWorkflow: boolean;
@Input() readonly: boolean;
+ @Input() isInputParam: boolean;
propTypeEnum: Array<String> = [];
filteredInputProps: Array<DropdownValue> = [];