3 * ============LICENSE_START=======================================================
4 * Copyright (C) 2022 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
23 import {PropertyBEModel} from "../../../../../models/properties-inputs/property-be-model";
24 import {AbstractControl, FormControl, FormGroup, ValidationErrors, Validators} from "@angular/forms";
25 import {PROPERTY_DATA} from "../../../../../utils/constants";
26 import {DataTypeService} from "../../../../services/data-type.service";
27 import {DataTypeModel} from "../../../../../models/data-types";
28 import {Subscription} from "rxjs";
29 import {ToscaTypeHelper} from "../../../../../utils/tosca-type-helper";
30 import {SchemaProperty, SchemaPropertyGroupModel} from "../../../../../models/schema-property";
33 selector: 'app-add-property',
34 templateUrl: './add-property.component.html',
35 styleUrls: ['./add-property.component.less']
37 export class AddPropertyComponent implements OnInit, OnDestroy {
39 @Input() property: PropertyBEModel;
40 @Input() readOnly: boolean = true;
41 @Input() model: string;
43 @Output() onValidityChange: EventEmitter<PropertyValidationEvent> = new EventEmitter<PropertyValidationEvent>();
45 private valueChangesSub: Subscription;
46 private descriptionForm: FormControl = new FormControl(undefined);
47 private requiredForm: FormControl = new FormControl(false, Validators.required);
48 nameForm: FormControl = new FormControl(undefined, [Validators.required]);
49 typeForm: FormControl = new FormControl(undefined, Validators.required);
50 schemaForm: FormControl = new FormControl(undefined, (control: AbstractControl): ValidationErrors | null => {
51 if (this.typeNeedsSchema() && !control.value) {
52 return {required: true};
56 hasDefaultValueForm: FormControl = new FormControl(false, Validators.required);
57 defaultValueForm: FormControl = new FormControl(undefined);
58 formGroup: FormGroup = new FormGroup({
59 'name': this.nameForm,
60 'description': this.descriptionForm,
61 'type': this.typeForm,
62 'required': this.requiredForm,
63 'schema': this.schemaForm,
64 'defaultValue': this.defaultValueForm,
65 'hasDefaultValue': this.hasDefaultValueForm,
68 isLoading: boolean = false;
69 showSchema: boolean = false;
71 dataTypeMap: Map<string, DataTypeModel>;
72 dataType: DataTypeModel;
73 schemaTypeList: string[];
75 constructor(private dataTypeService: DataTypeService) {
79 this.isLoading = true;
80 this.initTypeAndSchemaDropdown().then(() => this.updateDataType());
82 this.valueChangesSub = this.formGroup.valueChanges.subscribe(() => {
83 this.emitValidityChange();
88 if (this.valueChangesSub) {
89 this.valueChangesSub.unsubscribe();
93 onSchemaChange(): void {
94 this.resetDefaultValue();
97 onTypeChange(): void {
98 this.schemaForm.setValue(null);
99 this.showSchema = this.typeNeedsSchema();
100 this.updateDataType();
101 this.resetDefaultValue();
104 private updateDataType(): void {
105 this.dataType = this.dataTypeMap.get(this.typeForm.value);
108 private initForm(): void {
109 if (!this.property) {
113 this.nameForm.setValue(this.property.name);
114 this.descriptionForm.setValue(this.property.description);
115 this.typeForm.setValue(this.property.type);
116 this.showSchema = this.typeNeedsSchema();
117 this.requiredForm.setValue(this.property.required);
118 this.schemaForm.setValue(this.property.schemaType);
119 this.initDefaultValueForm();
122 private initDefaultValueForm() {
123 if (this.property.defaultValue == undefined) {
127 if (!this.isTypeSimple() && typeof this.property.defaultValue === 'string') {
128 defaultValue = JSON.parse(this.property.defaultValue);
130 defaultValue = this.property.defaultValue;
132 this.defaultValueForm.setValue(defaultValue);
133 this.hasDefaultValueForm.setValue(true);
136 private typeNeedsSchema() {
137 return PROPERTY_DATA.SCHEMA_TYPES.indexOf(this.typeForm.value) > -1;
140 private initTypeAndSchemaDropdown(): Promise<Map<string, DataTypeModel>> {
141 const primitiveTypes: string[] = Array.from(PROPERTY_DATA.TYPES).sort((a, b) => a.localeCompare(b));
142 const promise = this.dataTypeService.findAllDataTypesByModel(this.model);
143 promise.then((dataTypeMap: Map<string, DataTypeModel>) => {
144 this.dataTypeMap = dataTypeMap;
145 const nonPrimitiveTypes: string[] = Array.from(dataTypeMap.keys()).filter(type => {
146 return primitiveTypes.indexOf(type) === -1;
148 nonPrimitiveTypes.sort((a, b) => a.localeCompare(b));
149 this.typeList = [...primitiveTypes, ...nonPrimitiveTypes];
150 this.schemaTypeList = Array.from(this.typeList);
151 this.isLoading = false;
156 private emitValidityChange(): void {
157 const isValid: boolean = this.formGroup.valid;
158 this.onValidityChange.emit({
160 property: isValid ? this.buildPropertyFromForm() : undefined
164 private buildPropertyFromForm(): PropertyBEModel {
165 const property = new PropertyBEModel();
166 property.name = this.nameForm.value;
167 property.type = this.typeForm.value;
168 if (this.schemaForm.value) {
169 property.schemaType = this.schemaForm.value;
171 property.description = this.descriptionForm.value;
172 if (this.hasDefaultValueForm.value === true) {
173 property.defaultValue = this.defaultValueForm.value;
178 public isTypeSimple(): boolean {
179 return ToscaTypeHelper.isTypeSimple(this.typeForm.value);
182 public isTypeList(): boolean {
183 return ToscaTypeHelper.isTypeList(this.typeForm.value);
186 public isTypeMap(): boolean {
187 return ToscaTypeHelper.isTypeMap(this.typeForm.value);
190 public isTypeComplex(): boolean {
191 return ToscaTypeHelper.isTypeComplex(this.typeForm.value);
194 private isTypeRange() {
195 return ToscaTypeHelper.isTypeRange(this.typeForm.value);
198 onPropertyValueChange($event: any): void {
199 this.defaultValueForm.setValue($event.value);
202 showDefaultValue(): boolean {
204 return this.defaultValueForm.value != undefined && this.dataTypeMap && this.typeForm.valid && this.schemaForm.valid;
206 return this.dataTypeMap && this.typeForm.valid && this.schemaForm.valid;
209 getDataType(type: string): DataTypeModel {
210 return this.dataTypeMap.get(type);
213 private resetDefaultValue(): void {
214 this.defaultValueForm.reset();
215 if (this.isTypeComplex() || this.isTypeMap()) {
216 this.defaultValueForm.setValue({});
217 } else if (this.isTypeList() || this.isTypeRange()) {
218 this.defaultValueForm.setValue([]);
222 buildSchemaGroupProperty(): SchemaPropertyGroupModel {
223 const schemaProperty = new SchemaProperty();
224 schemaProperty.type = this.schemaForm.value
225 return new SchemaPropertyGroupModel(schemaProperty);
230 export class PropertyValidationEvent {
232 property: PropertyBEModel;