Merge "Add proxy support"
[sdc.git] / catalog-ui / src / app / directives / property-types / type-map / type-map-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 {ValidationUtils, PROPERTY_TYPES} from "app/utils";
26 import {DataTypesService} from "app/services";
27 import {SchemaProperty} from "app/models";
28
29 export interface ITypeMapScope extends ng.IScope {
30     parentFormObj:ng.IFormController;
31     schemaProperty:SchemaProperty;
32     isMapKeysUnique:boolean;
33     isSchemaTypeDataType:boolean;
34     valueObjRef:any;
35     mapKeys:Array<string>;//array of map keys
36     mapKeysStatic:Array<string>;
37     MapKeyValidationPattern:RegExp;
38     fieldsPrefixName:string;
39     readOnly:boolean;
40     mapDefaultValue:any;
41     maxLength:number;
42
43     getValidationPattern(type:string):RegExp;
44     validateIntRange(value:string):boolean;
45     changeKeyOfMap(newKey:string, index:number, fieldName:string):void;
46     deleteMapItem(index:number):void;
47     addMapItemFields():void;
48     parseToCorrectType(objectOfValues:any, locationInObj:string, type:string):void;
49     getNumber(num:number):Array<any>;
50 }
51
52
53 export class TypeMapDirective implements ng.IDirective {
54
55     constructor(private DataTypesService:DataTypesService,
56                 private MapKeyValidationPattern:RegExp,
57                 private ValidationUtils:ValidationUtils,
58                 private $timeout:ng.ITimeoutService) {
59     }
60
61     scope = {
62         valueObjRef: '=',//ref to map object in the parent value object
63         schemaProperty: '=',//get the schema.property object
64         parentFormObj: '=',//ref to parent form (get angular form object)
65         fieldsPrefixName: '=',//prefix for form fields names
66         readOnly: '=',//is form read only
67         defaultValue: '@',//this map default value
68         maxLength: '='
69     };
70
71     restrict = 'E';
72     replace = true;
73     template = ():string => {
74         return require('./type-map-directive.html');
75     };
76
77     link = (scope:ITypeMapScope, element:any, $attr:any) => {
78         scope.MapKeyValidationPattern = this.MapKeyValidationPattern;
79         scope.isMapKeysUnique = true;
80
81         //reset valueObjRef and mapKeys when schema type is changed
82         scope.$watchCollection('schemaProperty.type', (newData:any):void => {
83             scope.isSchemaTypeDataType = this.DataTypesService.isDataTypeForSchemaType(scope.schemaProperty);
84             if (scope.valueObjRef) {
85                 scope.mapKeys = Object.keys(scope.valueObjRef);
86                 //keeping another copy of the keys, as the mapKeys gets overridden sometimes
87                 scope.mapKeysStatic = Object.keys(scope.valueObjRef);
88             }
89         });
90
91         //when user brows between properties in "edit property form"
92         scope.$watchCollection('fieldsPrefixName', (newData:any):void => {
93             if (!scope.valueObjRef) {
94                 scope.valueObjRef = {};
95             }
96             scope.mapKeys = Object.keys(scope.valueObjRef);
97             //keeping another copy of the keys, as the mapKeys gets overridden sometimes
98             scope.mapKeysStatic = Object.keys(scope.valueObjRef);
99
100             if ($attr.defaultValue) {
101                 scope.mapDefaultValue = JSON.parse($attr.defaultValue);
102             }
103         });
104
105         //return dummy array in order to prevent rendering map-keys ng-repeat again when a map key is changed
106         scope.getNumber = (num:number):Array<any> => {
107             return new Array(num);
108         };
109
110         scope.getValidationPattern = (type:string):RegExp => {
111             return this.ValidationUtils.getValidationPattern(type);
112         };
113
114         scope.validateIntRange = (value:string):boolean => {
115             return !value || this.ValidationUtils.validateIntRange(value);
116         };
117
118         scope.changeKeyOfMap = (newKey:string, index:number, fieldName:string):void => {
119             let oldKey = Object.keys(scope.valueObjRef)[index];
120             let existsKeyIndex = Object.keys(scope.valueObjRef).indexOf(newKey);
121             if (existsKeyIndex > -1 && existsKeyIndex != index) {
122                 scope.parentFormObj[fieldName].$setValidity('keyExist', false);
123                 scope.isMapKeysUnique = false;
124             } else {
125                 scope.parentFormObj[fieldName].$setValidity('keyExist', true);
126                 scope.isMapKeysUnique = true;
127                 if (!scope.parentFormObj[fieldName].$invalid) {
128                     //To preserve the order of the keys, delete each one and recreate
129                     let newObj = {};
130                     angular.copy(scope.valueObjRef , newObj);
131                     angular.forEach(newObj,function(value:any,key:string){
132                         delete scope.valueObjRef[key];
133                         if(key == oldKey){
134                             scope.valueObjRef[newKey] = value;
135                         }else{
136                             scope.valueObjRef[key] = value;
137                         }
138                     });
139                 }
140             }
141         };
142
143         scope.deleteMapItem = (index:number):void=> {
144             delete scope.valueObjRef[scope.mapKeys[index]];
145             scope.mapKeys.splice(index, 1);
146             if (!scope.mapKeys.length) {//only when user removes all pairs of key-value fields - put the default
147                 if (scope.mapDefaultValue) {
148                     angular.copy(scope.mapDefaultValue, scope.valueObjRef);
149                     scope.mapKeys = Object.keys(scope.valueObjRef);
150                 }
151             }
152         };
153
154         scope.addMapItemFields = ():void => {
155             scope.valueObjRef[''] = null;
156             scope.mapKeys = Object.keys(scope.valueObjRef);
157         };
158
159         scope.parseToCorrectType = (objectOfValues:any, locationInObj:string, type:string):void => {
160             if (objectOfValues[locationInObj] && type != PROPERTY_TYPES.STRING) {
161                 objectOfValues[locationInObj] = JSON.parse(objectOfValues[locationInObj]);
162             }
163         }
164     };
165
166     public static factory = (DataTypesService:DataTypesService,
167                              MapKeyValidationPattern:RegExp,
168                              ValidationUtils:ValidationUtils,
169                              $timeout:ng.ITimeoutService)=> {
170         return new TypeMapDirective(DataTypesService, MapKeyValidationPattern, ValidationUtils, $timeout);
171     };
172 }
173
174 TypeMapDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'MapKeyValidationPattern', 'ValidationUtils', '$timeout'];