Revert "Provide tosca function capability to complex type fields in composition view"
[sdc.git] / catalog-ui / src / app / directives / property-types / data-type-fields-structure / data-type-fields-structure.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 /**
22  * Created by obarda on 1/27/2016.
23  */
24 'use strict';
25 import { DataTypesMap, PropertyModel } from 'app/models';
26 import { DataTypePropertyModel } from 'app/models/data-type-properties';
27 import { DataTypesService } from 'app/services';
28 import { ValidationUtils } from 'app/utils';
29 import {InstanceFeDetails} from "app/models/instance-fe-details";
30 import * as _ from 'lodash';
31
32 export interface IDataTypeFieldsStructureScope extends ng.IScope {
33     parentFormObj: ng.IFormController;
34     dataTypeProperties: DataTypePropertyModel[];
35     parentProperty:PropertyModel;
36     componentInstanceMap: Map<string, InstanceFeDetails>;
37     typeName: string;
38     valueObjRef: any;
39     propertyNameValidationPattern: RegExp;
40     fieldsPrefixName: string;
41     readOnly: boolean;
42     currentTypeDefaultValue: any;
43     types: DataTypesMap;
44     expandByDefault: boolean;
45     expand: boolean;
46     expanded: boolean;
47     dataTypesService: DataTypesService;
48     constraints: string[];
49     isService:boolean;
50
51     expandAndCollapse(): void;
52     getValidationPattern(type: string): RegExp;
53     validateIntRange(value: string): boolean;
54     onValueChange(propertyName: string, type: string): void;
55     inputOnValueChange(property: any): void;
56 }
57
58 export class DataTypeFieldsStructureDirective implements ng.IDirective {
59
60     constraints: string[];
61
62     scope = {
63         valueObjRef: '=',
64         typeName: '=',
65         componentInstanceMap: '=',
66         parentProperty: '=',
67         parentFormObj: '=',
68         fieldsPrefixName: '=',
69         readOnly: '=',
70         defaultValue: '@',
71         types: '=',
72         expandByDefault: '=',
73         isService: '='
74     };
75
76     restrict = 'E';
77     replace = true;
78
79     constructor(private DataTypesService: DataTypesService,
80                 private PropertyNameValidationPattern: RegExp,
81                 private ValidationUtils: ValidationUtils) {
82     }
83
84     public static factory = (DataTypesService: DataTypesService,
85                              PropertyNameValidationPattern: RegExp,
86                              ValidationUtils: ValidationUtils) => {
87         return new DataTypeFieldsStructureDirective(DataTypesService, PropertyNameValidationPattern, ValidationUtils);
88     }
89     template = (): string => {
90         return require('./data-type-fields-structure.html');
91     }
92
93     link = (scope: IDataTypeFieldsStructureScope, element: any, $attr: any) => {
94         scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
95
96         scope.$watchCollection('[typeName,fieldsPrefixName]', (newData: any): void => {
97             this.rerender(scope);
98         });
99
100         scope.expandAndCollapse = (): void => {
101             if (!scope.expanded) {
102                 this.initDataOnScope(scope, $attr);
103                 scope.expanded = true;
104             }
105             scope.expand = !scope.expand;
106         };
107
108         scope.getValidationPattern = (type: string): RegExp => {
109             return this.ValidationUtils.getValidationPattern(type);
110         };
111
112         scope.validateIntRange = (value: string): boolean => {
113             return !value || this.ValidationUtils.validateIntRange(value);
114         };
115
116         scope.onValueChange = (propertyName: string, type: string, ): void => {
117             scope.valueObjRef[propertyName] = !angular.isUndefined(scope.valueObjRef[propertyName]) ? scope.valueObjRef[propertyName] : scope.currentTypeDefaultValue[propertyName];
118             if (scope.valueObjRef[propertyName] && type != 'string') {
119                 scope.valueObjRef[propertyName] = JSON.parse(scope.valueObjRef[propertyName]);
120             }
121         };
122
123         scope.inputOnValueChange = (property: any) => {
124             if (property.constraints) {
125                 // this.constraints = property.constraints[0].validValues;
126             }
127
128             const value = !scope.parentFormObj[scope.fieldsPrefixName + property.name].$error.pattern
129                 && ('integer' == property.type && scope.parentFormObj[scope.fieldsPrefixName + property.name].$setValidity('pattern', scope.validateIntRange(scope.valueObjRef[property.name]))
130                 || scope.onValueChange(property.name, (property.simpleType || property.type)));
131             return value;
132         };
133     }
134     // public types=Utils.Constants.PROPERTY_DATA.TYPES;
135
136     // get data type properties array and return object with the properties and their default value
137     // (for example: get: [{name:"prop1",defaultValue:1 ...},{name:"prop2", defaultValue:"bla bla" ...}]
138     //              return: {prop1: 1, prop2: "bla bla"}
139     private getDefaultValue = (dataTypeProperties: DataTypePropertyModel[]): any => {
140         const defaultValue = {};
141         for (const element of dataTypeProperties) {
142             if (element.type != 'string') {
143                 if (!angular.isUndefined(element.defaultValue)) {
144                     defaultValue[element.name] = JSON.parse(element.defaultValue);
145                 }
146             } else {
147                 defaultValue[element.name] = element.defaultValue;
148             }
149         }
150         return defaultValue;
151     }
152
153     private initDataOnScope = (scope: any, $attr: any): void => {
154         scope.dataTypesService = this.DataTypesService;
155         scope.dataTypeProperties = this.getDataTypeProperties(scope.typeName, scope.types);
156         if ($attr.defaultValue) {
157             scope.currentTypeDefaultValue = JSON.parse($attr.defaultValue);
158         } else {
159             scope.currentTypeDefaultValue = this.getDefaultValue(scope.dataTypeProperties);
160         }
161
162         if (!scope.valueObjRef) {
163             scope.valueObjRef = {};
164         }
165
166         _.forEach(scope.currentTypeDefaultValue, (value, key) => {
167             if (angular.isUndefined(scope.valueObjRef[key])) {
168                 if (typeof scope.currentTypeDefaultValue[key] == 'object') {
169                     angular.copy(scope.currentTypeDefaultValue[key], scope.valueObjRef[key]);
170                 } else {
171                     scope.valueObjRef[key] = scope.currentTypeDefaultValue[key];
172                 }
173             }
174         });
175     }
176
177     private getDataTypeProperties = (dataTypeName: string, typesInModel: DataTypesMap): DataTypePropertyModel[] => {
178         let properties = typesInModel[dataTypeName].properties || [];
179         if (typesInModel[dataTypeName].derivedFromName != 'tosca.datatypes.Root') {
180             properties = this.getDataTypeProperties(typesInModel[dataTypeName].derivedFromName, typesInModel).concat(properties);
181         }
182         return properties;
183     }
184
185     private rerender = (scope: any): void => {
186         scope.expanded = false;
187         scope.expand = false;
188         if (scope.expandByDefault) {
189             scope.expandAndCollapse();
190         }
191     }
192 }
193
194 DataTypeFieldsStructureDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'PropertyNameValidationPattern', 'ValidationUtils'];