diff options
author | JvD_Ericsson <jeff.van.dam@est.tech> | 2023-03-31 14:42:07 +0100 |
---|---|---|
committer | JEFF VAN DAM <jeff.van.dam@est.tech> | 2023-04-13 15:35:54 +0000 |
commit | b6c9ed78e512e2d96f1725ca3748a5f02b31e7df (patch) | |
tree | 9723706e738bb041f339810cc233e2307d0c9018 /catalog-ui/src/app/ng2 | |
parent | b06691c5ed1fb02760a6440383dd40ec4894a9e5 (diff) |
UI support for custom functions
Issue-ID: SDC-4466
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I8ff794be8783dc31efecbd1f6abe2efefec6b819
Diffstat (limited to 'catalog-ui/src/app/ng2')
9 files changed, 402 insertions, 2 deletions
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 index 199f73349e..65e6339a7b 100644 --- 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 @@ -22,6 +22,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ToscaConcatFunctionComponent} from './tosca-concat-function.component'; +import {ToscaCustomFunctionComponent} from '../tosca-custom-function/tosca-custom-function.component'; import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import {ToscaFunctionComponent} from "../tosca-function.component"; import {TranslateModule} from "../../../../shared/translator/translate.module"; @@ -35,7 +36,7 @@ describe('ToscaConcatFunctionComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ToscaConcatFunctionComponent, ToscaFunctionComponent, ToscaGetFunctionComponent, YamlFunctionComponent], + declarations: [ToscaConcatFunctionComponent, ToscaFunctionComponent, ToscaGetFunctionComponent, YamlFunctionComponent, ToscaCustomFunctionComponent], imports: [ FormsModule, ReactiveFormsModule, diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.html new file mode 100644 index 0000000000..a67364cd60 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.html @@ -0,0 +1,50 @@ +<!-- + ~ - + ~ ============LICENSE_START======================================================= + ~ Copyright (C) 2023 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"> + <label>Custom function name: </label> + <input type="text" formControlName="customName" [value]="name" required/><br/><br/> + <div formArrayName="customParameterList"> + <div *ngFor="let parameter of parameters; let idx = index"> + <div *ngIf="idx > 0" class="text-center"><span class="custom-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()">TOSCA Function Expression</a> + </div> +</div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.less new file mode 100644 index 0000000000..f37e7befa2 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.less @@ -0,0 +1,98 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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; + } +} + +.custom-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-custom-function/tosca-custom-function.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.spec.ts new file mode 100644 index 0000000000..9c3c188711 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.spec.ts @@ -0,0 +1,64 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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/tosca-concat-function.component'; +import {ToscaCustomFunctionComponent} from './tosca-custom-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"; +import {YamlFunctionComponent} from "../yaml-function/yaml-function.component"; + +describe('ToscaCustomFunctionComponent', () => { + let component: ToscaCustomFunctionComponent; + let fixture: ComponentFixture<ToscaCustomFunctionComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + ToscaCustomFunctionComponent, + ToscaConcatFunctionComponent, + ToscaFunctionComponent, + ToscaGetFunctionComponent, + YamlFunctionComponent], + imports: [ + FormsModule, + ReactiveFormsModule, + TranslateModule, + UiElementsModule + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ToscaCustomFunctionComponent); + 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-custom-function/tosca-custom-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.ts new file mode 100644 index 0000000000..f3687880f2 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-custom-function/tosca-custom-function.component.ts @@ -0,0 +1,160 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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, OnInit, Output} from '@angular/core'; +import {FormArray, FormControl, FormGroup, Validators} from "@angular/forms"; +import {ToscaCustomFunction} from "../../../../../models/tosca-custom-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"; +import {ToscaFunction} from "../../../../../models/tosca-function"; + +@Component({ + selector: 'app-tosca-custom-function', + templateUrl: './tosca-custom-function.component.html', + styleUrls: ['./tosca-custom-function.component.less'] +}) +export class ToscaCustomFunctionComponent implements OnInit { + + @Input() toscaCustomFunction: ToscaCustomFunction; + @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); + @Output() onValidFunction: EventEmitter<ToscaCustomFunction> = new EventEmitter<ToscaCustomFunction>(); + @Output() onValidityChange: EventEmitter<ToscaCustomFunctionValidationEvent> = new EventEmitter<ToscaCustomFunctionValidationEvent>(); + + name: string = ''; + customFunctionFormName: FormControl = new FormControl('', [Validators.required, Validators.minLength(1)]); + customParameterFormArray: FormArray = new FormArray([], Validators.minLength(1)); + formGroup: FormGroup = new FormGroup( + { + 'customParameterList': this.customParameterFormArray, + 'customName': this.customFunctionFormName + } + ); + + parameters: ToscaFunctionParameter[] = []; + propertyInputList: Array<PropertyBEModel> = []; + + STRING_FUNCTION_TYPE = ToscaFunctionType.STRING + + ngOnInit() { + this.initForm(); + } + + private initForm(): void { + this.formGroup.valueChanges.subscribe(() => { + this.onValidityChange.emit({ + isValid: this.formGroup.valid, + toscaCustomFunction: this.formGroup.valid ? this.buildCustomFunctionFromForm() : undefined + }) + if (this.formGroup.valid) { + this.onValidFunction.emit(this.buildCustomFunctionFromForm()); + } + }); + if (!this.toscaCustomFunction) { + return; + } + if (this.toscaCustomFunction.parameters) { + this.name = this.toscaCustomFunction.name; + this.customFunctionFormName.setValue(this.name) + this.parameters = Array.from(this.toscaCustomFunction.parameters); + for (const parameter of this.parameters) { + if (parameter.type !== PROPERTY_TYPES.STRING) { + const propertyBEModel = this.createProperty(parameter.value); + propertyBEModel.toscaFunction = <ToscaFunction> parameter; + this.propertyInputList.push(propertyBEModel); + this.customParameterFormArray.push( + new FormControl(parameter, [Validators.required, Validators.minLength(1)]) + ); + } else { + this.propertyInputList.push(undefined); + this.customParameterFormArray.push( + new FormControl(parameter.value, [Validators.required, Validators.minLength(1)]) + ); + } + } + } + } + + private buildCustomFunctionFromForm(): ToscaCustomFunction { + const toscaCustomFunction1 = new ToscaCustomFunction(); + toscaCustomFunction1.name = this.customFunctionFormName.value; + this.customParameterFormArray.controls.forEach(control => { + const value = control.value; + if (typeof value === 'string') { + const stringParameter = new ToscaStringParameter(); + stringParameter.value = value; + toscaCustomFunction1.parameters.push(stringParameter); + } else { + toscaCustomFunction1.parameters.push(control.value); + } + }); + + return toscaCustomFunction1; + } + + addFunction(): void { + this.propertyInputList.push(this.createProperty()); + this.parameters.push({} as ToscaFunctionParameter); + this.customParameterFormArray.push( + new FormControl(undefined, [Validators.required, Validators.minLength(1)]) + ); + } + + addStringParameter(): void { + const toscaStringParameter = new ToscaStringParameter(); + toscaStringParameter.value = '' + this.parameters.push(toscaStringParameter); + this.propertyInputList.push(undefined); + this.customParameterFormArray.push( + new FormControl('', [Validators.required, Validators.minLength(1)]) + ); + } + + removeParameter(position): void { + this.propertyInputList.splice(position, 1); + this.parameters.splice(position, 1); + this.customParameterFormArray.removeAt(position); + } + + createProperty(value?: any): PropertyBEModel { + const property = new PropertyBEModel(); + property.type = PROPERTY_TYPES.ANY; + property.value = value ? value : undefined; + return property; + } + + onFunctionValidityChange(event: ToscaFunctionValidationEvent, index: number): void { + if (event.isValid && event.toscaFunction) { + this.customParameterFormArray.controls[index].setValue(event.toscaFunction) + } else { + this.customParameterFormArray.controls[index].setValue(undefined); + } + } +} + +export interface ToscaCustomFunctionValidationEvent { + isValid: boolean, + toscaCustomFunction: ToscaCustomFunction, +} 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 74a06baa53..3ec3fa45dc 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 @@ -30,6 +30,10 @@ <app-tosca-concat-function [toscaConcatFunction]="toscaFunction" [componentInstanceMap]="componentInstanceMap" (onValidityChange)="onConcatFunctionValidityChange($event)"></app-tosca-concat-function> </div> + <div *ngIf="isCustomSelected()"> + <app-tosca-custom-function [toscaCustomFunction]="toscaFunction" [componentInstanceMap]="componentInstanceMap" + (onValidityChange)="onCustomFunctionValidityChange($event)"></app-tosca-custom-function> + </div> <div *ngIf="isGetFunctionSelected()"> <app-tosca-get-function [property]="property" [toscaGetFunction]="toscaFunction" [componentInstanceMap]="componentInstanceMap" 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 d46ac2eb10..6783f5b13c 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 @@ -29,9 +29,11 @@ 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 {ToscaCustomFunctionValidationEvent} from "./tosca-custom-function/tosca-custom-function.component"; import {PROPERTY_TYPES, PROPERTY_DATA} from "../../../../utils/constants"; import {YamlFunctionValidationEvent} from "./yaml-function/yaml-function.component"; import {ToscaConcatFunction} from "../../../../models/tosca-concat-function"; +import {ToscaCustomFunction} from "../../../../models/tosca-custom-function"; import {YamlFunction} from "../../../../models/yaml-function"; @Component({ @@ -142,7 +144,8 @@ export class ToscaFunctionComponent implements OnInit, OnChanges { 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.CUSTOM); + if (this.property.type === PROPERTY_TYPES.STRING || this.property.type === PROPERTY_TYPES.ANY) { this.toscaFunctions.push(ToscaFunctionType.CONCAT); } this.toscaFunctions.push(ToscaFunctionType.YAML); @@ -169,6 +172,10 @@ export class ToscaFunctionComponent implements OnInit, OnChanges { return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.CONCAT; } + isCustomSelected(): boolean { + return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.CUSTOM; + } + isGetFunctionSelected(): boolean { return this.isGetInputSelected() || this.isGetPropertySelected() || this.isGetAttributeSelected(); } @@ -193,6 +200,14 @@ export class ToscaFunctionComponent implements OnInit, OnChanges { } } + onCustomFunctionValidityChange(validationEvent: ToscaCustomFunctionValidationEvent): void { + if (validationEvent.isValid) { + this.toscaFunctionForm.setValue(validationEvent.toscaCustomFunction); + } else { + this.toscaFunctionForm.setValue(undefined); + } + } + onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent): void { if (validationEvent.isValid) { this.toscaFunctionForm.setValue(validationEvent.toscaGetFunction); @@ -229,6 +244,9 @@ export class ToscaFunctionComponent implements OnInit, OnChanges { if (this.isConcatSelected()) { return new ToscaConcatFunction(this.toscaFunctionForm.value); } + if (this.isCustomSelected()) { + return new ToscaCustomFunction(this.toscaFunctionForm.value); + } if (this.isGetFunctionSelected()) { return new ToscaGetFunction(this.toscaFunctionForm.value); } 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 bcf10728f8..1452ed66f0 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 @@ -27,6 +27,7 @@ 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'; +import { ToscaCustomFunctionComponent } from './tosca-custom-function/tosca-custom-function.component'; import { YamlFunctionComponent } from './yaml-function/yaml-function.component'; @NgModule({ @@ -34,6 +35,7 @@ import { YamlFunctionComponent } from './yaml-function/yaml-function.component'; ToscaFunctionComponent, ToscaGetFunctionComponent, ToscaConcatFunctionComponent, + ToscaCustomFunctionComponent, YamlFunctionComponent, ], imports: [ 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 index 656d7d6d71..36ead13117 100644 --- 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 @@ -387,6 +387,9 @@ export class ToscaGetFunctionComponent implements OnInit, OnChanges { } private hasSameType(property: PropertyBEModel | AttributeBEModel): boolean { + if (this.property.type === PROPERTY_TYPES.ANY) { + return true; + } if (this.typeHasSchema(this.property.type)) { if ((this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel> this.property).input instanceof DerivedFEProperty) || this.compositionMap) { let childObject : DerivedFEProperty = (<DerivedFEProperty>(<PropertyDeclareAPIModel> this.property).input); |