]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/admin/org_unit_settings.js
CLEANUP ALL THE COUST and fix history view
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / admin / org_unit_settings.js
1 dojo.require('fieldmapper.AutoIDL');
2 dojo.require('dijit.layout.LayoutContainer');
3 dojo.require('dijit.layout.ContentPane');
4 dojo.require('dijit.form.FilteringSelect');
5 dojo.require('dijit.Dialog');
6 dojo.require('dijit.form.Textarea');
7 dojo.require('dijit.form.ComboBox');
8 dojo.require('dojox.grid.Grid');
9 dojo.require('fieldmapper.Fieldmapper');
10 dojo.require('fieldmapper.dojoData');
11 dojo.require('fieldmapper.OrgUtils');
12 dojo.require('dojo.cookie');
13 dojo.require('openils.CGI');
14 dojo.require('openils.User');
15 dojo.require('openils.Event');
16 dojo.require('openils.widget.OrgUnitFilteringSelect');
17 dojo.require('openils.PermaCrud');
18 dojo.require('openils.widget.AutoFieldWidget');
19 dojo.require('openils.widget.ProgressDialog');
20 dojo.require('dijit.Toolbar');
21
22 var authtoken;
23 var query;
24 var contextOrg;
25 var user;
26 var osSettings = {};
27 var ouSettingValues = {};
28 var ouSettingNames = {};
29 var ouNames = {};
30 var osEditAutoWidget;
31 var perm_codes = {};
32 var osGroups = {};
33 var searchAssist = [];
34 var pcrud;
35
36 function osInit(data) {
37     showProcessingDialog(true);
38     
39     authtoken = new openils.CGI().param('ses') || dojo.cookie('ses');
40     query = new openils.CGI().param('filter');
41     user = new openils.User({authtoken:authtoken});
42     contextOrg = user.user.ws_ou();
43     openils.User.authtoken = authtoken;
44     
45     pcrud = new openils.PermaCrud({authtoken:authtoken});
46     
47     var grps = pcrud.retrieveAll('csg');
48     dojo.forEach(grps, function(grp) { osGroups[grp.name()] = grp.label(); });
49     
50     var connect = function() { 
51         dojo.connect(contextOrg, 'onChange', osChangeContext); 
52
53         // don't draw the org settings grid unless the user has permission
54         // to view org settings in at least 1 org unit
55         osContextSelector.store.fetch({query: {}, start: 0, count: 0, 
56             onBegin: function(size) { 
57                 if(size) { osDraw();  return; }
58                 dojo.removeClass('no-perms', 'hide_me');
59             }
60         });
61         
62     };
63
64     new openils.User().buildPermOrgSelector('VIEW_ORG_SETTINGS', osContextSelector, null, connect);
65
66     fieldmapper.standardRequest(
67         [   'open-ils.actor',
68             'open-ils.actor.permissions.retrieve'],
69         {   async: true,
70             oncomplete: function(r) {
71                 var data = r.recv().content();
72                 if(e = openils.Event.parse(data))
73                     return alert(e);
74                 for(var key in data)
75                     perm_codes[data[key].id()] = data[key].code();
76             }
77         }
78     );
79     
80     var aous = pcrud.retrieveAll('aou');
81     dojo.forEach(aous, function(ou) { ouNames[ou.id()] = ou.shortname(); });
82     
83     showProcessingDialog(false);
84 }
85 dojo.addOnLoad(osInit);
86
87 function showProcessingDialog(toggle) {
88     var proc = dojo.byId('proci18n').innerHTML;
89     if(toggle)
90         progressDialog.show(true, proc);
91     else
92         progressDialog.hide();
93 }
94
95 function osDraw(specific_setting) {
96     showProcessingDialog(true);
97
98     var names = [];
99     if (specific_setting) {
100
101         for(var key in specific_setting)
102             names.push(key);
103
104     } else {
105         var types = new openils.PermaCrud({authtoken:authtoken}).retrieveAll('coust');
106
107         searchAssist =  [];
108         
109         dojo.forEach(types, 
110             function(type) {
111                 osSettings[type.name()] = {
112                     label : type.label(),
113                     desc : type.description(),
114                     type : type.datatype(),
115                     fm_class : type.fm_class(),
116                     update_perm : type.update_perm(),
117                     grp : osGroups[type.grp()]
118                 }
119                 
120                 var tmp = "" + type.label() + "" + type.description() + "" + type.fm_class() + "" + 
121                           osGroups[type.grp()] + "" + type.name();
122                 
123                 searchAssist[type.name()] = tmp.toLowerCase().replace(/[^a-z0-9]+/g, '');
124             }
125         );
126         
127         for(var key in osSettings)
128             names.push(key);
129     }
130     
131     osDrawNames(names);
132 }
133
134 /**
135  * Auto searches 500ms after entering text.
136  */
137 var osCurrentSearchTimeout;
138 function osSearchChange() {
139     if(osCurrentSearchTimeout != null)
140         clearTimeout(osCurrentSearchTimeout);
141         
142     osCurrentSearchTimeout = setTimeout("doSearch()", 500);
143 }
144
145 //Limits those functions seen to the ones that have similar text to 
146 //that which is provided. Not case sensitive.
147 function osLimitSeen(text) {
148     showProcessingDialog(true);
149     
150     text = text.split(' ');
151     
152     for(t in text)
153         text[t] = text[t].toLowerCase().replace(/[^a-z0-9]+/g, '');
154     
155     numTerms = text.length;
156     
157     var names = [];
158     for(var n in searchAssist) {
159         var numFound = 0;
160         
161         for(var t in text) 
162             if(searchAssist[n].indexOf(text[t]) != -1)
163                 numFound++;
164                 
165         if(numFound == numTerms)
166             names.push(n);
167     }
168     
169     //Don't update on an empty list as this causes bizarre errors.
170     if(names.length == 0) {
171         showProcessingDialog(false);
172         showAlert(dojo.byId('noresults').innerHTML);
173         return;
174     }
175     
176     ouSettingValues = {}; // Clear the values.
177     osDrawNames(names); // Repopulate setting values with the ones we want.
178 }
179
180 function doSearch() {
181     osCurrentSearchTimeout = null;
182     
183     var query = dojo.byId('searchBox').value;
184     
185     osLimitSeen(query);
186     
187     return false; //Keep form from submitting
188 }
189
190 function clearSearch() {
191     if(dojo.byId('searchBox').value != '') { // Don't refresh on blank.
192         dojo.byId('searchBox').value = '';
193         doSearch();
194     }
195 }
196
197 function osToJson() {
198     var out = dojo.fromJson(dojo.toJson(ouSettingValues)); // Easy deep copy
199     var context = osContextSelector.getValue();
200     
201     // Set all of the nulls in the outputs to be part of the current org
202     // this keeps from overwriting later if this file is transfered to another lib.
203     for(key in out)
204         if(out[key] == null)
205             out[key] = {'org':context, 'value':null};
206     
207     dojo.byId('jsonOutput').value = dojo.toJson(out);
208     osJSONOutDialog.show();
209 }
210
211 // Copies the text from the json output to the clipboard.
212 function osJsonOutputCopy() {
213     document.popupNode = dojo.byId('jsonOutput');
214     dojo.byId('jsonOutput').focus();
215     dojo.byId('jsonOutput').select();
216     util.clipboard.copy();
217     showAlert(dojo.byId('os-copy').innerHTML);
218 }
219
220 function osJsonInputPaste() {
221     document.popupNode = dojo.byId('jsonInput');
222     document.popupNode.focus();
223     document.popupNode.select();
224     util.clipboard.paste();
225 }
226
227 function osFromJson() {
228      dojo.byId('jsonInput').value = '';
229      osJSONInDialog.show();
230 }
231
232 function osFromJsonSubmit() {
233     var input = dojo.byId('jsonInput').value;
234     var from = dojo.fromJson(input);
235     
236     osJSONInDialog.hide();
237
238     showProcessingDialog(true);
239     for(key in from) {
240         
241         //Check that there isn't already set to the same value (speed increase);
242         if( ouSettingValues[key] == null && 
243             from[key]['value'] == null &&
244             osContextSelector.getValue() == from[key]['org'])
245             continue;
246                 
247         if( ouSettingValues[key] != null && 
248             ouSettingValues[key]['value'] == from[key]['value'] &&
249             ouSettingValues[key]['org'] == from[key]['org'])
250             continue;
251         
252         var obj = {};
253         var context;
254         
255         if(from[key] != null) { 
256             obj[key] = from[key]['value'];
257             context  = from[key]['org'];
258         }
259         
260         osUpdateSetting(obj, context);
261     }
262     showProcessingDialog(false);
263 }
264
265 //Draws the grid based upon a given array of items to draw.
266 function osDrawNames(names) {
267     fieldmapper.standardRequest(
268         [   'open-ils.actor', 
269             'open-ils.actor.ou_setting.ancestor_default.batch'],
270         {   async: true,
271             params: [contextOrg, names, authtoken],
272             oncomplete: function(r) {
273                 var data = r.recv().content();
274                 if(e = openils.Event.parse(data))
275                     return alert(e);
276                 for(var key in data)
277                     ouSettingValues[key] = data[key];
278                 osLoadGrid(ouSettingValues);
279                 
280                 showProcessingDialog(false);
281             }
282         }
283     );
284 }
285
286 function osChangeContext() {
287     if(contextOrg == osContextSelector.getValue())
288         return;
289     contextOrg = osContextSelector.getValue();
290     osDraw();
291 }
292
293 function osLoadGrid(data) {
294     var gridData = {items:[]}
295     for(var key in data) {
296         var setting = osSettings[key];
297         setting.context = null;
298         setting.value = null;
299         if(data[key]) {
300             setting.context = data[key].org;
301             setting.value = data[key].value;
302         }
303         gridData.items.push({name:key});
304     }
305     gridData.items = gridData.items.sort(
306         function(a, b) {
307             var seta = osSettings[a.name];
308             var setb = osSettings[b.name];
309             if(seta.grp + "" + seta.label > setb.grp + "" + setb.label) return 1;
310             if(seta.grp + "" + seta.label < setb.grp + "" + setb.label) return -1;
311             return 0;
312         }
313     );
314     gridData.identifier = 'name';
315     var store = new dojo.data.ItemFileReadStore({data:gridData});
316     var model = new dojox.grid.data.DojoData(
317         null, store, {rowsPerPage: 100, clientSort: true, query:{name:'*'}});
318
319     osGrid.setModel(model);
320     osGrid.setStructure(osGridLayout);
321     osGrid.update();
322 }
323
324 function osGetGridData(rowIdx) {
325     var data = this.grid.model.getRow(rowIdx);
326     if(!data) return '';
327     var setting = osSettings[data.name];
328     var value = setting[this.field];
329     if(value == null) return '';
330
331     switch(this.field) {
332         case 'context':
333             return fieldmapper.aou.findOrgUnit(value).shortname();
334         case 'label':
335             if(setting.noInherit)
336                 return value + ' *';
337             return value;
338         case 'value':
339             if(setting.fm_class) {
340                 var autoWidget = new openils.widget.AutoFieldWidget(
341                     {
342                         fmClass : setting.fm_class,
343                         selfReference : true,
344                         widgetValue : value,
345                         forceSync : true,
346                         readOnly : true
347                     }
348                 );
349                 autoWidget.build();
350                 if(autoWidget.getDisplayString())
351                     return autoWidget.getDisplayString();
352             }
353
354             if(setting.type == 'bool') {
355                 if(value) 
356                     return dojo.byId('os-true').innerHTML;
357                 return dojo.byId('os-false').innerHTML;
358             }
359         default:
360             return value;
361     }
362 }
363
364 function osGetEditLink(rowIdx) {
365     var data = this.grid.model.getRow(rowIdx);
366     if(!data) return '';
367     return data.name;
368 }
369
370 function osFormatEditLink(name) {
371     return this.value.replace(/SETTING/g, name);
372 }
373
374 function osLaunchEditor(name) {
375     osEditDialog._osattr = name;
376     osEditDialog.show();
377     var perms = ['UPDATE_ORG_UNIT_SETTING_ALL'];
378     if(osSettings[name].update_perm && perm_codes[osSettings[name].update_perm]) {
379         perms.push(perm_codes[osSettings[name].update_perm]);
380     }
381     user.buildPermOrgSelector(
382         perms,
383         osEditContextSelector, osSettings[name].context
384     );
385     dojo.byId('os-edit-name').innerHTML = osSettings[name].label;
386     dojo.byId('os-edit-desc').innerHTML = osSettings[name].desc || '';
387
388     dojo.style(osEditTextBox.domNode, 'display', 'none');
389     dojo.style(osEditCurrencyTextBox.domNode, 'display', 'none');
390     dojo.style(osEditNumberTextBox.domNode, 'display', 'none');
391     dojo.style(osEditBoolSelect.domNode, 'display', 'none');
392
393     var fmClass = osSettings[name].fm_class;
394
395     if(osEditAutoWidget) {
396         osEditAutoWidget.domNode.parentNode.removeChild(osEditAutoWidget.domNode);
397         osEditAutoWidget.destroy();
398         osEditAutoWidget = null;
399     }
400     
401     if(fmClass) {
402
403         if(osEditAutoWidget) {
404             osEditAutoWidget.domNode.parentNode.removeChild(osEditAutoWidget.domNode);
405             osEditAutoWidget.destroy();
406         }
407
408         var autoWidget = new openils.widget.AutoFieldWidget(
409             {
410                 fmClass : fmClass,
411                 selfReference : true,
412                 parentNode : dojo.create('div', null, dojo.byId('os-edit-auto-widget')),
413                 widgetValue : osSettings[name].value
414             }
415         );
416         autoWidget.build(
417             function(w) {
418                 osEditAutoWidget = w;
419             }
420         );
421
422     } else {
423         var widget;
424         switch(osSettings[name].type) {
425             case 'number':
426                 widget = osEditNumberTextBox; 
427                 break;
428             case 'currency':
429                 widget = osEditCurrencyTextBox; 
430                 break;
431             case 'bool':
432                 widget = osEditBoolSelect; 
433                 break;
434             default:
435                 widget = osEditTextBox;
436         }
437
438         dojo.style(widget.domNode, 'display', 'block');
439         widget.setValue(osSettings[name].value);
440     }
441 }
442
443 function osEditSetting(deleteMe) {
444     osEditDialog.hide();
445     var name = osEditDialog._osattr;
446
447     var obj = {};
448     if(deleteMe) {
449         obj[name] = null;
450     } else {
451         if(osSettings[name].fm_class) {
452             var val = osEditAutoWidget.attr('value');
453             osEditAutoWidget.domNode.parentNode.removeChild(osEditAutoWidget.domNode);
454             osEditAutoWidget.destroy();
455             osEditAutoWidget = null;
456             if(val == null || val == '') return;
457             obj[name] = val;
458
459         } else {
460             switch(osSettings[name].type) {
461                 case 'number':
462                     obj[name] = osEditNumberTextBox.getValue();
463                     if(obj[name] == null) return;
464                     break;
465                 case 'currency':
466                     obj[name] = osEditCurrencyTextBox.getValue();
467                     if(obj[name] == null) return;
468                     break;
469                 case 'bool':
470                     var val = osEditBoolSelect.getValue();
471                     obj[name] = (val == 'true') ? true : false;
472                     break;
473                 default:
474                     obj[name] = osEditTextBox.getValue();
475                     if(obj[name] == null) return;
476             }
477         }
478     }
479     osUpdateSetting(obj, osEditContextSelector.getValue(), name);
480 }
481
482 function osUpdateSetting(obj, context, name) {
483     fieldmapper.standardRequest(
484         ['open-ils.actor', 'open-ils.actor.org_unit.settings.update'],
485         {   async: true,
486             params: [authtoken, context, obj],
487             oncomplete: function(r) {
488                 var res = r.recv().content();
489                 if(e = openils.Event.parse(res))
490                     return alert(e);
491                 osDraw(obj);
492                 if(context != osContextSelector.getValue())
493                     showAlert(dojo.byId('os-not-chosen').innerHTML);
494             }
495         }
496     );
497 }
498
499 function osRevertSetting(context, name, value) {
500     osHistDialog.hide();
501
502     var obj = {};
503     
504     if(value == 'null' || value == null)
505         obj[name] = null;
506     else
507         obj[name] = value;
508     
509     osUpdateSetting(obj, context, name);
510 }
511
512 function osGetHistoryLink(rowIdx) {
513     var data = this.grid.model.getRow(rowIdx);
514     if(!data) return '';
515     return data.name;
516 }
517
518 function osFormatHistoryLink(name) {
519     return this.value.replace(/SETTING/, name);
520 }
521
522 function osLaunchHistory(name) {
523     showProcessingDialog(true);
524     
525     dojo.byId('osHistName').innerHTML = osSettings[name].label;
526     
527     var data = dojo.byId('histTitle').innerHTML;
528     var thisHist = pcrud.search('coustl', {'field_name':name});
529     for(var i in thisHist.reverse()) {
530         d = thisHist[i].date_applied();
531         a = ouNames[thisHist[i].org()];
532         o = thisHist[i].original_value();
533         if(o) o=o.replace(/\&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
534         n = thisHist[i].new_value();
535         if(n) n=n.replace(/\&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
536         r = thisHist[i].org();
537         // Table is: Date | Org Name | Orig Value | New Value | Revert
538         data += "<tr><td>" + d + "</td><td>" + a + "</td><td>" + o +
539         "</td><td>" + n + "</td><td>" +
540         "<a href='javascript:void(0);' onclick='osRevertSetting(" + r + ", &quot;" + name +"&quot;,"+o+");'>"+dojo.byId('os-revert').innerHTML+"</a></td></tr>";
541     }
542         
543     dojo.byId('historyData').innerHTML = data;
544     
545     showProcessingDialog(false);
546     osHistDialog.show();
547 }
548
549 function showAlert(message, timeout) {
550     if(timeout == null) {
551         timeout = 3000;
552         if(message.length > 50)
553             timeout = 5000;
554         if(message.length > 80)
555             timeout = 8000;
556     }
557     
558     dojo.removeClass('msgCont', 'hidden');
559     
560     dojo.byId('msgInner').innerHTML = message;
561     
562     var fadeArgs = { node: "msgCont" };
563     dojo.fadeIn(fadeArgs).play();
564     
565     window.setTimeout('hideAlert()', timeout);
566     
567 }
568
569 function hideAlert() {
570     var fadeArgs = { node: "msgCont" };
571     dojo.fadeOut(fadeArgs).play();
572     dojo.addClass('msgCont', 'hidden');
573 }