2 <!-- Application: Evergreen Staff Client -->
3 <!-- Screen: Patron Display -->
5 <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
7 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
8 <?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
9 <?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
10 <?xml-stylesheet href="/xul/server/skin/patron_display.css" type="text/css"?>
12 <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
14 <!DOCTYPE window PUBLIC "" ""[
15 <!--#include virtual="/opac/locale/en-US/lang.dtd"-->
18 <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
20 <?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
22 <window id="patron_info_group_win" width="700" height="550"
23 onload="try{ my_init(); font_helper(); } catch(E) { alert(E); }"
24 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
26 <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
28 <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
29 <scripts id="openils_util_scripts"/>
31 <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
35 function $(id) { return document.getElementById(id); }
39 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
40 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
41 JSAN.errorLevel = "die"; // none, warn, or die
42 JSAN.addRepository('/xul/server/');
44 JSAN.use('util.error'); g.error = new util.error();
45 JSAN.use('util.network'); g.network = new util.network();
46 JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('patron.util'); JSAN.use('util.functional');
47 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
49 g.error.sdump('D_TRACE','my_init() for patron_info_group.xul');
52 g.patron_id = g.cgi.param('patron_id');
59 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
60 "system administrator or software developer the following:\npatron_info_group.xul\n" + E + '\n';
61 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
66 function tree_init() {
67 JSAN.use('OpenILS.data'); g.OpenILS = {};
68 g.OpenILS.data = new OpenILS.data(); g.OpenILS.data.init({'via':'stash'});
70 JSAN.use('util.list'); g.list = new util.list('patron_list');
71 function getString(s) { return g.OpenILS.data.entities[s]; }
73 JSAN.use('patron.util');
74 var columns = patron.util.columns(
76 'active' : { 'hidden' : 'false' },
77 'barred' : { 'hidden' : 'false' },
78 'family_name' : { 'hidden' : 'false' },
79 'first_given_name' : { 'hidden' : 'false' },
80 'second_given_name' : { 'hidden' : 'false' },
81 'dob' : { 'hidden' : 'false' },
82 'master_account' : { 'hidden' : 'false' },
88 'map_row_to_column' : patron.util.std_map_row_to_column(),
89 'retrieve_row' : function(params) {
90 var id = params.retrieve_id;
91 var au_obj = patron.util.retrieve_au_via_id( ses(), id );
94 if (typeof row.my == 'undefined') row.my = {};
96 if (typeof params.on_retrieve == 'function') {
97 params.on_retrieve(row);
101 'on_select' : function(ev) {
102 JSAN.use('util.functional');
103 var sel = g.list.retrieve_selection();
104 g.sel_list = util.functional.map_list(
106 function(o) { return o.getAttribute('retrieve_id'); }
108 if (g.sel_list.length > 0) {
109 $('retrieve_p').disabled = false;
110 $('retrieve_p').setAttribute('disabled','false');
111 $('clone').disabled = false;
112 $('clone').setAttribute('disabled','false');
113 $('remove').disabled = false;
114 $('remove').setAttribute('disabled','false');
115 $('move').disabled = false;
116 $('move').setAttribute('disabled','false');
118 $('retrieve_p').disabled = true;
119 $('retrieve_p').setAttribute('disabled','true');
120 $('clone').disabled = true;
121 $('clone').setAttribute('disabled','true');
122 $('remove').disabled = true;
123 $('remove').setAttribute('disabled','true');
124 $('move').disabled = true;
125 $('move').setAttribute('disabled','true');
130 $('retrieve_p').disabled = true;
131 $('retrieve_p').setAttribute('disabled','true');
132 $('clone').disabled = true;
133 $('clone').setAttribute('disabled','true');
134 $('remove').disabled = true;
135 $('remove').setAttribute('disabled','true');
136 $('move').disabled = true;
137 $('move').setAttribute('disabled','true');
138 setTimeout( function() { $('patron_list').focus(); }, 0 );
142 retrieve_group_members();
145 function retrieve_group_members() {
147 JSAN.use('util.functional'); JSAN.use('patron.util');
148 g.group_members = [];
149 var p = patron.util.retrieve_au_via_id(ses(),g.patron_id);
150 if ((p == null) || (typeof p.ilsevent != 'undefined') ) throw(p);
151 var robj = g.network.simple_request(
152 'FM_AU_LIST_RETRIEVE_VIA_GROUP',
153 [ ses(), p.usrgroup() ]
155 if ((robj == null) || (typeof robj.ilsevent != 'undefined') ) throw(robj);
156 var ids = util.functional.filter_list( robj, function(o) { return o != g.patron_id; });
162 function gen_func(r) {
164 g.list.append( { 'retrieve_id' : r, 'row' : {} } );
168 funcs.push( gen_func(g.patron_id) );
169 for (var i = 0; i < ids.length; i++) {
170 funcs.push( gen_func(ids[i]) );
172 JSAN.use('util.exec'); var exec = new util.exec(4);
176 g.error.standard_unexpected_error_alert('Failed to retrieve all the group members.',E);
180 function retrieve_patron() {
182 if (! g.sel_list ) return;
183 if (typeof window.xulG == 'object' && typeof window.xulG.new_tab == 'function') {
184 for (var i = 0; i < g.sel_list.length; i++) {
186 var url = urls.XUL_PATRON_DISPLAY
187 + '?id=' + window.escape( g.sel_list[i] );
189 url, { 'tab_name' : 'Retrieving Patron..' }, {}
192 g.error.standard_unexpected_error_alert('Failed to retrieve patron.',E);
197 g.error.standard_unexpected_error_alert('Failed to retrieve patrons.',E);
201 function clone_patron() {
202 if (! g.sel_list ) return;
204 for (var i = 0; i < g.sel_list.length; i++) {
205 var loc = xulG.url_prefix( urls.XUL_REMOTE_BROWSER )
206 + '?url=' + window.escape( urls.XUL_PATRON_EDIT + '?ses='
207 + window.escape( ses() ) + '&clone=' + g.sel_list[i] );
212 'show_print_button' : true ,
213 'tab_name' : 'Register Patron Clone for Group' ,
214 'passthru_content_params' : {
215 'spawn_search' : spawn_search,
216 'spawn_editor' : spawn_editor,
217 'on_save' : function() { refresh(); },
218 'url_prefix' : xulG.url_prefix,
219 'new_tab' : xulG.new_tab,
221 'url_prefix' : xulG.url_prefix,
222 'new_tab' : xulG.new_tab,
227 g.error.standard_unexpected_error_alert('error spawning user editors',E);
231 function spawn_editor(p) {
232 var url = urls.XUL_PATRON_EDIT;
235 if (param_count++ == 0) url += '?'; else url += '&';
236 url += i + '=' + window.escape(p[i]);
238 var loc = xulG.url_prefix( urls.XUL_REMOTE_BROWSER ) + '?url=' + window.escape( url );
243 'show_print_button' : true ,
244 'tab_name' : 'Editing Related Patron' ,
245 'passthru_content_params' : {
246 'spawn_search' : spawn_search,
247 'spawn_editor' : spawn_editor,
248 'on_save' : function() { refresh(); },
249 'url_prefix' : xulG.url_prefix,
250 'new_tab' : xulG.new_tab,
252 'url_prefix' : xulG.url_prefix,
253 'new_tab' : xulG.new_tab,
259 function spawn_search(s) {
261 g.error.sdump('D_TRACE', 'Editor would like to search for: ' + js2JSON(s) );
262 var loc = xulG.url_prefix(urls.XUL_PATRON_DISPLAY);
263 loc += '?doit=1&query=' + window.escape(js2JSON(s));
264 xulG.new_tab( loc, {}, {} );
266 g.error.standard_unexpected_error_alert('spawn search',E);
270 function remove_patron() {
271 if (! g.sel_list ) return;
272 var msg = ''; for (var i = 0 ; i < g.sel_list.length; i++) if (g.sel_list[i] == g.patron_id) msg =
273 'WARNING: If you remove the currently displayed patron, a NEW group will be displayed in this interface.';
274 var c = window.confirm('Remove selected patrons from this group? ' + msg);
276 for (var i = 0; i < g.sel_list.length; i++) {
277 var robj = g.network.simple_request('FM_AU_NEW_USERGROUP', [ ses(), g.sel_list[i], get_db_true() ]);
278 if (typeof robj.ilsevent != 'undefined') {
279 g.error.standard_unexpected_error_alert('error removing patron (id=' + g.sel_list[i] + ') from usergroup',robj);
282 alert('Patrons removed from group.');
283 /* FIXME - xulrunner bug if this alert comes after refresh? */
284 /* that's okay, because now that we're on a distributed database, we want human delay to mitigate race conditions */
287 alert('Patron not removed from group.');
291 function link_patron(direction) {
293 if (! g.sel_list ) { g.sel_list = []; g.sel_list[0] = g.patron_id; }
294 if (direction == null) throw('null paramater not allowed');
295 var first_msg; var second_msg;
297 case true: first_msg = "-->"; break;
298 case false: first_msg = "<--"; break;
299 default: throw('Invalid parameter. Expected boolean.'); break;
301 var barcode = window.prompt('Please scan a patron barcode:','',first_msg);
302 if (!barcode) return;
303 JSAN.use('patron.util');
304 var patron_b = patron.util.retrieve_fleshed_au_via_barcode(ses(),barcode);
305 if (typeof patron_b.ilsevent != 'undefined') throw(patron_b);
307 if (g.sel_list.length == 0) g.sel_list[0] = g.patron_id;
308 for (var i = 0; i < g.sel_list.length; i++) {
310 var patron_a = patron.util.retrieve_fleshed_au_via_id(ses(),g.sel_list[i]);
311 if (typeof patron_a.ilsevent != 'undefined') throw(patron_a);
313 case true: second_msg = "Move patron " + patron_a.card().barcode() + " into patron " + patron_b.card().barcode() + "'s usergroup..."; break;
314 case false: second_msg = "Move patron " + patron_b.card().barcode() + " into patron " + patron_a.card().barcode() + "'s usergroup..."; break;
317 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
318 var top_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto"><description>' + second_msg + '</description><hbox><spacer flex="1"/><button label="Move" accesskey="M" name="fancy_submit"/><button label="Done" accesskey="D" name="fancy_cancel"/></hbox></vbox>';
319 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical"><hbox flex="1">';
321 xml += '<vbox flex="1">';
322 xml += '<hbox><spacer flex="1"/>';
324 xml += '<image src="/xul/server/skin/media/images/patron_right_arrow.png"/>';
326 xml += '<image src="/xul/server/skin/media/images/patron_left_arrow.png"/>';
329 xml += '<iframe style="min-height: 100px" flex="1" src="' + xulG.url_prefix( urls.XUL_PATRON_SUMMARY );
330 xml += '?show_name=1&id=' + g.sel_list[i] + '"/>';
332 xml += '<vbox flex="1">';
335 xml += '<image src="/xul/server/skin/media/images/patron_right_arrow.png"/>';
337 xml += '<image src="/xul/server/skin/media/images/patron_left_arrow.png"/>';
339 xml += '<spacer flex="1"/></hbox>';
340 xml += '<iframe style="min-height: 100px" flex="1" src="' + xulG.url_prefix( urls.XUL_PATRON_SUMMARY );
341 xml += '?show_name=1&id=' + patron_b.id() + '"/>';
344 xml += '</hbox></vbox>';
346 var bot_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto"><hbox>';
347 bot_xml += '</hbox></vbox>';
349 g.data.temp_top = top_xml; g.data.stash('temp_top');
350 g.data.temp_mid = xml; g.data.stash('temp_mid');
351 g.data.temp_bot = bot_xml; g.data.stash('temp_bot');
353 urls.XUL_FANCY_PROMPT
354 + '?xml_in_stash=temp_mid'
355 + '&top_xml_in_stash=temp_top'
356 + '&bottom_xml_in_stash=temp_bot'
357 + '&title=' + window.escape('Move Patron into a Usergroup'),
358 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500'
360 g.data.init({'via':'stash'});
361 if (g.data.fancy_prompt_data == '') { continue; }
366 patron_a.usrgroup( patron_b.usrgroup() );
367 patron_a.ischanged( '1' );
371 patron_b.usrgroup( patron_a.usrgroup() );
372 patron_b.ischanged( '1' );
376 var robj = g.network.simple_request('FM_AU_UPDATE',[ ses(), patron_c ]);
377 if (typeof robj.ilsevent != 'undefined') g.error.standard_unexpected_error_alert('error linking patron (id=' + g.sel_list[i] + ')', robj);
380 alert('User groups updated.');
383 g.error.standard_unexpected_error_alert('error linking patrons',E);
391 <commandset id="info_group_cmds">
392 <command id="clone" accesskey="N" label="Register a New Group Member by Cloning Selected Patrons" oncommand="try{clone_patron();}catch(E){alert('FIXME:'+E);}"/>
393 <command id="remove" accesskey="R" label="Remove Selected Patrons from the Group" oncommand="try{remove_patron();}catch(E){alert('FIXME:'+E);}"/>
394 <command id="move" accesskey="M" label="Move Selected Patrons to ANOTHER patron's group." oncommand="try{link_patron(true);}catch(E){alert('FIXME:'+E);}"/>
395 <command id="add" accesskey="A" label="Move ANOTHER patron to this patron group." oncommand="try{link_patron(false);}catch(E){alert('FIXME:'+E);}"/>
396 <command id="retrieve_p" label="Retrieve Selected Patrons" accesskey="P" oncommand="try{retrieve_patron();}catch(E){alert(E);}"/>
399 <popupset id="info_group_popupset">
400 <popup id="info_group_actions" position="at_pointer">
401 <menuitem command="clone" />
402 <menuitem command="remove" />
403 <menuitem command="move" />
404 <menuitem command="add" />
405 <menuitem command="retrieve_p" />
409 <vbox flex="1" class="my_overflow" id="group_panel">
411 <caption label="Group Members"/>
415 <menu label="Choose an Action..." accesskey="A" value="0">
417 <menuitem command="clone" />
418 <menuitem command="remove" />
419 <menuitem command="move" />
420 <menuitem command="add" />
421 <menuitem command="retrieve_p" />
426 <tree id="patron_list" flex="1" enableColumnDrag="true" seltype="multiple" context="info_group_actions"/>