]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
webstaff: Layout improvements and templates
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / cat / volcopy / app.js
1 /**
2  * Vol/Copy Editor
3  */
4
5 angular.module('egVolCopy',
6     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod'])
7
8 .filter('boolText', function(){
9     return function (v) {
10         return v == 't';
11     }
12 })
13
14 .config(function($routeProvider, $locationProvider, $compileProvider) {
15     $locationProvider.html5Mode(true);
16     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); // grid export
17
18     var resolver = {
19         delay : ['egStartup', function(egStartup) { return egStartup.go(); }]
20     };
21
22     $routeProvider.when('/cat/volcopy/:dataKey', {
23         templateUrl: './cat/volcopy/t_view',
24         controller: 'EditCtrl',
25         resolve : resolver
26     });
27
28 })
29
30 .factory('itemSvc', 
31        ['egCore','$q',
32 function(egCore , $q) {
33
34     var service = {
35         tree : {}, // holds lib->cn->copy hash stack
36         copies : [] // raw copy list
37     };
38
39     // returns a promise resolved with the list of circ mods
40     service.get_classifications = function() {
41         if (egCore.env.acnc)
42             return $q.when(egCore.env.acnc.list);
43
44         return egCore.pcrud.retrieveAll('acnc', null, {atomic : true})
45         .then(function(list) {
46             egCore.env.absorbList(list, 'acnc');
47             return list;
48         });
49     };
50
51     service.get_prefixes = function(org) {
52         return egCore.pcrud.search('acnp',
53             {owning_lib : egCore.org.fullPath(org, true)},
54             null, {atomic : true}
55         );
56
57     };
58
59     service.get_locations = function(orgs) {
60         return egCore.pcrud.search('acpl',
61             {owning_lib : orgs},
62             null, {atomic : true}
63         );
64     };
65
66     service.get_suffixes = function(org) {
67         return egCore.pcrud.search('acns',
68             {owning_lib : egCore.org.fullPath(org, true)},
69             null, {atomic : true}
70         );
71
72     };
73
74     service.get_statuses = function() {
75         if (egCore.env.ccs)
76             return $q.when(egCore.env.ccs.list);
77
78         return egCore.pcrud.retrieveAll('ccs', {}, {atomic : true}).then(
79             function(list) {
80                 egCore.env.absorbList(list, 'ccs');
81                 return list;
82             }
83         );
84
85     };
86
87     service.get_circ_mods = function() {
88         if (egCore.env.ccm)
89             return $q.when(egCore.env.ccm.list);
90
91         return egCore.pcrud.retrieveAll('ccm', {}, {atomic : true}).then(
92             function(list) {
93                 egCore.env.absorbList(list, 'ccm');
94                 return list;
95             }
96         );
97
98     };
99
100     service.get_circ_types = function() {
101         if (egCore.env.citm)
102             return $q.when(egCore.env.citm.list);
103
104         return egCore.pcrud.retrieveAll('citm', {}, {atomic : true}).then(
105             function(list) {
106                 egCore.env.absorbList(list, 'citm');
107                 return list;
108             }
109         );
110
111     };
112
113     service.get_age_protects = function() {
114         if (egCore.env.crahp)
115             return $q.when(egCore.env.crahp.list);
116
117         return egCore.pcrud.retrieveAll('crahp', {}, {atomic : true}).then(
118             function(list) {
119                 egCore.env.absorbList(list, 'crahp');
120                 return list;
121             }
122         );
123
124     };
125
126     service.bmp_parts = {};
127     service.get_parts = function(rec) {
128         if (service.bmp_parts[rec])
129             return $q.when(service.bmp_parts[rec]);
130
131         return egCore.pcrud.search('bmp',
132             {record : rec},
133             null, {atomic : true}
134         ).then(function(list) {
135             service.bmp_parts[rec] = list;
136             return list;
137         });
138
139     };
140
141     service.flesh = {   
142         flesh : 3, 
143         flesh_fields : {
144             acp : ['call_number','parts'],
145             acn : ['label_class','prefix','suffix']
146         }
147     }
148
149     service.addCopy = function (cp) {
150
151         if (!cp.parts()) cp.parts([]); // just in case...
152
153         var lib = cp.call_number().owning_lib();
154         var cn = cp.call_number().id();
155
156         if (!service.tree[lib]) service.tree[lib] = {};
157         if (!service.tree[lib][cn]) service.tree[lib][cn] = [];
158
159         service.tree[lib][cn].push(cp);
160         service.copies.push(cp);
161     }
162
163     service.fetchIds = function(idList) {
164         service.tree = {}; // clear the tree on fetch
165         service.copies = []; // clear the copy list on fetch
166         return egCore.pcrud.search('acp', { 'id' : idList }, service.flesh).then(null,null,
167             function(copy) {
168                 service.addCopy(copy);
169             }
170         );
171     }
172
173     return service;
174 }])
175
176 .directive("egVolCopyEdit", function () {
177     return {
178         restrict: 'E',
179         replace: true,
180         template:
181             '<div class="row">'+
182                 '<div class="col-xs-5">'+
183                     '<input id="{{callNumber.id()}}.{{copy.id()}}"'+
184                     ' eg-enter="nextBarcode()" class="form-control"'+
185                     ' type="text" ng-model="barcode" ng-change="updateBarcode()"/>'+
186                 '</div>'+
187                 '<div class="col-xs-3"><input class="form-control" type="number" ng-model="copy_number" ng-change="updateCopyNo()"/></div>'+
188                 '<div class="col-xs-4"><eg-basic-combo-box list="parts" selected="part"></eg-basic-combo-box></div>'+
189             '</div>',
190
191         scope: { copy: "=", callNumber: "=", index: "@" },
192         controller : ['$scope','itemSvc',
193             function ( $scope , itemSvc ) {
194                 $scope.new_part_id = 0;
195
196                 $scope.nextBarcode = function (i) {
197                     $scope.$parent.focusNextBarcode($scope.copy.id());
198                 }
199
200                 $scope.updateBarcode = function () { $scope.copy.barcode($scope.barcode); $scope.copy.ischanged(1); };
201                 $scope.updateCopyNo = function () { $scope.copy.copy_number($scope.copy_number); $scope.copy.ischanged(1); };
202                 $scope.updatePart = function () {
203                     var p = $scope.part_list.filter(function (x) {
204                         return x.label() == $scope.part
205                     });
206                     if (p.length > 0) { // preexisting part
207                         $scope.copy.parts(p)
208                     } else { // create one...
209                         var part = new egCore.idl.bmp();
210                         part.id( --$scope.new_part_id );
211                         part.isnew( true );
212                         part.label( $scope.part );
213                         part.record( $scope.callNumber.owning_lib() );
214                         $scope.copy.parts([part]);
215                         $scope.copy.ischanged(1);
216                     }
217                 }
218
219                 $scope.barcode = $scope.copy.barcode();
220                 $scope.copy_number = $scope.copy.copy_number();
221
222                 if ($scope.copy.parts()) {
223                     $scope.part = $scope.copy.parts()[0];
224                     if ($scope.part) $scope.part = $scope.part.label();
225                 };
226
227                 $scope.parts = [];
228                 $scope.part_list = [];
229
230                 itemSvc.get_parts($scope.callNumber.record()).then(function(list){
231                     $scope.part_list = list;
232                     angular.forEach(list, function(p){ $scope.parts.push(p.label()) });
233                 });
234
235             }
236         ]
237
238     }
239 })
240
241 .directive("egVolRow", function () {
242     return {
243         restrict: 'E',
244         replace: true,
245         transclude: true,
246         template:
247             '<div class="row">'+
248                 '<div class="col-xs-2">'+
249                     '<select class="form-control" ng-model="classification" ng-options="cl.name() for cl in classification_list track by idTracker(cl)"/>'+
250                 '</div>'+
251                 '<div class="col-xs-1">'+
252                     '<select class="form-control" ng-model="prefix" ng-change="updatePrefix()" ng-options="p.label() for p in prefix_list track by idTracker(p)"/>'+
253                 '</div>'+
254                 '<div class="col-xs-2"><input class="form-control" type="text" ng-change="updateLabel()" ng-model="label"/></div>'+
255                 '<div class="col-xs-1">'+
256                     '<select class="form-control" ng-model="suffix" ng-change="updateSuffix()" ng-options="s.label() for s in suffix_list track by idTracker(s)"/>'+
257                 '</div>'+
258                 '<div class="col-xs-1"><input class="form-control" type="number" ng-model="copy_count" min="{{orig_copy_count}}" ng-change="changeCPCount()"></div>'+
259                 '<div class="col-xs-5">'+
260                     '<eg-vol-copy-edit ng-repeat="cp in copies track by idTracker(cp)" copy="cp" call-number="callNumber"></eg-vol-copy-edit>'+
261                 '</div>'+
262             '</div>',
263
264         scope: {allcopies: "=", copies: "=" },
265         controller : ['$scope','itemSvc','egCore',
266             function ( $scope , itemSvc , egCore ) {
267                 $scope.new_cp_id = 0;
268                 $scope.callNumber =  $scope.copies[0].call_number();
269
270                 $scope.idTracker = function (x) { if (x) return x.id() };
271
272                 // XXX $() is not working! arg
273                 $scope.focusNextBarcode = function (i) {
274                     var n;
275                     var yep = false;
276                     angular.forEach($scope.copies, function (cp) {
277                         if (n) return;
278
279                         if (cp.id() == i) {
280                             yep = true;
281                             return;
282                         }
283
284                         if (yep) n = cp.id();
285                     });
286
287                     if (n) {
288                         var next = '#' + $scope.callNumber.id() + '.' + n;
289                         var el = $(next).get(0);
290                         if (el) el.focus()
291                     }
292                 }
293
294                 $scope.suffix_list = [];
295                 itemSvc.get_suffixes($scope.callNumber.owning_lib()).then(function(list){
296                     $scope.suffix_list = list;
297                 });
298                 $scope.updateSuffix = function () {
299                     angular.forEach($scope.copies, function(cp) {
300                         cp.call_number().suffix($scope.suffix);
301                         cp.call_number().ischanged(1);
302                     });
303                 }
304
305                 $scope.prefix_list = [];
306                 itemSvc.get_prefixes($scope.callNumber.owning_lib()).then(function(list){
307                     $scope.prefix_list = list;
308                 });
309                 $scope.updatePrefix = function () {
310                     angular.forEach($scope.copies, function(cp) {
311                         cp.call_number().prefix($scope.prefix);
312                         cp.call_number().ischanged(1);
313                     });
314                 }
315
316                 $scope.classification_list = [];
317                 itemSvc.get_classifications().then(function(list){
318                     $scope.classification_list = list;
319                 });
320                 $scope.updateClassification = function () {
321                     angular.forEach($scope.copies, function(cp) {
322                         cp.call_number().label_class($scope.classification);
323                         cp.call_number().ischanged(1);
324                     });
325                 }
326
327                 $scope.updateLabel = function () {
328                     angular.forEach($scope.copies, function(cp) {
329                         cp.call_number().label($scope.label);
330                         cp.call_number().ischanged(1);
331                     });
332                 }
333
334                 $scope.$watch('callNumber.prefix()', function (v) {
335                     if (typeof v != 'object') {
336                         $scope.prefix = $scope.prefix_list.filter(function (p) {
337                             return p.id() == v;
338                         })[0];
339                         $scope.callNumber.prefix($scope.prefix);
340                     }
341                 });
342
343                 $scope.$watch('callNumber.suffix()', function (v) {
344                     if (typeof v != 'object') {
345                         $scope.suffix = $scope.suffix_list.filter( function (s) {
346                             return s.id() == v;
347                         })[0];
348                         $scope.callNumber.suffix($scope.suffix);
349                     }
350                 });
351
352                 $scope.$watch('callNumber.label_class()', function (v) {
353                     if (typeof v != 'object') {
354                         $scope.classification = $scope.classification_list.filter(function (c) {
355                             return c.id() == v;
356                         })[0];
357                         $scope.callNumber.label_class($scope.classification);
358                     }
359                 });
360
361                 $scope.$watch('callNumber.label()', function (v) {
362                     $scope.label = v;
363                 });
364
365                 $scope.prefix = $scope.callNumber.prefix();
366                 $scope.suffix = $scope.callNumber.suffix();
367                 $scope.classification = $scope.callNumber.label_class();
368                 $scope.label = $scope.callNumber.label();
369
370                 $scope.copy_count = $scope.copies.length;
371                 $scope.orig_copy_count = $scope.copy_count;
372
373                 $scope.changeCPCount = function () {
374                     while ($scope.copy_count > $scope.copies.length) {
375                         var cp = new egCore.idl.acp();
376                         cp.id( --$scope.new_cp_id );
377                         cp.isnew( true );
378                         cp.circ_lib( $scope.lib );
379                         cp.call_number( $scope.callNumber );
380                         $scope.copies.push( cp );
381                         $scope.allcopies.push( cp );
382                     }
383
384                     var how_many = $scope.copies.length - $scope.copy_count;
385                     if (how_many > 0) {
386                         var dead = $scope.copies.splice($scope.copy_count,how_many);
387                         $scope.callNumber.copies($scope.copies);
388
389                         // Trimming the global list is a bit more tricky
390                         angular.forEach( dead, function (d) {
391                             angular.forEach( $scope.allcopies, function (l, i) { 
392                                 if (l === d) $scope.allcopies.splice(i,1);
393                             });
394                         });
395                     }
396                 }
397
398             }
399         ]
400
401     }
402 })
403
404 .directive("egVolEdit", function () {
405     return {
406         restrict: 'E',
407         replace: true,
408         template:
409             '<div class="row">'+
410                 '<div class="col-xs-1"><eg-org-selector selected="owning_lib" disableTest="cant_have_vols"></eg-org-selector></div>'+
411                 '<div class="col-xs-1"><input class="form-control" type="number" min="{{orig_cn_count}}" ng-model="cn_count" ng-change="changeCNCount()"/></div>'+
412                 '<div class="col-xs-10">'+
413                     '<eg-vol-row ng-repeat="(cn,copies) in struct track by cn" copies="copies" allcopies="allcopies"></eg-vol-row>'+
414                 '</div>'+
415             '</div>',
416
417         scope: { allcopies: "=", struct: "=", lib: "@", record: "@" },
418         controller : ['$scope','itemSvc','egCore',
419             function ( $scope , itemSvc , egCore ) {
420                 $scope.new_cn_id = 0;
421                 $scope.first_cn = Object.keys($scope.struct)[0];
422                 $scope.full_cn = $scope.struct[$scope.first_cn][0].call_number();
423
424                 $scope.cn_count = Object.keys($scope.struct).length;
425                 $scope.orig_cn_count = $scope.cn_count;
426
427                 $scope.owning_lib = egCore.org.get($scope.lib);
428                 $scope.$watch('owning_lib', function (l) {
429                     angular.forEach( $scope.struct[$scope.first_cn], function (cp) {
430                         cp.call_number().owning_lib( $scope.owning_lib.id() );
431                     });
432                 });
433
434                 $scope.cant_have_vols = function (id) { return !egCore.org.CanHaveVolumes(id); };
435
436                 $scope.$watch('cn_count', function (n) {
437                     var o = Object.keys($scope.struct).length;
438                     if (n > o) { // adding
439                         for (var i = o; o < n; o++) {
440                             var cn = new egCore.idl.acn();
441                             cn.id( --$scope.new_cn_id );
442                             cn.isnew( true );
443                             cn.owning_lib( $scope.owning_lib.id() );
444                             cn.record( $scope.full_cn.record() );
445
446                             var cp = new egCore.idl.acp();
447                             cp.id( --$scope.new_cp_id );
448                             cp.isnew( true );
449                             cp.circ_lib( $scope.owning_lib.id() );
450                             cp.call_number( cn );
451
452                             $scope.struct[cn.id()] = [cp];
453                             $scope.allcopies.push(cp);
454                         }
455                     } else if (n < o) { // removing
456                         var how_many = o - n;
457                         var list = Object
458                                 .keys($scope.struct)
459                                 .sort(function(a, b){return a-b})
460                                 .reverse();
461                         for (var i = how_many; i > 0; i--) {
462                             // Trimming the global list is a bit more tricky
463                             angular.forEach($scope.struct[list[i]], function (d) {
464                                 angular.forEach( $scope.allcopies, function (l, j) { 
465                                     if (l === d) $scope.allcopies.splice(j,1);
466                                 });
467                             });
468                             delete $scope.struct[list[i]];
469                         }
470                     }
471                 });
472             }
473         ]
474
475     }
476 })
477
478 /**
479  * Edit controller!
480  */
481 .controller('EditCtrl', 
482        ['$scope','$q','$routeParams','$location','$timeout','egCore','egNet','egGridDataProvider','itemSvc',
483 function($scope , $q , $routeParams , $location , $timeout , egCore , egNet , egGridDataProvider , itemSvc) {
484
485     $scope.dirty = false;
486
487     $scope.show_vols = true;
488     $scope.show_copies = true;
489
490     $scope.tracker = function (x,f) { if (x) return x[f]() };
491     $scope.idTracker = function (x) { if (x) return $scope.tracker(x,'id') };
492     $scope.cant_have_vols = function (id) { return !egCore.org.CanHaveVolumes(id); };
493
494     $scope.orgById = function (id) { return egCore.org.get(id) }
495     $scope.statusById = function (id) {
496         return $scope.status_list.filter( function (s) { return s.id() == id } )[0];
497     }
498     $scope.locationById = function (id) {
499         return $scope.location_cache[''+id];
500     }
501
502     $scope.workingToComplete = function () {
503         angular.forEach( $scope.workingGridControls.selectedItems(), function (c) {
504             angular.forEach( itemSvc.copies, function (w, i) {
505                 if (c === w)
506                     $scope.completed_copies = $scope.completed_copies.concat(itemSvc.copies.splice(i,1));
507             });
508         });
509     }
510
511     $scope.completeToWorking = function () {
512         angular.forEach( $scope.completedGridControls.selectedItems(), function (c) {
513             angular.forEach( $scope.completed_copies, function (w, i) {
514                 if (c === w)
515                     itemSvc.copies = itemSvc.copies.concat($scope.completed_copies.splice(i,1));
516             });
517         });
518     }
519
520     createSimpleUpdateWatcher = function (field) {
521         $scope.$watch('working.' + field, function () {
522             var newval = $scope.working[field];
523
524             if (typeof newval != 'undefined') {
525                 if (angular.isObject(newval)) { // we'll use the pkey
526                     if (newval.id) newval = newval.id();
527                     else if (newval.code) newval = newval.code();
528                 }
529
530                 if (newval == "") {
531                     $scope.working[field] = undefined;
532                     newval = null;
533                 }
534
535                 if ($scope.workingGridControls && $scope.workingGridControls.selectedItems) {
536                     angular.forEach(
537                         $scope.workingGridControls.selectedItems(),
538                         function (cp) { cp[field](newval); cp.ischanged(1); }
539                     );
540                 }
541             }
542         });
543     }
544
545     $scope.applyTemplate = function (n) {
546         angular.forEach($scope.templates[n], function (v,k) {
547             $scope.working[k] = angular.copy(v);
548         });
549     }
550
551     var dataKey = $routeParams.dataKey;
552     console.debug('dataKey: ' + dataKey);
553
554     if (dataKey && dataKey.length > 0) {
555
556         $scope.templates = {};
557         $scope.template_name = '';
558         $scope.template_name_list = [];
559
560         $scope.fetchTemplates = function () {
561             egCore.hatch.getItem('cat.copy.templates').then(function(t) {
562                 if (t) {
563                     $scope.templates = t;
564                     $scope.template_name_list = Object.keys(t);
565                 }
566             });
567         }
568         $scope.fetchTemplates();
569  
570         $scope.working = {};
571
572         $scope.copytab = 'working';
573         $scope.tab = 'edit';
574         $scope.summaryRecord = null;
575         $scope.record_id = null;
576         $scope.data = {};
577         $scope.completed_copies = [];
578         $scope.location_orgs = [];
579         $scope.location_cache = {};
580         $scope.batch = {};
581
582         $scope.applyBatchCNValues = function () {
583             if ($scope.data.tree) {
584                 angular.forEach($scope.data.tree, function(cn_hash) {
585                     angular.forEach(cn_hash, function(copies) {
586                         angular.forEach(copies, function(cp) {
587                             if (typeof $scope.batch.classification != 'undefined' && $scope.batch.classification != '')
588                                 cp.call_number().label_class($scope.batch.classification);
589                             if (typeof $scope.batch.prefix != 'undefined' && $scope.batch.prefix != '')
590                                 cp.call_number().prefix($scope.batch.prefix);
591                             if (typeof $scope.batch.label != 'undefined' && $scope.batch.label != '')
592                                 cp.call_number().label($scope.batch.label);
593                             if (typeof $scope.batch.suffix != 'undefined' && $scope.batch.suffix != '')
594                                 cp.call_number().suffix($scope.batch.suffix);
595                         });
596                     });
597                 });
598             }
599         }
600
601         $scope.clearWorking = function () {
602             angular.forEach($scope.working, function (v,k,o) {
603                 if (typeof v != 'undefined')
604                     $scope.working[k] = undefined;
605             });
606         }
607
608         $scope.completedGridDataProvider = egGridDataProvider.instance({
609             get : function(offset, count) {
610                 //return provider.arrayNotifier(itemSvc.copies, offset, count);
611                 return this.arrayNotifier($scope.completed_copies, offset, count);
612             }
613         });
614
615         $scope.completedGridControls = {};
616
617         $scope.workingGridDataProvider = egGridDataProvider.instance({
618             get : function(offset, count) {
619                 //return provider.arrayNotifier(itemSvc.copies, offset, count);
620                 return this.arrayNotifier(itemSvc.copies, offset, count);
621             }
622         });
623
624         $scope.workingGridControls = {};
625
626         egNet.request(
627             'open-ils.actor',
628             'open-ils.actor.anon_cache.get_value',
629             dataKey, 'edit-these-copies'
630         ).then(function (data) {
631
632             if (data) {
633                 if (data.hide_vols) $scope.show_vols = false;
634                 if (data.hide_copies) $scope.show_copies = false;
635
636                 $scope.record_id = data.record_id;
637
638                 if (data.copies && data.copies.length)
639                     return itemSvc.fetchIds(data.copies);
640
641                 if (data.raw && data.raw.length) {
642
643                     /* data.raw must be an array of copies with (at least)
644                      * the call number fleshed on each.  For new copies
645                      * create from whole cloth, the id for each should
646                      * probably be negative and isnew() should return true.
647                      * Each /distinct/ call number must have a distinct id
648                      * as well, probably negative also if they're new. Clear?
649                      */
650
651                     angular.forEach(
652                         data.raw,
653                         function (cp) { itemSvc.addCopy(cp) }
654                     );
655
656                     return itemSvc.copies;
657                 }
658             }
659
660         }).then( function() {
661             $scope.data = itemSvc;
662             $scope.workingGridDataProvider.refresh();
663         });
664
665         $scope.$watch('data.copies.length', function () {
666             if ($scope.data.copies) {
667                 var base_orgs = $scope.data.copies.map(function(cp){
668                     return cp.circ_lib()
669                 }).filter(function(e,i,a){
670                     return a.lastIndexOf(e) === i;
671                 });
672
673                 var all_orgs = [];
674                 angular.forEach(base_orgs, function(o) {
675                     all_orgs = all_orgs.concat( egCore.org.fullPath(o, true) );
676                 });
677
678                 var final_orgs = all_orgs.filter(function(e,i,a){
679                     return a.lastIndexOf(e) === i;
680                 }).sort(function(a,b){return b-a});
681
682                 if ($scope.location_orgs.toString() != final_orgs.toString()) {
683                     $scope.location_orgs = final_orgs;
684                     if ($scope.location_orgs.length) {
685                         itemSvc.get_locations($scope.location_orgs).then(function(list){
686                             angular.forEach(list, function(l) {
687                                 $scope.location_cache[ ''+l.id() ] = l;
688                             });
689                             $scope.location_list = list;
690                         });
691                     }
692                 }
693             }
694
695             $scope.workingGridDataProvider.refresh();
696         });
697
698         $scope.suffix_list = [];
699         itemSvc.get_suffixes(egCore.auth.user().ws_ou()).then(function(list){
700             $scope.suffix_list = list;
701         });
702
703         $scope.prefix_list = [];
704         itemSvc.get_prefixes(egCore.auth.user().ws_ou()).then(function(list){
705             $scope.prefix_list = list;
706         });
707
708         $scope.classification_list = [];
709         itemSvc.get_classifications().then(function(list){
710             $scope.classification_list = list;
711         });
712
713         $scope.$watch('completed_copies.length', function () {
714             $scope.completedGridDataProvider.refresh();
715         });
716
717         $scope.location_list = [];
718         itemSvc.get_locations().then(function(list){
719             $scope.location_list = list;
720         });
721         createSimpleUpdateWatcher('location');
722
723         $scope.status_list = [];
724         itemSvc.get_statuses().then(function(list){
725             $scope.status_list = list;
726         });
727         createSimpleUpdateWatcher('status');
728
729         $scope.circ_modifier_list = [];
730         itemSvc.get_circ_mods().then(function(list){
731             $scope.circ_modifier_list = list;
732         });
733         createSimpleUpdateWatcher('circ_modifier');
734
735         $scope.circ_type_list = [];
736         itemSvc.get_circ_types().then(function(list){
737             $scope.circ_type_list = list;
738         });
739         createSimpleUpdateWatcher('circ_as_type');
740
741         $scope.age_protect_list = [];
742         itemSvc.get_age_protects().then(function(list){
743             $scope.age_protect_list = list;
744         });
745         createSimpleUpdateWatcher('age_protect');
746
747         createSimpleUpdateWatcher('circ_lib');
748         createSimpleUpdateWatcher('circulate');
749         createSimpleUpdateWatcher('holdable');
750         createSimpleUpdateWatcher('fine_level');
751         createSimpleUpdateWatcher('loan_duration');
752         createSimpleUpdateWatcher('cost');
753         createSimpleUpdateWatcher('deposit');
754         createSimpleUpdateWatcher('deposit_amount');
755         createSimpleUpdateWatcher('mint_condition');
756         createSimpleUpdateWatcher('opac_visible');
757         createSimpleUpdateWatcher('ref');
758
759     }
760
761 }])
762
763 .directive("egVolTemplate", function () {
764     return {
765         restrict: 'E',
766         replace: true,
767         template: '<div ng-include="'+"'/eg/staff/cat/volcopy/t_attr_edit'"+'"></div>',
768         scope: { },
769         controller : ['$scope','itemSvc','egCore',
770             function ( $scope , itemSvc , egCore ) {
771
772                 $scope.dirty = false;
773                 $scope.template_controls = true;
774
775                 $scope.fetchTemplates = function () {
776                     egCore.hatch.getItem('cat.copy.templates').then(function(t) {
777                         if (t) {
778                             $scope.templates = t;
779                             $scope.template_name_list = Object.keys(t);
780                         }
781                     });
782                 }
783                 $scope.fetchTemplates();
784             
785                 $scope.applyTemplate = function (n) {
786                     angular.forEach($scope.templates[n], function (v,k) {
787                         $scope.working[k] = angular.copy(v);
788                     });
789                 }
790             
791                 $scope.deleteTemplate = function (n) {
792                     if (n) {
793                         delete $scope.templates[n]
794                         $scope.template_name_list = Object.keys($scope.templates);
795                         $scope.template_name = '';
796                         egCore.hatch.setItem('cat.copy.templates', $scope.templates);
797                         $scope.$parent.fetchTemplates();
798                     }
799                 }
800
801                 $scope.saveTemplate = function (n) {
802                     if (n) {
803                         var tmpl = {};
804             
805                         angular.forEach($scope.working, function (v,k) {
806                             if (angular.isObject(v)) { // we'll use the pkey
807                                 if (v.id) v = v.id();
808                                 else if (v.code) v = v.code();
809                             }
810             
811                             tmpl[k] = v;
812                         });
813             
814                         $scope.templates[n] = tmpl;
815                         $scope.template_name_list = Object.keys($scope.templates);
816             
817                         egCore.hatch.setItem('cat.copy.templates', $scope.templates);
818                         $scope.$parent.fetchTemplates();
819                     }
820                 }
821             
822                 $scope.templates = {};
823                 $scope.template_name = '';
824                 $scope.template_name_list = [];
825             
826                 $scope.tracker = function (x,f) { if (x) return x[f]() };
827                 $scope.idTracker = function (x) { if (x) return $scope.tracker(x,'id') };
828                 $scope.cant_have_vols = function (id) { return !egCore.org.CanHaveVolumes(id); };
829             
830                 $scope.orgById = function (id) { return egCore.org.get(id) }
831                 $scope.statusById = function (id) {
832                     return $scope.status_list.filter( function (s) { return s.id() == id } )[0];
833                 }
834                 $scope.locationById = function (id) {
835                     return $scope.location_cache[''+id];
836                 }
837             
838                 createSimpleUpdateWatcher = function (field) {
839                     $scope.$watch('working.' + field, function () {
840                         var newval = $scope.working[field];
841             
842                         if (typeof newval != 'undefined') {
843                             $scope.dirty = true;
844                             if (angular.isObject(newval)) { // we'll use the pkey
845                                 if (newval.id) $scope.working[field] = newval.id();
846                                 else if (newval.code) $scope.working[field] = newval.code();
847                             }
848             
849                             if (newval == "") {
850                                 $scope.working[field] = undefined;
851                             }
852             
853                         }
854                     });
855                 }
856             
857                 $scope.clearWorking = function () {
858                     angular.forEach($scope.working, function (v,k) {
859                         if (typeof v != 'undefined')
860                             $scope.working[k] = undefined;
861                     });
862                 }
863             
864                 $scope.working = {};
865                 $scope.location_orgs = [];
866                 $scope.location_cache = {};
867             
868                 $scope.location_list = [];
869                 itemSvc.get_locations(
870                     egCore.org.fullPath( egCore.auth.user().ws_ou(), true )
871                 ).then(function(list){
872                     $scope.location_list = list;
873                 });
874                 createSimpleUpdateWatcher('location');
875             
876                 $scope.status_list = [];
877                 itemSvc.get_statuses().then(function(list){
878                     $scope.status_list = list;
879                 });
880                 createSimpleUpdateWatcher('status');
881             
882                 $scope.circ_modifier_list = [];
883                 itemSvc.get_circ_mods().then(function(list){
884                     $scope.circ_modifier_list = list;
885                 });
886                 createSimpleUpdateWatcher('circ_modifier');
887             
888                 $scope.circ_type_list = [];
889                 itemSvc.get_circ_types().then(function(list){
890                     $scope.circ_type_list = list;
891                 });
892                 createSimpleUpdateWatcher('circ_as_type');
893             
894                 $scope.age_protect_list = [];
895                 itemSvc.get_age_protects().then(function(list){
896                     $scope.age_protect_list = list;
897                 });
898                 createSimpleUpdateWatcher('age_protect');
899             
900                 createSimpleUpdateWatcher('circ_lib');
901                 createSimpleUpdateWatcher('circulate');
902                 createSimpleUpdateWatcher('holdable');
903                 createSimpleUpdateWatcher('fine_level');
904                 createSimpleUpdateWatcher('loan_duration');
905                 createSimpleUpdateWatcher('cost');
906                 createSimpleUpdateWatcher('deposit');
907                 createSimpleUpdateWatcher('deposit_amount');
908                 createSimpleUpdateWatcher('mint_condition');
909                 createSimpleUpdateWatcher('opac_visible');
910                 createSimpleUpdateWatcher('ref');
911             }
912         ]
913     }
914 })
915
916