]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/info_group.js
LP#1086458: clean up after event listeners in circ/patron interface
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / patron / info_group.js
1 function $(id) { return document.getElementById(id); }
2
3 function my_init() {
4     try {
5         if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
6         JSAN.errorLevel = "die"; // none, warn, or die
7         JSAN.addRepository('/xul/server/');
8
9         JSAN.use('util.error'); g.error = new util.error();
10         JSAN.use('util.network'); g.network = new util.network();
11         JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('patron.util'); JSAN.use('util.functional');
12         JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.stash_retrieve();
13
14         g.error.sdump('D_TRACE','my_init() for patron_info_group.xul');
15
16         g.patron_id = xul_param('patron_id');
17
18         tree_init();
19
20         g.patron = patron.util.retrieve_au_via_id(ses(),g.patron_id);
21         if ((g.patron == null) || (typeof g.patron.ilsevent != 'undefined') ) throw(p);
22
23         refresh();
24
25     } catch(E) {
26         var err_msg = $("commonStrings").getFormattedString('common.exception', ['patron/info_group.xul', E]);
27         try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
28         alert(err_msg);
29     }
30 }
31
32 function my_cleanup() {
33     try {
34         list.cleanup();
35     } catch(E) {
36         var err_msg = $("commonStrings").getFormattedString('common.exception', ['patron/info_group.xul', E]);
37         try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
38         alert(err_msg);
39     }
40 }
41
42 function retrieve_money_summaries() {
43     try {
44         JSAN.use('util.money');
45         var robj = g.network.simple_request( 'BLOB_BALANCE_OWED_VIA_USERGROUP', [ ses(), g.patron.usrgroup() ]);
46         if (typeof robj.ilsevent != 'undefined') { throw(robj); }
47
48         var sum = 0; /* in cents */
49         g.group_owed = {};
50
51         for (var i = 0; i < robj.length; i++) {
52             sum += util.money.dollars_float_to_cents_integer( robj[i].balance_owed );
53             g.group_owed[ robj[i].usr ] = robj[i].balance_owed;
54         }
55
56         $('total_owed').setAttribute(
57             'value',
58             $('patronStrings').getFormattedString( 'staff.patron.info_group.total_owed.label', [ util.money.cents_as_dollars(sum) ] )
59         );
60
61     } catch(E) {
62         alert('Error in info_group.js, retrieve_money_summaries(): ' + E);
63     }
64 }
65
66 function tree_init() {
67     try {
68         var obscure_dob = String( g.data.hash.aous['circ.obscure_dob'] ) == 'true';
69
70         JSAN.use('util.list'); g.list = new util.list('patron_list');
71
72         var columns = g.list.fm_columns( 'au', {
73             '*' : { 'hidden' : true },
74             'au_active' : { 'hidden' : 'false' },
75             'au_barred' : { 'hidden' : 'false' },
76             'au_family_name' : { 'hidden' : 'false' },
77             'au_first_given_name' : { 'hidden' : 'false' },
78             'au_second_given_name' : { 'hidden' : 'false' },
79             'au_dob' : { 'hidden' : obscure_dob },
80             'au_master_account' : { 'hidden' : 'false' }
81         }).concat([
82             {
83                 'id' : 'gl_balance_owed', 'flex' : 1, 'sort_type' : 'money',
84                 'label' : $("patronStrings").getString('staff.patron.summary.group_list.column.balance_owed.label'),
85                 'render' : function(my) { return my.balance_owed; } 
86             },
87             {
88                 'id' : 'gl_circ_count_out', 'flex' : 1, 'sort_type' : 'number',
89                 'label' : $("patronStrings").getString('staff.patron.info_group.column.circs_out.label'),
90                 'render' : function(my) { return my.circ_counts.out; }
91             },
92             {
93                 'id' : 'gl_circ_count_overdue', 'flex' : 1, 'sort_type' : 'number',
94                 'label' : $("patronStrings").getString('staff.patron.info_group.column.circs_overdue.label'),
95                 'render' : function(my) { return my.circ_counts.overdue; }
96             },
97             {
98                 'id' : 'gl_circ_count_claims_returned', 'flex' : 1, 'sort_type' : 'number', 'hidden' : true,
99                 'label' : $("patronStrings").getString('staff.patron.info_group.column.circs_claimed_returned.label'),
100                 'render' : function(my) { return my.circ_counts.claims_returned; }
101             },
102             {
103                 'id' : 'gl_circ_count_long_overdue', 'flex' : 1, 'sort_type' : 'number', 'hidden' : true,
104                 'label' : $("patronStrings").getString('staff.patron.info_group.column.circs_long_overdue.label'),
105                 'render' : function(my) { return my.circ_counts.long_overdue; }
106             },
107             {
108                 'id' : 'gl_circ_count_lost', 'flex' : 1, 'sort_type' : 'number', 'hidden' : true,
109                 'label' : $("patronStrings").getString('staff.patron.info_group.column.circs_lost.label'),
110                 'render' : function(my) { return my.circ_counts.lost; }
111             }
112         ]);
113         g.list.init(
114             {
115                 'columns' : columns,
116                 'retrieve_row' : function(params) {
117                     var id = params.retrieve_id;
118                     var row = params.row;
119                     if (typeof row.my == 'undefined') row.my = {};
120
121                     function process_and_return() {
122                         if (typeof params.on_retrieve == 'function') {
123                             params.on_retrieve(row);
124                         }
125                         return row;
126                     }
127
128                     patron.util.retrieve_fleshed_au_via_id( ses(), id, null, function(req) {
129                         row.my.au = req.getResultObject();
130                         process_and_return();
131                     });
132                     g.network.simple_request(
133                         'FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',
134                         [ ses(), id ],
135                         function(req) {
136                             try {
137                                 var robj = req.getResultObject();
138                                 // robj.out / robj.overdue / robj.claims_returned / robj.long_overdue / robj.lost
139                                 row.my.circ_counts = robj;
140                                 g.flesh_count++;
141                                 if (g.flesh_count >= g.row_count) {
142                                     $('total_out').setAttribute(
143                                         'value',
144                                         $('patronStrings').getFormattedString(
145                                             'staff.patron.info_group.total_out.label', 
146                                             [ g.total_out ]
147                                         )
148                                     );
149                                     $('total_overdue').setAttribute(
150                                         'value',
151                                         $('patronStrings').getFormattedString(
152                                             'staff.patron.info_group.total_overdue.label', 
153                                             [ g.total_overdue ]
154                                         )
155                                     );
156                                 }
157                                 process_and_return();
158                             } catch(E) {
159                                 alert('Error in info_group.js, circ count retrieve(): ' + E);
160                             }
161                         }
162                     );
163
164                     process_and_return();
165                 },
166                 'on_select' : function(ev) {
167                     JSAN.use('util.functional');
168                     var sel = g.list.retrieve_selection();
169                     g.sel_list = util.functional.map_list(
170                         sel,
171                         function(o) { return o.getAttribute('retrieve_id'); }
172                     );
173                     if (g.sel_list.length > 0) {
174                         $('retrieve_p').disabled = false;
175                         $('retrieve_p').setAttribute('disabled','false');
176                         if (g.sel_list.length > 1) {
177                             $('merge_p').disabled = false;
178                             $('merge_p').setAttribute('disabled','false');
179                         }
180                         $('clone').disabled = false;
181                         $('clone').setAttribute('disabled','false');
182                         $('remove').disabled = false;
183                         $('remove').setAttribute('disabled','false');
184                         $('move').disabled = false;
185                         $('move').setAttribute('disabled','false');
186                     } else {
187                         $('retrieve_p').disabled = true;
188                         $('retrieve_p').setAttribute('disabled','true');
189                         $('merge_p').disabled = true;
190                         $('merge_p').setAttribute('disabled','true');
191                         $('clone').disabled = true;
192                         $('clone').setAttribute('disabled','true');
193                         $('remove').disabled = true;
194                         $('remove').setAttribute('disabled','true');
195                         $('move').disabled = true;
196                         $('move').setAttribute('disabled','true');
197                     }
198                 }
199             }
200         );
201         $('list_actions').appendChild( g.list.render_list_actions() );
202         g.list.set_list_actions();
203         $('retrieve_p').disabled = true;
204         $('retrieve_p').setAttribute('disabled','true');
205         $('merge_p').disabled = true;
206         $('merge_p').setAttribute('disabled','true');
207         $('clone').disabled = true;
208         $('clone').setAttribute('disabled','true');
209         $('remove').disabled = true;
210         $('remove').setAttribute('disabled','true');
211         $('move').disabled = true;
212         $('move').setAttribute('disabled','true');
213         setTimeout( function() { $('patron_list').focus(); }, 0 );
214     } catch(E) {
215         alert('Error in info_group.js, tree_init(): ' + E);
216     }
217 }
218
219 function refresh() {
220     try {
221         retrieve_money_summaries();
222         retrieve_group_members();
223     } catch(E) {
224         alert('Error in info_group.js, refresh(): ' + E);
225     }
226 }
227
228 function retrieve_group_members() {
229     try {
230         JSAN.use('util.functional'); JSAN.use('patron.util');
231         g.group_members = [];
232         var robj = g.network.simple_request(
233             'FM_AU_LIST_RETRIEVE_VIA_GROUP.authoritative',
234             [ ses(), g.patron.usrgroup() ]
235         );
236         if ((robj == null) || (typeof robj.ilsevent != 'undefined') ) throw(robj);
237         var ids = util.functional.filter_list( robj, function(o) { return o != g.patron_id; });
238         g.row_count = ids.length + 1;
239         g.flesh_count = 0;
240         g.total_out = 0;
241         g.total_overdue = 0;
242
243         g.list.clear();
244
245         var funcs = [];
246
247             function gen_func(r) {
248                 return function() {
249                     g.list.append( {
250                         'retrieve_id' : r, 
251                         'row' : {
252                             'my' : {
253                                 'balance_owed' : g.group_owed[r]
254                             }
255                          }
256                     } );
257                 }
258             }
259
260         funcs.push( gen_func(g.patron_id) );
261         for (var i = 0; i < ids.length; i++) {
262             funcs.push( gen_func(ids[i]) );
263         }
264         JSAN.use('util.exec'); var exec = new util.exec(4);
265         exec.on_error = function(E) { alert('Error in info_group.js, retrieve_group_members chain exec: ' + E); }
266         exec.chain( funcs );
267
268     } catch(E) {
269         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.retrieve_group_members.failure'),E);
270     }
271 }
272
273 function retrieve_patron() {
274     try {
275         if (! g.sel_list ) return;
276         if (typeof window.xulG == 'object' && typeof window.xulG.new_patron_tab == 'function') {
277             for (var i = 0; i < g.sel_list.length; i++) {    
278                 try {
279                     window.xulG.new_patron_tab(
280                         { 'tab_name' : $("patronStrings").getString('staff.patron.info_group.retrieve_patron.tab_name') }, 
281                         { 
282                             'id' : g.sel_list[i],
283                             'url_prefix' : xulG.url_prefix,
284                             'new_tab' : xulG.new_tab,
285                             'set_tab' : xulG.set_tab
286                         }
287                     );
288                 } catch(E) {
289                     g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.retrieve_patron.failed_retrieving_patron'),E);
290                 }
291             }
292         }
293     } catch(E) {
294         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.retrieve_patron.failed_retrieving_patrons'),E);
295     }
296 }
297
298 function merge_patrons() {
299     try {
300         if (! g.sel_list ) return;
301         JSAN.use('patron.util'); 
302         var result = patron.util.merge(g.sel_list);
303         if (result) {
304             if (result != g.patron_id && g.sel_list.indexOf( g.patron_id ) != -1) {
305                 xulG.set_patron_tab(
306                     { 'tab_name' : $("patronStrings").getString('staff.patron.info_group.retrieve_patron.tab_name') }, 
307                     {
308                         'id' : result
309                     } 
310                 );
311             } else {
312                 refresh();
313             }
314         }
315     } catch(E) {
316         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.merge_patrons.failed_merging_patrons'),E);
317     }
318 }
319
320 function clone_patron() {
321     if (! g.sel_list ) return;
322     try {
323         for (var i = 0; i < g.sel_list.length; i++) {    
324             var loc = xulG.url_prefix('XUL_REMOTE_BROWSER'); 
325                 //+ '?url=' + window.escape( urls.XUL_PATRON_EDIT + '?ses=' 
326                 //+ window.escape( ses() ) + '&clone=' + g.sel_list[i] );
327             if (typeof window.xulG == 'object' && typeof window.xulG.new_tab == 'function') xulG.new_tab(
328                 loc, 
329                 {}, 
330                 { 
331                     'url' : urls.XUL_PATRON_EDIT, // + '?ses=' + window.escape(ses()) + '&clone=' + g.sel_list[i],
332                     'show_print_button' : true , 
333                     'tab_name' : $("patronStrings").getString('staff.patron.info_group.clone_patron.register_clone.tab_name'),
334                     'passthru_content_params' : {
335                         'ses' : ses(),
336                         'clone' : g.sel_list[i],
337                         'spawn_search' : spawn_search,
338                         'spawn_editor' : spawn_editor,
339                         'on_save' : function(p) { patron.util.work_log_patron_edit(p); refresh(); },
340                         'url_prefix' : xulG.url_prefix,
341                         'new_tab' : xulG.new_tab,
342                     },
343                     'url_prefix' : xulG.url_prefix,
344                     'new_tab' : xulG.new_tab,
345                     'lock_tab' : xulG.lock_tab,
346                     'unlock_tab' : xulG.unlock_tab
347                 }
348             );
349         }
350     } catch(E) {
351         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.clone_patron.error_spawning_editors'),E);
352     }
353 }
354
355 function spawn_editor(p) {
356     var url = urls.XUL_PATRON_EDIT;
357     var passthru = {
358         'spawn_search' : spawn_search,
359         'spawn_editor' : spawn_editor,
360         'on_save' : function(p) { patron.util.work_log_patron_edit(p); refresh(); },
361         'url_prefix' : xulG.url_prefix,
362         'new_tab' : xulG.new_tab,
363     };
364     for (var i in p) {
365         passthru[i] = p[i];
366     }
367     var loc = xulG.url_prefix('XUL_REMOTE_BROWSER'); // + '?url=' + window.escape( url );
368     if (typeof window.xulG == 'object' && typeof window.xulG.new_tab == 'function') xulG.new_tab(
369         loc, 
370         {}, 
371         { 
372             'url' : url,
373             'show_print_button' : true , 
374             'tab_name' : $("patronStrings").getString('staff.patron.info_group.spawn_editor.editing_patron'),
375             'passthru_content_params' : passthru,
376             'url_prefix' : xulG.url_prefix,
377             'new_tab' : xulG.new_tab,
378             'lock_tab' : xulG.lock_tab,
379             'unlock_tab' : xulG.unlock_tab
380         }
381     );
382
383 }
384
385 function spawn_search(s) {
386     try {
387         g.error.sdump('D_TRACE', 'Editor would like to search for: ' + js2JSON(s) ); 
388         if (typeof window.xulG == 'object' && typeof window.xulG.new_patron_tab == 'function') 
389             xulG.new_patron_tab( {}, {'doit':1,'query':s} );
390     } catch(E) {
391         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.spawn_search'),E);
392     }
393 }
394
395 function remove_patron() {
396     if (! g.sel_list ) return;
397     var msg = '';
398     for (var i = 0 ; i < g.sel_list.length; i++)
399         if (g.sel_list[i] == g.patron_id)
400             msg = $("patronStrings").getString('staff.patron.info_group.remove_patron.warning_message');
401             
402     var c = window.confirm($("patronStrings").getFormattedString('staff.patron.info_group.remove_patron.warning_message_confirm', [msg]));
403     if (c) {
404         for (var i = 0; i < g.sel_list.length; i++) {    
405             var robj = g.network.simple_request('FM_AU_NEW_USERGROUP', [ ses(), g.sel_list[i], get_db_true() ]);
406             if (typeof robj.ilsevent != 'undefined') {
407                 g.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.info_group.remove_patron.error_removing_patron', [g.sel_list[i]]), robj);
408             }
409         }
410         alert($("patronStrings").getString('staff.patron.info_group.remove_patron.patrons_removed_from_group')); 
411         /* FIXME - xulrunner bug if this alert comes after refresh? */
412         /* that's okay, because now that we're on a distributed database, we want human delay to mitigate race conditions */
413         refresh();
414     } else {
415         alert($("patronStrings").getString('staff.patron.info_group.remove_patron.patrons_not_removed_from_group'));
416     }
417 }
418
419 function link_patron(direction) {
420     try {
421         if (! g.sel_list ) { g.sel_list = []; g.sel_list[0] = g.patron_id; }
422         if (direction == null) throw($("patronStrings").getString('staff.patron.info_group.link_patron.null_not_allowed'));
423         var first_msg; var second_msg;
424         switch(direction) {
425             case true:
426                 first_msg = "-->";
427                 break;
428             case false:
429                 first_msg = "<--";
430                 break;
431             default:
432                 throw($("patronStrings").getString('staff.patron.info_group.link_patron.invalid_parameter'));
433                 break;
434         }
435         var barcode = window.prompt($("patronStrings").getString('staff.patron.info_group.link_patron.scan_patron_barcode'),'',first_msg);
436         if (!barcode) return;
437         JSAN.use('patron.util');
438         var patron_b = patron.util.retrieve_fleshed_au_via_barcode(ses(),barcode);
439         if (typeof patron_b.ilsevent != 'undefined') throw(patron_b);
440
441         if (g.sel_list.length == 0) g.sel_list[0] = g.patron_id;
442         for (var i = 0; i < g.sel_list.length; i++) {    
443
444             var patron_a = patron.util.retrieve_fleshed_au_via_id(ses(),g.sel_list[i],null);
445             if (typeof patron_a.ilsevent != 'undefined') throw(patron_a);
446             switch(direction) {
447                 case true:
448                     second_msg = $("patronStrings").getFormattedString('staff.patron.info_group.link_patron.move_patron_to_new_usergroup',[patron_a.card().barcode(), patron_b.card().barcode()]);
449                     break;
450                 case false:
451                     second_msg = $("patronStrings").getFormattedString('staff.patron.info_group.link_patron.move_patron_to_new_usergroup',[patron_b.card().barcode(), patron_a.card().barcode()]);
452                     break;
453             }
454
455             var horizontal_interface = String( g.data.hash.aous['ui.circ.patron_summary.horizontal'] ) == 'true';
456             var top_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto"><description>' + second_msg + '</description>';
457             top_xml += '<hbox><spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.info_group.link_patron.move.label')+'"';
458             top_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.info_group.link_patron.move.accesskey')+'" name="fancy_submit"/>';
459             top_xml += '<button label="'+$("patronStrings").getString('staff.patron.info_group.link_patron.done.label')+'"';
460             top_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.info_group.link_patron.done.accesskey')+'" name="fancy_cancel"/></hbox></vbox>';
461             var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
462             if (horizontal_interface) {
463                 xml += '<vbox flex="1">';
464             } else {
465                 xml += '<hbox flex="1">';
466             }
467             /************/
468             xml += '<vbox flex="1">';
469             xml += '<hbox><spacer flex="1"/>';
470             if (direction) {
471                 xml += '<image src="/xul/server/skin/media/images/patron_right_arrow.png"/>';
472             } else {
473                 xml += '<image src="/xul/server/skin/media/images/patron_left_arrow.png"/>';
474             }
475             xml += '</hbox>';
476             xml += '<iframe style="min-height: 100px" flex="1" src="' + xulG.url_prefix('XUL_PATRON_SUMMARY');
477             xml += '?show_name=1&amp;id=' + g.sel_list[i] + '" oils_force_external="true"/>';
478             xml += '</vbox>';
479             xml += '<vbox flex="1">';
480             xml += '<hbox>';
481             if (direction) {
482                 xml += '<image src="/xul/server/skin/media/images/patron_right_arrow.png"/>';
483             } else {
484                 xml += '<image src="/xul/server/skin/media/images/patron_left_arrow.png"/>';
485             }
486             xml += '<spacer flex="1"/></hbox>';
487             xml += '<iframe style="min-height: 100px" flex="1" src="' + xulG.url_prefix('XUL_PATRON_SUMMARY');
488             xml += '?show_name=1&amp;id=' + patron_b.id() + '" oils_force_external="true"/>';
489             xml += '</vbox>';
490             /************/
491             if (horizontal_interface) {
492                 xml += '</vbox>';
493             } else {
494                 xml += '</hbox>';
495             }
496             xml += '</vbox>';
497             
498             var bot_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto"><hbox>';
499             bot_xml += '</hbox></vbox>';
500
501             //g.data.temp_top = top_xml; g.data.stash('temp_top');
502             //g.data.temp_mid = xml; g.data.stash('temp_mid');
503             //g.data.temp_bot = bot_xml; g.data.stash('temp_bot');
504             JSAN.use('util.window'); var win = new util.window();
505             var fancy_prompt_data = win.open(
506                 urls.XUL_FANCY_PROMPT,
507                 //+ '?xml_in_stash=temp_mid'
508                 //+ '&top_xml_in_stash=temp_top'
509                 //+ '&bottom_xml_in_stash=temp_bot'
510                 //+ '&title=' + window.escape('Move Patron into a Usergroup'),
511                 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
512                 { 'xml' : xml, 'top_xml' : top_xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.info_group.link_patron.move_patron_to_usergroup')}
513             );
514             if (fancy_prompt_data.fancy_status == 'incomplete') { continue; }
515             else {
516                 var patron_c;
517                 switch(direction) {
518                     case true:
519                         patron_a.usrgroup( patron_b.usrgroup() );
520                         patron_a.ischanged( '1' );
521                         patron_c = patron_a;
522                     break;
523                     case false:
524                         patron_b.usrgroup( patron_a.usrgroup() );
525                         patron_b.ischanged( '1' );
526                         patron_c = patron_b;
527                     break;
528                 }
529                 var robj = g.network.simple_request('FM_AU_UPDATE',[ ses(), patron_c ]);
530                 if (typeof robj.ilsevent != 'undefined') g.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.info_group.link_patron.error_linking_patron', [g.sel_list[i]]), robj);
531             }
532         }
533         alert($("patronStrings").getString('staff.patron.info_group.link_patron.usergroups_updated'));
534         refresh();
535     } catch(E) {
536         g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.info_group.link_patron.error_linking_patrons'),E);
537         refresh();
538     }
539 }
540
541