Provide tosca function as list primitive type entry values in composition view
[sdc.git] / catalog-ui / src / app / directives / property-types / type-list / type-list-directive.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 rcohen on 9/15/2016.
23  */
24 'use strict';
25 import {SchemaProperty, PropertyModel} from "app/models";
26 import {ValidationUtils, PROPERTY_TYPES} from "app/utils";
27 import {DataTypesService} from "app/services";
28 import {InstanceFeDetails} from "app/models/instance-fe-details";
29 import {ToscaGetFunction} from "app/models/tosca-get-function";
30 import {SubPropertyToscaFunction} from "app/models/sub-property-tosca-function";
31
32 export interface ITypeListScope extends ng.IScope {
33     parentFormObj:ng.IFormController;
34     schemaProperty:SchemaProperty;
35     parentProperty:PropertyModel;
36     componentInstanceMap: Map<string, InstanceFeDetails>;
37     isSchemaTypeDataType:boolean;
38     valueObjRef:any;
39     propertyNameValidationPattern:RegExp;
40     fieldsPrefixName:string;
41     readOnly:boolean;
42     listDefaultValue:any;
43     listNewItem:any;
44     maxLength:number;
45     stringSchema: SchemaProperty;
46     showToscaFunction: Array<boolean>;
47     constraints:string[];
48
49     getValidationPattern(type:string):RegExp;
50     validateIntRange(value:string):boolean;
51     addListItem():void;
52     addValueToList(value:string,index:number);
53     deleteListItem(listItemIndex:number):void;
54     getStringSchemaProperty():SchemaProperty;
55     getNumber(num:number):Array<any>;
56     onEnableTosca(toscaFlag:boolean,index:number);
57     onGetToscaFunction(toscaGetFunction: ToscaGetFunction, index:number);
58 }
59
60
61 export class TypeListDirective implements ng.IDirective {
62
63     private readonly stringSchema: SchemaProperty;
64
65     constructor(private DataTypesService:DataTypesService,
66                 private PropertyNameValidationPattern:RegExp,
67                 private ValidationUtils:ValidationUtils) {
68         this.stringSchema = new SchemaProperty();
69         this.stringSchema.type = PROPERTY_TYPES.STRING;
70         this.stringSchema.isSimpleType = true;
71         this.stringSchema.isDataType = false;
72     }
73
74     scope = {
75         valueObjRef: '=',//ref to list object in the parent value object
76         schemaProperty: '=',//get the schema.property object
77         componentInstanceMap: '=',
78         parentProperty: '=',
79         parentFormObj: '=',//ref to parent form (get angular form object)
80         fieldsPrefixName: '=',//prefix for form fields names
81         readOnly: '=',//is form read only
82         defaultValue: '@',//this list default value
83         maxLength: '=',
84         constraints: '='
85     };
86
87     restrict = 'E';
88     replace = true;
89     template = ():string => {
90         return require('./type-list-directive.html');
91     };
92
93     link = (scope:ITypeListScope, element:any, $attr:any) => {
94         scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
95         scope.stringSchema = this.stringSchema;
96         if (scope.valueObjRef.length == 0) {
97             scope.valueObjRef.push("");
98         }
99         scope.showToscaFunction = new Array(scope.valueObjRef.length);
100         scope.valueObjRef.forEach((value, index) => {
101             scope.showToscaFunction[index] = false;
102             let key : string = index.toString();
103             if (scope.parentProperty.subPropertyToscaFunctions != null) {
104                 scope.parentProperty.subPropertyToscaFunctions.forEach(SubPropertyToscaFunction => {
105                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
106                         scope.showToscaFunction[index] = true;
107                     }
108                 });
109             }
110         });
111         //reset valueObjRef when schema type is changed
112         scope.$watchCollection('schemaProperty.type', (newData:any):void => {
113             scope.isSchemaTypeDataType = this.DataTypesService.isDataTypeForSchemaType(scope.schemaProperty);
114         });
115
116         //when user brows between properties in "edit property form"
117         scope.$watchCollection('fieldsPrefixName', (newData:any):void => {
118             scope.listNewItem = {value: ''};
119
120             if ($attr.defaultValue) {
121                 scope.listDefaultValue = JSON.parse($attr.defaultValue);
122             }
123         });
124
125         scope.getValidationPattern = (type:string):RegExp => {
126             return this.ValidationUtils.getValidationPattern(type);
127         };
128
129         scope.validateIntRange = (value:string):boolean => {
130             return !value || this.ValidationUtils.validateIntRange(value);
131         };
132
133         scope.addListItem = ():void => {
134             scope.valueObjRef = scope.valueObjRef || [];
135             let newVal;
136             if (scope.schemaProperty.type === PROPERTY_TYPES.MAP) {
137                 newVal = {"": ""};
138             } else if ((scope.schemaProperty.simpleType || scope.schemaProperty.type) == PROPERTY_TYPES.STRING) {
139                 newVal = scope.listNewItem.value;
140             } else {
141                 if (scope.listNewItem.value != "") {
142                     newVal = JSON.parse(scope.listNewItem.value);
143                 }
144             }
145             scope.valueObjRef.push(newVal);
146             scope.showToscaFunction.push(false);
147             scope.listNewItem.value = "";
148         };
149
150         //return dummy array in order to prevent rendering map-keys ng-repeat again when a map key is changed
151         scope.getNumber = (num:number):Array<any> => {
152             return new Array(num);
153         };
154
155         scope.addValueToList = (value:string,index:number):void => {
156             console.log("value : "+value+" , index : "+index);
157             scope.valueObjRef[index] = value;
158             scope.parentProperty.value = scope.valueObjRef;
159         }
160
161         scope.deleteListItem = (listItemIndex: number): void => {
162             scope.valueObjRef.splice(listItemIndex, 1);
163             let key : string = listItemIndex.toString();
164             if (scope.parentProperty.subPropertyToscaFunctions != null) {
165                 let subToscaFunctionList : Array<SubPropertyToscaFunction> = [];
166                 scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction, index) => {
167                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) == -1) {
168                         subToscaFunctionList.push(SubPropertyToscaFunction);
169                     }
170                 });
171                 scope.parentProperty.subPropertyToscaFunctions = subToscaFunctionList;
172             }
173             if (!scope.valueObjRef.length && scope.listDefaultValue) {
174                 angular.copy(scope.listDefaultValue, scope.valueObjRef);
175             }
176         };
177
178         scope.onEnableTosca = (toscaFlag:boolean,flagIndex:number):void => {
179             scope.showToscaFunction[flagIndex] = toscaFlag;
180             scope.valueObjRef[flagIndex] = "";
181             let key:string = flagIndex.toString();
182             if (!toscaFlag) {
183                 if (scope.parentProperty.subPropertyToscaFunctions != null) {
184                     let subToscaFunctionList : Array<SubPropertyToscaFunction> = [];
185                     scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction, index) => {
186                         if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) == -1) {
187                             subToscaFunctionList.push(SubPropertyToscaFunction);
188                         }
189                     });
190                     scope.parentProperty.subPropertyToscaFunctions = subToscaFunctionList;
191                 }
192             }
193         };
194
195         scope.onGetToscaFunction = (toscaGetFunction: ToscaGetFunction, index:number): void => {
196             let key:string = index.toString();
197             if (scope.parentProperty.subPropertyToscaFunctions != null) {
198                 scope.parentProperty.subPropertyToscaFunctions.forEach(SubPropertyToscaFunction => {
199                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
200                         SubPropertyToscaFunction.toscaFunction = toscaGetFunction;
201                         return;
202                     }
203                 });
204
205             }
206             if (scope.parentProperty.subPropertyToscaFunctions == null){
207                 scope.parentProperty.subPropertyToscaFunctions = [];
208             }
209             let subPropertyToscaFunction = new SubPropertyToscaFunction();
210             subPropertyToscaFunction.toscaFunction = toscaGetFunction;
211             subPropertyToscaFunction.subPropertyPath = [key];
212             scope.parentProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
213         }
214
215     };
216
217     public static factory = (DataTypesService:DataTypesService,
218                              PropertyNameValidationPattern:RegExp,
219                              ValidationUtils:ValidationUtils)=> {
220         return new TypeListDirective(DataTypesService, PropertyNameValidationPattern, ValidationUtils);
221     };
222 }
223
224 TypeListDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'PropertyNameValidationPattern', 'ValidationUtils'];
225