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