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