diff options
author | JvD_Ericsson <jeff.van.dam@est.tech> | 2023-07-06 13:17:48 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2023-07-13 15:05:06 +0000 |
commit | 825411a75557943e988d3601690cdf75c2bf0588 (patch) | |
tree | 76fcb694b9f224cb7138c4d25912b7ed8b406a1c /catalog-ui/src | |
parent | 7b8acdf5b70fdcda448fa1ae871df0e0723f08db (diff) |
UI support for metadata when editing properties of VFCs
Issue-ID: SDC-4561
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I642fa4ce09fe669e5722dbbf18dd23daa23761d3
Diffstat (limited to 'catalog-ui/src')
10 files changed, 310 insertions, 0 deletions
diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts index cff1324c30..83cc062367 100644 --- a/catalog-ui/src/app/models/properties.ts +++ b/catalog-ui/src/app/models/properties.ts @@ -136,6 +136,7 @@ export class PropertyModel extends PropertyBEModel implements IPropertyModel { "defaultValue": this.defaultValue != "" && this.defaultValue != "[]" && this.defaultValue != "{}" ? this.defaultValue : null, "description": this.description, "constraints": this.constraints, + "metadata": this.metadata, "propertyConstraints": this.propertyConstraints, "isPassword": this.password || false, "schema": this.schema, diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index 8907f5a0ea..2cf3832625 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -97,6 +97,7 @@ import {AttributesOutputsComponent} from "../ng2/pages/attributes-outputs/attrib import {InterfaceDefinitionComponent} from "../ng2/pages/interface-definition/interface-definition.page.component"; import {ToscaFunctionComponent} from '../ng2/pages/properties-assignment/tosca-function/tosca-function.component'; import {ConstraintsComponent} from '../ng2/pages/properties-assignment/constraints/constraints.component'; +import {PropertyMetadataComponent} from '../ng2/pages/properties-assignment/property-metadata/property-metadata.component'; import {TypeWorkspaceComponent} from "../ng2/pages/type-workspace/type-workspace.component"; import {TypeWorkspaceGeneralComponent} from "../ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component"; import {DeclareInputComponent} from "../ng2/pages/properties-assignment/declare-input/declare-input.component"; @@ -332,6 +333,12 @@ directiveModule.directive('appConstraints', downgradeComponent({ outputs: ['onConstraintChange'] }) as angular.IDirectiveFactory); +directiveModule.directive('appPropertyMetadata', downgradeComponent({ + component: PropertyMetadataComponent, + inputs: ['propertyMetadata', 'isViewOnly'], + outputs: ['onPropertyMetadataChange'] +}) as angular.IDirectiveFactory); + directiveModule.directive('appTypeWorkspace', downgradeComponent({ component: TypeWorkspaceComponent, inputs: [], diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 0c5b10f1e4..ffb894fcb9 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -101,6 +101,7 @@ import {PropertyCreatorModule} from './pages/properties-assignment/property-crea import {DeclareListModule} from './pages/properties-assignment/declare-list/declare-list.module'; import {ToscaFunctionModule} from "./pages/properties-assignment/tosca-function/tosca-function.module"; import {ConstraintsModule} from "./pages/properties-assignment/constraints/constraints.module"; +import {PropertyMetadataModule} from "./pages/properties-assignment/property-metadata/property-metadata.module"; import {WorkflowServiceNg2} from './services/workflow.service'; import {ToscaTypesServiceNg2} from "./services/tosca-types.service"; import {InterfaceOperationHandlerModule} from "./pages/composition/interface-operatons/operation-creator/interface-operation-handler.module"; @@ -163,6 +164,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent DeclareListModule, ToscaFunctionModule, ConstraintsModule, + PropertyMetadataModule, PluginFrameModule, PluginsModule, InterfaceOperationModule, diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.html new file mode 100644 index 0000000000..420d7ebe8b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.html @@ -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========================================================= + --> +<div class="app-property-metadata"> + <form novalidate class="w-sdc-form two-columns" [formGroup]="metadataForm"> + <div formArrayName="metadataFormList"> + <div *ngFor="let metadata of propertyMetadataArray; let idx = index"> + <div class="w-sdc-form-columns-wrapper"> + <div class="w-sdc-form-column"> + <input type="text" + class="i-sdc-form-input myClass" + placeholder="new metadata key" + (input)="onChangePropertyMetadataKey(idx, $event.target.value)" + [value]="metadata.key" + [ngClass]="{'disabled': isViewOnly}" + required/> + </div> + <div class="w-sdc-form-column"> + <input type="text" + class="i-sdc-form-input myClass" + placeholder="new metadata value" + (input)="onChangePropertyMetadataValue(idx, $event.target.value)" + [value]="metadata.value" + [ngClass]="{'disabled': isViewOnly}" + required/> + </div> + <div class="w-sdc-form-column"> + <span class="sprite-new delete-btn" [ngClass]="{'disabled': isViewOnly}" (click)="removeFromList(idx)"></span> + </div> + </div> + <div class="w-sdc-form-columns-wrapper"> + <div class="validation-errors"> + <ng-container *ngFor="let validation of validationMessages.metadata"> + <div class="input-error" *ngIf="metadataFormArray.at(idx).hasError(validation.type);"> + {{ validation.message }} + </div> + </ng-container> + </div> + </div> + </div> + <div class="w-sdc-form-columns-wrapper" *ngIf="!isViewOnly"> + <div class="add-btn add-list-item w-sdc-form-column" *ngIf="!isViewOnly" [ngClass]="{'disabled': isViewOnly}" + (click)="addMetadataField()"> Add Metadata Entry </div> + </div> + </div> + </form> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.less new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.less diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.spec.ts new file mode 100644 index 0000000000..0a0b2c0914 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.spec.ts @@ -0,0 +1,45 @@ +/* + * ============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 { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { PropertyMetadataComponent } from './property-metadata.component'; + +describe('PropertyMetadataComponent', () => { + let component: PropertyMetadataComponent; + let fixture: ComponentFixture<PropertyMetadataComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PropertyMetadataComponent ], + imports: [FormsModule, ReactiveFormsModule] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PropertyMetadataComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.ts new file mode 100644 index 0000000000..dc4c283a5d --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.component.ts @@ -0,0 +1,132 @@ +/* + * ============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 { + AbstractControl, FormArray, + FormControl, + FormGroup, ValidationErrors, + ValidatorFn, + Validators +} from '@angular/forms'; + +@Component({ + selector: 'app-property-metadata', + templateUrl: './property-metadata.component.html', + styleUrls: ['./property-metadata.component.less'] +}) +export class PropertyMetadataComponent implements OnInit { + + @Input() propertyMetadata: any; + @Input() isViewOnly: boolean = false; + @Output() onPropertyMetadataChange: EventEmitter<any> = new EventEmitter<any>(); + + propertyMetadataArray: Metadata[] = []; + metadataFormArray: FormArray = new FormArray([]); + metadataForm: FormGroup = new FormGroup ( + { + 'metadataFormList': this.metadataFormArray + } + ); + validationMessages = { + metadata: [ + { type: 'required', message: 'Metadata key and value is required'} + ] + }; + + ngOnInit() { + this.initForm(); + } + + private initForm(): void { + this.metadataForm.valueChanges.subscribe(() => { + this.emitOnPropertyMetadataChange(); + }); + if (this.propertyMetadata) { + for (const key in this.propertyMetadata) { + const value = this.propertyMetadata[key]; + let metadata: Metadata = { + key: key, + value: value + } + this.propertyMetadataArray.push(metadata); + this.metadataFormArray.push( + new FormControl(metadata, [Validators.required, Validators.minLength(1)]) + ); + } + } + } + + addMetadataField() { + let metadata: Metadata = { + key: null, + value: null, + } + this.propertyMetadataArray.push(metadata); + this.metadataFormArray.push( + new FormControl(metadata, [Validators.required, this.formControlValidator()]) + ); + } + + private formControlValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const metadata = control.value; + + if (!metadata || !metadata.key || !metadata.value) { + return {required:true}; + } + return null; + } + } + + removeFromList(index: number) { + this.propertyMetadataArray.splice(index, 1);; + this.metadataFormArray.removeAt(index); + } + + private emitOnPropertyMetadataChange(): void { + let newMetadata = new Object; + for (const metadata of this.propertyMetadataArray) { + const key = metadata.key; + const value = metadata.value; + newMetadata[key] = value; + } + + this.onPropertyMetadataChange.emit({ + metadata: newMetadata, + valid: this.metadataForm.valid + }); + } + + onChangePropertyMetadataValue(index: number, newValue: any) { + let metadata = this.metadataFormArray.controls[index].value; + metadata.value = newValue; + this.metadataFormArray.controls[index].setValue(metadata); + } + + onChangePropertyMetadataKey(index: number, newKey: any) { + let metadata = this.metadataFormArray.controls[index].value; + metadata.key = newKey; + this.metadataFormArray.controls[index].setValue(metadata); + } +} + +export interface Metadata { + key: string, + value: string +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.module.ts new file mode 100644 index 0000000000..00324e01ca --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-metadata/property-metadata.module.ts @@ -0,0 +1,37 @@ +/* + * ============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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { PropertyMetadataComponent } from './property-metadata.component'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule + ], + declarations: [PropertyMetadataComponent], + exports: [PropertyMetadataComponent], + entryComponents: [ + PropertyMetadataComponent + ], +}) + +export class PropertyMetadataModule { } diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts index 0be5193298..faf2a0fb88 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts @@ -537,6 +537,19 @@ export class PropertyFormViewModel { this.$scope.editPropertyModel.property.constraints = constraints.constraints; } + this.$scope.onPropertyMetadataChange = (metadata: any): void => { + if (!this.$scope.invalidMandatoryFields) { + this.$scope.footerButtons[0].disabled = !metadata.valid; + } else { + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; + } + if (!metadata.metadata || metadata.metadata.length == 0) { + this.$scope.editPropertyModel.property.metadata = null; + return; + } + this.$scope.editPropertyModel.property.metadata = metadata.metadata; + } + this.$scope.onGetFunctionValidFunction = (toscaGetFunction: ToscaGetFunction): void => { this.$scope.editPropertyModel.property.toscaFunction = toscaGetFunction; } diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html index d7c2af5b6e..bd2126b369 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html @@ -263,6 +263,15 @@ </app-constraints> </ng-container> </div> + <div class="constraints-section i-sdc-form-item" data-ng-if="editPropertyModel.property.propertyView || editPropertyModel.property.metadata || !(isViewOnly || componentMetadata.isService)"> + <label class="i-sdc-form-label">Metadata</label> + <ng-container> + <app-property-metadata [property-metadata]="editPropertyModel.property.metadata" + [is-view-only]="editPropertyModel.property.propertyView? !editPropertyModel.property.propertyView : (isViewOnly || componentMetadata.isService)" + (on-property-metadata-change)="onPropertyMetadataChange($event)"> + </app-property-metadata> + </ng-container> + </div> <span class="w-sdc-form-note" data-ng-show="forms.editForm.$invalid && false" translate="LABEL_ALL_FIELDS_ARE_MANDATORY"></span> </form> </perfect-scrollbar> |