140aea945e4921282eac0739e96599f9e34bab39
[portal.git] / ecomp-portal-FE-os / client / src / views / functionalMenu / functionalMenu-dialog / menu-details.controller.js
1 /*-
2  * ================================================================================
3  * ECOMP Portal
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property
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  * ================================================================================
19  */
20 /**
21  * Created by nnaffar on 12/20/15.
22  */
23 'use strict';
24 (function () {
25     class MenuDetailsModalCtrl {
26         constructor($scope, $log, functionalMenuService, errorMessageByCode, ECOMP_URL_REGEX,$rootScope,confirmBoxService) {
27
28
29             let newMenuModel = {
30                 name: null,
31                 menuId: null,
32                 parentMenuId: null,
33                 url: null
34             };
35
36             let getAvailableRoles = (appid) => {
37                 this.isSaving = true;
38                 if (appid != null) {
39                     $log.debug("MenuDetailsModalCtrl::getAvailableRoles: About to call getManagedRolesMenu");
40                     functionalMenuService.getManagedRolesMenu(appid).then(rolesObj => {
41                         $log.debug("MenuDetailsModalCtrl::getAvailableRoles: Roles returned = " + JSON.stringify(rolesObj))
42                         this.availableRoles = rolesObj;
43                         this.preSelectedRoles = {roles:[]};
44
45                         if(($scope.ngDialogData.source==='edit') && this.isMidLevelMenuItem()){
46                             // in Edit flow , for Midlevel menu item no need to preSelect.
47                             this.preSelectedRoles = {roles:[]};
48                         }else if(!angular.isUndefined(this.menuItem.menuDetails) &&
49                             $scope.ngDialogData.source==='edit' && this.isLeafMenuItem() &&
50                             this.menuItem.menuDetails.appid!=appid) {
51                             // in Edit flow , for LeafMenuItem, if appid changed then no need to preSelect.
52                             this.preSelectedRoles = {roles:[]};
53                         }else{
54                             if((!angular.isUndefined(this.menuItem.menuDetails)) &&
55                                 (!angular.isUndefined(this.menuItem.menuDetails.roles))){
56                                     $log.debug('menuDetails.roles: ' + this.menuItem.menuDetails.roles);
57                                     for(var i=0; i<this.menuItem.menuDetails.roles.length; i++){
58                                         var role = {"roleId":this.menuItem.menuDetails.roles[i]};
59                                         $log.debug('MenuDetailsModalCtrl::getAvailableRoles: adding role to preselected: ' + i + ': ' + JSON.stringify(role));
60                                         this.preSelectedRoles.roles.push(role);
61                                     }
62                             }
63                         }
64                         $rootScope.$broadcast('availableRolesReady');
65                         this.isSaving = false;
66                     }).catch(err => {
67                         $log.error("MenuDetailsModalCtrl::getAvailableRoles: error: " + err);
68                     });
69                 } else {
70                     $log.debug("MenuDetailsModalCtrl::getAvailableRoles: appid was null");
71                 }
72             };
73
74             let getAvailableApps = () => {
75                 functionalMenuService.getAvailableApplications().then(apps => {
76                     $log.debug("MenuDetailsModalCtrl::getAvailableApps: Apps returned = " + JSON.stringify(apps))
77                     this.availableApps = apps;
78                     // Keep track of whether or not the selected app is disabled
79                     if (angular.isDefined(this.selectedApp) && angular.isDefined(this.selectedApp.index)) {
80                         for (var i = 0; i < apps.length; i++) {
81                             if (apps[i].index === this.selectedApp.index) {
82                                 $log.debug("MenuDetailsModalCtrl::getAvailableApps: found app with index: " + this.selectedApp.index);
83                                 $log.debug("MenuDetailsModalCtrl::getAvailableApps: setting isDisabled to: " + !apps[i].enabled);
84                                 this.selectedApp.isDisabled = !apps[i].enabled;
85                                 break;
86                             }
87                         }
88                         $log.debug("didn't find index: " + this.selectedApp.index);
89                     }
90                 })['catch'](function (err) {
91                     confirmBoxService.showInformation('There was a problem retrieving the Applications. ' +
92                         'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
93                     $log.error("MenuDetailsModalCtrl::getAvailableApps: getAvailableApps error: " + err);
94                 }).finally(()=>{
95                     this.isSaving = false;
96                 });
97             };
98
99             let init = () => {
100                 $log.info('MenuDetailsModalCtrl::init');
101                 this.saveOrContinueBtnText = "Save";
102                 this.isSaving = false;
103                 this.displayRoles = $scope.ngDialogData.source==='view' ? true : false;
104                 this.formEditable = $scope.ngDialogData.source==='view' ? false : true;
105                 this.selectedRole = [];
106                 this.availableRoles = [];
107                 this.menuItem = _.clone($scope.ngDialogData.menuItem);
108                 $log.info('MenuDetailsModalCtrl::getAvailableApps: Within init, about to check menuDetails for defined');
109                 if(!angular.isUndefined(this.menuItem.menuDetails) &&
110                     ($scope.ngDialogData.source==='view' ||
111                     ($scope.ngDialogData.source==='edit') && this.isLeafMenuItem() )){
112
113                     $log.debug("MenuDetailsModalCtrl::init: menuItem: ");
114                     $log.debug('MenuDetailsModalCtrl::init: ',this.menuItem);
115                     this.menuItem.menu.url = this.menuItem.menuDetails.url;
116                     this.selectedApp={};
117                     this.selectedApp.index = this.menuItem.menuDetails.appid;
118                     getAvailableRoles(this.selectedApp.index);
119
120                 }
121
122                 if($scope.ngDialogData.source==='view' || $scope.ngDialogData.source==='edit'){
123                     this.menutitle = this.menuItem.menu.name;
124                     this.menuLocation = this.isParentMenuItem() ? this.menuItem.menu.name : this.menuItem.menu.parent.name;
125                 }else{
126                     this.menutitle = '';
127                     this.menuLocation = this.menuItem.menu.name;
128                 }
129                 // Temporarily passing 0 as dummy for getAvailableRoles incase of this.selectedApp is not there i.e., in Add flow
130                 //  getAvailableRoles(angular.isUndefined(this.selectedApp) ? 0: this.selectedApp.index );
131                 getAvailableApps();
132                 $log.debug("MenuDetailsModalCtrl::init: Menu details: " +  JSON.stringify(this.menuItem.menuDetails));
133             };
134
135
136             this.ECOMP_URL_REGEX = ECOMP_URL_REGEX;
137
138             //This part handles conflict errors (409)
139             this.conflictMessages = {};
140             this.scrollApi = {};
141             let handleConflictErrors = err => {
142                 if(!err.data){
143                     return;
144                 }
145                 if(!err.data.length){ //support objects
146                     err.data = [err.data]
147                 }
148                 $log.debug('MenuDetailsModalCtrl::handleConflictErrors: err.data = ' + JSON.stringify(err.data));
149                 _.forEach(err.data, item => {
150                     _.forEach(item.fields, field => {
151                         //set conflict message
152                         this.conflictMessages[field.name] = errorMessageByCode[item.errorCode];
153                         //set field as invalid
154                         $log.debug('MenuDetailsModalCtrl::handleConflictErrors: fieldName = ' + field.name);
155                         $scope.functionalMenuForm[field.name].$setValidity('conflict', false);
156                         //set watch once to clear error after user correction
157                         watchOnce[field.name]();
158                     });
159                 });
160                 this.scrollApi.scrollTop();
161             };
162
163             let resetConflict = fieldName => {
164                 delete this.conflictMessages[fieldName];
165                 $log.debug('MenuDetailsModalCtrl::resetConflict: $setValidity(true) = ' + fieldName);
166                 if($scope.functionalMenuForm[fieldName]){
167                     $scope.functionalMenuForm[fieldName].$setValidity('conflict', true);
168                 }
169             };
170
171             let watchOnce = {
172                 text: () => {
173                     let unregisterName = $scope.$watch('functionalMenuDetails.menutitle', (newVal, oldVal) => {
174                         // $log.debug('title:: newVal, oldVal = ' + newVal.toLowerCase() + " | " + oldVal.toLowerCase());
175                         if(newVal.toLowerCase() !== oldVal.toLowerCase()){
176                             resetConflict('text');
177                             unregisterName();
178                         }
179                     });
180                 },
181                 url: () => {
182                     let unregisterUrl = $scope.$watch('functionalMenuDetails.menuItem.menu.url', (newVal, oldVal) => {
183                         if(newVal.toLowerCase() !== oldVal.toLowerCase()){
184                             resetConflict('url');
185                             unregisterUrl();
186                         }
187                     });
188                 }
189             };
190
191             //***************************
192
193             this.isLeafMenuItem = () => {
194                 return this.menuItem.menu.children.length>0 ? false : true;
195             };
196
197             this.isMidLevelMenuItem = () => {
198                 return this.menuItem.menu.parentMenuId!=null && this.menuItem.menu.children.length>0 ? true : false;
199             };
200
201             this.isParentMenuItem = () => {
202                 return this.menuItem.menu.parentMenuId!=null ? false : true;
203             };
204
205             this.updateSelectedApp = (appItem) => {
206                 if (!appItem) {
207                     return;
208                 }
209                 $log.debug('MenuDetailsModalCtrl::updateSelectedApp: drop down app item = ' + JSON.stringify(appItem.index));
210                 $log.debug("MenuDetailsModalCtrl::updateSelectedApp: appItem in updateSelectedApp: ");
211                 $log.debug('MenuDetailsModalCtrl::updateSelectedApp: ',appItem);
212                 this.selectedApp.isDisabled = ! appItem.enabled;
213                 $log.debug("MenuDetailsModalCtrl::updateSelectedApp: isDisabled: "+this.selectedApp.isDisabled);
214                 getAvailableRoles(appItem.index);
215             };
216
217             this.continue = () => {
218                 this.displayRoles = true;
219                 this.formEditable = false;
220             };
221
222             this.saveChanges = () => {
223
224                 //todo : form validation was commented as dialog message is kept for error validations
225                 /*if($scope.functionalMenuForm.$invalid){
226                  return;
227                  }*/
228
229                 if(!!this.menuItem.menu.url && (angular.isUndefined(this.selectedApp) || !this.selectedApp.index>0)) {
230                     confirmBoxService.showInformation('Please select the appropriate app, or remove the url').then(isConfirmed => {});
231                     return;
232                 }else if(!this.menuItem.menu.url && !angular.isUndefined(this.selectedApp) && this.selectedApp.index>0){
233                     confirmBoxService.showInformation('Please enter url, or select "No Application"').then(isConfirmed => {});
234                     return;
235                 }else if(!this.menutitle){
236                     confirmBoxService.showInformation('Please enter the Menu title').then(isConfirmed => {});
237                     return;
238                 }
239
240                 this.isSaving = true;
241                 var activeMenuItem = {};
242
243                 if ($scope.ngDialogData.source === 'edit') {     // Edit Menu Item
244                     $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving an edit menu item');
245                     activeMenuItem = {
246                         menuId:this.menuItem.menu.menuId,
247                         column:this.menuItem.menu.column,
248                         text:this.menutitle,
249                         parentMenuId:this.menuItem.menu.parentMenuId,
250                         url:this.menuItem.menu.url,
251                         appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index,
252                         roles:this.selectedRole
253                     };
254                     // If we have removed the url and appid, we must remove the roles
255                     if (!activeMenuItem.appid && !activeMenuItem.url) {
256                         activeMenuItem.roles = null;
257                     }
258                     functionalMenuService.saveEditedMenuItem(activeMenuItem)
259                         .then(() => {
260                             $log.debug('MenuDetailsModalCtrl::saveChanges:  Menu Item saved');
261                             $scope.closeThisDialog(true);
262                         }).catch(err => {
263                         if(err.status === 409){//Conflict
264                             handleConflictErrors(err);
265                         } else {
266                             confirmBoxService.showInformation('There was a problem saving your change. ' +
267                                 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
268                         }
269                         $log.error('MenuDetailsModalCtrl::saveChanges: error - ',err);
270                     }).finally(()=>{
271                         this.isSaving = false;
272                     });
273
274                     $log.debug("MenuDetailsModalCtrl::saveChanges: Edit Menu output will be: " + JSON.stringify(activeMenuItem));
275                 } else {   // New Menu Item
276                     $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving a New menu item');
277                     var newMenuItem = {
278                         menuId:null, // this is a new menu item
279                         column:this.menuItem.menu.column,
280                         text:this.menutitle,
281                         // We are creating this new menu item under the menu item that was clicked on.
282                         parentMenuId:this.menuItem.menu.menuId,
283                         url:this.menuItem.menu.url,
284                         appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index,
285                         roles:this.selectedRole
286                     };
287
288                     $log.debug("MenuDetailsModalCtrl::saveChanges:  New Menu output will be: " + JSON.stringify(newMenuItem));
289                     functionalMenuService.saveMenuItem(newMenuItem)
290                         .then(() => {
291                             $log.debug('MenuDetailsModalCtrl::saveChanges:  Menu Item saved');
292                             $scope.closeThisDialog(true);
293                         }).catch(err => {
294                         if(err.status === 409){//Conflict
295                             handleConflictErrors(err);
296                         } else {
297                             confirmBoxService.showInformation('There was a problem saving your menu. ' +
298                                 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
299                         }
300                         $log.error('MenuDetailsModalCtrl::saveChanges error: ', err);
301                     }).finally(()=>{
302                         this.isSaving = false;
303                     });
304
305                 }
306             };
307
308             init();
309
310             $scope.$on('$stateChangeStart', e => {
311                 //Disable navigation when modal is opened
312                 e.preventDefault();
313             });
314         }
315     }
316     MenuDetailsModalCtrl.$inject = ['$scope', '$log', 'functionalMenuService', 'errorMessageByCode', 'ECOMP_URL_REGEX','$rootScope','confirmBoxService'];
317     angular.module('ecompApp').controller('MenuDetailsModalCtrl', MenuDetailsModalCtrl);
318
319     angular.module('ecompApp').directive('dropdownMultiselect', ['functionalMenuService',function(){
320         return {
321             restrict: 'E',
322             scope: {
323                 model: '=',
324                 options: '=',
325                 populated_roles: '=preSelected',
326                 dropdownTitle: '@',
327                 source: '='
328             },
329             template: "<div class='btn-group' data-ng-class='{open: open}'>" +
330             "<button class='btn btn-medium'>{{dropdownTitle}}</button>" +
331             "<button class='btn dropdown-toggle' data-ng-click='open=!open;openDropDown()'><span class='caret'></span></button>" +
332             "<ul class='dropdown-menu dropdown-menu-medium' aria-labelledby='dropdownMenu'>" +
333             "<li data-ng-repeat='option in options'> <input ng-disabled='setDisable(source)'  type='checkbox' data-ng-change='setSelectedItem(option.roleId)' ng-model='selectedItems[option.roleId]'>{{option.rolename}}</li>" +
334             "</ul>" +
335             "</div>",
336             controller: function ($scope) {
337                 $scope.selectedItems = {};
338                 $scope.checkAll = false;
339                 $scope.$on('availableRolesReady', function() {
340                     init();
341                 });
342
343                 function init() {
344                     console.log('dropdownMultiselect init');
345                     $scope.dropdownTitle = $scope.source ==='view' ? 'View Roles' : 'Select Roles';
346                     console.log('$scope.populated_roles = ' + $scope.populated_roles);
347                 }
348
349                 $scope.$watch('populated_roles', function(){
350                     if ($scope.populated_roles && $scope.populated_roles.length>0) {
351                         for (var i = 0; i < $scope.populated_roles.length; i++) {
352                             $scope.model.push($scope.populated_roles[i].roleId);
353                             $scope.selectedItems[$scope.populated_roles[i].roleId] = true;
354                         }
355                         if ($scope.populated_roles.length === $scope.options.length) {
356                             $scope.checkAll = true;
357                         }
358                     }else{
359                         deselectAll();
360                     }
361                 });
362
363                 $scope.openDropDown = function () {
364
365                 };
366
367                 $scope.checkAllClicked = function () {
368                     if ($scope.checkAll) {
369                         selectAll();
370                     } else {
371                         deselectAll();
372                     }
373                 };
374
375                 function selectAll() {
376                     $scope.model = [];
377                     $scope.selectedItems = {};
378                     angular.forEach($scope.options, function (option) {
379                         $scope.model.push(option.roleId);
380                     });
381                     angular.forEach($scope.model, function (id) {
382                         $scope.selectedItems[id] = true;
383                     });
384                     console.log($scope.model);
385                 };
386
387                 function deselectAll() {
388                     $scope.model = [];
389                     $scope.selectedItems = {};
390                     console.log($scope.model);
391                 };
392
393                 $scope.setSelectedItem = function (id) {
394                     var filteredArray = [];
395                     if ($scope.selectedItems[id] === true) {
396                         $scope.model.push(id);
397                     } else {
398                         filteredArray = $scope.model.filter(function (value) {
399                             return value != id;
400                         });
401                         $scope.model = filteredArray;
402                         $scope.checkAll = false;
403                     }
404                     console.log(filteredArray);
405                     return false;
406                 };
407
408                 $scope.setDisable = function(source){
409                     return source ==='view' ? true : false;
410                 }
411             }
412         }
413     }]);
414
415 })();