aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2')
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts50
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.html48
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.less98
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.spec.ts57
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts140
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html27
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts436
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts7
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.html38
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.less21
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.spec.ts74
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts443
12 files changed, 1026 insertions, 413 deletions
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
index 9f721d5cdd..2ae5ce8c09 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
@@ -61,13 +61,12 @@ import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-chang
import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
import {ModalService} from "../../services/modal.service";
import {DeclareListComponent} from "./declare-list/declare-list.component";
-import {ToscaFunctionComponent} from "./tosca-function/tosca-function.component";
+import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
import {CapabilitiesGroup, Capability} from "../../../models/capability";
import {ToscaPresentationData} from "../../../models/tosca-presentation";
import {Observable} from "rxjs";
import {TranslateService} from "../../shared/translator/translate.service";
-import {ToscaGetFunctionDtoBuilder} from '../../../models/tosca-get-function-dto';
-import {ToscaGetFunction} from "../../../models/tosca-get-function";
+import {ToscaFunction} from "../../../models/tosca-function";
const SERVICE_SELF_TITLE = "SELF";
@Component({
@@ -539,36 +538,37 @@ export class PropertiesAssignmentComponent {
const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
const modalButtons = [];
let disableSaveButtonFlag = true;
+ const modal = this.modalService.createCustomModal(new ModalModel(
+ 'sm',
+ modalTitle,
+ null,
+ modalButtons,
+ null /* type */
+ ));
modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
() => {
- const toscaGetFunction: ToscaGetFunction = modal.instance.dynamicContent.instance.toscaGetFunction;
- if (toscaGetFunction.functionType) {
- this.updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction);
+ const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
+ if (toscaGetFunction) {
+ this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
} else {
this.clearCheckedInstancePropertyValue();
}
- modal.instance.close();
+ this.modalService.closeCurrentModal();
},
(): boolean => { return disableSaveButtonFlag }
));
const checkedInstanceProperty = this.buildCheckedInstanceProperty();
modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
- modal.instance.close();
+ this.modalService.closeCurrentModal();
}));
- const modal = this.modalService.createCustomModal(new ModalModel(
- 'sm',
- modalTitle,
- null,
- modalButtons,
- null /* type */
- ));
+
this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
'property': checkedInstanceProperty,
'componentInstanceMap': this.componentInstanceMap
});
- modal.instance.dynamicContent.instance.onValidityChange.subscribe(isValid => {
- disableSaveButtonFlag = !isValid;
+ modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
+ disableSaveButtonFlag = !validationEvent.isValid;
});
modal.instance.open();
}
@@ -577,23 +577,13 @@ export class PropertiesAssignmentComponent {
const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
checkedInstanceProperty.getInputValues = null;
checkedInstanceProperty.value = null;
- checkedInstanceProperty.toscaGetFunction = null;
+ checkedInstanceProperty.toscaFunction = null;
this.updateInstanceProperty(checkedInstanceProperty);
}
- private updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction: ToscaGetFunction) {
- const toscaGetFunctionBuilder: ToscaGetFunctionDtoBuilder =
- new ToscaGetFunctionDtoBuilder()
- .withPropertyUniqueId(toscaGetFunction.propertyUniqueId)
- .withFunctionType(toscaGetFunction.functionType)
- .withPropertySource(toscaGetFunction.propertySource)
- .withPropertyName(toscaGetFunction.propertyName)
- .withSourceName(toscaGetFunction.sourceName)
- .withSourceUniqueId(toscaGetFunction.sourceUniqueId)
- .withPropertyPathFromSource(toscaGetFunction.propertyPathFromSource);
-
+ private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
- checkedProperty.toscaGetFunction = toscaGetFunctionBuilder.build();
+ checkedProperty.toscaFunction = toscaFunction;
this.updateInstanceProperty(checkedProperty);
}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.html
new file mode 100644
index 0000000000..6320058d9d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.html
@@ -0,0 +1,48 @@
+<!--
+ ~ -
+ ~ ============LICENSE_START=======================================================
+ ~ Copyright (C) 2022 Nordix Foundation.
+ ~ ================================================================================
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ ~ SPDX-License-Identifier: Apache-2.0
+ ~ ============LICENSE_END=========================================================
+ -->
+
+<div class="component-container">
+ <ng-container [formGroup]="formGroup">
+ <div formArrayName="concatParameterList">
+ <div *ngFor="let parameter of parameters; let idx = index">
+ <div *ngIf="idx > 0" class="text-center"><span class="concat-plus-icon"></span></div>
+ <div class="parameter-card">
+ <div class="card-content">
+ <ng-container *ngIf="parameter.type === STRING_FUNCTION_TYPE">
+ <input type="text" [formControlName]="idx" [value]="parameter.value"/><br/>
+ </ng-container>
+ <ng-container *ngIf="parameter.type !== STRING_FUNCTION_TYPE">
+ <tosca-function [property]="propertyInputList[idx]" [componentInstanceMap]="componentInstanceMap" [allowClear]="false"
+ (onValidityChange)="onFunctionValidityChange($event, idx)">
+ </tosca-function>
+ </ng-container>
+ <div class="buttons-container">
+ <span class="delete-icon" (click)="removeParameter(idx)"></span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-container>
+ <div class="buttons-container">
+ <a class="add-link" (click)="addStringParameter()">String Value</a> <a class="add-link" (click)="addFunction()">String Value Expression</a>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.less
new file mode 100644
index 0000000000..b9c59831ad
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.less
@@ -0,0 +1,98 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+@import "../../../../../../assets/styles/mixins.less";
+@import "../../../../../../assets/styles/sprite.less";
+
+.component-container {
+ max-height: 500px;
+ overflow: scroll;
+ padding: 0 5px;
+ &::-webkit-scrollbar-track {
+ border: 0;
+ }
+}
+
+.buttons-container {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-bottom: 10px;
+
+ .add-link {
+ .f-color.a();
+ .f-type._14_m();
+ cursor: pointer;
+
+ &:before {
+ .sprite-new();
+ .plus-icon();
+ margin-right: 5px;
+ content: "";
+ }
+
+ &:hover {
+ .f-color.b();
+ &:before {
+ .sprite-new();
+ .plus-icon-hover();
+ }
+ }
+ }
+
+ .delete-icon {
+ .sprite-new();
+ .delete-btn();
+ cursor: pointer;
+ }
+}
+
+.parameter-card {
+ border: 2px solid @main_color_o;
+ box-shadow: 0 0 0 0 rgba(0,0,0,0.2);
+ //padding: 10px;
+ border-radius: 2px;
+ transition: 0.3s;
+ margin-bottom: 5px;
+ &:hover {
+ box-shadow: 0 1px 8px 2px rgba(0,0,0,0.2);
+ }
+
+ .card-content {
+ padding: 5px 10px;
+ }
+
+ .text-center {
+ text-align: center;
+ }
+
+ input {
+ border: solid 1px @main_color_o;
+ }
+}
+
+.concat-plus-icon {
+ .sprite-new();
+ background-position: -216px -1388px;
+ width: 14px;
+ height: 14px;
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.spec.ts
new file mode 100644
index 0000000000..5c9af47361
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.spec.ts
@@ -0,0 +1,57 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {ToscaConcatFunctionComponent} from './tosca-concat-function.component';
+import {FormsModule, ReactiveFormsModule} from "@angular/forms";
+import {ToscaFunctionComponent} from "../tosca-function.component";
+import {TranslateModule} from "../../../../shared/translator/translate.module";
+import {ToscaGetFunctionComponent} from "../tosca-get-function/tosca-get-function.component";
+import {UiElementsModule} from "../../../../components/ui/ui-elements.module";
+
+describe('ToscaConcatFunctionComponent', () => {
+ let component: ToscaConcatFunctionComponent;
+ let fixture: ComponentFixture<ToscaConcatFunctionComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ToscaConcatFunctionComponent, ToscaFunctionComponent, ToscaGetFunctionComponent],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ TranslateModule,
+ UiElementsModule
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ToscaConcatFunctionComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts
new file mode 100644
index 0000000000..d808c284a8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts
@@ -0,0 +1,140 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {FormArray, FormControl, FormGroup, Validators} from "@angular/forms";
+import {ToscaConcatFunction} from "../../../../../models/tosca-concat-function";
+import {ToscaFunctionParameter} from "../../../../../models/tosca-function-parameter";
+import {ToscaStringParameter} from "../../../../../models/tosca-string-parameter";
+import {ToscaFunctionType} from "../../../../../models/tosca-function-type.enum";
+import {PropertyBEModel} from "../../../../../models/properties-inputs/property-be-model";
+import {PROPERTY_TYPES} from "../../../../../utils/constants";
+import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
+import {ToscaFunctionValidationEvent} from "../tosca-function.component";
+
+@Component({
+ selector: 'app-tosca-concat-function',
+ templateUrl: './tosca-concat-function.component.html',
+ styleUrls: ['./tosca-concat-function.component.less']
+})
+export class ToscaConcatFunctionComponent implements OnInit {
+
+ @Input() toscaConcatFunction: ToscaConcatFunction;
+ @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
+ @Output() onValidFunction: EventEmitter<ToscaConcatFunction> = new EventEmitter<ToscaConcatFunction>();
+ @Output() onValidityChange: EventEmitter<ToscaConcatFunctionValidationEvent> = new EventEmitter<ToscaConcatFunctionValidationEvent>();
+
+ concatParameterFormArray: FormArray = new FormArray([], Validators.minLength(2));
+ formGroup: FormGroup = new FormGroup(
+ {
+ 'concatParameterList': this.concatParameterFormArray
+ }
+ );
+
+ parameters: ToscaFunctionParameter[] = [];
+ propertyInputList: Array<PropertyBEModel> = [];
+
+ stringProperty: PropertyBEModel
+
+ STRING_FUNCTION_TYPE = ToscaFunctionType.STRING
+
+ constructor() {
+ this.stringProperty = new PropertyBEModel();
+ this.stringProperty.type = PROPERTY_TYPES.STRING
+ }
+
+ ngOnInit() {
+ this.initForm();
+ }
+
+ private initForm() {
+ this.formGroup.valueChanges.subscribe(() => {
+ this.onValidityChange.emit({
+ isValid: this.formGroup.valid,
+ toscaConcatFunction: this.formGroup.valid ? this.buildConcatFunctionFromForm() : undefined
+ })
+ if (this.formGroup.valid) {
+ this.onValidFunction.emit(this.buildConcatFunctionFromForm());
+ }
+ });
+ if (!this.toscaConcatFunction) {
+ return;
+ }
+
+ if (this.toscaConcatFunction.parameters) {
+ this.parameters = Array.from(this.toscaConcatFunction.parameters);
+ for (const parameter of this.parameters) {
+ if (parameter.type !== PROPERTY_TYPES.STRING) {
+ this.propertyInputList.push(this.createStringProperty(parameter));
+ this.concatParameterFormArray.push(
+ new FormControl(parameter, [Validators.required, Validators.minLength(1)])
+ );
+ } else {
+ this.propertyInputList.push(undefined);
+ this.concatParameterFormArray.push(
+ new FormControl(parameter.value, [Validators.required, Validators.minLength(1)])
+ );
+ }
+ }
+ }
+ }
+
+ private buildConcatFunctionFromForm(): ToscaConcatFunction {
+ const toscaConcatFunction1 = new ToscaConcatFunction();
+ this.concatParameterFormArray.controls.forEach(control => {
+ const value = control.value;
+ if (typeof value === 'string') {
+ const stringParameter = new ToscaStringParameter();
+ stringParameter.value = value;
+ toscaConcatFunction1.parameters.push(stringParameter);
+ } else {
+ toscaConcatFunction1.parameters.push(control.value);
+ }
+ });
+
+ return toscaConcatFunction1;
+ }
+
+ addFunction() {
+ this.propertyInputList.push(this.createStringProperty());
+ this.parameters.push({} as ToscaFunctionParameter);
+ this.concatParameterFormArray.push(
+ new FormControl(undefined, [Validators.required, Validators.minLength(1)])
+ );
+ }
+
+ addStringParameter() {
+ this.parameters.push({
+ type: ToscaFunctionType.STRING,
+ value: ''
+ });
+ this.propertyInputList.push(undefined);
+ this.concatParameterFormArray.push(
+ new FormControl('', [Validators.required, Validators.minLength(1)])
+ );
+ }
+
+ removeParameter(position) {
+ this.propertyInputList.splice(position, 1);
+ this.parameters.splice(position, 1);
+ this.concatParameterFormArray.removeAt(position);
+ }
+
+ createStringProperty(toscaFunctionParameter?: ToscaFunctionParameter) {
+ const property = new PropertyBEModel();
+ property.type = PROPERTY_TYPES.STRING;
+ property.toscaFunction = toscaFunctionParameter ? toscaFunctionParameter : undefined;
+ property.value = toscaFunctionParameter ? toscaFunctionParameter.value : undefined;
+ return property;
+ }
+
+ onFunctionValidityChange(event: ToscaFunctionValidationEvent, index: number) {
+ if (event.isValid && event.toscaFunction) {
+ this.concatParameterFormArray.controls[index].setValue(event.toscaFunction)
+ } else {
+ this.concatParameterFormArray.controls[index].setValue(undefined);
+ }
+ }
+}
+
+export interface ToscaConcatFunctionValidationEvent {
+ isValid: boolean,
+ toscaConcatFunction: ToscaConcatFunction,
+}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html
index b6b313d93c..e98f688eef 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html
@@ -18,32 +18,27 @@
-->
<div class="tosca-function">
- <loader [display]="isLoading" [loaderDelay]="500" [relative]="true" [size]="'large'"></loader>
- <form class="w-sdc-form">
+ <div class="w-sdc-form" [formGroup]="formGroup">
<div class="i-sdc-form-item">
<label class="i-sdc-form-label">{{'TOSCA_FUNCTION_LABEL' | translate}}</label>
- <select [(ngModel)]="toscaGetFunction.functionType" (change)="onToscaFunctionChange()" name="toscaFunctionType">
+ <select formControlName="toscaFunctionType">
<option *ngFor="let toscaFunction of toscaFunctions"
[ngValue]="toscaFunction">{{toscaFunction | lowercase}}</option>
</select>
</div>
- <div class="i-sdc-form-item" *ngIf="showPropertySourceDropdown()">
- <label class="i-sdc-form-label required">{{'TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL' | translate}}</label>
- <select name="propertySource" [(ngModel)]="propertySource" (change)="onPropertySourceChange()">
- <option *ngFor="let propertySource of propertySourceList"
- [ngValue]="propertySource">{{propertySource}}</option>
- </select>
+ <div *ngIf="isConcatSelected()">
+ <app-tosca-concat-function [toscaConcatFunction]="toscaFunction" [componentInstanceMap]="componentInstanceMap"
+ (onValidityChange)="onConcatFunctionValidityChange($event)"></app-tosca-concat-function>
</div>
- <div *ngIf="showPropertyDropdown()" class="i-sdc-form-item">
- <label class="i-sdc-form-label required">{{dropdownValuesLabel}}</label>
- <select [(ngModel)]="selectedProperty" name="selectedProperty" (change)="onPropertyChange()">
- <option *ngFor="let value of propertyDropdownList" [ngValue]="value">{{value.propertyLabel}}</option>
- </select>
+ <div *ngIf="isGetFunctionSelected()">
+ <app-tosca-get-function [property]="property" [toscaGetFunction]="toscaFunction"
+ [componentInstanceMap]="componentInstanceMap"
+ [functionType]="toscaFunctionTypeForm.value"
+ (onValidityChange)="onGetFunctionValidityChange($event)"></app-tosca-get-function>
</div>
- <div *ngIf="dropDownErrorMsg">{{dropDownErrorMsg}}</div>
<div *ngIf="showClearButton()" class="button-container">
<button (click)="onClearValues()" class="tlv-btn red ng-star-inserted">{{'TOSCA_FUNCTION_CLEAR_VALUE_BUTTON' | translate}}</button>
</div>
- </form>
+ </div>
<loader [display]="isLoading" [size]="'medium'" [relative]="true"></loader>
</div>
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
index b71a61dc01..076e1182ad 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
@@ -18,20 +18,18 @@
*/
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
-import {AttributeModel, ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel} from 'app/models';
+import {ComponentMetadata, PropertyBEModel} from 'app/models';
import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
import {WorkspaceService} from "../../workspace/workspace.service";
-import {PropertiesService} from "../../../services/properties.service";
-import {PROPERTY_DATA, PROPERTY_TYPES} from "../../../../utils/constants";
-import {DataTypeService} from "../../../services/data-type.service";
import {ToscaGetFunctionType} from "../../../../models/tosca-get-function-type";
-import {TranslateService} from "../../../shared/translator/translate.service";
-import {ComponentGenericResponse} from '../../../services/responses/component-generic-response';
-import {Observable} from 'rxjs/Observable';
-import {PropertySource} from "../../../../models/property-source";
import {InstanceFeDetails} from "../../../../models/instance-fe-details";
import {ToscaGetFunction} from "../../../../models/tosca-get-function";
-import {AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
+import {FormControl, FormGroup, Validators} from "@angular/forms";
+import {ToscaFunctionType} from "../../../../models/tosca-function-type.enum";
+import {ToscaGetFunctionValidationEvent} from "./tosca-get-function/tosca-get-function.component";
+import {ToscaFunction} from "../../../../models/tosca-function";
+import {ToscaConcatFunctionValidationEvent} from "./tosca-concat-function/tosca-concat-function.component";
+import {PROPERTY_TYPES} from "../../../../utils/constants";
@Component({
selector: 'tosca-function',
@@ -44,418 +42,124 @@ export class ToscaFunctionComponent implements OnInit {
@Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
@Input() allowClear: boolean = true;
@Output() onValidFunction: EventEmitter<ToscaGetFunction> = new EventEmitter<ToscaGetFunction>();
- @Output() onValidityChange: EventEmitter<boolean> = new EventEmitter<boolean>();
+ @Output() onValidityChange: EventEmitter<ToscaFunctionValidationEvent> = new EventEmitter<ToscaFunctionValidationEvent>();
- toscaGetFunctionValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
- const toscaGetFunction: ToscaGetFunction = control.value;
- const hasAnyValue = Object.keys(toscaGetFunction).find(key => toscaGetFunction[key]);
- if (!hasAnyValue) {
- return null;
- }
- const errors: ValidationErrors = {};
- if (!toscaGetFunction.sourceName) {
- errors.sourceName = { required: true };
- }
- if (!toscaGetFunction.functionType) {
- errors.functionType = { required: true };
- }
- if (!toscaGetFunction.sourceUniqueId) {
- errors.sourceUniqueId = { required: true };
- }
- if (!toscaGetFunction.sourceName) {
- errors.sourceName = { required: true };
- }
- if (!toscaGetFunction.propertyPathFromSource) {
- errors.propertyPathFromSource = { required: true };
- }
- if (!toscaGetFunction.propertyName) {
- errors.propertyName = { required: true };
- }
- if (!toscaGetFunction.propertySource) {
- errors.propertySource = { required: true };
- }
- return errors ? errors : null;
- };
-
- toscaGetFunctionForm: FormControl = new FormControl(new ToscaGetFunction(undefined), [this.toscaGetFunctionValidator]);
+ toscaFunctionForm: FormControl = new FormControl(undefined, [Validators.required]);
+ toscaFunctionTypeForm: FormControl = new FormControl(undefined, Validators.required);
formGroup: FormGroup = new FormGroup({
- 'toscaGetFunction': this.toscaGetFunctionForm
+ 'toscaFunction': this.toscaFunctionForm,
+ 'toscaFunctionType': this.toscaFunctionTypeForm,
});
- selectedProperty: PropertyDropdownValue;
isLoading: boolean = false;
- propertyDropdownList: Array<PropertyDropdownValue> = [];
+ toscaFunction: ToscaFunction;
toscaFunctions: Array<string> = [];
- propertySourceList: Array<string> = [];
- instanceNameAndIdMap: Map<string, string> = new Map<string, string>();
- dropdownValuesLabel: string;
- dropDownErrorMsg: string;
- propertySource: string
- toscaGetFunction: ToscaGetFunction = new ToscaGetFunction(undefined);
+ private isInitialized: boolean = false;
private componentMetadata: ComponentMetadata;
constructor(private topologyTemplateService: TopologyTemplateService,
- private workspaceService: WorkspaceService,
- private propertiesService: PropertiesService,
- private dataTypeService: DataTypeService,
- private translateService: TranslateService) {
+ private workspaceService: WorkspaceService) {
}
ngOnInit(): void {
this.componentMetadata = this.workspaceService.metadata;
+ this.toscaFunction = this.property.toscaFunction ? this.property.toscaFunction : undefined;
this.loadToscaFunctions();
- this.loadPropertySourceDropdown();
- this.initToscaGetFunction();
- }
-
- private initToscaGetFunction(): void {
- this.toscaGetFunctionForm.valueChanges.subscribe(toscaGetFunction => {
- this.onValidityChange.emit(this.toscaGetFunctionForm.valid);
- if (this.toscaGetFunctionForm.valid) {
- this.onValidFunction.emit(toscaGetFunction);
- }
- });
- if (!this.property.isToscaGetFunction()) {
- return;
- }
- this.toscaGetFunction = new ToscaGetFunction(this.property.toscaGetFunction);
- this.toscaGetFunctionForm.setValue(this.toscaGetFunction);
- if (this.isGetPropertySelected() || this.isGetAttributeSelected()) {
- if (this.toscaGetFunction.propertySource === PropertySource.SELF) {
- this.propertySource = PropertySource.SELF;
- } else {
- this.propertySource = this.toscaGetFunction.sourceName;
- }
- }
- if (this.toscaGetFunction.propertyName) {
- this.loadPropertyDropdown(() => {
- this.selectedProperty = this.propertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.propertyName)
- });
- }
- }
-
- private loadToscaFunctions(): void {
- this.toscaFunctions.push(ToscaGetFunctionType.GET_ATTRIBUTE);
- this.toscaFunctions.push(ToscaGetFunctionType.GET_INPUT);
- this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY);
- }
-
- private loadPropertySourceDropdown(): void {
- this.propertySourceList.push(PropertySource.SELF);
- this.componentInstanceMap.forEach((value, key) => {
- const instanceName = value.name;
- this.instanceNameAndIdMap.set(instanceName, key);
- if (instanceName !== PropertySource.SELF) {
- this.addToPropertySource(instanceName);
- }
- });
- }
-
- private addToPropertySource(source: string): void {
- this.propertySourceList.push(source);
- this.propertySourceList.sort((a, b) => {
- if (a === PropertySource.SELF) {
- return -1;
- } else if (b === PropertySource.SELF) {
- return 1;
- }
-
- return a.localeCompare(b);
- });
- }
-
- onToscaFunctionChange(): void {
- this.resetPropertySource();
- this.resetPropertyDropdown();
- if (this.isGetInputSelected()) {
- this.setSelfPropertySource();
- this.loadPropertyDropdown();
- }
- }
-
- private loadPropertyDropdown(onComplete?: () => any): void {
- this.loadPropertyDropdownLabel();
- this.loadPropertyDropdownValues(onComplete);
- }
-
- private resetForm(): void {
- this.toscaGetFunction = new ToscaGetFunction();
- this.toscaGetFunctionForm.setValue(new ToscaGetFunction());
- this.propertySource = undefined;
- this.selectedProperty = undefined;
- }
-
- private resetPropertySource(): void {
- this.toscaGetFunction.propertyUniqueId = undefined;
- this.toscaGetFunction.propertyName = undefined;
- this.toscaGetFunction.propertySource = undefined;
- this.toscaGetFunction.sourceUniqueId = undefined;
- this.toscaGetFunction.sourceName = undefined;
- this.toscaGetFunction.propertyPathFromSource = undefined;
- this.propertySource = undefined;
- this.selectedProperty = undefined;
-
- const toscaGetFunction1 = new ToscaGetFunction(undefined);
- toscaGetFunction1.functionType = this.toscaGetFunction.functionType;
- this.toscaGetFunctionForm.setValue(toscaGetFunction1);
- }
-
- private loadPropertyDropdownLabel(): void {
- if (!this.toscaGetFunction.functionType) {
- return;
- }
- if (this.isGetInputSelected()) {
- this.dropdownValuesLabel = this.translateService.translate('INPUT_DROPDOWN_LABEL');
- } else if (this.isGetPropertySelected()) {
- this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL');
- } else if (this.isGetAttributeSelected()) {
- this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_ATTRIBUTE_DROPDOWN_LABEL');
- }
- }
-
- private loadPropertyDropdownValues(onComplete?: () => any): void {
- if (!this.toscaGetFunction.functionType) {
- return;
- }
- this.resetPropertyDropdown();
- this.fillPropertyDropdownValues(onComplete);
- }
-
- private resetPropertyDropdown(): void {
- this.dropDownErrorMsg = undefined;
- this.selectedProperty = undefined;
- this.propertyDropdownList = [];
- }
-
- private fillPropertyDropdownValues(onComplete?: () => any): void {
- this.startLoading();
- const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable();
- propertiesObservable.subscribe( (response: ComponentGenericResponse) => {
- const properties: Array<PropertyBEModel | AttributeModel> = this.extractProperties(response);
- if (!properties || properties.length === 0) {
- const msgCode = this.getNotFoundMsgCode();
- this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
+ this.formGroup.valueChanges.subscribe(() => {
+ if (!this.isInitialized) {
return;
}
- this.addPropertiesToDropdown(properties);
- if (this.propertyDropdownList.length == 0) {
- const msgCode = this.getNotFoundMsgCode();
- this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
- }
- }, (error) => {
- console.error('An error occurred while loading properties.', error);
- this.stopLoading();
- }, () => {
- if (onComplete) {
- onComplete();
+ this.emitValidityChange();
+ if (this.formGroup.valid) {
+ this.onValidFunction.emit(this.toscaFunctionForm.value);
}
- this.stopLoading();
});
+ this.initToscaGetFunction();
+ this.emitValidityChange();
+ this.isInitialized = true;
}
- private getNotFoundMsgCode(): string {
- if (this.isGetInputSelected()) {
- return 'TOSCA_FUNCTION_NO_INPUT_FOUND';
- }
- if (this.isGetAttributeSelected()) {
- return 'TOSCA_FUNCTION_NO_ATTRIBUTE_FOUND';
- }
- if (this.isGetPropertySelected()) {
- return 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
- }
-
- return undefined;
- }
-
- private propertyTypeToString() {
- if (this.property.schemaType) {
- return `${this.property.type} of ${this.property.schemaType}`;
- }
- return this.property.type;
- }
-
- private extractProperties(componentGenericResponse: ComponentGenericResponse): Array<PropertyBEModel | AttributeModel> {
- if (this.isGetInputSelected()) {
- return componentGenericResponse.inputs;
- }
- if (this.isGetPropertySelected()) {
- if (this.propertySource === PropertySource.SELF) {
- return componentGenericResponse.properties;
- }
- const componentInstanceProperties: PropertyModel[] = componentGenericResponse.componentInstancesProperties[this.instanceNameAndIdMap.get(this.propertySource)];
- return this.removeSelectedProperty(componentInstanceProperties);
- }
- if (this.propertySource === PropertySource.SELF) {
- return componentGenericResponse.attributes;
- }
- return componentGenericResponse.componentInstancesAttributes[this.instanceNameAndIdMap.get(this.propertySource)];
- }
-
- private getPropertyObservable(): Observable<ComponentGenericResponse> {
- if (this.isGetInputSelected()) {
- return this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
- }
- if (this.isGetPropertySelected()) {
- if (this.propertySource === PropertySource.SELF) {
- return this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
- }
- return this.topologyTemplateService.getComponentInstanceProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
- }
- if (this.isGetAttributeSelected()) {
- if (this.propertySource === PropertySource.SELF) {
- return this.topologyTemplateService.findAllComponentAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
- }
- return this.topologyTemplateService.findAllComponentInstanceAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
- }
- }
-
- private removeSelectedProperty(componentInstanceProperties: PropertyModel[]): PropertyModel[] {
- if (!componentInstanceProperties) {
- return [];
- }
- return componentInstanceProperties.filter(property =>
- (property.uniqueId !== this.property.uniqueId) ||
- (property.uniqueId === this.property.uniqueId && property.resourceInstanceUniqueId !== this.property.parentUniqueId)
- );
- }
-
- private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue): void {
- this.propertyDropdownList.push(propertyDropdownValue);
- this.propertyDropdownList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
+ private validate() {
+ return (!this.toscaFunctionForm.value && !this.toscaFunctionTypeForm.value) || this.formGroup.valid;
}
- private addPropertiesToDropdown(properties: Array<PropertyBEModel | AttributeModel>): void {
- for (const property of properties) {
- if (this.hasSameType(property)) {
- this.addPropertyToDropdown({
- propertyName: property.name,
- propertyId: property.uniqueId,
- propertyLabel: property.name,
- propertyPath: [property.name]
- });
- } else if (this.isComplexType(property.type)) {
- this.fillPropertyDropdownWithMatchingChildProperties(property);
- }
- }
- }
-
- private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel | AttributeModel,
- parentPropertyList: Array<PropertyBEModel | AttributeModel> = []): void {
- const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
- if (!dataTypeFound || !dataTypeFound.properties) {
+ private initToscaGetFunction() {
+ if (!this.property.isToscaGetFunction()) {
return;
}
- parentPropertyList.push(inputProperty);
- dataTypeFound.properties.forEach(dataTypeProperty => {
- if (this.hasSameType(dataTypeProperty)) {
- this.addPropertyToDropdown({
- propertyName: dataTypeProperty.name,
- propertyId: parentPropertyList[0].uniqueId,
- propertyLabel: parentPropertyList.map(property => property.name).join('->') + '->' + dataTypeProperty.name,
- propertyPath: [...parentPropertyList.map(property => property.name), dataTypeProperty.name]
- });
- } else if (this.isComplexType(dataTypeProperty.type)) {
- this.fillPropertyDropdownWithMatchingChildProperties(dataTypeProperty, [...parentPropertyList])
- }
- });
+ this.toscaFunctionForm.setValue(this.property.toscaFunction);
+ this.toscaFunctionTypeForm.setValue(this.property.toscaFunction.type);
}
- private hasSameType(property: PropertyBEModel | AttributeModel) {
- if (this.typeHasSchema(this.property.type)) {
- if (!property.schema || !property.schema.property) {
- return false;
- }
- return property.type === this.property.type && this.property.schema.property.type === property.schema.property.type;
+ private loadToscaFunctions(): void {
+ this.toscaFunctions.push(ToscaFunctionType.GET_ATTRIBUTE);
+ this.toscaFunctions.push(ToscaFunctionType.GET_INPUT);
+ this.toscaFunctions.push(ToscaFunctionType.GET_PROPERTY);
+ if (this.property.type === PROPERTY_TYPES.STRING) {
+ this.toscaFunctions.push(ToscaFunctionType.CONCAT);
}
+ }
- return property.type === this.property.type;
+ private resetForm(): void {
+ this.formGroup.reset();
+ this.toscaFunction = undefined;
}
private isGetPropertySelected(): boolean {
- return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY;
+ return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_PROPERTY;
}
private isGetAttributeSelected(): boolean {
- return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_ATTRIBUTE;
+ return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_ATTRIBUTE;
}
private isGetInputSelected(): boolean {
- return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_INPUT;
+ return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_INPUT;
}
- private isComplexType(propertyType: string): boolean {
- return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
+ isConcatSelected(): boolean {
+ return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.CONCAT;
}
- private typeHasSchema(propertyType: string): boolean {
- return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
+ isGetFunctionSelected(): boolean {
+ return this.isGetInputSelected() || this.isGetPropertySelected() || this.isGetAttributeSelected();
}
- private stopLoading(): void {
- this.isLoading = false;
+ onClearValues() {
+ this.resetForm();
}
- private startLoading(): void {
- this.isLoading = true;
+ showClearButton(): boolean {
+ return this.allowClear && this.toscaFunctionTypeForm.value;
}
- showPropertyDropdown(): boolean {
- if (this.isGetPropertySelected() || this.isGetAttributeSelected()) {
- return this.toscaGetFunction.propertySource && !this.isLoading && !this.dropDownErrorMsg;
+ onConcatFunctionValidityChange(validationEvent: ToscaConcatFunctionValidationEvent) {
+ if (validationEvent.isValid) {
+ this.toscaFunctionForm.setValue(validationEvent.toscaConcatFunction);
+ } else {
+ this.toscaFunctionForm.setValue(undefined);
}
-
- return this.toscaGetFunction.functionType && !this.isLoading && !this.dropDownErrorMsg;
}
- onPropertySourceChange(): void {
- if (!this.toscaGetFunction.functionType || !this.propertySource) {
- return;
- }
- this.toscaGetFunction.propertyUniqueId = undefined;
- this.toscaGetFunction.propertyName = undefined;
- this.toscaGetFunction.propertyPathFromSource = undefined;
- if (this.propertySource === PropertySource.SELF) {
- this.setSelfPropertySource();
+ onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent) {
+ if (validationEvent.isValid) {
+ this.toscaFunctionForm.setValue(validationEvent.toscaGetFunction);
} else {
- this.toscaGetFunction.propertySource = PropertySource.INSTANCE;
- this.toscaGetFunction.sourceName = this.propertySource;
- this.toscaGetFunction.sourceUniqueId = this.instanceNameAndIdMap.get(this.propertySource);
+ this.toscaFunctionForm.setValue(undefined);
}
- this.toscaGetFunctionForm.setValue(this.toscaGetFunction);
- this.loadPropertyDropdown();
- }
-
- private setSelfPropertySource(): void {
- this.toscaGetFunction.propertySource = PropertySource.SELF;
- this.toscaGetFunction.sourceName = this.componentMetadata.name;
- this.toscaGetFunction.sourceUniqueId = this.componentMetadata.uniqueId;
- this.toscaGetFunctionForm.setValue(this.toscaGetFunction);
- }
-
- onPropertyChange(): void {
- this.toscaGetFunction.propertyUniqueId = this.selectedProperty.propertyId;
- this.toscaGetFunction.propertyName = this.selectedProperty.propertyName;
- this.toscaGetFunction.propertyPathFromSource = this.selectedProperty.propertyPath;
- this.toscaGetFunctionForm.setValue(this.toscaGetFunction);
- }
-
- onClearValues() {
- this.resetForm();
}
- showClearButton(): boolean {
- return this.allowClear && this.toscaGetFunction.functionType !== undefined;
- }
-
- showPropertySourceDropdown(): boolean {
- return this.isGetPropertySelected() || this.isGetAttributeSelected();
+ private emitValidityChange() {
+ const isValid = this.validate();
+ this.onValidityChange.emit({
+ isValid: isValid,
+ toscaFunction: isValid ? this.toscaFunctionForm.value : undefined
+ });
}
}
-export interface PropertyDropdownValue {
- propertyName: string;
- propertyId: string;
- propertyLabel: string;
- propertyPath: Array<string>;
-}
+export class ToscaFunctionValidationEvent {
+ isValid: boolean;
+ toscaFunction: ToscaFunction;
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts
index efe45c3d27..2db76cf544 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts
@@ -19,20 +19,25 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
-import { FormsModule } from '@angular/forms';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-elements.module';
import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module';
import { TranslateModule } from '../../../shared/translator/translate.module';
import { ToscaFunctionComponent } from './tosca-function.component';
import { SdcUiComponentsModule } from 'onap-ui-angular';
+import { ToscaGetFunctionComponent } from './tosca-get-function/tosca-get-function.component';
+import { ToscaConcatFunctionComponent } from './tosca-concat-function/tosca-concat-function.component';
@NgModule({
declarations: [
ToscaFunctionComponent,
+ ToscaGetFunctionComponent,
+ ToscaConcatFunctionComponent,
],
imports: [
CommonModule,
FormsModule,
+ ReactiveFormsModule,
FormElementsModule,
UiElementsModule,
TranslateModule,
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.html
new file mode 100644
index 0000000000..6f19d5eff4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.html
@@ -0,0 +1,38 @@
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Copyright (C) 2021 Nordix Foundation
+ ~ ================================================================================
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ ~ SPDX-License-Identifier: Apache-2.0
+ ~ ============LICENSE_END=========================================================
+ -->
+
+<div class="tosca-function">
+ <form class="w-sdc-form" [formGroup]="formGroup">
+ <div class="i-sdc-form-item" *ngIf="showPropertySourceDropdown()">
+ <label class="i-sdc-form-label required">{{'TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL' | translate}}</label>
+ <select formControlName="propertySource" (change)="onPropertySourceChange()">
+ <option *ngFor="let propertySource of propertySourceList"
+ [ngValue]="propertySource">{{propertySource}}</option>
+ </select>
+ </div>
+ <div *ngIf="showPropertyDropdown()" class="i-sdc-form-item">
+ <label class="i-sdc-form-label required">{{dropdownValuesLabel}}</label>
+ <select formControlName="selectedProperty">
+ <option *ngFor="let value of propertyDropdownList" [ngValue]="value">{{value.propertyLabel}}</option>
+ </select>
+ </div>
+ <div *ngIf="dropDownErrorMsg">{{dropDownErrorMsg}}</div>
+ </form>
+ <loader [display]="isLoading" [size]="'medium'" [relative]="true"></loader>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.less
new file mode 100644
index 0000000000..b14edc25e9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.less
@@ -0,0 +1,21 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.spec.ts
new file mode 100644
index 0000000000..6c7d986150
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.spec.ts
@@ -0,0 +1,74 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {ToscaGetFunctionComponent} from './tosca-get-function.component';
+import {FormsModule, ReactiveFormsModule} from "@angular/forms";
+import {TranslateModule} from "../../../../shared/translator/translate.module";
+import {UiElementsModule} from "../../../../components/ui/ui-elements.module";
+import {TopologyTemplateService} from "../../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../../../workspace/workspace.service";
+import {PropertiesService} from "../../../../services/properties.service";
+import {DataTypeService} from "../../../../services/data-type.service";
+import {TranslateService} from "../../../../shared/translator/translate.service";
+import {ComponentMetadata} from "../../../../../models/component-metadata";
+
+describe('ToscaGetFunctionComponent', () => {
+ let component: ToscaGetFunctionComponent;
+ let fixture: ComponentFixture<ToscaGetFunctionComponent>;
+ let topologyTemplateServiceMock: Partial<TopologyTemplateService>;
+ let workspaceServiceMock: Partial<WorkspaceService> = {
+ metadata: new ComponentMetadata()
+ };
+ let propertiesServiceMock: Partial<PropertiesService>;
+ let dataTypeServiceMock: Partial<DataTypeService>;
+ let translateServiceMock: Partial<TranslateService>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ToscaGetFunctionComponent],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ TranslateModule,
+ UiElementsModule
+ ],
+ providers: [
+ {provide: TopologyTemplateService, useValue: topologyTemplateServiceMock},
+ {provide: WorkspaceService, useValue: workspaceServiceMock},
+ {provide: PropertiesService, useValue: propertiesServiceMock},
+ {provide: DataTypeService, useValue: dataTypeServiceMock},
+ {provide: TranslateService, useValue: translateServiceMock}
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ToscaGetFunctionComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts
new file mode 100644
index 0000000000..8f50cc14cd
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts
@@ -0,0 +1,443 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
+import {AttributeModel, ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel} from 'app/models';
+import {TopologyTemplateService} from "../../../../services/component-services/topology-template.service";
+import {WorkspaceService} from "../../../workspace/workspace.service";
+import {PropertiesService} from "../../../../services/properties.service";
+import {PROPERTY_DATA, PROPERTY_TYPES} from "../../../../../utils/constants";
+import {DataTypeService} from "../../../../services/data-type.service";
+import {ToscaGetFunctionType} from "../../../../../models/tosca-get-function-type";
+import {TranslateService} from "../../../../shared/translator/translate.service";
+import {ComponentGenericResponse} from '../../../../services/responses/component-generic-response';
+import {Observable} from 'rxjs/Observable';
+import {PropertySource} from "../../../../../models/property-source";
+import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
+import {ToscaGetFunction} from "../../../../../models/tosca-get-function";
+import {FormControl, FormGroup, Validators} from "@angular/forms";
+import {ToscaGetFunctionTypeConverter} from "../../../../../models/tosca-get-function-type-converter";
+
+@Component({
+ selector: 'app-tosca-get-function',
+ templateUrl: './tosca-get-function.component.html',
+ styleUrls: ['./tosca-get-function.component.less']
+})
+export class ToscaGetFunctionComponent implements OnInit, OnChanges {
+
+ @Input() property: PropertyBEModel;
+ @Input() toscaGetFunction: ToscaGetFunction;
+ @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
+ @Input() functionType: ToscaGetFunctionType;
+ @Output() onValidFunction: EventEmitter<ToscaGetFunction> = new EventEmitter<ToscaGetFunction>();
+ @Output() onValidityChange: EventEmitter<ToscaGetFunctionValidationEvent> = new EventEmitter<ToscaGetFunctionValidationEvent>();
+
+ formGroup: FormGroup = new FormGroup({
+ 'selectedProperty': new FormControl(undefined, Validators.required),
+ 'propertySource': new FormControl(undefined, Validators.required)
+ });
+
+ isLoading: boolean = false;
+ propertyDropdownList: Array<PropertyDropdownValue> = [];
+ propertySourceList: Array<string> = [];
+ instanceNameAndIdMap: Map<string, string> = new Map<string, string>();
+ dropdownValuesLabel: string;
+ dropDownErrorMsg: string;
+
+ private isInitialized: boolean = false;
+ private componentMetadata: ComponentMetadata;
+
+ constructor(private topologyTemplateService: TopologyTemplateService,
+ private workspaceService: WorkspaceService,
+ private propertiesService: PropertiesService,
+ private dataTypeService: DataTypeService,
+ private translateService: TranslateService) {
+ }
+
+ ngOnInit(): void {
+ this.componentMetadata = this.workspaceService.metadata;
+ this.formGroup.valueChanges.subscribe(() => {
+ if (!this.isInitialized) {
+ return;
+ }
+ this.onValidityChange.emit({
+ isValid: this.formGroup.valid,
+ toscaGetFunction: this.formGroup.valid ? this.buildGetFunctionFromForm() : undefined
+ });
+ if (this.formGroup.valid) {
+ this.onValidFunction.emit(this.buildGetFunctionFromForm());
+ }
+ });
+ this.loadPropertySourceDropdown();
+ this.loadPropertyDropdownLabel();
+ this.initToscaGetFunction().subscribe(() => {
+ this.isInitialized = true;
+ });
+
+ }
+
+ ngOnChanges(_changes: SimpleChanges): void {
+ if (!this.isInitialized) {
+ return;
+ }
+ this.isInitialized = false;
+ this.resetForm();
+ this.loadPropertySourceDropdown();
+ this.loadPropertyDropdownLabel();
+ this.initToscaGetFunction().subscribe(() => {
+ this.isInitialized = true;
+ });
+ }
+
+ private initToscaGetFunction(): Observable<void> {
+ return new Observable(subscriber => {
+ if (!this.toscaGetFunction) {
+ if (this.isGetInput()) {
+ this.setSelfPropertySource();
+ this.loadPropertyDropdown();
+ }
+ subscriber.next();
+ return;
+ }
+ if (this.toscaGetFunction.propertySource == PropertySource.SELF) {
+ this.propertySource.setValue(PropertySource.SELF);
+ } else if (this.toscaGetFunction.propertySource == PropertySource.INSTANCE) {
+ this.propertySource
+ .setValue(this.propertySourceList.find(source => this.toscaGetFunction.sourceName === source));
+ }
+ if (this.propertySource.valid) {
+ this.loadPropertyDropdown(() => {
+ this.selectedProperty
+ .setValue(this.propertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.propertyName));
+ subscriber.next();
+ });
+ } else {
+ subscriber.next();
+ }
+ });
+ }
+
+ private buildGetFunctionFromForm() {
+ const toscaGetFunction = new ToscaGetFunction();
+ toscaGetFunction.type = ToscaGetFunctionTypeConverter.convertToToscaFunctionType(this.functionType);
+ toscaGetFunction.functionType = this.functionType;
+ const propertySource = this.propertySource.value;
+ if (this.isPropertySourceSelf()) {
+ toscaGetFunction.propertySource = propertySource
+ toscaGetFunction.sourceName = this.componentMetadata.name;
+ toscaGetFunction.sourceUniqueId = this.componentMetadata.uniqueId;
+ } else {
+ toscaGetFunction.propertySource = PropertySource.INSTANCE;
+ toscaGetFunction.sourceName = propertySource;
+ toscaGetFunction.sourceUniqueId = this.instanceNameAndIdMap.get(propertySource);
+ }
+
+ const selectedProperty: PropertyDropdownValue = this.selectedProperty.value;
+ toscaGetFunction.propertyUniqueId = selectedProperty.propertyId;
+ toscaGetFunction.propertyName = selectedProperty.propertyName;
+ toscaGetFunction.propertyPathFromSource = selectedProperty.propertyPath;
+
+ return toscaGetFunction;
+ }
+
+ private loadPropertySourceDropdown(): void {
+ if (this.isGetInput()) {
+ return;
+ }
+ this.propertySourceList = [];
+ this.propertySourceList.push(PropertySource.SELF);
+ this.componentInstanceMap.forEach((value, key) => {
+ const instanceName = value.name;
+ this.instanceNameAndIdMap.set(instanceName, key);
+ if (instanceName !== PropertySource.SELF) {
+ this.addToPropertySource(instanceName);
+ }
+ });
+ }
+
+ private addToPropertySource(source: string): void {
+ this.propertySourceList.push(source);
+ this.propertySourceList.sort((a, b) => {
+ if (a === PropertySource.SELF) {
+ return -1;
+ } else if (b === PropertySource.SELF) {
+ return 1;
+ }
+
+ return a.localeCompare(b);
+ });
+ }
+
+ private loadPropertyDropdown(onComplete?: () => any): void {
+ this.loadPropertyDropdownLabel();
+ this.loadPropertyDropdownValues(onComplete);
+ }
+
+ private resetForm(): void {
+ this.formGroup.reset();
+ }
+
+ private loadPropertyDropdownLabel(): void {
+ if (!this.functionType) {
+ return;
+ }
+ if (this.isGetInput()) {
+ this.dropdownValuesLabel = this.translateService.translate('INPUT_DROPDOWN_LABEL');
+ } else if (this.isGetProperty()) {
+ this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL');
+ } else if (this.isGetAttribute()) {
+ this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_ATTRIBUTE_DROPDOWN_LABEL');
+ }
+ }
+
+ private loadPropertyDropdownValues(onComplete?: () => any): void {
+ if (!this.functionType) {
+ return;
+ }
+ this.resetPropertyDropdown();
+ this.fillPropertyDropdownValues(onComplete);
+ }
+
+ private resetPropertyDropdown(): void {
+ this.dropDownErrorMsg = undefined;
+ this.selectedProperty.reset();
+ this.propertyDropdownList = [];
+ }
+
+ private fillPropertyDropdownValues(onComplete?: () => any): void {
+ this.startLoading();
+ const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable();
+ propertiesObservable.subscribe( (response: ComponentGenericResponse) => {
+ const properties: Array<PropertyBEModel | AttributeModel> = this.extractProperties(response);
+ if (!properties || properties.length === 0) {
+ const msgCode = this.getNotFoundMsgCode();
+ this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
+ return;
+ }
+ this.addPropertiesToDropdown(properties);
+ if (this.propertyDropdownList.length == 0) {
+ const msgCode = this.getNotFoundMsgCode();
+ this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
+ }
+ }, (error) => {
+ console.error('An error occurred while loading properties.', error);
+ this.stopLoading();
+ }, () => {
+ if (onComplete) {
+ onComplete();
+ }
+ this.stopLoading();
+ });
+ }
+
+ private getNotFoundMsgCode(): string {
+ if (this.isGetInput()) {
+ return 'TOSCA_FUNCTION_NO_INPUT_FOUND';
+ }
+ if (this.isGetAttribute()) {
+ return 'TOSCA_FUNCTION_NO_ATTRIBUTE_FOUND';
+ }
+ if (this.isGetProperty()) {
+ return 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
+ }
+
+ return undefined;
+ }
+
+ private propertyTypeToString() {
+ if (this.property.schemaType) {
+ return `${this.property.type} of ${this.property.schemaType}`;
+ }
+ return this.property.type;
+ }
+
+ private extractProperties(componentGenericResponse: ComponentGenericResponse): Array<PropertyBEModel | AttributeModel> {
+ if (this.isGetInput()) {
+ return componentGenericResponse.inputs;
+ }
+ const propertySource = this.propertySource.value;
+ if (this.isGetProperty()) {
+ if (this.isPropertySourceSelf()) {
+ return componentGenericResponse.properties;
+ }
+ const componentInstanceProperties: PropertyModel[] = componentGenericResponse.componentInstancesProperties[this.instanceNameAndIdMap.get(propertySource)];
+ return this.removeSelectedProperty(componentInstanceProperties);
+ }
+ if (this.isPropertySourceSelf()) {
+ return componentGenericResponse.attributes;
+ }
+ return componentGenericResponse.componentInstancesAttributes[this.instanceNameAndIdMap.get(propertySource)];
+ }
+
+ private isPropertySourceSelf() {
+ return this.propertySource.value === PropertySource.SELF;
+ }
+
+ private getPropertyObservable(): Observable<ComponentGenericResponse> {
+ if (this.isGetInput()) {
+ return this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+ }
+ if (this.isGetProperty()) {
+ if (this.isPropertySourceSelf()) {
+ return this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+ }
+ return this.topologyTemplateService.getComponentInstanceProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+ }
+ if (this.isGetAttribute()) {
+ if (this.isPropertySourceSelf()) {
+ return this.topologyTemplateService.findAllComponentAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+ }
+ return this.topologyTemplateService.findAllComponentInstanceAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+ }
+ }
+
+ private removeSelectedProperty(componentInstanceProperties: PropertyModel[]): PropertyModel[] {
+ if (!componentInstanceProperties) {
+ return [];
+ }
+ return componentInstanceProperties.filter(property =>
+ (property.uniqueId !== this.property.uniqueId) ||
+ (property.uniqueId === this.property.uniqueId && property.resourceInstanceUniqueId !== this.property.parentUniqueId)
+ );
+ }
+
+ private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue): void {
+ this.propertyDropdownList.push(propertyDropdownValue);
+ this.propertyDropdownList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
+ }
+
+ private addPropertiesToDropdown(properties: Array<PropertyBEModel | AttributeModel>): void {
+ for (const property of properties) {
+ if (this.hasSameType(property)) {
+ this.addPropertyToDropdown({
+ propertyName: property.name,
+ propertyId: property.uniqueId,
+ propertyLabel: property.name,
+ propertyPath: [property.name]
+ });
+ } else if (this.isComplexType(property.type)) {
+ this.fillPropertyDropdownWithMatchingChildProperties(property);
+ }
+ }
+ }
+
+ private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel | AttributeModel,
+ parentPropertyList: Array<PropertyBEModel | AttributeModel> = []): void {
+ const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
+ if (!dataTypeFound || !dataTypeFound.properties) {
+ return;
+ }
+ parentPropertyList.push(inputProperty);
+ dataTypeFound.properties.forEach(dataTypeProperty => {
+ if (this.hasSameType(dataTypeProperty)) {
+ this.addPropertyToDropdown({
+ propertyName: dataTypeProperty.name,
+ propertyId: parentPropertyList[0].uniqueId,
+ propertyLabel: parentPropertyList.map(property => property.name).join('->') + '->' + dataTypeProperty.name,
+ propertyPath: [...parentPropertyList.map(property => property.name), dataTypeProperty.name]
+ });
+ } else if (this.isComplexType(dataTypeProperty.type)) {
+ this.fillPropertyDropdownWithMatchingChildProperties(dataTypeProperty, [...parentPropertyList])
+ }
+ });
+ }
+
+ private hasSameType(property: PropertyBEModel | AttributeModel) {
+ if (this.typeHasSchema(this.property.type)) {
+ if (!property.schema || !property.schema.property) {
+ return false;
+ }
+ return property.type === this.property.type && this.property.schema.property.type === property.schema.property.type;
+ }
+
+ return property.type === this.property.type;
+ }
+
+ private isGetProperty(): boolean {
+ return this.functionType === ToscaGetFunctionType.GET_PROPERTY;
+ }
+
+ private isGetAttribute(): boolean {
+ return this.functionType === ToscaGetFunctionType.GET_ATTRIBUTE;
+ }
+
+ private isGetInput(): boolean {
+ return this.functionType === ToscaGetFunctionType.GET_INPUT;
+ }
+
+ private isComplexType(propertyType: string): boolean {
+ return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
+ }
+
+ private typeHasSchema(propertyType: string): boolean {
+ return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
+ }
+
+ private stopLoading(): void {
+ this.isLoading = false;
+ }
+
+ private startLoading(): void {
+ this.isLoading = true;
+ }
+
+ showPropertyDropdown(): boolean {
+ if (this.isGetProperty() || this.isGetAttribute()) {
+ return this.propertySource.valid && !this.isLoading && !this.dropDownErrorMsg;
+ }
+
+ return this.functionType && !this.isLoading && !this.dropDownErrorMsg;
+ }
+
+ onPropertySourceChange(): void {
+ if (!this.functionType || !this.propertySource.valid) {
+ return;
+ }
+ this.loadPropertyDropdown();
+ }
+
+ showPropertySourceDropdown(): boolean {
+ return this.isGetProperty() || this.isGetAttribute();
+ }
+
+ private setSelfPropertySource(): void {
+ this.propertySource.setValue(PropertySource.SELF);
+ }
+
+ private get propertySource(): FormControl {
+ return this.formGroup.get('propertySource') as FormControl;
+ }
+
+ private get selectedProperty(): FormControl {
+ return this.formGroup.get('selectedProperty') as FormControl;
+ }
+
+}
+
+export interface PropertyDropdownValue {
+ propertyName: string;
+ propertyId: string;
+ propertyLabel: string;
+ propertyPath: Array<string>;
+}
+
+export interface ToscaGetFunctionValidationEvent {
+ isValid: boolean,
+ toscaGetFunction: ToscaGetFunction,
+} \ No newline at end of file