Added new componetnts inside page modules
[portal.git] / portal-FE-common / src / app / pages / user-notification-admin / new-notification-modal / new-notification-modal.component.ts
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * 
37  */
38
39 import { Component, OnInit, Input, Output, EventEmitter, Injectable} from '@angular/core';
40 import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
41 import { NotificationService, FunctionalMenuService } from 'src/app/shared/services';
42 import { SelectionModel } from '@angular/cdk/collections';
43 import { FlatTreeControl } from '@angular/cdk/tree';
44 import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
45 import { BehaviorSubject } from 'rxjs';
46 import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
47 import { InformationModalComponent } from 'src/app/modals/information-modal/information-modal.component';
48
49 @Component({
50   selector: 'app-new-notification-modal',
51   templateUrl: './new-notification-modal.component.html',
52   styleUrls: ['./new-notification-modal.component.scss']
53 })
54 export class NewNotificationModalComponent implements OnInit {
55
56   notification = {
57     'notificationId': null,
58     'isOnlineUsersOnly': null,
59     'isForAllRoles': null,
60     'priority': null,
61     'isActive': null,
62     'startTime': null,
63     'endTime': null,
64     'msgHeader': null,
65     'msgDescription': null,
66     'roleIds': null,
67     'isFunctionalMenu': null,
68     'treeTitle': null,
69     'anyTreeItemSelected': false,
70     'notifObj':null,
71     'roleObj': {
72         notificationRoleIds: null
73     },
74     'notificationRoleIds': null
75   };
76   
77   /**
78   * The Json object for to-do list data.
79   */
80   MAT_TREE_DATA = {};
81   notificationId = null;
82   selectedCat = null;
83   selectedEcompFunc = null;
84   YN_index_mapping = {
85       "Y": 0,
86       "N": 1
87   }
88
89   onlineAllUsersOptions = [{
90           "index": 0,
91           "value": "Y",
92           "title": "Online Users Only"
93       },
94       {
95           "index": 1,
96           "value": "N",
97           "title": "Online & Offline Users"
98       }
99   ];
100
101   isForAllRoles = [{
102           "index": 0,
103           "value": "Y",
104           "title": "Yes"
105       },
106       {
107           "index": 1,
108           "value": "N",
109           "title": "No"
110       }
111   ];
112
113   priorityOptions = [{
114           "index": 0,
115           "value": "1",
116           "title": "Normal"
117       },
118       {
119           "index": 1,
120           "value": "2",
121           "title": "Important"
122       }
123   ];
124
125   isActiveOptions = [{
126     "index": 0,
127     "value": "Y",
128     "title": "Yes"
129     },
130     {
131         "index": 1,
132         "value": "N",
133         "title": "No"
134     }
135   ];
136
137   @Input() selectedNotification: any;
138   @Output() passEntry: EventEmitter<any> = new EventEmitter();
139   result: any;
140   isEditMode: any;
141   functionalMenuRes = {};
142   treedata = [];
143   checkBoxObj: any;
144
145   dataChange = new BehaviorSubject<TodoItemNode[]>([]);
146   get data(): TodoItemNode[] { return this.dataChange.value; }
147
148   constructor(public ngbModal: NgbModal, 
149     public activeModal: NgbActiveModal, 
150     private notificationService: NotificationService,
151     public functionalMenuService: FunctionalMenuService) { }
152
153   ngOnInit() {
154     this.notification.isFunctionalMenu='Y';
155     console.log("selectedNotification ::::",this.selectedNotification);
156     if(this.selectedNotification && this.selectedNotification.msgSource !=''){
157      
158       this.isEditMode = true;
159       this.notification = Object.assign({}, this.selectedNotification);
160       if(this.selectedNotification && this.selectedNotification.priority ==1 ){
161         this.notification.priority = this.priorityOptions[0].value;
162       }else{
163         this.notification.priority = this.priorityOptions[1].value;
164       }
165       if(this.selectedNotification && this.selectedNotification.startTime){
166         this.notification.startTime = new Date(this.selectedNotification.startTime);
167       }
168       if(this.selectedNotification && this.selectedNotification.endTime ){
169         this.notification.endTime = new Date(this.selectedNotification.endTime);
170       }
171       this.notification.isFunctionalMenu='Y';
172     }else{
173       this.isEditMode = false;
174       this.notification.isActive = this.isActiveOptions[0];
175       this.notification.isOnlineUsersOnly = this.onlineAllUsersOptions[1];
176       this.notification.isForAllRoles = this.isForAllRoles[0].value;
177       this.notification.priority = this.priorityOptions[0].value;
178       this.notification.isFunctionalMenu = "Y";      
179       this.notification.msgHeader = '';
180       this.notification.msgDescription = '';
181       this.notification.treeTitle = "Functional Menu";
182       this.notification.notifObj = {
183           isCategoriesFunctionalMenu: true
184       }
185     }
186     this.getFunctionalMenu();
187     this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren);
188     this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable);
189     this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
190     const data = this.buildFileTree(this.MAT_TREE_DATA, 0);
191     this.dataChange.next(data);
192     this.dataChange.subscribe(data => {
193       this.dataSource.data = data;
194     }); 
195   }
196
197   addUserNotification(){
198     let notificationRoleIds = []
199     let endDate = new Date(this.notification.endTime);
200     let selectedTreeNode: Array<TodoItemFlatNode> = this.checklistSelection.selected;
201     selectedTreeNode.forEach(element => {
202       if(element && element.roleIds && element.roleIds.length >0){
203         element.roleIds.forEach(id =>{
204           if(id && id !='undefined'){
205             notificationRoleIds.push(id);
206           }
207         });
208       }
209     });
210     console.log("notificationRoleIds >>>>>>>>",notificationRoleIds);
211     if(notificationRoleIds && notificationRoleIds.length >0){
212       notificationRoleIds.sort();
213     }
214     
215     let newUserNotification = {
216       'notificationId': (this.notification && this.notification.notificationId ? this.notification.notificationId: null),
217       'isForOnlineUsers': (this.notification && this.notification.isOnlineUsersOnly ? this.notification.isOnlineUsersOnly.value : null),
218       'isForAllRoles': this.notification.isForAllRoles,
219       'priority': this.notification.priority,
220       'activeYn': (this.notification && this.notification.isActive ? this.notification.isActive.value :'Y'),
221       'startTime': new Date(this.notification.startTime),
222       'endTime': new Date(this.notification.endTime),
223       'msgHeader': this.notification.msgHeader,
224       'msgDescription': this.notification.msgDescription,
225       'roleIds': notificationRoleIds,
226       'createdDate': new Date()
227     };
228
229     if((newUserNotification.isForAllRoles) && (newUserNotification.priority) && (newUserNotification.activeYn) 
230         && (newUserNotification.startTime) && (newUserNotification.endTime) 
231         && (newUserNotification.msgHeader != '') && (newUserNotification.msgDescription != '')){
232
233       console.log("newUserNotification >>> ",newUserNotification);
234       // POST ajax call here;
235       if (this.isEditMode) {
236         this.notificationService.updateAdminNotification(newUserNotification)
237         .subscribe(_data => {
238             this.result = _data;
239             if(this.result && this.result.status ==='ERROR'){
240               this.openConfirmationModal('Error', this.result.response);
241             }else{
242               this.passEntry.emit(this.result);
243               this.ngbModal.dismissAll(); 
244             }       
245         }, error =>{
246           console.log(error);
247           this.openConfirmationModal('Error', error);
248           return;
249         });
250       }else{
251         this.notificationService.addAdminNotification(newUserNotification)
252         .subscribe(_data => {
253             this.result = _data;
254             if(this.result && this.result.status ==='ERROR'){
255               this.openConfirmationModal('Error', this.result.response);
256               return;
257             }else{
258               this.passEntry.emit(this.result);
259               this.ngbModal.dismissAll(); 
260             }
261         }, error =>{
262           console.log(error);
263           this.openConfirmationModal('Error', error);
264           return;
265         });
266       }
267     }else{
268       this.openConfirmationModal("","Please fill in all required(*) fields.");
269       return;
270     }
271   }
272
273   getFunctionalMenu(){
274     let menu_role_dict = {};
275     /**First Rest Call */
276     this.functionalMenuService.getFunctionalMenuRole()
277     .subscribe(role_res => {
278         this.result = role_res;
279         if (this.result == null || this.result == 'undefined') {
280           console.log('FunctionalMenuService::getFunctionalMenu Failed: Result or result.data is null');
281         }else {
282           //console.log('First Rest Call Data ::',this.result);
283           for (var i in role_res) {
284             // if first time appear in menu_role_dict
285             if (!(role_res[i].menuId in menu_role_dict)) {
286                 menu_role_dict[role_res[i].menuId] = [role_res[i].roleId];
287             } else {
288                 menu_role_dict[role_res[i].menuId].push(role_res[i].roleId);
289             }
290           }
291
292           /** 2nd Rest Call */
293           this.functionalMenuService.getManagedFunctionalMenuForNotificationTree()
294           .subscribe(res => {
295               this.result = res;
296               //console.log("2nd REST CALL RESPONSE :: ",this.result);
297               var exclude_list = ['Favorites'];
298               let actualData = [];
299               //Adding children and label attribute to all objects in res
300               for (let i = 0; i < this.result.length; i++) {
301                 res[i].child = [];
302                 res[i].name = res[i].text;
303                 res[i].id = res[i].text;
304                 res[i].displayCheckbox = true;
305                 let checkBoxObj = {
306                     isAnyRoleSelected: false
307                 };
308                 res[i].roleId = menu_role_dict[res[i].menuId];
309                 res[i].onSelect = function() {
310                   this.notification.anyTreeItemSelected = this.checkTreeSelect();
311                 };
312
313                 let intersectionObj: any; 
314                 intersectionObj = res[i].roleId & this.notification.notificationRoleIds;
315                 if (res[i].roleId && res[i].roleId.length == intersectionObj.length) {
316                     res[i].isSelected = true;
317                     res[i].selected = true;
318                     res[i].indeterminate = false;
319                 } else {
320                     /*default*/
321                     res[i].isSelected = false;
322                     res[i].selected = false;
323                     res[i].indeterminate = false;
324                 }
325             }
326
327             // Adding actual child items to children array in res
328                         // objects
329             let parentChildDict = {};
330             let parentChildRoleIdDict = {};
331             for (let i = 0; i < this.result.length; i++) {
332                 let parentId = this.result[i].menuId;
333                 parentChildDict[parentId] = [];
334                 parentChildRoleIdDict[parentId] = [];
335                 for (let j = 0; j < this.result.length; j++) {
336                     let childId = res[j].parentMenuId;
337                     if (parentId === childId) {
338                         res[i].child.push(res[j]);
339                         parentChildDict[parentId].push(res[j].menuId);
340                         //if res[j].roleId is defined
341                         if (res[j].roleId) {
342                             for (let k in res[j].roleId) {
343                                 parentChildRoleIdDict[parentId].push(res[j].roleId[k]);
344                             }
345
346                         }
347                     }
348                 }
349             }
350             
351             //check if grand children exist
352             for (var key in parentChildDict) {
353               var child = parentChildDict[key];
354               var isGrandParent = false;
355               if (child.length > 0) {
356                   for (var i in child) {
357                       if (parentChildDict[child[i]].length > 0) {
358                           isGrandParent = true;
359                           break;
360                       }
361                   }
362               }
363               if (isGrandParent) {
364                   for (var i in child) {
365                       // if the child has children
366                       if (parentChildDict[child[i]].length > 0) {
367                           for (var j in parentChildRoleIdDict[child[i]]) {
368                               if (parentChildRoleIdDict[key].indexOf(parentChildRoleIdDict[child[i]][j]) === -1) {
369                                   parentChildRoleIdDict[key].push(parentChildRoleIdDict[child[i]][j]);
370                               }
371                           }
372                       }
373                   }
374               }
375
376           };
377
378           // Sort the top-level menu items in order based on the column
379           this.result.sort(function(a, b) {
380             return a.column - b.column;
381           });
382
383           // Sort all the child in order based on the column
384           for (let i = 0; i < this.result.length; i++) {
385               res[i].child.sort(function(a, b) {
386                   return a.column - b.column;
387               });
388           }
389
390           //Forming actual parent items
391           for (let i = 0; i < this.result.length; i++) {
392               let pmid = res[i].parentMenuId;
393               if (pmid === null) {
394                   actualData.push(res[i]);
395               }
396           }
397           var treedata = actualData[0].child;
398           
399           this.treedata = [];
400
401           /*Remove favorite from the list */
402           for (var i in treedata) {
403               if (!(treedata[i].name.indexOf(exclude_list) > -1)) {
404                   this.treedata.push(treedata[i])
405               }
406           }
407           //setting b2b tree parameter
408           this.settingTreeParam();
409           this.populateTreeDataSourceByFunctionalMenu(this.treedata);
410
411           }, error =>{
412             console.log(error);
413           });
414         }
415     }, error =>{
416       console.log(error);
417     });
418   }
419
420   settingTreeParam() {
421     /**************first level****************/
422     for (var fi = 0; fi < this.treedata.length; fi++) {
423         var fLevel = this.treedata[fi];
424         var sLevel = this.treedata[fi].child;
425         var sLevelSelectedCount = 0;
426         var sLevelChildNumber = 0
427         if (fLevel.child.length == 0 && fLevel.roleId == null) {
428             delete fLevel.child;
429         } else if (sLevel) {
430             /**************Second level****************/
431             var sLevelDelArray = [];
432             for (var si = 0; si < sLevel.length; si++) {
433                 var deletThisSLev = false;
434                 if (sLevel[si].child.length == 0 && sLevel[si].roleId == null) {
435                     sLevel[si].displayCheckbox = false;
436                     sLevelDelArray.push(sLevel[si].name);
437                     sLevel[si].name = '';
438                     sLevel[si].active = false;
439                     delete sLevel[si].child;
440                 } else if (sLevel[si].child.length == 0) {
441                     delete sLevel[si].child;
442                 } else {
443                     /**************Third level****************/
444                     var tLevel = sLevel[si].child;
445                     var tLevelSelectedCount = 0;
446                     var tLevelChildNumber = 0;
447                     if (tLevel) {
448                         var tLevelDelArray = [];
449                         var tLevelLen = tLevel.length;
450                         var tLevelRoleIdUndefined = 0;
451                         for (var ti = 0; ti < tLevel.length; ti++) {
452                             delete tLevel[ti].child;
453                             if (tLevel[ti].roleId == null) {
454                                 tLevel[ti].displayCheckbox = false;
455                                 tLevelDelArray.push(tLevel[ti].name);
456                                 tLevel[ti].name = '';
457                                 tLevel[ti].active = false;
458                                 tLevelRoleIdUndefined++
459                             } else {
460                                 if (tLevel[ti].isSelected)
461                                     tLevelSelectedCount++;
462
463                                 if (tLevel[ti].displayCheckbox)
464                                     tLevelChildNumber++;
465                             }
466                         }
467                         if (tLevelRoleIdUndefined == tLevelLen)
468                             deletThisSLev = true;
469                         if (tLevelSelectedCount == tLevelChildNumber) {
470                             sLevel[si].isSelected = true;
471                             sLevel[si].indeterminate = false;
472                             sLevel[si].active = true;
473                         } else if (tLevelSelectedCount > 0) {
474                             sLevel[si].indeterminate = true;
475                             sLevel[si].active = true;
476                         }
477
478                         /*Cleanup unused third level items*/
479                         for (var i = 0; i < tLevelDelArray.length; i++) {
480                             var name = tLevelDelArray[i];
481                             for (var ti = 0; ti < tLevel.length; ti++) {
482                                 if (name == tLevel[ti].text) {
483                                     tLevel.splice(ti, 1);
484                                     break;
485                                 }
486                             }
487                         }
488                     }
489                 }
490                 if (deletThisSLev) { //remove the whole second level item if all it's child has no roleId
491                     sLevel[si].displayCheckbox = false;
492                     sLevelDelArray.push(sLevel[si].name);
493                     sLevel[si].name = '';
494                     sLevel[si].active = false;
495                 } else {
496                     if (sLevel[si].isSelected)
497                         sLevelSelectedCount++;
498                     if (sLevel[si].displayCheckbox)
499                         sLevelChildNumber++;
500                 }
501             }
502             if (sLevelSelectedCount == sLevelChildNumber && sLevelChildNumber != 0) {
503                 fLevel.isSelected = true;
504                 fLevel.indeterminate = false;
505                 fLevel.active = true;
506             } else if (sLevelSelectedCount > 0) {
507                 fLevel.indeterminate = true;
508                 fLevel.active = true;
509             } else {
510                 //fLevel.active=false;
511                 fLevel.indeterminate = false;
512             }
513             /*Cleanup unused second level items*/
514             for (var i = 0; i < sLevelDelArray.length; i++) {
515                 var name = sLevelDelArray[i];
516                 for (var si = 0; si < sLevel.length; si++) {
517                     if (name == sLevel[si].text) {
518                         sLevel.splice(si, 1);
519                         break;
520                     }
521                 }
522             }
523         }
524     }
525 }
526
527   
528 checkTreeSelect() {
529     if (this.treedata) {
530         for (var fi = 0; fi < this.treedata.length; fi++) {
531             var fLevel = this.treedata[fi];
532             if (fLevel.isSelected) {
533                 return true;
534             }
535             var sLevel = fLevel.child;
536             if (sLevel) {
537                 for (var si = 0; si < sLevel.length; si++) {
538                     if (sLevel[si].isSelected) {
539                         return true;
540                     }
541                     var tLevel = sLevel[si].child;
542                     if (tLevel) {
543                         for (var ti = 0; ti < tLevel.length; ti++) {
544                             if (tLevel[ti].isSelected) {
545                                 return true;
546                             }
547                         }
548                     }
549                 }
550             }
551         }
552     }
553     return false;
554   }
555
556   getAppRoleIds() {
557     this.notification.notifObj = {
558         isCategoriesFunctionalMenu: false
559     };
560     this.notificationService.getAppRoleIds()
561       .subscribe(_data => {
562         this.result = _data;
563         let actualData = [];
564         var app_id_name_list = {};
565         this.checkBoxObj = {
566             isAnyRoleSelected: false
567         };
568         for (let i = 0; i < this.result.length; i++) {
569             if (!(this.result[i].appId in app_id_name_list)) {
570               app_id_name_list[this.result[i].appId] = this.result[i].appName;
571             }
572             this.result[i].child = [];
573             this.result[i].name = this.result[i].roleName;
574             this.result[i].displayCheckbox = true;
575             this.result[i].id = this.result[i].roleId;
576             this.result[i].menuId = this.result[i].roleId;
577             this.result[i].parentMenuId = this.result[i].appId;
578             this.result[i].can_check = true;
579             this.result[i].roleId = [this.result[i].roleId];
580             this.result[i].onSelect = function() {
581               this.notification.anyTreeItemSelected = this.checkTreeSelect();
582             };
583             /*assigning selected value*/
584             let intersectionObj: any; 
585             intersectionObj = this.result[i].roleId & this.notification.notificationRoleIds;
586             if (this.result[i].roleId && this.result[i].roleId.length == intersectionObj.length) {
587                 this.result[i].isSelected = true;
588                 this.result[i].selected = true;
589                 this.result[i].indeterminate = false;
590             } else {
591                 /*default*/
592                 this.result[i].isSelected = false;
593                 this.result[i].selected = false;
594                 this.result[i].indeterminate = false;
595             }       
596         }
597
598         for (var app_id in app_id_name_list) {
599
600           let new_res = {
601             'child': null,
602             'name': null,
603             'id': null,
604             'displayCheckbox': null,
605             'menuId': null,
606             'parentMenuId': '',
607             'appId': '',
608             'can_check': null,
609             'msgDescription': null,
610             'roleIds': null,
611             'roleId': null,
612             'onSelect': null,
613           };
614
615           new_res.child = [];
616           new_res.name = app_id_name_list[app_id];
617           new_res.id = app_id;
618           new_res.displayCheckbox = true;
619           new_res.menuId = app_id;
620           new_res.parentMenuId = null;
621           new_res.appId = null;
622           new_res.can_check = true;
623           new_res.roleId = null;
624           new_res.onSelect = function() {
625               this.notification.anyTreeItemSelected = this.checkTreeSelect();
626           };
627           this.result.push(new_res);
628         }
629
630         let parentChildRoleIdDict = {};
631         //Adding actual child items to child array in res objects
632         for (let i = 0; i < this.result.length; i++) {
633           let parentId = this.result[i].menuId;
634           parentChildRoleIdDict[parentId] = [];
635           for (let j = 0; j < this.result.length; j++) {
636             let childId = this.result[j].parentMenuId;
637             if (parentId == childId) {
638               this.result[i].child.push(this.result[j]);
639               if (this.result[j].roleId) {
640                 for (let k in this.result[j].roleId) {
641                   parentChildRoleIdDict[parentId].push(this.result[j].roleId[k]);
642                 }
643               }
644             }
645           }
646         }
647
648         //Forming actual parent items
649         for (let i = 0; i < this.result.length; i++) {
650           let parentId = this.result[i].parentMenuId;
651           if (parentId === null) {
652               actualData.push(this.result[i]);
653           }
654         }
655
656         this.treedata = actualData;
657         //setting correct parameters for b2b tree
658         this.settingTreeParam();
659         this.makeFinalTreeDataByProcessingAppRoleIds(this.treedata);
660
661       }, error =>{
662         console.log(error);
663       });
664   }
665
666   makeFinalTreeDataByProcessingAppRoleIds(treeData_approleids){
667     let datamap: any  = new Map();
668     let data = treeData_approleids;
669     
670     if(data && data.length > 0){
671       data.forEach(element => {
672         let iskeyPresent: boolean = false;
673         try{
674           if(datamap.get(element.id)){
675             iskeyPresent = true;
676           }
677         }catch(e){// 
678         }
679         if(iskeyPresent){
680           let temp = datamap.get(element.id);
681           temp.push(element);
682           datamap.set(element.id,temp)
683         }else{
684           datamap.set(element.id,element);
685         }  
686       });
687     }
688
689     if(datamap && datamap.size > 0){
690       let treeNode = {};
691       datamap.forEach((value, key) => {
692         if(value.child){
693           let keyname = "";
694           let childArray = [];
695           for(let item of value.child){
696             keyname = item.appName+"~"+'undefined';
697             let childItem = item.roleName+"~"+item.roleId;
698             childArray.push(childItem);
699           }
700           treeNode[keyname] = childArray;
701         }
702       });
703       console.log("makeFinalTreeDataByProcessingAppRoleIds >>",treeNode);
704
705       this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren);
706       this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable);
707       this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
708       const data = this.buildFileTree(treeNode, 0);
709       this.dataChange.next(data);
710       this.dataChange.subscribe(data => {
711         this.dataSource.data = data;
712       }); 
713     }
714   }
715
716   
717   /**
718    * Prepare Tree datasoure using functional Menu Data.
719    * @param functionMenuData 
720    */
721   populateTreeDataSourceByFunctionalMenu(functionMenuData: any){
722     console.log("populateTreeDataSourceByFunctionalMenu :: ",functionMenuData);
723     if(functionMenuData){
724       let treeNode = {};
725       functionMenuData.forEach(element => {
726         let name = element.text+"~"+element.roleId;
727         treeNode[name] = { };
728
729         if(element.child && element.child.length >0){
730           let childArray = [];
731           element.child.forEach(element => {
732             let childItem = element.text+"~"+element.roleId;
733             childArray.push(childItem); 
734           });
735           treeNode[name] = childArray;
736         }
737
738       });
739       console.log("treeNode>>",treeNode);
740
741       this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren);
742       this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable);
743       this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
744       const data = this.buildFileTree(treeNode, 0);
745       this.dataChange.next(data);
746       this.dataChange.subscribe(data => {
747         this.dataSource.data = data;
748       }); 
749     }
750  }
751
752  openConfirmationModal(_title: string, _message: string) {
753     const modalInfoRef = this.ngbModal.open(ConfirmationModalComponent);
754     modalInfoRef.componentInstance.title = _title;
755     modalInfoRef.componentInstance.message = _message;
756  }
757
758  openInformationModal(_title: string, _message: string){
759     const modalInfoRef = this.ngbModal.open(InformationModalComponent);
760     modalInfoRef.componentInstance.title = _title;
761     modalInfoRef.componentInstance.message = _message;
762     return modalInfoRef;
763  }
764   
765   
766   /*************************************** mat-tree code start here ******************************/
767
768   /** Map from flat node to nested node. This helps us finding the nested node to be modified */
769   flatNodeMap = new Map<TodoItemFlatNode, TodoItemNode>();
770   /** Map from nested node to flattened node. This helps us to keep the same object for selection */
771   nestedNodeMap = new Map<TodoItemNode, TodoItemFlatNode>();
772   /** A selected parent node to be inserted */
773   selectedParent: TodoItemFlatNode | null = null;
774   /** The new item's name */
775   newItemName = '';
776   treeControl: FlatTreeControl<TodoItemFlatNode>;
777   treeFlattener: MatTreeFlattener<TodoItemNode, TodoItemFlatNode>;
778   dataSource: MatTreeFlatDataSource<TodoItemNode, TodoItemFlatNode>;
779   /** The selection for checklist */
780   checklistSelection = new SelectionModel<TodoItemFlatNode>(true /* multiple */);
781   getLevel = (node: TodoItemFlatNode) => node.level;
782   isExpandable = (node: TodoItemFlatNode) => node.expandable;
783   getChildren = (node: TodoItemNode): TodoItemNode[] => node.children;
784   hasChild = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.expandable;
785   hasNoContent = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.item === '';
786
787   /**
788    * Transformer to convert nested node to flat node. Record the nodes in maps for later use.
789    */
790   transformer = (node: TodoItemNode, level: number) => {
791     const existingNode = this.nestedNodeMap.get(node);
792     const flatNode = existingNode && existingNode.item === node.item
793         ? existingNode
794         : new TodoItemFlatNode();
795     flatNode.item = node.item;
796     flatNode.level = level;
797     flatNode.expandable = !!node.children;
798     flatNode.roleIds = node.roleIds;
799     this.flatNodeMap.set(flatNode, node);
800     this.nestedNodeMap.set(node, flatNode);
801     return flatNode;
802   }
803
804   /** Whether all the descendants of the node are selected. */
805   descendantsAllSelected(node: TodoItemFlatNode): boolean {
806     const descendants = this.treeControl.getDescendants(node);
807     const descAllSelected = descendants.every(child =>
808       this.checklistSelection.isSelected(child)
809     );
810     return descAllSelected;
811   }
812
813   /** Whether part of the descendants are selected */
814   descendantsPartiallySelected(node: TodoItemFlatNode): boolean {
815     const descendants = this.treeControl.getDescendants(node);
816     const result = descendants.some(child => this.checklistSelection.isSelected(child));
817     return result && !this.descendantsAllSelected(node);
818   }
819
820   /** Toggle the to-do item selection. Select/deselect all the descendants node */
821   todoItemSelectionToggle(node: TodoItemFlatNode): void {
822     this.checklistSelection.toggle(node);
823     const descendants = this.treeControl.getDescendants(node);
824     this.checklistSelection.isSelected(node)
825       ? this.checklistSelection.select(...descendants)
826       : this.checklistSelection.deselect(...descendants);
827
828     // Force update for the parent
829     descendants.every(child =>
830       this.checklistSelection.isSelected(child)
831     );
832     this.checkAllParentsSelection(node);
833   }
834
835   /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
836   todoLeafItemSelectionToggle(node: TodoItemFlatNode): void {
837     this.checklistSelection.toggle(node);
838     this.checkAllParentsSelection(node);
839   }
840
841   /* Checks all the parents when a leaf node is selected/unselected */
842   checkAllParentsSelection(node: TodoItemFlatNode): void {
843     let parent: TodoItemFlatNode | null = this.getParentNode(node);
844     while (parent) {
845       this.checkRootNodeSelection(parent);
846       parent = this.getParentNode(parent);
847     }
848   }
849
850   /** Check root node checked state and change it accordingly */
851   checkRootNodeSelection(node: TodoItemFlatNode): void {
852     const nodeSelected = this.checklistSelection.isSelected(node);
853     const descendants = this.treeControl.getDescendants(node);
854     const descAllSelected = descendants.every(child =>
855       this.checklistSelection.isSelected(child)
856     );
857     if (nodeSelected && !descAllSelected) {
858       this.checklistSelection.deselect(node);
859     } else if (!nodeSelected && descAllSelected) {
860       this.checklistSelection.select(node);
861     }
862   }
863
864   /* Get the parent node of a node */
865   getParentNode(node: TodoItemFlatNode): TodoItemFlatNode | null {
866     const currentLevel = this.getLevel(node);
867
868     if (currentLevel < 1) {
869       return null;
870     }
871
872     const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;
873
874     for (let i = startIndex; i >= 0; i--) {
875       const currentNode = this.treeControl.dataNodes[i];
876
877       if (this.getLevel(currentNode) < currentLevel) {
878         return currentNode;
879       }
880     }
881     return null;
882   }
883
884
885   /**
886    * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
887    * The return value is the list of `TodoItemNode`.
888    */
889   buildFileTree(obj: {[key: string]: any}, level: number): TodoItemNode[] {
890     return Object.keys(obj).reduce<TodoItemNode[]>((accumulator, key) => {
891       const value = obj[key]; 
892       const node = new TodoItemNode();
893       node.item = key;
894             
895       if(key.indexOf("~") !== -1){
896         let nodeDetails  = key.split("~");
897         node.item = nodeDetails[0];
898         if(nodeDetails[1]){
899           node.roleIds = nodeDetails[1].split(",");
900         }else{
901           node.roleIds = [];
902         }
903       }
904
905       if (value != null) {
906         if (typeof value === 'object') {
907           node.children = this.buildFileTree(value, level + 1);
908         } else {
909           node.item = value;
910           if(value.indexOf("~") !== -1){
911             let nodeDetails  = value.split("~");
912             node.item = nodeDetails[0];
913             if(nodeDetails[1]){
914               node.roleIds = nodeDetails[1].split(",");
915             }else{
916               node.roleIds = [];
917             }
918           }
919         }
920       }
921
922       return accumulator.concat(node);
923     }, []);
924   }
925   /*************************************** mat-tree code end here ******************************/
926 }
927
928 /**
929  * Node for to-do item
930  */
931 export class TodoItemNode {
932   children: TodoItemNode[];
933   item: string;
934   roleIds: string[];
935 }
936
937 /** Flat to-do item node with expandable and level information */
938 export class TodoItemFlatNode {
939   item: string;
940   level: number;
941   expandable: boolean;
942   roleIds: string[];
943 }