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