]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/admin/local/permission/app.js
LP#1812389: make Group Penalty Threshold admin page accessible again
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / admin / local / permission / app.js
1 angular.module('egAdminPermGrpTreeApp',
2     ['ngRoute','ui.bootstrap','egCoreMod','egUiMod','treeControl'])
3
4 .config(function($routeProvider, $locationProvider, $compileProvider) {
5     $locationProvider.html5Mode(true);
6     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/);
7
8     var resolver = {delay :
9         ['egStartup', function(egStartup) {return egStartup.go()}]}
10
11     $routeProvider.when('/admin/local/permission/grp_tree_display_entry', {
12         templateUrl : './admin/local/permission/t_grp_tree_display_entry',
13         controller : 'PermGrpTreeCtrl',
14         resolve : resolver
15     });
16
17     // catch admin/local/permission/grp_penalty_threshold
18     var eframe_template = 
19         '<eg-embed-frame allow-escape="true" min-height="min_height" url="local_admin_url" handlers="funcs"></eg-embed-frame>';
20     $routeProvider.when('/admin/local/:schema/:page', {
21         template: eframe_template,
22         controller: 'EmbedConifyCtl',
23         resolve : resolver
24     });
25
26     $routeProvider.otherwise({redirectTo : '/admin/local/permission/grp_tree'});
27 })
28
29 .factory('egPermGrpTreeSvc',
30         ['$q','egCore', function($q , egCore) {
31     var service = {
32         pgtde_array: [],
33         display_entries: [],
34         disabled_entries: [],
35         profiles: [],
36         edit_profiles: []
37     };
38
39     // determine which user groups our user is not allowed to modify
40     service.set_edit_profiles = function() {
41         var all_app_perms = [];
42         var failed_perms = [];
43
44         // extract the application permissions
45         angular.forEach(service.profiles, function(grp) {
46             if (grp.application_perm())
47                 all_app_perms.push(grp.application_perm());
48         }); 
49
50         // fill in service.edit_profiles by inspecting failed_perms
51         function traverse_grp_tree(grp, failed) {
52             failed = failed || 
53                 failed_perms.indexOf(grp.application_perm()) > -1;
54
55             if (!failed) service.edit_profiles.push(grp);
56
57             angular.forEach(
58                 service.profiles.filter( // children of grp
59                     function(p) { return p.parent() == grp.id() }),
60                 function(child) {traverse_grp_tree(child, failed)}
61             );
62         }
63
64         return egCore.perm.hasPermAt(all_app_perms, true).then(
65             function(perm_orgs) {
66                 angular.forEach(all_app_perms, function(p) {
67                     if (perm_orgs[p].length == 0)
68                         failed_perms.push(p);
69                 });
70
71                 traverse_grp_tree(egCore.env.pgt.tree);
72             }
73         );
74     }
75
76     service.get_perm_groups = function() {
77         if (egCore.env.pgt) {
78             service.profiles = egCore.env.pgt.list;
79             return service.set_edit_profiles();
80         } else {
81             return egCore.pcrud.search('pgt', {parent : null}, 
82                 {flesh : -1, flesh_fields : {pgt : ['children']}}
83             ).then(
84                 function(tree) {
85                     egCore.env.absorbTree(tree, 'pgt')
86                     service.profiles = egCore.env.pgt.list;
87                     return service.set_edit_profiles();
88                 }
89             );
90         }
91     }
92
93     service.fetchDisplayEntries = function(ou_id) {
94         service.edit_profiles = [];
95         service.get_perm_groups();
96         return egCore.pcrud.search('pgtde',
97             {org : egCore.org.ancestors(ou_id, true)},
98             { flesh : 1,
99               flesh_fields : {
100                   pgtde: ['grp', 'org']
101               },
102               order_by: {pgtde : 'id'}
103             },
104             {atomic: true}
105         ).then(function(entries) {
106             service.pgtde_array = [];
107             service.disabled_entries = [];
108             angular.forEach(entries, function(entry) {
109                 service.pgtde_array.push(entry);
110             });
111         });
112     }
113
114     service.organizeDisplayEntries = function(selectedOrg) {
115         service.display_entries = [];
116
117         angular.forEach(service.pgtde_array, function(pgtde) {
118             if (pgtde.org().id() == selectedOrg) {
119                 if (!pgtde.child_entries) pgtde.child_entries = [];
120                 var isChild = false;
121                 angular.forEach(service.display_entries, function(entry) {
122                     if (pgtde.parent() && pgtde.parent() == entry.id()) {
123                         entry.child_entries.push(pgtde);
124                         isChild = true;
125                         return;
126                     } else {
127                         if (service.iterateChildEntries(pgtde, entry)) {
128                             isChild = true;
129                             return;
130                         }
131                     }
132                 });
133                 if (!pgtde.parent() || !isChild) {
134                     service.display_entries.push(pgtde);
135                 }
136             }
137         });
138     }
139
140     service.iterateChildEntries = function(pgtde, entry) {
141         if (entry.child_entries.length) {
142             return angular.forEach(entry.child_entries, function(child) {
143                 if (pgtde.parent() == child.id()) {
144                     child.child_entries.push(pgtde);
145                     return true;
146                 } else {
147                     return service.iterateChildEntries(pgtde, child);
148                 }
149             });
150         }
151     }
152
153     service.updateDisplayEntries = function(tree, ou_id) {
154         return egCore.pcrud.search('pgtde',
155             {org : ou_id},
156             { flesh : 1,
157               flesh_fields : {
158                   pgtde: ['grp', 'org']
159               },
160               order_by: {pgtde : 'id'}
161             },
162             {atomic: true}
163         ).then(function(entries) {
164             return egCore.pcrud.update(tree).then(function(res) {
165                 return res;
166             });
167         });
168     }
169
170     service.removeDisplayEntries = function(entries) {
171         return egCore.pcrud.remove(entries).then(function(res) {
172             return res;
173         });
174     }
175
176     service.addDisplayEntries = function(entries) {
177         return egCore.pcrud.create(entries).then(function(res) {
178             return res;
179         });
180     }
181
182     service.findEntry = function(id, entries) {
183         var match;
184         angular.forEach(entries, function(entry) {
185             if (!match) {
186                 if (!entry.child_entries) entry.child_entries = [];
187                 if (id == entry.id()) {
188                     match = entry;
189                 } else if (entry.child_entries.length) {
190                     match = service.findEntry(id, entry.child_entries);
191                 }
192             }
193         });
194
195         return match;
196     }
197
198     return service;
199 }])
200
201 .controller('PermGrpTreeCtrl',
202     ['$scope','$q','$timeout','$location','$uibModal','egCore','egPermGrpTreeSvc', 'ngToast', 'egProgressDialog',
203 function($scope , $q , $timeout , $location , $uibModal , egCore , egPermGrpTreeSvc, ngToast, egProgressDialog) {
204     $scope.perm_tree = [{
205         grp: function() {
206             return {
207                 name: function() {return egCore.strings.ROOT_NODE_NAME;}
208             }
209         },
210         child_entries: [],
211         permanent: 'true'
212     }];
213     $scope.display_entries = [];
214     $scope.new_entries = [];
215     $scope.tree_options = {nodeChildren: 'child_entries'};
216     $scope.selected_entry;
217     $scope.expanded_nodes = [];
218     $scope.orderby = ['position()','grp().name()'];
219
220     if (!$scope.selectedOrg)
221         $scope.selectedOrg = egCore.org.get(egCore.auth.user().ws_ou());
222
223     $scope.updateSelection = function(node, selected) {
224         $scope.selected_entry = node;
225         if (!selected) $scope.selected_entry = null;
226     }
227
228     $scope.setPosition = function(node, direction) {
229         var newPos = node.position();
230         var siblings;
231         if (node.parent()) {
232             siblings = egPermGrpTreeSvc.findEntry(node.parent(), $scope.perm_tree[0].child_entries).child_entries;
233         } else {
234             siblings = $scope.perm_tree[0].child_entries;
235         }
236         if (direction == 'up' && newPos < siblings.length) newPos++;
237         if (direction == 'down' && newPos > 1) newPos--;
238
239         angular.forEach(siblings, function(entry) {
240             if (entry.position() == newPos) entry.position(node.position());
241             angular.forEach($scope.display_entries, function(display_entry) {
242                 if (display_entry.id() == entry.id()) {
243                     if (display_entry.position() == newPos) {
244                         display_entry.position(node.position);
245                     };
246                 }
247             });
248         });
249
250         angular.forEach($scope.display_entries, function(display_entry) {
251             if (display_entry.id() == node.id()) {
252                 display_entry.position(newPos);
253             }
254         });
255
256         node.position(newPos);
257     }
258
259     $scope.addChildEntry = function(node) {
260
261         $scope.openAddDialog(node, $scope.disabled_entries, $scope.edit_profiles, $scope.display_entries, $scope.selectedOrg)
262         .then(function(res) {
263             if (res) {
264
265                 var siblings = []
266                 var new_entry = new egCore.idl.pgtde();
267                 new_entry.org($scope.selectedOrg.id());
268                 new_entry.grp(res.selected_grp);
269                 new_entry.position(1);
270                 new_entry.child_entries = [];
271                 var is_expanded;
272                 if (res.selected_parent) {
273                     new_entry.parent(res.selected_parent);
274                     angular.forEach($scope.expanded_nodes, function(expanded_node) {
275                         if (expanded_node == res.selected_parent) is_expanded = true;
276                     });
277                     if (!is_expanded) $scope.expanded_nodes.push(res.selected_parent);
278                 } else {
279                     angular.forEach($scope.expanded_nodes, function(expanded_node) {
280                         if (expanded_node == $scope.perm_tree[0]) is_expanded = true;
281                     });
282                     if (!is_expanded) $scope.expanded_nodes.push($scope.perm_tree[0]);
283                 }
284
285                 $scope.display_entries.push(new_entry);
286                 egPermGrpTreeSvc.addDisplayEntries([new_entry]).then(function(addRes) {
287                     if (addRes) {
288                         if (res.is_root || !res.selected_parent) {
289                             angular.forEach($scope.perm_tree[0].child_entries, function(entry) {
290                                 var newPos = entry.position();
291                                 newPos++;
292                                 entry.position(newPos);
293                                 siblings.push(entry);
294                             });
295                         } else {
296                             var parent = egPermGrpTreeSvc.findEntry(res.selected_parent.id(), $scope.perm_tree[0].child_entries);
297                             angular.forEach(parent.child_entries, function(entry) {
298                                 var newPos = entry.position();
299                                 newPos++;
300                                 entry.position(newPos);
301                                 siblings.push(entry);
302                             });
303                         }
304
305                         egPermGrpTreeSvc.updateDisplayEntries(siblings).then(function(updateRes) {
306                             ngToast.create(egCore.strings.ADD_SUCCESS);
307                             $scope.refreshTree($scope.selectedOrg, $scope.selected_entry);
308                         });
309                     } else {
310                         ngToast.create(egCore.strings.ADD_FAILURE);
311                     }
312                 });
313             }
314         });
315     }
316
317     $scope.openAddDialog = function(node, disabled_entries, edit_profiles, display_entries, selected_org) {
318
319         return $uibModal.open({
320             templateUrl : './admin/local/permission/t_pgtde_add_dialog',
321             backdrop: 'static',
322             controller : [
323                         '$scope','$uibModalInstance',
324                 function($scope , $uibModalInstance) {
325                     var getIsRoot = function() {
326                         if (!node || node.permanent) return true;
327                         return false;
328                     }
329
330                     var getSelectedParent = function() {
331                         if (!node || node.permanent) return $scope.perm_tree;
332                         return node;
333                     }
334
335                     var available_profiles = [];
336                     angular.forEach(edit_profiles, function(grp) {
337                         grp._filter_grp = false;
338                         angular.forEach(display_entries, function(entry) {
339                             if (entry.org().id() == selected_org.id()) {
340                                 if (entry.grp().id() == grp.id()) grp._filter_grp = true;
341                             }
342                         });
343                         if (!grp._filter_grp) available_profiles.push(grp);
344                     });
345
346                     $scope.context = {
347                         is_root : getIsRoot(),
348                         selected_parent : getSelectedParent(),
349                         edit_profiles : available_profiles,
350                         display_entries : display_entries,
351                         selected_org : selected_org
352                     }
353
354                     $scope.context.selected_grp = $scope.context.edit_profiles[0];
355
356                     $scope.ok = function() {
357                         $uibModalInstance.close($scope.context);
358                     }
359
360                     $scope.cancel = function() {
361                         $uibModalInstance.dismiss();
362                     }
363                 }
364             ]
365         }).result;
366     }
367
368     var iteratePermTree = function(arr1, arr2) {
369         angular.forEach(arr1, function(entry) {
370             arr2.push(entry);
371             if (entry.child_entries) iteratePermTree(entry.child_entries, arr2);
372         });
373     }
374
375     $scope.removeEntry = function(node) {
376         $scope.disabled_entries.push(node);
377         iteratePermTree(node.child_entries, $scope.disabled_entries);
378
379         var siblings;
380         if (node.parent()) {
381             siblings = egPermGrpTreeSvc.findEntry(node.parent(), $scope.perm_tree[0].child_entries).child_entries;
382         } else {
383             siblings = $scope.perm_tree[0].child_entries;
384         }
385         angular.forEach(siblings, function(sibling) {
386             var newPos = sibling.position();
387             if (node.position() < sibling.position()) {
388                 newPos--;
389             }
390             sibling.position(newPos);
391         });
392
393         $scope.selected_entry = null;
394
395         egPermGrpTreeSvc.removeDisplayEntries($scope.disabled_entries).then(function(res) {
396             if (res) {
397                 ngToast.create(egCore.strings.REMOVE_SUCCESS);
398                 $scope.refreshTree($scope.selectedOrg);
399             } else {
400                 ngToast.create(egCore.strings.REMOVE_FAILURE);
401             }
402         })
403     }
404
405     var getDisplayEntries = function() {
406         $scope.edit_profiles = egPermGrpTreeSvc.edit_profiles;
407         egPermGrpTreeSvc.organizeDisplayEntries($scope.selectedOrg.id());
408         $scope.perm_tree[0].child_entries = egPermGrpTreeSvc.display_entries;
409         $scope.display_entries = egPermGrpTreeSvc.pgtde_array;
410         $scope.new_entries = [];
411         $scope.disabled_entries = [];
412         $scope.selected_entry = $scope.perm_tree[0];
413         if (!$scope.expanded_nodes.length) iteratePermTree($scope.perm_tree, $scope.expanded_nodes);
414     }
415
416     $scope.saveEntries = function() {
417         egProgressDialog.open();
418
419         // Save Remaining Display Entries
420         egPermGrpTreeSvc.updateDisplayEntries($scope.display_entries, $scope.selectedOrg.id())
421         .then(function(res) {
422             if (res) {
423                 ngToast.create(egCore.strings.UPDATE_SUCCESS);
424                 $scope.refreshTree($scope.selectedOrg, $scope.selected_entry);
425             } else {
426                 ngToast.create(egCore.strings.UPDATE_FAILURE);
427             }
428         }).finally(egProgressDialog.close);
429     }
430
431     $scope.org_changed = function(org) {
432         $scope.refreshTree(org.id());
433     }
434
435     $scope.refreshTree = function(ou_id, node) {
436         egPermGrpTreeSvc.fetchDisplayEntries(ou_id).then(function() {
437             getDisplayEntries();
438             if (node) $scope.selected_entry = node;
439         });
440     }
441
442     egCore.startup.go(function() {
443         $scope.refreshTree(egCore.auth.user().ws_ou());
444     });
445 }])
446
447 .controller('EmbedConifyCtl', 
448        ['$scope','$routeParams','$location','egCore',
449 function($scope , $routeParams , $location , egCore) {
450
451     $scope.funcs = {
452         ses : egCore.auth.token(),
453     }
454
455     var conify_path = '/eg/conify/global/' + 
456         $routeParams.schema + '/' + $routeParams.page;
457
458     $scope.min_height = 800;
459
460     // embed URL must include protocol/domain or it will be loaded via
461     // push-state, resulting in an infinitely nested pages.
462     $scope.local_admin_url = 
463         $location.absUrl().replace(/\/eg\/staff.*/, conify_path);
464
465     console.log('Loading local admin URL: ' + $scope.local_admin_url);
466
467 }])