In reports, show old label name as the default in the Alter Display Header -prompt
[working/Evergreen.git] / Open-ILS / web / reports / xul / template-config.js
1 dojo.requireLocalization("openils.reports", "reports");
2
3 var rpt_strings = dojo.i18n.getLocalization("openils.reports", "reports");
4
5 function removeReportAtom (args) {
6         if (!args) args = {};
7
8         var active_tab = filterByAttribute(
9                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
10                 'selected',
11                 'true'
12         )[0];
13         var tabname = active_tab.getAttribute('id');
14
15         var tabpanel = $( tabname + 'panel' );
16         var tree = tabpanel.getElementsByTagName('tree')[0];
17         var fields = getSelectedItems(tree);
18
19
20         for (var i in fields) {
21                 var field = fields[i];
22                 var colname = field.firstChild.firstChild.nextSibling.getAttribute('label');
23                 var relation_alias = field.getAttribute('relation');
24
25                 delete rpt_rel_cache[relation_alias].fields[tabname][colname];
26                 if (tabname == 'dis_tab') {
27                         var _o_tmp = [];
28                         for each (var _o_col in rpt_rel_cache.order_by) {
29                                 if (_o_col.relation == relation_alias && _o_col.field == colname) continue;
30                                 _o_tmp.push( _o_col );
31                         }
32                         rpt_rel_cache.order_by = _o_tmp
33                 }
34
35                 with (rpt_rel_cache[relation_alias].fields) {
36                         if ( getKeys(dis_tab).length == 0 && getKeys(filter_tab).length == 0 && getKeys(aggfilter_tab).length == 0 )
37                                 delete rpt_rel_cache[relation_alias];
38                 }
39         }
40
41         renderSources();
42
43         return true;
44 }
45
46 function getSourceDefinition(aClass) {
47         var class_obj = getIDLClass(aClass);
48         return class_obj.getAttributeNS(persistNS,'tablename') || 
49         '(' + class_obj.getElementsByTagNameNS(persistNS,'source_definition')[0].textContent + ')';
50 }
51
52 function addReportAtoms () {
53         var nope = $( 'source-add' ).getAttribute('disabled');
54         if (nope == 'true') return false;
55
56         var class_tree = $('class-view');
57         var transform_tree = $('trans-view');
58
59         var active_tab = filterByAttribute(
60                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
61                 'selected',
62                 'true'
63         )[0];
64
65         var tabname = active_tab.getAttribute('id')
66
67         var items = getSelectedItems(class_tree);
68         var transform = getSelectedItems(transform_tree)[0];
69
70         var reltype = $('path-label').getAttribute('reltype');
71         var class_label = $('path-label').value;
72         var relation_alias = hex_md5(class_label);
73
74         for (var i in items) {
75                 var item = items[i];
76
77                 var class_path = item.getAttribute('fullpath');
78                 var field_class = item.getAttribute('idlclass');
79                 var datatype = item.getAttribute('datatype');
80                 var colname = item.getAttribute('idlfield');
81                 var jointype = item.getAttribute('join');
82                 var field_label = item.firstChild.firstChild.getAttribute('label');
83
84                 var table_name = getSourceDefinition(field_class);
85
86                 if ( !rpt_rel_cache[relation_alias] ) {
87                         rpt_rel_cache[relation_alias] =
88                                 { label     : class_label,
89                                   alias     : relation_alias,
90                                   path      : class_path,
91                                   join      : jointype,
92                                   reltype   : reltype,
93                                   idlclass  : field_class,
94                                   table     : table_name,
95                                   fields    : { dis_tab : {}, filter_tab : {}, aggfilter_tab : {} }
96                                 };
97                 }
98
99                 if ( !rpt_rel_cache[relation_alias].fields[tabname][colname] ) {
100                         rpt_rel_cache[relation_alias].fields[tabname][colname] =
101                                 { colname   : colname,
102                                   transform : (transform && transform.getAttribute('name')) || rpt_strings.TEMPLATE_CONF_BARE,
103                                   aggregate : transform && transform.getAttribute('aggregate'),
104                                   params    : transform && transform.getAttribute('params'),
105                                   transform_label: (transform && transform.getAttribute('alias')) || rpt_strings.TEMPLATE_CONF_RAW_DATA,
106                                   alias     : field_label,
107                                   join      : jointype,
108                                   datatype  : datatype,
109                                   op        : (datatype == 'array') ? '= any' : '=',
110                                   op_label  : rpt_strings.TEMPLATE_CONF_EQUALS,
111                                   op_value  : {}
112                                 };
113
114                         if (!rpt_rel_cache.order_by)
115                                 rpt_rel_cache.order_by = [];
116
117                         if (tabname == 'dis_tab')
118                                 rpt_rel_cache.order_by.push( { relation : relation_alias, field : colname } );
119
120                 } else if (confirm(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_CONFIRM_RESET, [field_label, class_label] )) ) {
121                         rpt_rel_cache[relation_alias].fields[tabname][colname] =
122                                 { colname   : colname,
123                                   transform : (transform && transform.getAttribute('name')) || rpt_strings.TEMPLATE_CONF_BARE,
124                                   aggregate : transform && transform.getAttribute('aggregate'),
125                                   params    : transform && transform.getAttribute('params'),
126                                   transform_label: (transform && transform.getAttribute('alias')) || rpt_strings.TEMPLATE_CONF_RAW_DATA,
127                                   alias     : field_label,
128                                   join      : jointype,
129                                   datatype  : datatype,
130                                   op        : '=',
131                                   op_label  : rpt_strings.TEMPLATE_CONF_EQUALS,
132                                   op_value  : {}
133                                 };
134                 }
135         }
136
137         renderSources();
138
139         return true;
140 }
141
142 function changeDisplayOrder (dir) {
143         var active_tab = filterByAttribute(
144                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
145                 'selected',
146                 'true'
147         )[0];
148
149         var tabname = active_tab.getAttribute('id');
150
151         var tabpanel = $( tabname + 'panel' );
152         var tree = tabpanel.getElementsByTagName('tree')[0];
153         var item = getSelectedItems(tree)[0];
154
155         var item_pos = tree.view.selection.currentIndex;
156
157         if (dir == 'u') {
158                 if ( item.previousSibling ) {
159                         item.parentNode.insertBefore( item, item.previousSibling );
160                         item_pos--;
161                 }
162         } else if (dir == 'd') {
163                 if ( item.nextSibling ) {
164                         if (item.nextSibling.nextSibling ) item.parentNode.insertBefore( item, item.nextSibling.nextSibling );
165                         else item.parentNode.appendChild( item );
166                         item_pos++;
167                 }
168         }
169         
170         rpt_rel_cache.order_by = [];
171         var ordered_list = tree.getElementsByTagName('treeitem');
172         for (var i = 0; i < ordered_list.length; i++) {
173                 rpt_rel_cache.order_by.push(
174                         { relation : ordered_list[i].getAttribute('relation'),
175                           field    : ordered_list[i].firstChild.firstChild.nextSibling.getAttribute('label')
176                         }
177                 );
178         }
179
180         tree.view.selection.select( item_pos );
181         return true;
182 }
183
184 function alterColumnLabel () {
185         var active_tab = filterByAttribute(
186                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
187                 'selected',
188                 'true'
189         )[0];
190
191         var tabname = active_tab.getAttribute('id');
192
193         var tabpanel = $( tabname + 'panel' );
194         var tree = tabpanel.getElementsByTagName('tree')[0];
195         var item_pos = tree.view.selection.currentIndex;
196
197         var item = getSelectedItems(tree)[0];
198         var relation_alias = item.getAttribute('relation');
199
200         var field = item.firstChild.firstChild;
201         var colname = field.nextSibling.getAttribute('label');
202
203         var old_label = field.getAttribute("label");
204         var new_label = prompt( dojo.string.substitute(rpt_strings.TEMPLATE_CONF_PROMPT_CHANGE, [old_label]), old_label );
205
206         if (new_label) {
207                 rpt_rel_cache[relation_alias].fields[tabname][colname].alias = new_label;
208                 renderSources(true);
209                 tree.view.selection.select( item_pos );
210                 tree.focus();
211                 tree.click();
212         }
213
214         return true;
215 }
216
217 function alterColumnTransform (trans) {
218
219         var transform = OILS_RPT_TRANSFORMS[trans];
220
221         var active_tab = filterByAttribute(
222                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
223                 'selected',
224                 'true'
225         )[0];
226
227         var tabname = active_tab.getAttribute('id');
228
229         var tabpanel = $( tabname + 'panel' );
230         var tree = tabpanel.getElementsByTagName('tree')[0];
231         var item_pos = tree.view.selection.currentIndex;
232         var item =  getSelectedItems(tree)[0];
233         var relation_alias = item.getAttribute('relation');
234
235         var field = item.firstChild.firstChild;
236         var colname = field.nextSibling.getAttribute('label');
237
238         rpt_rel_cache[relation_alias].fields[tabname][colname].transform = trans;
239         rpt_rel_cache[relation_alias].fields[tabname][colname].aggregate = transform.aggregate;
240         rpt_rel_cache[relation_alias].fields[tabname][colname].params = transform.params;
241         rpt_rel_cache[relation_alias].fields[tabname][colname].transform_label = transform.label;
242
243         renderSources(true);
244         tree.view.selection.select( item_pos );
245         tree.focus();
246         tree.click();
247
248         $(tabname + '_trans_menu').hidePopup();
249         return true;
250 }
251
252 function changeOperator (args) {
253
254         var active_tab = filterByAttribute(
255                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
256                 'selected',
257                 'true'
258         )[0];
259
260         var tabname = active_tab.getAttribute('id');
261
262         var tabpanel = $( tabname + 'panel' );
263         var tree = tabpanel.getElementsByTagName('tree')[0];
264         var item_pos = tree.view.selection.currentIndex;
265         var item = getSelectedItems(tree)[0];
266
267         var relation_alias = item.getAttribute('relation');
268
269         var field = item.firstChild.firstChild;
270         var colname = field.nextSibling.getAttribute('label');
271
272         rpt_rel_cache[relation_alias].fields[tabname][colname].op = args.op;
273         rpt_rel_cache[relation_alias].fields[tabname][colname].op_label = args.label;
274
275         renderSources(true);
276         tree.view.selection.select( item_pos );
277         tree.focus();
278         tree.click();
279
280         $(tabname + '_op_menu').hidePopup();
281         return true;
282 }
283
284 function removeTemplateFilterValue () {
285
286         var active_tab = filterByAttribute(
287                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
288                 'selected',
289                 'true'
290         )[0];
291
292         var tabname = active_tab.getAttribute('id');
293
294         var tabpanel = $( tabname + 'panel' );
295         var tree = tabpanel.getElementsByTagName('tree')[0];
296         var item_pos = tree.view.selection.currentIndex;
297         var items = getSelectedItems(tree);
298
299         for (var i in items) {
300                 var item = items[i];
301                 var relation_alias = item.getAttribute('relation');
302
303                 var field = item.firstChild.firstChild;
304                 var colname = field.nextSibling.getAttribute('label');
305
306                 rpt_rel_cache[relation_alias].fields[tabname][colname].op_value = {};
307         }
308
309         renderSources(true);
310         tree.view.selection.select( item_pos );
311         return true;
312 }
313
314 function timestampSetDate (obj, cal, date) {
315         obj.op_value.value = date;
316         obj.op_value.object = cal.date;
317         obj.op_value.label = '"' + date + '"';
318
319         renderSources(true);
320         return true;
321 }
322
323 var __handler_cache;
324
325 function changeTemplateFilterValue () {
326
327         var active_tab = filterByAttribute(
328                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
329                 'selected',
330                 'true'
331         )[0];
332
333         var tabname = active_tab.getAttribute('id');
334
335         var tabpanel = $( tabname + 'panel' );
336         var tree = tabpanel.getElementsByTagName('tree')[0];
337         var items = getSelectedItems(tree);
338
339         var targetCmd = $( tabname + '_value_action' );
340
341         targetCmd.menu = null;
342         targetCmd.command = null;
343         targetCmd.oncommand = null;
344         targetCmd.removeEventListener( 'command', __handler_cache, true );
345
346         for (var i in items) {
347                 var item = items[i];
348                 var relation_alias = item.getAttribute('relation');
349
350                 var field = item.firstChild.firstChild;
351                 var colname = field.nextSibling.getAttribute('label');
352
353                 var obj = rpt_rel_cache[relation_alias].fields[tabname][colname]
354                 var operation = OILS_RPT_FILTERS[obj.op];
355
356                 switch (obj.datatype) {
357                         case 'timestamp':
358                                 var cal_popup = $('calendar-widget');
359
360                                 while (cal_popup.firstChild) cal_popup.removeChild(cal_popup.lastChild);
361                                 var calendar = new Calendar(
362                                         0,
363                                         obj.op_value.object,
364                                         function (cal,date) { return timestampSetDate(obj,cal,date) },
365                                         function (cal) { cal_popup.hidePopup(); cal.destroy(); return true; }
366                                 );
367
368                                 var format = OILS_RPT_TRANSFORMS[obj.transform].cal_format || '%Y-%m-%d';
369
370                                 calendar.setDateFormat(format);
371                                 calendar.create(cal_popup);
372
373                                 targetCmd.menu = 'calendar-widget';
374
375                                 break;
376
377                         case 'bool':
378
379                                 function __bool_value_event_handler () {
380                                         var state, answer;
381
382                                         try {
383                                                 // get a reference to the prompt service component.
384                                                 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
385                                                                     .getService(Components.interfaces.nsIPromptService);
386
387                                                 // set the buttons that will appear on the dialog. It should be
388                                                 // a set of constants multiplied by button position constants. In this case,
389                                                 // three buttons appear, Save, Cancel and a custom button.
390                                                 var flags=promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
391                                                         promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
392                                                         promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_2;
393
394                                                 // display the dialog box. The flags set above are passed
395                                                 // as the fourth argument. The next three arguments are custom labels used for
396                                                 // the buttons, which are used if BUTTON_TITLE_IS_STRING is assigned to a
397                                                 // particular button. The last two arguments are for an optional check box.
398                                                 answer = promptService.select(
399                                                         window,
400                                                         rpt_strings.TEMPLATE_CONF_BOOLEAN_VALUE,
401                                                         rpt_strings.TEMPLATE_CONF_SELECT_CANCEL,
402                                                         2, [rpt_strings.TEMPLATE_CONF_TRUE, rpt_strings.TEMPLATE_CONF_FALSE], state
403                                                 );
404                                         } catch (e) {
405                                                 answer = true;
406                                                 state = confirm(rpt_strings.TEMPLATE_CONF_CONFIRM_STATE);
407                                                 state ? state = 0 : state = 1;
408                                         }
409
410                                         if (answer) {
411                                                 if (state) {
412                                                         obj.op_value.value = 'f';
413                                                         obj.op_value.label = rpt_strings.TEMPLATE_CONF_FALSE;
414                                                 } else {
415                                                         obj.op_value.value = 't';
416                                                         obj.op_value.label = rpt_strings.TEMPLATE_CONF_TRUE;
417                                                 }
418                                         }
419
420                                         targetCmd.removeEventListener( 'command', __bool_value_event_handler, true );
421                                         renderSources(true);
422                                         tree.view.selection.select( item_pos );
423                                         return true;
424                                 }
425
426                                 __handler_cache = __bool_value_event_handler;
427                                 targetCmd.addEventListener( 'command', __bool_value_event_handler, true );
428
429                                 break;
430
431                         default:
432
433
434                                 var promptstring = rpt_strings.TEMPLATE_CONF_NO_MATCH;
435
436                                 switch (obj.op) {
437                                         case 'not between':
438                                                 promptstring = rpt_strings.TEMPLATE_CONF_NOT_BETWEEN;
439                                                 break;
440
441                                         case 'between':
442                                                 promptstring = rpt_strings.TEMPLATE_CONF_BETWEEN;
443                                                 break;
444
445                                         case 'not in':
446                                                 promptstring = rpt_strings.TEMPLATE_CONF_NOT_IN;
447                                                 break;
448
449                                         case 'in':
450                                                 promptstring = rpt_strings.TEMPLATE_CONF_IN;
451                                                 break;
452
453                                         default:
454                                                 promptstring =  dojo.string.substitute( rpt_strings.TEMPLATE_CONF_DEFAULT, [obj.op_label]);
455                                                 break;
456                                 }
457
458                                 function __default_value_event_handler () {
459                                         var _v;
460                                         if (_v  = prompt( promptstring, obj.op_value.value || '' )) {
461                                                 switch (obj.op) {
462                                                         case 'between':
463                                                         case 'not between':
464                                                         case 'not in':
465                                                         case 'in':
466                                                                 obj.op_value.value = _v.split(/\s*,\s*/);
467                                                                 break;
468
469                                                         default:
470                                                                 obj.op_value.value = _v;
471                                                                 break;
472                                                 }
473
474                                                 obj.op_value.label = '"' + obj.op_value.value + '"';
475                                         }
476
477                                         targetCmd.removeEventListener( 'command', __default_value_event_handler, true );
478                                         renderSources(true);
479                                         tree.view.selection.select( item_pos );
480                                         return true;
481                                 }
482
483                                 __handler_cache = __default_value_event_handler;
484                                 targetCmd.addEventListener( 'command', __default_value_event_handler, true );
485
486                                 break;
487                 }
488         }
489
490         return true;
491 }
492
493 function populateOperatorContext () {
494
495         var active_tab = filterByAttribute(
496                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
497                 'selected',
498                 'true'
499         )[0];
500
501         var tabname = active_tab.getAttribute('id');
502
503         var tabpanel = $( tabname + 'panel' );
504         var tree = tabpanel.getElementsByTagName('tree')[0];
505         var items = getSelectedItems(tree);
506
507         var dtypes = [];
508         for (var i in items) {
509                 var item = items[i];
510                 dtypes.push( item.getAttribute('datatype') );
511         }
512
513         var menu = $(tabname + '_op_menu');
514         while (menu.firstChild) menu.removeChild(menu.lastChild);
515
516         for (var i in OILS_RPT_FILTERS) {
517                 var o = OILS_RPT_FILTERS[i];
518         if (o.label) {
519                 menu.appendChild(
520                         createMenuItem(
521                                 { label : o.label,
522                                   onmouseup : "changeOperator({op:'"+i+"',label:'"+o.label+"'})"
523                                     }
524                         )
525                 );
526         }
527
528                 if (o.labels) {
529                         var keys = getKeys(o.labels);
530                         for ( var k in keys ) {
531                                 var key = keys[k];
532                                 if ( grep(function(x){return key==x},dtypes).length ) {
533                                         menu.appendChild(
534                                                 createMenuItem(
535                                                         { label : o.labels[key],
536                                                           onmouseup : "changeOperator({op:'"+i+"',label:'"+o.labels[key]+"'});"
537                                                         }
538                                                 )
539                                         );
540                                 }
541                         }
542                 }
543         }
544 }
545
546 function populateTransformContext () {
547
548         var active_tab = filterByAttribute(
549                 $('used-source-fields-tabbox').getElementsByTagName('tab'),
550                 'selected',
551                 'true'
552         )[0];
553
554         var tabname = active_tab.getAttribute('id');
555
556         var tabpanel = $( tabname + 'panel' );
557         var tree = tabpanel.getElementsByTagName('tree')[0];
558         var items = getSelectedItems(tree);
559
560         var transforms = {};
561         for (var i in items) {
562                 var item = items[i];
563                 var dtype = item.getAttribute('datatype');
564                 var item_transforms = getTransforms({ datatype : dtype });
565
566                 for (var j in item_transforms) {
567                         transforms[item_transforms[j]] = OILS_RPT_TRANSFORMS[item_transforms[j]];
568                         transforms[item_transforms[j]].name = item_transforms[j];
569                 }
570         }
571
572         var transformList = [];
573         for (var i in transforms) {
574                 transformList.push( transforms[i] );
575         }
576
577         transformList.sort( sortHashLabels );
578
579         var menu = $(tabname + '_trans_menu');
580         while (menu.firstChild) menu.removeChild(menu.lastChild);
581
582         for (var i in transformList) {
583                 var t = transformList[i];
584
585                 if (tabname.match(/filter/)) {
586                         if (tabname.match(/^agg/)) {
587                                 if (!t.aggregate) continue;
588                         } else {
589                                 if (t.aggregate) continue;
590                         }
591                 }
592
593                 menu.appendChild(
594                         createMenuItem(
595                                 { aggregate : t.aggregate,
596                                   name : t.name,
597                                   alias : t.label,
598                                   label : t.label,
599                                   params : t.params,
600                                   onmouseup : "alterColumnTransform('"+t.name+"')"
601                                 }
602                         )
603                 );
604         }
605
606         menu.parentNode.setAttribute('disabled','false');
607         if (menu.childNodes.length == 0) {
608                 menu.parentNode.setAttribute('disabled','true');
609         }
610 }
611
612
613 function renderSources (selected) {
614
615         var tree = $('used-sources');
616         var sources = $('used-sources-treetop');
617         var tabs = $('used-source-fields-tabbox').getElementsByTagName('tab');
618
619         if (!selected) {
620                 while (sources.firstChild) sources.removeChild(sources.lastChild);
621         } else {
622                 selected = getSelectedItems(tree);
623                 if (!selected.length) {
624                         selected = undefined;
625                         while (sources.firstChild) sources.removeChild(sources.lastChild);
626                 }
627         }
628
629         for (var j = 0; j < tabs.length; j++) {
630                 var tab = tabs[j];
631                 var tabname = tab.getAttribute('id')
632                 var tabpanel = $( tab.getAttribute('id') + 'panel' );
633                 var fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
634
635                 while (fieldtree.firstChild) fieldtree.removeChild(fieldtree.lastChild);
636         }
637
638         for (var relation_alias in rpt_rel_cache) {
639                 if (!rpt_rel_cache[relation_alias].fields) continue;
640
641                 if (selected) {
642                         if (
643                                 !grep(
644                                         function (x) {
645                                                 return x.getAttribute('relation') == relation_alias;
646                                         },
647                                         selected
648                                 ).length
649                         ) continue;
650                 } else {
651
652                         $('used-sources-treetop').appendChild(
653                                 createTreeItem(
654                                         { relation : rpt_rel_cache[relation_alias].alias,
655                                           idlclass : rpt_rel_cache[relation_alias].idlclass,
656                                           reltype  : rpt_rel_cache[relation_alias].reltype,
657                                           path     : rpt_rel_cache[relation_alias].path
658                                         },
659                                         createTreeRow(
660                                                 {},
661                                                 createTreeCell({ label : rpt_rel_cache[relation_alias].label }),
662                                                 createTreeCell({ label : rpt_rel_cache[relation_alias].table }),
663                                                 createTreeCell({ label : rpt_rel_cache[relation_alias].alias }),
664                                                 createTreeCell({ label : rpt_rel_cache[relation_alias].reltype })
665                                         )
666                                 )
667                         );
668                 }
669
670                 for each (var tabname in ['filter_tab','aggfilter_tab']) {
671                         tabpanel = $( tabname + 'panel' );
672                         fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
673
674                         for (var colname in rpt_rel_cache[relation_alias].fields[tabname]) {
675                                 with (rpt_rel_cache[relation_alias].fields[tabname][colname]) {
676                                         fieldtree.appendChild(
677                                                 createTreeItem(
678                                                         { relation : relation_alias, datatype : datatype },
679                                                         createTreeRow(
680                                                                 {},
681                                                                 createTreeCell({ label : alias }),
682                                                                 createTreeCell({ label : colname }),
683                                                                 createTreeCell({ label : datatype }),
684                                                                 createTreeCell({ label : transform_label }),
685                                                                 createTreeCell({ label : transform })
686                                                         )
687                                                 )
688                                         );
689
690                                         fieldtree.lastChild.firstChild.appendChild(
691                                                 createTreeCell({ op : op, label : op_label })
692                                         );
693
694                                         if (op_value.value != undefined) {
695                                                 fieldtree.lastChild.firstChild.appendChild(
696                                                         createTreeCell({ label : op_value.label })
697                                                 );
698                                         }
699                                 }
700                         }
701                 }
702         }
703
704         tabpanel = $( 'dis_tabpanel' );
705         fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
706         for each (var order in rpt_rel_cache.order_by) {
707
708                 if (selected) {
709                         if (
710                                 !grep(
711                                         function (x) {
712                                                 return x.getAttribute('relation') == order.relation;
713                                         },
714                                         selected
715                                 ).length
716                         ) continue;
717                 }
718
719                 with (rpt_rel_cache[order.relation].fields.dis_tab[order.field]) {
720                         fieldtree.appendChild(
721                                 createTreeItem(
722                                         { relation : order.relation, datatype : datatype },
723                                         createTreeRow(
724                                                 {},
725                                                 createTreeCell({ label : alias }),
726                                                 createTreeCell({ label : colname }),
727                                                 createTreeCell({ label : datatype }),
728                                                 createTreeCell({ label : transform_label }),
729                                                 createTreeCell({ label : transform })
730                                         )
731                                 )
732                         );
733
734                         fieldtree.lastChild.firstChild.appendChild(
735                                 createTreeCell({ op : op, label : op_label })
736                         );
737
738                         if (op_value.value != undefined) {
739                                 fieldtree.lastChild.firstChild.appendChild(
740                                         createTreeCell({ label : op_value.label })
741                                 );
742                         }
743                 }
744         }
745 }
746
747 var param_count;
748 var tab_use = {
749         dis_tab       : 'select',
750         filter_tab    : 'where',
751         aggfilter_tab : 'having',
752 };
753
754
755 function save_template () {
756         param_count = 0;
757
758         var template = {
759                 version    : 3,
760                 core_class : $('sources-treetop').getElementsByTagName('treeitem')[0].getAttribute('idlclass'),
761                 select     : [],
762                 from       : {},
763                 where      : [],
764                 having     : [],
765                 order_by   : []
766         };
767
768         for (var relname in rpt_rel_cache) {
769                 var relation = rpt_rel_cache[relname];
770                 if (!relation.fields) continue;
771
772                 // first, add the where and having clauses (easier)
773                 for each (var tab_name in [ 'filter_tab', 'aggfilter_tab' ]) {
774                         var tab = relation.fields[tab_name];
775                         for (var field in tab) {
776                                 fleshTemplateField( template, relation, tab_name, field );
777                         }
778                 }
779
780                 // now the from clause
781                 fleshFromPath( template, relation );
782         }
783
784         // and now for select (based on order_by)
785         for each (var order in rpt_rel_cache.order_by)
786                 fleshTemplateField( template, rpt_rel_cache[order.relation], 'dis_tab', order.field );
787
788         template.rel_cache = rpt_rel_cache;
789
790         //prompt( 'template', js2JSON( template ) );
791
792         // and the saving throw ...
793         var cgi = new CGI();
794         var session = cgi.param('ses');
795         fetchUser( session );
796
797         var tmpl = new rt();
798         tmpl.name( $('template-name').value );
799         tmpl.description( $('template-description').value );
800         tmpl.owner(USER.id());
801         tmpl.folder(cgi.param('folder'));
802         tmpl.data(js2JSON(template));
803
804         if(!confirm(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_CONFIRM_SAVE, [tmpl.name(), tmpl.description()] )))
805                 return;
806
807         var req = new Request('open-ils.reporter:open-ils.reporter.template.create', session, tmpl);
808         req.request.alertEvent = false;
809         req.callback(
810                 function(r) {
811                         var res = r.getResultObject();
812                         if(checkILSEvent(res)) {
813                                 alertILSEvent(res);
814                         } else {
815                                 if( res && res != '0' ) {
816                                         alert(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_SUCCESS_SAVE, [tmpl.name()] ));
817                                         _l('../oils_rpt.xhtml');
818                                 }
819                         }
820                 }
821         );
822
823         req.send();
824 }
825
826 function fleshFromPath ( template, rel ) {
827         var table_path = rel.path.split( /\./ );
828         if (table_path.length > 1 || rel.path.indexOf('-') > -1) table_path.push( rel.idlclass );
829
830         var prev_type = '';
831         var prev_link = '';
832         var current_path = '';
833         var current_obj = template.from;
834         var link;
835         while (link = table_path.shift()) {
836
837                 if (prev_link != '') {
838                         var prev_class = getIDLClass( prev_link.split(/-/)[0] );
839                         var prev_field = prev_link.split(/-/)[1];
840
841                         var prev_join = prev_field;
842
843                         prev_field = prev_field.split(/>/)[0];
844                         prev_join = prev_join.split(/>/)[1];
845
846                         var current_link = getIDLLink( prev_class, prev_field );
847                         current_obj.key = current_link.getAttribute('key');
848
849             //console.log("prev_link in fleshFromPath is: " + prev_link);
850             //console.log("prev_join in fleshFromPath is: " + prev_join);
851
852             if (prev_join) current_obj.type = prev_join
853                         else if ( 
854                                 (
855                                         current_link.getAttribute('reltype') != 'has_a' ||
856                                         prev_type == 'left' ||
857                                         rel.reltype != 'has_a'
858
859 // This disallows outer joins when the item is used in a filter
860 //                              ) && (
861 //                                      getKeys(rel.fields.filter_tab).length == 0 &&
862 //                                      getKeys(rel.fields.aggfitler_tab).length == 0
863
864                                 )
865                         ) current_obj.type = 'left';
866
867                         prev_type = current_obj.type; 
868
869                 }
870
871                 if (current_path) current_path += '-';
872                 current_path += link.split(/>/)[0];
873
874                 var leaf = table_path.length == 0 ? true : false;
875
876                 current_obj.path = current_path;
877                 current_obj.table = getSourceDefinition( link.split(/-/)[0] );
878
879
880                 if (leaf) {
881
882                 var join_type = link.split(/-/)[1];
883             if (join_type) {
884                         join_type = join_type.split(/>/)[1];
885                             if (join_type && join_type != 'undefined') current_obj.type = join_type;
886             }
887
888                         current_obj.label = rel.label;
889                         current_obj.alias = rel.alias;
890                         current_obj.idlclass = rel.idlclass;
891                         current_obj.template_path = rel.path;
892                 } else {
893                         var current_class = getIDLClass( link.split(/-/)[0] );
894                         var join_field = link.split(/-/)[1];
895                         var join_type = join_field;
896
897                         join_field = join_field.split(/>/)[0];
898                         join_type = join_type.split(/>/)[1];
899
900             //console.log("join_field in fleshFromPath is: " + join_field);
901
902                         var join_link = getIDLLink(current_class, join_field);
903
904                         if (join_link.getAttribute('reltype') != 'has_a') {
905                                 var fields_el = current_class.getElementsByTagName('fields')[0];
906                                 join_field =
907                                         fields_el.getAttributeNS(persistNS, 'primary') +
908                                         '-' + join_link.getAttribute('class') +
909                                         '-' + join_link.getAttribute('key');
910                         }
911
912                         if (!current_obj.alias) current_obj.alias = hex_md5( current_path ) ;
913                         join_field += '-' + current_obj.alias;
914
915                         if (!current_obj.join) current_obj.join = {};
916                         if (!current_obj.join[join_field]) current_obj.join[join_field] = {};
917
918                         if (current_obj.type == 'left') current_obj.join[join_field].type = 'left';
919
920                         current_obj = current_obj.join[join_field];
921                 }
922
923                 prev_link = link;
924         }
925
926
927 }
928
929 function fleshTemplateField ( template, rel, tab_name, field ) {
930
931         if (!rel.fields[tab_name] || !rel.fields[tab_name][field]) return;
932
933         var tab = rel.fields[tab_name];
934
935         var table_path = rel.path.split( /\./ );
936         if (table_path.length > 1 || rel.path.indexOf('-') > -1)
937                 table_path.push( rel.idlclass );
938
939         table_path.push( field );
940
941         var field_path = table_path.join('-');
942
943         var element = {
944                 alias : tab[field].alias,
945                 column :
946                         { colname : field,
947                           transform : tab[field].transform,
948                           transform_label : tab[field].transform_label
949                         },
950                 path : field_path,
951                 relation : rel.alias
952         };
953
954         if (tab_name.match(/filter/)) {
955                 element.condition = {};
956                 if (tab[field].op == 'is' || tab[field].op == 'is not' || tab[field].op == 'is blank' || tab[field].op == 'is not blank') {
957                         element.condition[tab[field].op] = null;
958                 } else {
959                         element.condition[tab[field].op] =
960                                 tab[field].op_value.value ?
961                                         tab[field].op_value.value :
962                                         '::P' + param_count++;
963                 }
964         }
965
966         template[tab_use[tab_name]].push(element);
967 }
968