Allow to edit or clear a TOSCA function value 25/129425/3
authorandre.schmid <andre.schmid@est.tech>
Mon, 30 May 2022 15:21:52 +0000 (16:21 +0100)
committerMichael Morris <michael.morris@est.tech>
Tue, 7 Jun 2022 13:10:34 +0000 (13:10 +0000)
In the properties assignment view, when a property that has a TOSCA
function value is selected, a button "Clear Value" will show allowing
to clear the property value.
This behaviour was changed to show the TOSCA function button, which,
when clicked, will open the TOSCA function modal with the function
values loaded, allowing to edit or clear the existing value.

Change-Id: Ic365f81921052aa2c5737d2a1ac956a3fb745db6
Issue-ID: SDC-4028
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-ui/src/app/models/tosca-get-function.ts
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.less
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
catalog-ui/src/assets/languages/en_US.json

index 0fe0831..6d5642e 100644 (file)
@@ -30,4 +30,19 @@ export class ToscaGetFunction {
     sourceName: string;
     functionType: ToscaGetFunctionType;
     propertyPathFromSource: Array<string>;
+
+    constructor(toscaGetFunction: ToscaGetFunction) {
+        if (!toscaGetFunction) {
+            return;
+        }
+        this.propertyUniqueId = toscaGetFunction.propertyUniqueId;
+        this.propertyName = toscaGetFunction.propertyName;
+        this.propertySource = toscaGetFunction.propertySource;
+        this.sourceUniqueId = toscaGetFunction.sourceUniqueId;
+        this.sourceName = toscaGetFunction.sourceName;
+        this.functionType = toscaGetFunction.functionType;
+        if (toscaGetFunction.propertyPathFromSource) {
+            this.propertyPathFromSource = [...toscaGetFunction.propertyPathFromSource];
+        }
+    }
 }
\ No newline at end of file
index 10273e2..6bb2e9d 100644 (file)
@@ -37,6 +37,7 @@ import {SdcUiComponentsModule} from "onap-ui-angular";
 import {ModalFormsModule} from "app/ng2/components/ui/forms/modal-forms.module";
 import {HierarchyNavigationModule} from "../../components/logic/hierarchy-navigtion/hierarchy-navigation.module";
 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
+import {TranslateModule} from '../../shared/translator/translate.module';
 
 @NgModule({
   declarations: [
@@ -53,7 +54,8 @@ import {PropertyCreatorComponent} from "./property-creator/property-creator.comp
     HierarchyNavigationModule,
     UiElementsModule,
     SdcUiComponentsModule,
-    ModalFormsModule
+    ModalFormsModule,
+    TranslateModule
   ],
 
   entryComponents: [PropertiesAssignmentComponent],
index c1a1ae5..c01cf95 100644 (file)
@@ -79,7 +79,7 @@
                         *ngIf="isPropertiesTabSelected && !isSelf()"
                         [disabled]="checkedPropertiesCount != 1 || isReadonly || hasChangedData"
                         class="tlv-btn blue declare-button"
-                        data-tests-id="declare-button select-tosca-function">{{btnToscaFunctionText}}</button>
+                        data-tests-id="declare-button select-tosca-function">{{'TOSCA_FUNCTION_LABEL' | translate}}</button>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData || isSelf()" (click)="declarePropertiesToPolicies()" data-tests-id="declare-button declare-policy">Declare Policy</button>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || checkedChildPropertiesCount || isReadonly || hasChangedData" (click)="declareListProperties()" data-tests-id="declare-but($event)ton declare-list-input">Create List Input</button>
index 6584b47..7feea50 100644 (file)
@@ -118,7 +118,6 @@ export class PropertiesAssignmentComponent {
     serviceBePropertiesMap: InstanceBePropertiesMap;
     serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
     selectedInstance_FlattenCapabilitiesList: Capability[];
-    btnToscaFunctionText: string;
 
     @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
     @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
@@ -156,7 +155,6 @@ export class PropertiesAssignmentComponent {
 
     ngOnInit() {
         console.debug("==>" + this.constructor.name + ": ngOnInit");
-        this.btnToscaFunctionText = this.translateService.translate('TOSCA_FUNCTION_LABEL');
         this.loadingInputs = true;
         this.loadingPolicies = true;
         this.loadingInstances = true;
@@ -518,11 +516,6 @@ export class PropertiesAssignmentComponent {
         if (!selectedInstanceData) {
             return;
         }
-        const property: PropertyBEModel = this.buildCheckedInstanceProperty();
-        if (property.isToscaGetFunction()) {
-            this.clearCheckedInstancePropertyValue();
-            return;
-        }
         this.openToscaGetFunctionModal();
     }
 
@@ -543,26 +536,31 @@ export class PropertiesAssignmentComponent {
     }
 
     private openToscaGetFunctionModal() {
-        const modalTitle = 'Set value using TOSCA functions';
+        const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
+        const modalButtons = [];
+        modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
+            () => {
+                const toscaGetFunction: ToscaGetFunction = modal.instance.dynamicContent.instance.toscaGetFunction;
+                if (toscaGetFunction.functionType) {
+                    this.updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction);
+                } else {
+                    this.clearCheckedInstancePropertyValue();
+                }
+                modal.instance.close();
+            }
+        ));
+        const checkedInstanceProperty = this.buildCheckedInstanceProperty();
+        modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
+            modal.instance.close();
+        }));
         const modal = this.modalService.createCustomModal(new ModalModel(
             'sm',
             modalTitle,
             null,
-            [
-                new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
-                    () => {
-                        const toscaGetFunction: ToscaGetFunction = modal.instance.dynamicContent.instance.toscaGetFunction;
-                        this.updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction);
-                        modal.instance.close();
-                    }
-                ),
-                new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
-                    modal.instance.close();
-                }),
-            ],
+            modalButtons,
             null /* type */
         ));
-        const checkedInstanceProperty = this.buildCheckedInstanceProperty();
+
         this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
             'property': checkedInstanceProperty,
             'componentInstanceMap': this.componentInstanceMap
@@ -610,25 +608,6 @@ export class PropertiesAssignmentComponent {
             console.error(errorMsg, error);
         }, () => {
             this.loadingProperties = false;
-            this.btnToscaFunctionText = this.translateService.translate('TOSCA_FUNCTION_LABEL');
-        });
-    }
-
-    selectInputBtnLabel = () => {
-        let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
-        angular.forEach(instancesIds, (instanceId: string): void => {
-            let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
-            angular.forEach(checkedProperties, (property: PropertyBEModel) => {
-                if(this.checkedPropertiesCount == 1) {
-                    if (property.isToscaGetFunction()) {
-                        this.btnToscaFunctionText = this.translateService.translate('CLEAR_VALUE_LABEL');
-                    } else {
-                        this.btnToscaFunctionText = this.translateService.translate('TOSCA_FUNCTION_LABEL');
-                    }
-                } else {
-                    this.btnToscaFunctionText = this.translateService.translate('TOSCA_FUNCTION_LABEL');
-                }
-            });
         });
     }
 
@@ -1106,7 +1085,6 @@ export class PropertiesAssignmentComponent {
     updateCheckedPropertyCount = (increment: boolean): void => {
         this.checkedPropertiesCount += (increment) ? 1 : -1;
         console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
-        this.selectInputBtnLabel();
     };
 
     updateCheckedChildPropertyCount = (increment: boolean): void => {
index 1f81ebe..f0db645 100644 (file)
@@ -21,7 +21,7 @@
   <loader [display]="isLoading" [loaderDelay]="500" [relative]="true" [size]="'large'"></loader>
   <form class="w-sdc-form">
     <div class="i-sdc-form-item">
-      <label class="i-sdc-form-label required">{{'TOSCA_FUNCTION_LABEL' | translate}}</label>
+      <label class="i-sdc-form-label">{{'TOSCA_FUNCTION_LABEL' | translate}}</label>
       <select [(ngModel)]="toscaGetFunction.functionType" (change)="onToscaFunctionChange()" name="toscaFunctionType">
         <option *ngFor="let toscaFunction of toscaFunctions"
                 [ngValue]="toscaFunction">{{toscaFunction | lowercase}}</option>
@@ -41,6 +41,9 @@
       </select>
     </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>
   <loader [display]="isLoading" [size]="'medium'" [relative]="true"></loader>
 </div>
index e1e9b0d..7857771 100644 (file)
 
 @import '../../../../../assets/styles/variables.less';
 
-.input-list {
-    font-family: @font-opensans-regular;
-    user-select: none;
-    padding-top: 12px;
-    padding-bottom: 20px;
-
-    .i-sdc-form-label {
-        font-size: 12px;
-    }
-
-    .w-sdc-form .i-sdc-form-item {
-        margin-bottom: 15px;
-    }
-
-    .side-by-side {
-        display: flex;
-
-        .i-sdc-form-item {
-            flex-basis: 100%;
-        }
+.button-container {
+    display: flex;
+    padding: 5px 5px;
+    flex-grow: 1;
+    clear: both;
+    justify-content: flex-end;
+    border-radius: 4px;
+    button {
+        margin: 0 12px 0 6px;
     }
 }
index 054a21f..6b0cdd0 100644 (file)
@@ -17,7 +17,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-import {Component, Input} from '@angular/core';
+import {Component, Input, OnInit} from '@angular/core';
 import {ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel} from 'app/models';
 import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
 import {WorkspaceService} from "../../workspace/workspace.service";
@@ -37,10 +37,11 @@ import {ToscaGetFunction} from "../../../../models/tosca-get-function";
     templateUrl: './tosca-function.component.html',
     styleUrls: ['./tosca-function.component.less'],
 })
-export class ToscaFunctionComponent {
+export class ToscaFunctionComponent implements OnInit {
 
     @Input() property: PropertyBEModel;
     @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
+    @Input() allowClear: boolean = true;
 
     TOSCA_FUNCTION_GET_PROPERTY = ToscaGetFunctionType.GET_PROPERTY;
 
@@ -53,7 +54,7 @@ export class ToscaFunctionComponent {
     dropdownValuesLabel: string;
     dropDownErrorMsg: string;
     propertySource: string
-    toscaGetFunction: ToscaGetFunction = new ToscaGetFunction();
+    toscaGetFunction: ToscaGetFunction = new ToscaGetFunction(undefined);
 
     private componentMetadata: ComponentMetadata;
 
@@ -64,10 +65,31 @@ export class ToscaFunctionComponent {
                 private translateService: TranslateService) {
     }
 
-    ngOnInit() {
+    ngOnInit(): void {
         this.componentMetadata = this.workspaceService.metadata;
         this.loadToscaFunctions();
         this.loadPropertySourceDropdown();
+        this.initToscaGetFunction();
+    }
+
+    private initToscaGetFunction(): void {
+        if (!this.property.isToscaGetFunction()) {
+            return;
+        }
+        this.toscaGetFunction = new ToscaGetFunction(this.property.toscaGetFunction);
+        if (this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY) {
+            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 {
@@ -75,7 +97,7 @@ export class ToscaFunctionComponent {
         this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY);
     }
 
-    private loadPropertySourceDropdown() {
+    private loadPropertySourceDropdown(): void {
         this.propertySourceList.push(PropertySource.SELF);
         this.componentInstanceMap.forEach((value, key) => {
             const instanceName = value.name;
@@ -86,7 +108,7 @@ export class ToscaFunctionComponent {
         });
     }
 
-    private addToPropertySource(source: string) {
+    private addToPropertySource(source: string): void {
         this.propertySourceList.push(source);
         this.propertySourceList.sort((a, b) => {
             if (a === PropertySource.SELF) {
@@ -100,6 +122,25 @@ export class ToscaFunctionComponent {
     }
 
     onToscaFunctionChange(): void {
+        this.resetPropertySource();
+        if (this.isGetInputSelected()) {
+            this.setSelfPropertySource();
+            this.loadPropertyDropdown();
+        }
+    }
+
+    private loadPropertyDropdown(onComplete: () => any = () => {}): void  {
+        this.loadPropertyDropdownLabel();
+        this.loadPropertyDropdownValues(onComplete);
+    }
+
+    private resetForm(): void {
+        this.toscaGetFunction = new ToscaGetFunction(undefined);
+        this.propertySource = undefined;
+        this.selectedProperty = undefined;
+    }
+
+    private resetPropertySource(): void {
         this.toscaGetFunction.propertyUniqueId = undefined;
         this.toscaGetFunction.propertyName = undefined;
         this.toscaGetFunction.propertySource = undefined;
@@ -107,14 +148,10 @@ export class ToscaFunctionComponent {
         this.toscaGetFunction.sourceName = undefined;
         this.toscaGetFunction.propertyPathFromSource = undefined;
         this.propertySource = undefined;
-        if (this.isGetInputSelected()) {
-            this.setSelfPropertySource();
-            this.loadDropdownValueLabel();
-            this.loadDropdownValues();
-        }
+        this.selectedProperty = undefined;
     }
 
-    private loadDropdownValueLabel(): void {
+    private loadPropertyDropdownLabel(): void {
         if (!this.toscaGetFunction.functionType) {
             return;
         }
@@ -125,20 +162,21 @@ export class ToscaFunctionComponent {
         }
     }
 
-    private loadDropdownValues(): void {
+    private loadPropertyDropdownValues(onComplete: () => any = () => {}): void {
         if (!this.toscaGetFunction.functionType) {
             return;
         }
-        this.resetDropDown();
-        this.loadPropertiesInDropdown();
+        this.resetPropertyDropdown();
+        this.fillPropertyDropdownValues(onComplete);
     }
 
-    private resetDropDown() {
+    private resetPropertyDropdown(): void {
         this.dropDownErrorMsg = undefined;
+        this.selectedProperty = undefined;
         this.propertyDropdownList = [];
     }
 
-    private loadPropertiesInDropdown() {
+    private fillPropertyDropdownValues(onComplete: () => any = () => {}): void {
         this.startLoading();
         const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable();
         propertiesObservable.subscribe( (response: ComponentGenericResponse) => {
@@ -156,6 +194,7 @@ export class ToscaFunctionComponent {
         }, (error) => {
             console.error('An error occurred while loading properties.', error);
         }, () => {
+            onComplete();
             this.stopLoading();
         });
     }
@@ -195,12 +234,12 @@ export class ToscaFunctionComponent {
         );
     }
 
-    private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue) {
+    private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue): void {
         this.propertyDropdownList.push(propertyDropdownValue);
         this.propertyDropdownList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
     }
 
-    private addPropertiesToDropdown(properties: PropertyBEModel[]) {
+    private addPropertiesToDropdown(properties: PropertyBEModel[]): void {
         for (const property of properties) {
             if (this.property.type === property.type) {
                 this.addPropertyToDropdown({
@@ -215,7 +254,7 @@ export class ToscaFunctionComponent {
         }
     }
 
-    private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel, parentPropertyList: Array<PropertyBEModel> = []) {
+    private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel, parentPropertyList: Array<PropertyBEModel> = []): void {
         const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
         if (!dataTypeFound || !dataTypeFound.properties) {
             return;
@@ -235,23 +274,23 @@ export class ToscaFunctionComponent {
         });
     }
 
-    private isGetPropertySelected() {
+    private isGetPropertySelected(): boolean {
         return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY;
     }
 
-    private isGetInputSelected() {
+    private isGetInputSelected(): boolean {
         return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_INPUT;
     }
 
-    private isComplexType(propertyType: string) {
+    private isComplexType(propertyType: string): boolean {
         return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
     }
 
-    private stopLoading() {
+    private stopLoading(): void {
         this.isLoading = false;
     }
 
-    private startLoading() {
+    private startLoading(): void {
         this.isLoading = true;
     }
 
@@ -263,7 +302,7 @@ export class ToscaFunctionComponent {
         return this.toscaGetFunction.functionType && !this.isLoading && !this.dropDownErrorMsg;
     }
 
-    onPropertySourceChange() {
+    onPropertySourceChange(): void {
         if (!this.toscaGetFunction.functionType || !this.propertySource) {
             return;
         }
@@ -277,23 +316,28 @@ export class ToscaFunctionComponent {
             this.toscaGetFunction.sourceName = this.propertySource;
             this.toscaGetFunction.sourceUniqueId = this.instanceNameAndIdMap.get(this.propertySource);
         }
-        this.loadDropdownValueLabel();
-        this.resetDropDown();
-        this.loadPropertiesInDropdown();
+        this.loadPropertyDropdown();
     }
 
-    private setSelfPropertySource() {
+    private setSelfPropertySource(): void {
         this.toscaGetFunction.propertySource = PropertySource.SELF;
         this.toscaGetFunction.sourceName = this.componentMetadata.name;
         this.toscaGetFunction.sourceUniqueId = this.componentMetadata.uniqueId;
     }
 
-    onPropertyChange() {
+    onPropertyChange(): void {
         this.toscaGetFunction.propertyUniqueId = this.selectedProperty.propertyId;
         this.toscaGetFunction.propertyName = this.selectedProperty.propertyName;
         this.toscaGetFunction.propertyPathFromSource = this.selectedProperty.propertyPath;
     }
 
+    onClearValues() {
+        this.resetForm();
+    }
+
+    showClearButton(): boolean {
+        return this.allowClear && this.toscaGetFunction.functionType !== undefined;
+    }
 }
 
 export interface PropertyDropdownValue {
index d869a43..7225a1d 100644 (file)
   "=========== PROPERTIES ASSIGNMENT TOSCA FUNCTION BUTTON ===========": "",
   "TOSCA_FUNCTION_LABEL": "TOSCA function",
   "TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL": "Property Source",
-  "CLEAR_VALUE_LABEL": "Clear Value",
+  "TOSCA_FUNCTION_CLEAR_VALUE_BUTTON": "Clear Value",
+  "TOSCA_FUNCTION_MODAL_TITLE": "Set value using TOSCA functions",
   "INPUT_DROPDOWN_LABEL": "Input",
   "TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL": "Property",
   "TOSCA_FUNCTION_NO_INPUT_FOUND": "No input found with type {{type}}",