Sync Integ to Master
[sdc.git] / catalog-ui / src / app / directives / select-property-types / select-data-type-fields-structure / select-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 * as _ from "lodash";
26 import {ValidationUtils} from "app/utils";
27 import { DataTypesService } from "app/services";
28 import { DataTypePropertyModel } from "app/models/data-type-properties";
29 import {DataTypesMap, PropertyModel} from "app/models";
30
31 export interface ISelectDataTypeFieldsStructureScope extends ng.IScope {
32     parentFormObj:ng.IFormController;
33     dataTypeProperties:Array<DataTypePropertyModel>;
34     typeName:string;
35     valueObjRef:any;
36     propertyNameValidationPattern:RegExp;
37     fieldsPrefixName:string;
38     readOnly:boolean;
39     currentTypeDefaultValue:any;
40     types:DataTypesMap;
41     expandByDefault:boolean;
42     expand:boolean;
43     expanded:boolean;
44     dataTypesService:DataTypesService;
45     path:string;
46     isParentAlreadyInput:boolean;
47
48     expandAndCollapse():void;
49     getValidationPattern(type:string):RegExp;
50     validateIntRange(value:string):boolean;
51     isAlreadyInput(property:PropertyModel):boolean;
52     setSelectedType(property:PropertyModel):void;
53     onValueChange(propertyName:string, type:string):void;
54 }
55
56
57 export class SelectDataTypeFieldsStructureDirective implements ng.IDirective {
58
59     constructor(private DataTypesService:DataTypesService,
60                 private PropertyNameValidationPattern:RegExp,
61                 private ValidationUtils:ValidationUtils) {
62     }
63
64     scope = {
65         valueObjRef: '=',
66         typeName: '=',
67         parentFormObj: '=',
68         fieldsPrefixName: '=',
69         readOnly: '=',
70         defaultValue: '@',
71         expandByDefault: '=',
72         path: '@',
73         isParentAlreadyInput: '='
74     };
75
76     restrict = 'E';
77     replace = true;
78     template = ():string => {
79         return require('./select-data-type-fields-structure.html');
80     };
81     // public types=Utils.Constants.PROPERTY_DATA.TYPES;
82
83     //get data type properties array and return object with the properties and their default value
84     //(for example: get: [{name:"prop1",defaultValue:1 ...},{name:"prop2", defaultValue:"bla bla" ...}]
85     //              return: {prop1: 1, prop2: "bla bla"}
86     private getDefaultValue = (dataTypeProperties:Array<DataTypePropertyModel>):any => {
87         let defaultValue = {};
88         for (let i = 0; i < dataTypeProperties.length; i++) {
89             if (dataTypeProperties[i].type != 'string') {
90                 if (!angular.isUndefined(dataTypeProperties[i].defaultValue)) {
91                     defaultValue[dataTypeProperties[i].name] = JSON.parse(dataTypeProperties[i].defaultValue);
92                 }
93             } else {
94                 defaultValue[dataTypeProperties[i].name] = dataTypeProperties[i].defaultValue;
95             }
96         }
97         return defaultValue;
98     };
99
100     private initDataOnScope = (scope:ISelectDataTypeFieldsStructureScope, $attr:any):void => {
101         scope.dataTypesService = this.DataTypesService;
102         scope.dataTypeProperties = angular.copy(this.DataTypesService.getFirsLevelOfDataTypeProperties(scope.typeName));
103         if ($attr.defaultValue) {
104             scope.currentTypeDefaultValue = JSON.parse($attr.defaultValue);
105         } else {
106             scope.currentTypeDefaultValue = this.getDefaultValue(scope.dataTypeProperties);
107         }
108
109         if (!scope.valueObjRef) {
110             scope.valueObjRef = {};
111         }
112
113         _.forEach(scope.currentTypeDefaultValue, (value, key)=> {
114             if (angular.isUndefined(scope.valueObjRef[key])) {
115                 if (typeof scope.currentTypeDefaultValue[key] == 'object') {
116                     angular.copy(scope.currentTypeDefaultValue[key], scope.valueObjRef[key]);
117                 } else {
118                     scope.valueObjRef[key] = scope.currentTypeDefaultValue[key];
119                 }
120             }
121         });
122     };
123
124     private rerender = (scope:any):void => {
125         scope.expanded = false;
126         scope.expand = false;
127         if (scope.expandByDefault) {
128             scope.expandAndCollapse();
129         }
130     };
131
132     link = (scope:ISelectDataTypeFieldsStructureScope, element:any, $attr:any) => {
133         scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
134
135         scope.$watchCollection('[typeName,fieldsPrefixName]', (newData:any):void => {
136             this.rerender(scope);
137         });
138
139
140         scope.expandAndCollapse = ():void => {
141             if (!scope.expanded) {
142                 this.initDataOnScope(scope, $attr);
143                 scope.expanded = true;
144             }
145             scope.expand = !scope.expand;
146         };
147
148         scope.getValidationPattern = (type:string):RegExp => {
149             return this.ValidationUtils.getValidationPattern(type);
150         };
151
152         scope.validateIntRange = (value:string):boolean => {
153             return !value || this.ValidationUtils.validateIntRange(value);
154         };
155
156         /*
157          check if property is alrady declered on the service by meatching the input name & the property name
158
159          */
160         scope.isAlreadyInput = (property:PropertyModel):boolean => {
161             if (scope.path) {
162                 if (scope.isParentAlreadyInput) {
163                     return true;
164                 }
165                 let parentInputName = this.DataTypesService.selectedInstance.normalizedName + '_' + scope.path.replace('#', '_');// set the input parent  as he need to declared as input
166                 let inputName = parentInputName + '_' + property.name;// set the input name as he need to declared as input
167                 let selectedProperty = _.find(this.DataTypesService.selectedComponentInputs, (componentInput)=> {
168                     if (componentInput.name == parentInputName) { //check if the parent(all the complex) is already declared
169                         scope.isParentAlreadyInput = true;
170                         return true;
171                     } else if (componentInput.name.substring(0, inputName.length) == inputName) { //check if specific property inside the complex
172                         return true;
173                     }
174                     //return componentInput.name == parentInputName || componentInput.name.substring(0,inputName.length) == inputName;//check if the parent(all the complex) is already declared or specific property inside the complex
175                 });
176                 if (selectedProperty) {
177                     return true;
178                 }
179             }
180             return false;
181         };
182
183         scope.setSelectedType = (property:PropertyModel):void=> {
184             scope.dataTypesService.selectedInput = property;
185             scope.dataTypesService.selectedPropertiesName = scope.path + '#' + property.name;
186         };
187
188         scope.onValueChange = (propertyName:string, type:string):void => {
189             scope.valueObjRef[propertyName] = !angular.isUndefined(scope.valueObjRef[propertyName]) ? scope.valueObjRef[propertyName] : scope.currentTypeDefaultValue[propertyName];
190             if (scope.valueObjRef[propertyName] && type != 'string') {
191                 scope.valueObjRef[propertyName] = JSON.parse(scope.valueObjRef[propertyName]);
192             }
193         };
194
195
196     };
197
198     public static factory = (DataTypesService:DataTypesService,
199                              PropertyNameValidationPattern:RegExp,
200                              ValidationUtils:ValidationUtils)=> {
201         return new SelectDataTypeFieldsStructureDirective(DataTypesService, PropertyNameValidationPattern, ValidationUtils);
202     };
203 }
204
205 SelectDataTypeFieldsStructureDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'PropertyNameValidationPattern', 'ValidationUtils'];