]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/serial/sdist_editor.js
LP#882586: In Serial Control View, show copy templates owned by ancestors
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / serial / sdist_editor.js
1 dump('entering serial/sdist_editor.js\n');
2 // vim:noet:sw=4:ts=4:
3
4 JSAN.use('serial.editor_base');
5
6 if (typeof serial == 'undefined') serial = {};
7 serial.sdist_editor = function (params) {
8     try {
9         JSAN.use('util.error'); this.error = new util.error();
10         JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
11         JSAN.use('util.network'); this.network = new util.network();
12     } catch(E) {
13         dump('serial/sdist_editor: ' + E + '\n');
14     }
15
16     /* This keeps track of what fields have been edited for styling purposes */
17     this.changed = {};
18
19     /* This holds the original values for prepopulating the field editors */
20     this.editor_values = {};
21
22     // setup sre arrays
23     this.sre_id_map = {};
24     this.sres_ou_map = {};
25     this.build_sre_maps();
26
27     // update sre maps on demand
28     var obj = this;
29     window.parent.addEventListener("MFHDChange", function() {obj.build_sre_maps()}, false);
30 };
31
32 serial.sdist_editor.prototype = {
33     // we could do this with non-standard '__proto__' property instead
34     'editor_base_init' : serial.editor_base.editor_base_init,
35     'editor_base_apply' : serial.editor_base.editor_base_apply,
36     'editor_base_save' : serial.editor_base.editor_base_save,
37
38     'fm_type' : 'sdist',
39     'fm_type_plural' : 'sdists',
40     'can_have_notes' : true,
41
42     'init' : function (params) {
43         var obj = this;
44
45         params.retrieve_function = 'FM_SDIST_FLESHED_BATCH_RETRIEVE.authoritative';
46
47         obj.editor_base_init(params);
48
49         obj.multi_org_edit = false;
50         var org_unit = obj.sdists[0].holding_lib();
51         for (var i = 1; i < obj.sdists.length; i++) {
52             if (obj.sdists[i].holding_lib() != org_unit) {
53                 obj.multi_org_edit = true;
54                 break;
55             }
56         }        
57
58         /* Do it */
59         obj.summarize( obj.sdists );
60         obj.render();
61     },
62
63     /******************************************************************************************************/
64     /* Restore backup copies */
65
66     'reset' :  serial.editor_base.editor_base_reset,
67
68     /******************************************************************************************************/
69     /* Apply a value to a specific field on all the copies being edited */
70
71     'apply' : function(field,value) {
72         var obj = this;
73
74         var field_name_list = ['bind_call_number','receive_call_number','bind_unit_template','receive_unit_template','record_entry'];
75
76         // null out call number if the holding lib is changed
77         obj.holding_lib_changed = (field == 'holding_lib');
78         var loop_func = function(sdist) {
79             if (obj.holding_lib_changed) {
80                 for (var i = 0; i < field_name_list.length; i++) {
81                     sdist[field_name_list[i]](null);
82                     obj.changed[fieldmapper.IDL.fmclasses.sdist.field_map[field_name_list[i]].label] = true;
83                 }
84             }
85         }
86
87         // check for blank drop-down submits
88         for (var i = 0; i < field_name_list.length; i++) {
89             if (field == field_name_list[i] && value === '') {
90                 value = null;
91                 break;
92             }
93         }
94         obj.editor_base_apply(field, value, loop_func);
95         obj.holding_lib_changed = false;
96     },
97
98     /******************************************************************************************************/
99
100     'render_call_number' : function(cn) {
101         var obj = this;
102         if (cn == null) { // true for both 'null' AND undefined
103             return '';
104         } else if (typeof cn != 'object') {
105             return obj.acn_label_map[cn];
106         } else {
107             return cn.label()
108         }
109     },
110
111     'render_unit_template' : function(ut) {
112         var obj = this;
113         if (ut == null) { // true for both 'null' AND undefined
114             return '';
115         } else if (typeof ut != 'object') {
116             return obj.act_name_map[ut];
117         } else {
118             return ut.name()
119         }
120     },
121
122     'render_record_entry' : function(sre) {
123         var obj = this;
124         var sre_id;
125         if (sre == null) { // true for both 'null' AND undefined
126             return '';
127         } else if (typeof sre != 'object') {
128             sre_id = sre;
129         } else {
130             sre_id = sre.id();
131         }
132         return obj.sre_id_map[sre_id].label;
133     },
134
135     'init_panes' : function () {
136         var obj = this;
137         obj.panes_and_field_names = {
138
139         /* These get shown in the left panel */
140         '_editor_left_pane' :
141         [
142             [
143                 'id',
144                 { 
145                     //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
146
147                 }
148             ],
149             [
150                 'label',
151                 { 
152                     input: 'c = function(v){ obj.apply("label",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.label); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
153                     value_key: 'label',
154                     required: true
155                 }
156             ],
157             [
158                 'summary_method',
159                 {
160                     render: 'obj.summary_methods[fm.summary_method()]',
161                     input: 'c = function(v){ obj.apply("summary_method",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_object_to_list( obj.summary_methods, function(obj,i) { return [ obj[i], i ]; })); x.setAttribute("value",obj.editor_values.summary_method); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
162                     value_key: 'summary_method',
163                     dropdown_key: 'fm.summary_method() == null ? null : fm.summary_method()'
164                 }
165             ],
166             [
167                 'unit_label_prefix',
168                 {
169                     input: 'c = function(v){ obj.apply("unit_label_prefix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_prefix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
170                     value_key: 'unit_label_prefix'
171                 }
172             ],
173             [
174                 'unit_label_suffix',
175                 { 
176                     input: 'c = function(v){ obj.apply("unit_label_suffix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_suffix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
177                     value_key: 'unit_label_suffix'
178                 }
179             ],
180         ],
181         /* These get shown in the right panel */
182             '_editor_right_pane' :
183         [
184             [
185                 'holding_lib',
186                 {
187                     render: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().shortname() : obj.data.hash.aou[ fm.holding_lib() ].shortname()',
188                     input: 'c = function(v){ if (obj.editor_values.holding_lib != v) obj.apply("holding_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.aou, function(myobj) { var sname = myobj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ myobj.name() ? sname + " " + myobj.name() : myobj.shortname(), myobj.id(), ( ! get_bool( obj.data.hash.aout[ myobj.ou_type() ].can_have_vols() ) ), ( obj.data.hash.aout[ myobj.ou_type() ].depth() * 2), ]; }), obj.data.list.au[0].ws_ou()); x.setAttribute("value",obj.editor_values.holding_lib); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
189                     value_key: 'holding_lib',
190                     dropdown_key: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().id() : fm.holding_lib()',
191                 }
192             ],
193         ],
194         /* These get shown in the right 'library-specific-options' panel */
195         '_editor_lso_pane' :
196         [
197             [
198                 'record_entry',
199                 {
200                     render: 'obj.render_record_entry(fm.record_entry())',
201                     input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("record_entry",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_sre_details_list(), function(obj) { return [ obj.label, obj.id ]; }).sort()); x.setAttribute("value",obj.editor_values.record_entry); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
202                     value_key: 'record_entry',
203                     dropdown_key: 'fm.record_entry() == null ? null : typeof fm.record_entry() == "object" ? fm.record_entry().id() : fm.record_entry()'
204                 }
205             ],
206             [
207                 'receive_call_number',
208                 {
209                     render: 'obj.render_call_number(fm.receive_call_number())',
210                     input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
211                     value_key: 'receive_call_number',
212                     dropdown_key: 'fm.receive_call_number() == null ? null : typeof fm.receive_call_number() == "object" ? fm.receive_call_number().id() : fm.receive_call_number()'
213                 }
214             ],
215             [
216                 'bind_call_number',
217                 {
218                     render: 'obj.render_call_number(fm.bind_call_number())',
219                     input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
220                     value_key: 'bind_call_number',
221                     dropdown_key: 'fm.bind_call_number() == null ? null : typeof fm.bind_call_number() == "object" ? fm.bind_call_number().id() : fm.bind_call_number()'
222                 }
223             ],
224             [
225                 'receive_unit_template',
226                 {
227                     render: 'obj.render_unit_template(fm.receive_unit_template())',
228                     input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
229                     value_key: 'receive_unit_template',
230                     dropdown_key: 'fm.receive_unit_template() == null ? null : typeof fm.receive_unit_template() == "object" ? fm.receive_unit_template().id() : fm.receive_unit_template()'
231                 }
232             ],
233             [
234                 'bind_unit_template',
235                 {
236                     render: 'obj.render_unit_template(fm.bind_unit_template())',
237                     input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
238                     value_key: 'bind_unit_template',
239                     dropdown_key: 'fm.bind_unit_template() == null ? null : typeof fm.bind_unit_template() == "object" ? fm.bind_unit_template().id() : fm.bind_unit_template()'
240                 }
241             ],
242         ],
243
244         };
245         for (i in obj.panes_and_field_names) {
246             obj.panes_and_field_names[obj.xul_id_prefix + i] = obj.panes_and_field_names[i];
247             delete obj.panes_and_field_names[i];
248         }
249     },
250
251     /******************************************************************************************************/
252     /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
253
254     'summarize' :  serial.editor_base.editor_base_summarize,
255
256     /******************************************************************************************************/
257     /* Display the summarized data and inputs for editing */
258
259     'render' :  serial.editor_base.editor_base_render,
260
261     /******************************************************************************************************/
262     /* This actually draws the change button and input widget for a given field */
263     'render_input' : serial.editor_base.editor_base_render_input,
264
265     /******************************************************************************************************/
266     /* save the distributions */
267
268     'save' : function() {
269         var obj = this;
270         obj.editor_base_save('open-ils.serial.distribution.fleshed.batch.update');
271     },
272
273     /******************************************************************************************************/
274     /* spawn notes interface */
275
276     'notes' : function() {
277         var obj = this;
278         JSAN.use('util.window'); var win = new util.window();
279         win.open(
280             urls.XUL_SERIAL_NOTES, 
281             $('serialStrings').getString('staff.serial.sdist_editor.notes'),'chrome,resizable,modal',
282             { 'object_id' : obj.sdists[0].id(), 'function_type' : 'SDISTN', 'object_type' : 'distribution', 'constructor' : sdistn }
283         );
284     },
285
286     /******************************************************************************************************/
287     'save_attributes' : serial.editor_base.editor_base_save_attributes,
288
289     /******************************************************************************************************/
290     /* Build maps of sre details for both display and selection purposes */
291
292     'build_sre_maps' : function() {
293         var obj = this;
294         try {
295             obj.sre_id_map = {};
296             obj.sres_ou_map = {};
297             var parent_g = window.parent.g;
298             if (parent_g.mfhd) {
299                 var mfhd_details = parent_g.mfhd.details;
300                 for (var i = 0; i < mfhd_details.length; i++) {
301                     var mfhd_detail = {};
302                     for (j in mfhd_details[i]) {
303                         mfhd_detail[j] = mfhd_details[i][j];
304                     }
305                     mfhd_detail.label = mfhd_detail.label + ' (' + (mfhd_detail.entryNum + 1) + ')';
306                     var sre_id = mfhd_detail.id;
307                     var org_unit_id = mfhd_detail.owning_lib;
308                     obj.sre_id_map[sre_id] = mfhd_detail;
309                     if (!obj.sres_ou_map[org_unit_id]) {
310                         obj.sres_ou_map[org_unit_id] = [];
311                     }
312                     obj.sres_ou_map[org_unit_id].push(mfhd_detail);
313                 }
314             }
315         } catch(E) {
316             obj.error.standard_unexpected_error_alert('build_sre_maps',E);
317         }
318     },
319
320     /******************************************************************************************************/
321     /* This returns a list of sre details appropriate for the distributions being edited */
322
323     'get_sre_details_list' : function() {
324         var obj = this;
325         try {
326             /* we only show this list if dealing with one org_unit, default to first sdist*/
327             var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
328             var sre_details_list = obj.sres_ou_map[lib_id];
329             if (sre_details_list == null) {
330                 return [{'label' : $('serialStrings').getString('staff.serial.sdist_editor.no_mfhd_available.label'), 'id' : ''}];
331             } else {
332                 return sre_details_list;
333             }
334         } catch(E) {
335             obj.error.standard_unexpected_error_alert('get_sre_details_list',E);
336             return [];
337         }
338     },
339
340     /******************************************************************************************************/
341     /* This returns a list of acn's appropriate for the distributions being edited */
342
343     'get_acn_list' : function() {
344         var obj = this;
345         try {
346             var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
347
348             if (!obj.acn_lists) {
349                 obj.acn_lists = {};
350             }
351
352             // return cached version if we have it
353             // TODO: clear cache on holding_lib change? (cannot remember how to reproduce this bug)
354             if (obj.acn_lists[lib_id]) {
355                 return obj.acn_lists[lib_id];
356             }
357
358             var acn_list = obj.network.request(
359                 'open-ils.pcrud',
360                 'open-ils.pcrud.search.acn',
361                 [ ses(), {"record" : obj.docid, "owning_lib" : lib_id, "deleted" : 'f' }, {"order_by" : {"acn" : "label"} } ]
362             );
363
364             if (!acn_list) {
365                 return [];
366             } else if (!acn_list.length) {
367                 acn_list = [acn_list];
368             }
369
370             // build label map
371             obj.acn_label_map = {};
372             for (i = 0; i < acn_list.length; i++) {
373                 obj.acn_label_map[acn_list[i].id()] = acn_list[i].label();
374             }
375
376             // cache the list
377             obj.acn_lists[lib_id] = acn_list;
378             return acn_list;
379
380         } catch(E) {
381             obj.error.standard_unexpected_error_alert('get_acn_list',E);
382             return [];
383         }
384     },
385
386     /******************************************************************************************************/
387     /* This returns a list of asset copy templates appropriate for the distributions being edited */
388
389     'get_act_list' : function() {
390         var obj = this;
391         try {
392             /* we only show this list if dealing with one org_unit, default to first sdist*/
393             var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
394
395             if (!obj.act_lists) {
396                 obj.act_lists = {};
397             }
398
399             // return cached version if we have it
400             if (obj.act_lists[lib_id]) {
401                 return obj.act_lists[lib_id];
402             }
403             
404             /* get (and cache) list of ancestors for lib_id */
405             obj.aou_ancestor_list_by_id =
406                 obj.aou_ancestor_list_by_id || [];
407
408             if (!obj.aou_ancestor_list_by_id[lib_id]) {
409                 JSAN.use('util.fm_utils');
410                 obj.aou_ancestor_list_by_id[lib_id] = util.fm_utils.aou_get_ancestor_list_by_id(lib_id);
411
412                 if (!obj.aou_ancestor_list_by_id[lib_id].length)
413                     throw "ancestor list for " + lib_id + " empty?"; /* unlikely */
414             }
415
416             var act_list = obj.network.request(
417                 'open-ils.pcrud',
418                 'open-ils.pcrud.search.act',
419                 [ ses(), {"owning_lib" : obj.aou_ancestor_list_by_id[lib_id] }, {"order_by" : {"act" : "name"} } ]
420             );
421
422             if (act_list == null) {
423                 return [];
424             } else if (!act_list.length) {
425                 act_list = [act_list];
426             }
427
428             // build name map
429             obj.act_name_map = {};
430             for (i = 0; i < act_list.length; i++) {
431                 obj.act_name_map[act_list[i].id()] = act_list[i].name();
432             }
433
434             // cache the list
435             obj.act_lists[lib_id] = act_list;
436             return act_list;
437         } catch(E) {
438             obj.error.standard_unexpected_error_alert('get_act_list',E);
439             return [];
440         }
441     },
442     /******************************************************************************************************/
443     'summary_methods' : {
444         "add_to_sre" : $('serialStrings').getString('staff.serial.sdist_editor.add_to_sre.label'),
445         "merge_with_sre" : $('serialStrings').getString('staff.serial.sdist_editor.merge_with_sre.label'),
446         "use_sre_only" : $('serialStrings').getString('staff.serial.sdist_editor.use_sre_only.label'),
447         "use_sdist_only" : $('serialStrings').getString('staff.serial.sdist_editor.use_sdist_only.label'),
448     }
449 };
450
451 dump('exiting serial/sdist_editor.js\n');