]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/admin/serials/app.js
81f68e4aa424a0b95d92842f1cc2eecefbb2ab0d
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / admin / serials / app.js
1 angular.module('egSerialsAdmin',
2     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod'])
3
4 .config(['$routeProvider','$locationProvider','$compileProvider', 
5  function($routeProvider , $locationProvider , $compileProvider) {
6
7     $locationProvider.html5Mode(true);
8     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); 
9     var resolver = {delay : function(egStartup) {return egStartup.go()}};
10
11     $routeProvider.when('/admin/serials/templates', {
12         templateUrl: './admin/serials/t_templates',
13         controller: 'TemplatesCtrl',
14         resolve : resolver
15     });
16
17     // default page 
18     $routeProvider.otherwise({
19         templateUrl : './admin/serials/t_splash',
20         resolve : resolver
21     });
22 }])
23
24 // cheating
25 .factory("sharedScope",function(){
26     return {};
27 })
28
29 .factory('templateSvc', 
30        ['egCore','$q','$uibModal','ngToast',
31 function(egCore , $q , $uibModal , ngToast ) {
32
33     var service = {
34     };
35
36     service.create_or_edit_template = function(id,ou,cb) {
37         $uibModal.open({
38             template: '<eg-serials-template template_id="' + id + '" owning_lib="' + ou + '"></eg-serials-template>',
39             controller:
40                    ['sharedScope','$uibModalInstance',
41             function(sharedScope , $uibModalInstance ) {
42                 sharedScope.close_modal = function(count) { $uibModalInstance.close({}) }
43             }],
44             windowClass: 'app-modal-window',
45             backdrop: 'static',
46             keyboard: false
47         }).result.then(
48             function(args) {
49                 if (cb) { cb(); }
50             }
51         );
52     }
53
54     service.delete_template = function(id,cb) {
55         return egCore.pcrud.search('act',
56             {id : id},
57             null, {atomic : true}
58         ).then(function(resp) {
59             var evt = egCore.evt.parse(resp);
60             if (evt) { console.log(evt); }
61             if (!evt && resp && resp.length > 0) {
62                 return resp[0];
63             }
64         }).then(function(resp) {
65             resp.isdeleted(true); // needed?
66             return egCore.pcrud.remove(resp);
67         }).then(
68             function(resp) {
69                 console.log(resp);
70                 ngToast.success(egCore.strings.SERIALS_TEMPLATE_SUCCESS_DELETE);
71             },function(resp) {
72                 console.log(resp);
73                 ngToast.danger(egCore.strings.SERIALS_TEMPLATE_FAIL_DELETE);
74             }
75         ).finally(function() {
76             if (cb) { cb(); }
77         });
78     }
79
80     return service;
81 }])
82
83 .factory('itemSvc', 
84        ['egCore','$q',
85 function(egCore , $q) {
86
87     var service = {
88     };
89
90     service.get_locations = function(orgs) {
91         return egCore.pcrud.search('acpl',
92             {
93                 owning_lib : orgs,
94                 deleted    : 'f'
95             },
96             {
97                 flesh : 1,
98                 flesh_fields : {
99                     'acpl' : ['owning_lib']
100                 },
101                 order_by : { acpl : 'name' }
102             }, {atomic : true}
103         );
104     };
105
106     service.get_statuses = function() {
107         if (egCore.env.ccs)
108             return $q.when(egCore.env.ccs.list);
109
110         return egCore.pcrud.retrieveAll('ccs', {order_by : { ccs : 'name' }}, {atomic : true}).then(
111             function(list) {
112                 egCore.env.absorbList(list, 'ccs');
113                 return list;
114             }
115         );
116
117     };
118
119     service.get_circ_mods = function() {
120         if (egCore.env.ccm)
121             return $q.when(egCore.env.ccm.list);
122
123         return egCore.pcrud.retrieveAll('ccm', {}, {atomic : true}).then(
124             function(list) {
125                 egCore.env.absorbList(list, 'ccm');
126                 return list;
127             }
128         );
129
130     };
131
132     service.get_circ_types = function() {
133         if (egCore.env.citm)
134             return $q.when(egCore.env.citm.list);
135
136         return egCore.pcrud.retrieveAll('citm', {}, {atomic : true}).then(
137             function(list) {
138                 egCore.env.absorbList(list, 'citm');
139                 return list;
140             }
141         );
142
143     };
144
145     service.get_age_protects = function() {
146         if (egCore.env.crahp)
147             return $q.when(egCore.env.crahp.list);
148
149         return egCore.pcrud.retrieveAll('crahp', {}, {atomic : true}).then(
150             function(list) {
151                 egCore.env.absorbList(list, 'crahp');
152                 return list;
153             }
154         );
155
156     };
157
158     service.get_floating_groups = function() {
159         if (egCore.env.cfg)
160             return $q.when(egCore.env.cfg.list);
161
162         return egCore.pcrud.retrieveAll('cfg', {}, {atomic : true}).then(
163             function(list) {
164                 egCore.env.absorbList(list, 'cfg');
165                 return list;
166             }
167         );
168
169     };
170
171     service.bmp_parts = {};
172     service.get_parts = function(rec) {
173         if (service.bmp_parts[rec])
174             return $q.when(service.bmp_parts[rec]);
175
176         return egCore.pcrud.search('bmp',
177             {record : rec, deleted : 'f'},
178             null, {atomic : true}
179         ).then(function(list) {
180             service.bmp_parts[rec] = list;
181             return list;
182         });
183
184     };
185
186     return service;
187 }])
188
189 .controller('TemplatesCtrl', 
190        ['$scope','$q','$window','$routeParams','$location','$timeout','egCore','egNet','itemSvc','templateSvc',
191         'egGridDataProvider',
192 function($scope , $q , $window , $routeParams , $location , $timeout , egCore , egNet , itemSvc , templateSvc ,
193          egGridDataProvider ) {
194
195     function current_query() {
196         var filter = {
197             'owning_lib' : egCore.org.descendants($scope.context_ou.id(), true)
198         };
199         return filter;
200     }
201
202     function refresh_page() {
203         $scope.grid_controls.setQuery(current_query());
204     }
205
206     $scope.grid_actions = {
207         create_template : function() {
208             templateSvc.create_or_edit_template(null,$scope.context_ou.id(),refresh_page);
209         },
210         edit_template : function(items) {
211             templateSvc.create_or_edit_template(items[0].id,$scope.context_ou.id(),refresh_page);
212         },
213         delete_template : function(items) {
214             var promises = [];
215             angular.forEach(items,function(item) {
216                 promises.push(templateSvc.delete_template(item.id));
217             });
218             $q.all(promises).then(function() {
219                 refresh_page();
220             });
221         }
222     }
223     $scope.grid_controls = {
224         activateItem : function(item) {
225             templateSvc.create_or_edit_template(item.id,$scope.context_ou.id(),refresh_page);
226         },
227         setQuery : function(x) { return x || current_query(); },
228         setSort : function() { return ['name','id'] }
229     }
230
231     $scope.need_one_selected = function() {
232         var items = $scope.grid_controls.selectedItems();
233         if (items.length == 1) return false;
234         return true;
235     };
236
237     // called after any egGridActions action occurs
238     $scope.grid_actions.refresh = refresh_page;
239
240     // re-draw the grid when user changes the org selector
241     $scope.context_ou = egCore.org.get(egCore.auth.user().ws_ou());
242     $scope.$watch('context_ou', function(newVal, oldVal) {
243         if (newVal && newVal != oldVal) 
244             refresh_page();
245     });
246
247     refresh_page();
248
249 }])
250
251 .directive("egSerialsTemplate", function () {
252     return {
253         restrict: 'E',
254         replace: true,
255         template: '<div ng-include="'+"'/eg/staff/admin/serials/t_attr_edit'"+'"></div>',
256         scope: {
257             templateId: '=',
258              owningLib: '='
259         },
260         controller : ['$scope','$q','$window','itemSvc','egCore','ngToast','sharedScope',
261             function ( $scope , $q , $window , itemSvc , egCore , ngToast , sharedScope ) {
262
263                 $scope.close_modal = function() {
264                     if ($scope.dirty && !window.confirm(egCore.strings.CONFIRM_DIRTY_EXIT)) {
265                         return;
266                     }
267                     //console.log('unsetting dirty for close_modal');
268                     $scope.dirty = false;
269                     sharedScope.close_modal();
270                 };
271
272                 $scope.defaults = { // If defaults are not set at all, allow everything
273                     attributes : {
274                         status : true,
275                         loan_duration : true,
276                         fine_level : true,
277                         alerts : true,
278                         deposit : true,
279                         deposit_amount : true,
280                         opac_visible : true,
281                         price : true,
282                         circulate : true,
283                         mint_condition : true,
284                         circ_lib : true,
285                         ref : true,
286                         circ_modifier : true,
287                         circ_as_type : true,
288                         location : true,
289                         holdable : true,
290                         age_protect : true,
291                         floating : true
292                     }
293                 };
294
295                 $scope.fetchDefaults = function () {
296                     egCore.hatch.getItem('serials.copy.defaults').then(function(t) {
297                         if (t) {
298                             $scope.defaults = t;
299                         }
300                     });
301                 }
302                 $scope.fetchDefaults();
303
304                 //console.log('unsetting dirty by default');
305                 $scope.dirty = false;
306                 $scope.$watch('dirty',
307                     function(newVal, oldVal) {
308                         //console.log('watching dirty');
309                         //console.log('...oldVal',oldVal);
310                         //console.log('...newVal',newVal);
311                         //console.log('...fetching',$scope.fetching);
312                         if (newVal && $scope.fetching) {
313                             // KLUDGY
314                             // so after fetchTemplate -> applyTemplate
315                             // the working watches will fire and set
316                             // dirty to true.  We'll undo that at this
317                             // point.
318                             //console.log('unsetting dirty via kludge');
319                             $scope.fetching = false;
320                             $scope.dirty = false;
321                             newVal = false;
322                         }
323                         if (newVal && newVal != oldVal) {
324                             $($window).on('beforeunload.template', function(){
325                                 return 'There is unsaved template data!'
326                             });
327                         } else {
328                             $($window).off('beforeunload.template');
329                         }
330                     }
331                 );
332
333                 $scope.applyTemplate = function() {
334                     //console.log('applying...');
335                     angular.forEach($scope.hashed_template, function (v,k) {
336                         //console.log(k,v);
337                         if (k == 'circ_lib') {
338                             $scope.working[k] = egCore.org.get(v);
339                         } else if (!angular.isObject(v)) {
340                             $scope.working[k] = angular.copy(v);
341                         } else {
342                             angular.forEach(v, function (sv,sk) {
343                                 if (!(k in $scope.working))
344                                     $scope.working[k] = {};
345                                 $scope.working[k][sk] = angular.copy(sv);
346                             });
347                         }
348                     });
349                     //console.log('unsetting dirty via applyTemplate');
350                     $scope.dirty = false;
351                 }
352
353                 $scope.fetching = false;
354                 $scope.fetchTemplate = function () {
355                     $scope.fetching = true;
356                     return egCore.pcrud.search('act',
357                         {id : $scope.templateId},
358                         null, {atomic : true}
359                     ).then(function(resp) {
360                         var evt = egCore.evt.parse(resp);
361                         if (evt) { console.log(evt); }
362                         if (!evt && resp && resp.length > 0) {
363                             $scope.fm_template =  resp[0];
364                             $scope.hashed_template = egCore.idl.toHash(resp[0]); 
365                             $scope.applyTemplate();
366                         } else {
367                             console.log('new template');
368                         }
369                     });
370                 }
371  
372                 $scope.saveTemplate = function() {
373                     var tmpl = {};
374         
375                     angular.forEach($scope.working, function (v,k) {
376                         if (angular.isObject(v)) { // we'll use the pkey
377                             if (v.id) v = v.id();
378                             else if (v.code) v = v.code();
379                         }
380         
381                         tmpl[k] = v;
382                     });
383         
384                     $scope.hashed_template = tmpl;
385
386                     var act_obj = $scope.fm_template || new egCore.idl.act() ;
387                     //console.log('consuming...');
388                     angular.forEach($scope.hashed_template, function (v,k) {
389                         //console.log(k,v);
390                         if (typeof act_obj[k] == 'function') {
391                             act_obj[k](v);
392                         } else {
393                             console.log('something wrong here',k,act_obj[k]);
394                         }
395                     });
396                     if ($scope.fm_template) {
397                         console.log('edit');
398                         act_obj.ischanged('t');
399                         act_obj.editor( egCore.auth.user().id() );
400                         act_obj.edit_date( new Date() );
401                     } else {
402                         console.log('create');
403                         act_obj.isnew('t');
404                         act_obj.creator( egCore.auth.user().id() );
405                         act_obj.owning_lib( $scope.owningLib );
406                         act_obj.create_date( new Date() );
407                     }
408                     var some_failure = false;
409                     var some_success = false;
410                     egCore.net.request(
411                         'open-ils.cat', // worth replacing with pcrud?
412                         'open-ils.cat.asset.copy_template.create_or_update',
413                         egCore.auth.token(),
414                         act_obj
415                     ).then(
416                         function(resp) {
417                             var evt = egCore.evt.parse(resp);
418                             if (evt) { // any way to just throw or return this to the error handler?
419                                 console.log('failure',resp);
420                                 some_failure = true;
421                                 ngToast.danger(egCore.strings.SERIALS_TEMPLATE_FAIL_SAVE);
422                             } else {
423                                 console.log('success',resp);
424                                 some_success = true;
425                                 ngToast.success(egCore.strings.SERIALS_TEMPLATE_SUCCESS_SAVE);
426                             }
427                         },
428                         function(resp) {
429                             console.log('failure',resp);
430                             some_failure = true;
431                             ngToast.danger(egCore.strings.SERIALS_TEMPLATE_FAIL_SAVE);
432                         }
433                     ).then(function(){
434                         if (some_success && !some_failure) {
435                             //console.log('unsetting dirty for save');
436                             $scope.dirty = false;
437                             $scope.close_modal();
438                         }
439                     });
440                 }
441             
442                 $scope.hashed_template = {};
443                 $scope.imported_template = { data : '' };
444                 $scope.fetchTemplate();
445
446                 // FIXME - leaving this for now
447                 $scope.$watch('imported_template.data', function(newVal, oldVal) {
448                     if (newVal && newVal != oldVal) {
449                         try {
450                             var newTemplate = JSON.parse(newVal);
451                             if (!Object.keys(newTemplate).length) return;
452                             $scope.hashed_template = newTemplate;
453                         } catch (E) {
454                             console.log('tried to import an invalid serials template file');
455                         }
456                     }
457                 });
458
459                 $scope.orgById = function (id) { return egCore.org.get(id) }
460                 $scope.statusById = function (id) {
461                     return $scope.status_list.filter( function (s) { return s.id() == id } )[0];
462                 }
463                 $scope.locationById = function (id) {
464                     return $scope.location_cache[''+id];
465                 }
466             
467                 createSimpleUpdateWatcher = function (field) {
468                     $scope.$watch('working.' + field, function () {
469                         var newval = $scope.working[field];
470             
471                         if (typeof newval != 'undefined') {
472                             //console.log('setting dirty for field',field);
473                             $scope.dirty = true;
474                             if (angular.isObject(newval)) { // we'll use the pkey
475                                 if (newval.id) $scope.working[field] = newval.id();
476                                 else if (newval.code) $scope.working[field] = newval.code();
477                             }
478             
479                             if (""+newval == "" || newval == null) {
480                                 $scope.working[field] = undefined;
481                             }
482             
483                         }
484                     });
485                 }
486
487                 $scope.clearWorking = function () {
488                     angular.forEach($scope.working, function (v,k,o) {
489                         if (!angular.isObject(v)) {
490                             if (typeof v != 'undefined')
491                                 $scope.working[k] = undefined;
492                         } else if (k != 'circ_lib') {
493                             angular.forEach(v, function (sv,sk) {
494                                 $scope.working[k][sk] = undefined;
495                             });
496                         }
497                     });
498                     $scope.working.circ_lib = undefined; // special
499                     $scope.working.loan_duration = 2;
500                     $scope.working.fine_level    = 2;
501                     //console.log('unsetting dirty for clearWorking');
502                     $scope.dirty = false;
503                 }
504
505                 $scope.working = {
506                     loan_duration : 2,
507                     fine_level    : 2
508                 };
509                 $scope.location_orgs = [];
510                 $scope.location_cache = {};
511
512                 $scope.i18n = egCore.i18n;
513                 $scope.location_list = [];
514                 itemSvc.get_locations(
515                     egCore.org.fullPath( egCore.auth.user().ws_ou(), true )
516                 ).then(function(list){
517                     $scope.location_list = list;
518                 });
519                 createSimpleUpdateWatcher('location');
520
521                 $scope.status_list = [];
522                 itemSvc.get_statuses().then(function(list){
523                     $scope.status_list = list;
524                 });
525                 createSimpleUpdateWatcher('status');
526             
527                 $scope.circ_modifier_list = [];
528                 itemSvc.get_circ_mods().then(function(list){
529                     $scope.circ_modifier_list = list;
530                 });
531                 createSimpleUpdateWatcher('circ_modifier');
532             
533                 $scope.circ_type_list = [];
534                 itemSvc.get_circ_types().then(function(list){
535                     $scope.circ_type_list = list;
536                 });
537                 createSimpleUpdateWatcher('circ_as_type');
538             
539                 $scope.age_protect_list = [];
540                 itemSvc.get_age_protects().then(function(list){
541                     $scope.age_protect_list = list;
542                 });
543                 createSimpleUpdateWatcher('age_protect');
544             
545                 createSimpleUpdateWatcher('circulate');
546                 createSimpleUpdateWatcher('holdable');
547
548                 $scope.loan_duration_options = [
549                     {
550                         v: function(){return 1;},
551                         l: function(){return egCore.strings.LOAN_DURATION_SHORT;}
552                     },
553                     {
554                         v: function(){return 2;},
555                         l: function(){return egCore.strings.LOAN_DURATION_NORMAL;}
556                     },
557                     {
558                         v: function(){return 3;},
559                         l: function(){return egCore.strings.LOAN_DURATION_EXTENDED;}
560                     }
561                 ];
562                 createSimpleUpdateWatcher('loan_duration');
563
564                 $scope.fine_level_options = [
565                     {
566                         v: function(){return 1;},
567                         l: function(){return egCore.strings.FINE_LEVEL_LOW;}
568                     },
569                     {
570                         v: function(){return 2;},
571                         l: function(){return egCore.strings.FINE_LEVEL_NORMAL;}
572                     },
573                     {
574                         v: function(){return 3;},
575                         l: function(){return egCore.strings.FINE_LEVEL_HIGH;}
576                     }
577                 ];
578                 createSimpleUpdateWatcher('fine_level');
579
580                 createSimpleUpdateWatcher('name');
581                 createSimpleUpdateWatcher('price');
582                 createSimpleUpdateWatcher('deposit');
583                 createSimpleUpdateWatcher('deposit_amount');
584                 createSimpleUpdateWatcher('mint_condition');
585                 createSimpleUpdateWatcher('opac_visible');
586                 createSimpleUpdateWatcher('ref');
587             }
588         ]
589     }
590 })
591
592