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