1 dojo.requireLocalization("openils.reports", "reports");
3 var rpt_strings = dojo.i18n.getLocalization("openils.reports", "reports");
5 function removeReportAtom (args) {
8 var active_tab = filterByAttribute(
9 $('used-source-fields-tabbox').getElementsByTagName('tab'),
13 var tabname = active_tab.getAttribute('id');
15 var tabpanel = $( tabname + 'panel' );
16 var tree = tabpanel.getElementsByTagName('tree')[0];
17 var fields = getSelectedItems(tree);
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');
25 delete rpt_rel_cache[relation_alias].fields[tabname][colname];
26 if (tabname == 'dis_tab') {
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 );
32 rpt_rel_cache.order_by = _o_tmp
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];
46 function getSourceDefinition(class) {
47 var class_obj = getIDLClass(class);
48 return class_obj.getAttributeNS(persistNS,'tablename') || '(' + class_obj.getElementsByTagNameNS(persistNS,'source_definition')[0].nodeValue + ')';
51 function addReportAtoms () {
52 var nope = $( 'source-add' ).getAttribute('disabled');
53 if (nope == 'true') return false;
55 var class_tree = $('class-view');
56 var transform_tree = $('trans-view');
58 var active_tab = filterByAttribute(
59 $('used-source-fields-tabbox').getElementsByTagName('tab'),
64 var tabname = active_tab.getAttribute('id')
66 var items = getSelectedItems(class_tree);
67 var transform = getSelectedItems(transform_tree)[0];
69 var reltype = $('path-label').getAttribute('reltype');
70 var class_label = $('path-label').value;
71 var relation_alias = hex_md5(class_label);
73 for (var i in items) {
76 var class_path = item.getAttribute('fullpath');
77 var field_class = item.getAttribute('idlclass');
78 var datatype = item.getAttribute('datatype');
79 var colname = item.getAttribute('idlfield');
80 var field_label = item.firstChild.firstChild.getAttribute('label');
82 var table_name = getSourceDefinition(field_class);
84 if ( !rpt_rel_cache[relation_alias] ) {
85 rpt_rel_cache[relation_alias] =
86 { label : class_label,
87 alias : relation_alias,
90 idlclass : field_class,
92 fields: { dis_tab : {}, filter_tab : {}, aggfilter_tab : {} }
96 if ( !rpt_rel_cache[relation_alias].fields[tabname][colname] ) {
97 rpt_rel_cache[relation_alias].fields[tabname][colname] =
99 transform : (transform && transform.getAttribute('name')) || rpt_strings.TEMPLATE_CONF_BARE,
100 aggregate : transform && transform.getAttribute('aggregate'),
101 params : transform && transform.getAttribute('params'),
102 transform_label: (transform && transform.getAttribute('alias')) || rpt_strings.TEMPLATE_CONF_RAW_DATA,
106 op_label : rpt_strings.TEMPLATE_CONF_EQUALS,
110 if (!rpt_rel_cache.order_by)
111 rpt_rel_cache.order_by = [];
113 if (tabname == 'dis_tab')
114 rpt_rel_cache.order_by.push( { relation : relation_alias, field : colname } );
116 } else if (confirm(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_CONFIRM_RESET, [field_label, class_label] )) ) {
117 rpt_rel_cache[relation_alias].fields[tabname][colname] =
119 transform : (transform && transform.getAttribute('name')) || rpt_strings.TEMPLATE_CONF_BARE,
120 aggregate : transform && transform.getAttribute('aggregate'),
121 params : transform && transform.getAttribute('params'),
122 transform_label: (transform && transform.getAttribute('alias')) || rpt_strings.TEMPLATE_CONF_RAW_DATA,
126 op_label : rpt_strings.TEMPLATE_CONF_EQUALS,
137 function changeDisplayOrder (dir) {
138 var active_tab = filterByAttribute(
139 $('used-source-fields-tabbox').getElementsByTagName('tab'),
144 var tabname = active_tab.getAttribute('id');
146 var tabpanel = $( tabname + 'panel' );
147 var tree = tabpanel.getElementsByTagName('tree')[0];
148 var item = getSelectedItems(tree)[0];
150 var item_pos = tree.view.selection.currentIndex;
153 if ( item.previousSibling ) {
154 item.parentNode.insertBefore( item, item.previousSibling );
157 } else if (dir == 'd') {
158 if ( item.nextSibling ) {
159 if (item.nextSibling.nextSibling ) item.parentNode.insertBefore( item, item.nextSibling.nextSibling );
160 else item.parentNode.appendChild( item );
165 rpt_rel_cache.order_by = [];
166 var ordered_list = tree.getElementsByTagName('treeitem');
167 for (var i = 0; i < ordered_list.length; i++) {
168 rpt_rel_cache.order_by.push(
169 { relation : ordered_list[i].getAttribute('relation'),
170 field : ordered_list[i].firstChild.firstChild.nextSibling.getAttribute('label')
175 tree.view.selection.select( item_pos );
179 function alterColumnLabel () {
180 var active_tab = filterByAttribute(
181 $('used-source-fields-tabbox').getElementsByTagName('tab'),
186 var tabname = active_tab.getAttribute('id');
188 var tabpanel = $( tabname + 'panel' );
189 var tree = tabpanel.getElementsByTagName('tree')[0];
190 var item_pos = tree.view.selection.currentIndex;
192 var item = getSelectedItems(tree)[0];
193 var relation_alias = item.getAttribute('relation');
195 var field = item.firstChild.firstChild;
196 var colname = field.nextSibling.getAttribute('label');
198 var new_label = prompt( dojo.string.substitute(rpt_strings.TEMPLATE_CONF_PROMPT_CHANGE, [field.getAttribute("label")]) );
201 rpt_rel_cache[relation_alias].fields[tabname][colname].alias = new_label;
203 tree.view.selection.select( item_pos );
211 function alterColumnTransform (trans) {
213 var transform = OILS_RPT_TRANSFORMS[trans];
215 var active_tab = filterByAttribute(
216 $('used-source-fields-tabbox').getElementsByTagName('tab'),
221 var tabname = active_tab.getAttribute('id');
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');
229 var field = item.firstChild.firstChild;
230 var colname = field.nextSibling.getAttribute('label');
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;
238 tree.view.selection.select( item_pos );
242 $(tabname + '_trans_menu').hidePopup();
246 function changeOperator (args) {
248 var active_tab = filterByAttribute(
249 $('used-source-fields-tabbox').getElementsByTagName('tab'),
254 var tabname = active_tab.getAttribute('id');
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];
261 var relation_alias = item.getAttribute('relation');
263 var field = item.firstChild.firstChild;
264 var colname = field.nextSibling.getAttribute('label');
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;
270 tree.view.selection.select( item_pos );
274 $(tabname + '_op_menu').hidePopup();
278 function removeTemplateFilterValue () {
280 var active_tab = filterByAttribute(
281 $('used-source-fields-tabbox').getElementsByTagName('tab'),
286 var tabname = active_tab.getAttribute('id');
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);
293 for (var i in items) {
295 var relation_alias = item.getAttribute('relation');
297 var field = item.firstChild.firstChild;
298 var colname = field.nextSibling.getAttribute('label');
300 rpt_rel_cache[relation_alias].fields[tabname][colname].op_value = {};
304 tree.view.selection.select( item_pos );
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 + '"';
319 function changeTemplateFilterValue () {
321 var active_tab = filterByAttribute(
322 $('used-source-fields-tabbox').getElementsByTagName('tab'),
327 var tabname = active_tab.getAttribute('id');
329 var tabpanel = $( tabname + 'panel' );
330 var tree = tabpanel.getElementsByTagName('tree')[0];
331 var items = getSelectedItems(tree);
333 var targetCmd = $( tabname + '_value_action' );
335 targetCmd.menu = null;
336 targetCmd.command = null;
337 targetCmd.oncommand = null;
338 targetCmd.removeEventListener( 'command', __handler_cache, true );
340 for (var i in items) {
342 var relation_alias = item.getAttribute('relation');
344 var field = item.firstChild.firstChild;
345 var colname = field.nextSibling.getAttribute('label');
347 var obj = rpt_rel_cache[relation_alias].fields[tabname][colname]
348 var operation = OILS_RPT_FILTERS[obj.op];
350 switch (obj.datatype) {
352 var cal_popup = $('calendar-widget');
354 while (cal_popup.firstChild) cal_popup.removeChild(cal_popup.lastChild);
355 var calendar = new Calendar(
358 function (cal,date) { return timestampSetDate(obj,cal,date) },
359 function (cal) { cal_popup.hidePopup(); cal.destroy(); return true; }
362 var format = OILS_RPT_TRANSFORMS[obj.transform].cal_format || '%Y-%m-%d';
364 calendar.setDateFormat(format);
365 calendar.create(cal_popup);
367 targetCmd.menu = 'calendar-widget';
373 function __bool_value_event_handler () {
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);
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;
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(
394 rpt_strings.TEMPLATE_CONF_BOOLEAN_VALUE,
395 rpt_strings.TEMPLATE_CONF_SELECT_CANCEL,
396 2, [rpt_strings.TEMPLATE_CONF_TRUE, rpt_strings.TEMPLATE_CONF_FALSE], state
400 state = confirm(rpt_strings.TEMPLATE_CONF_CONFIRM_STATE);
401 state ? state = 0 : state = 1;
406 obj.op_value.value = 'f';
407 obj.op_value.label = rpt_strings.TEMPLATE_CONF_FALSE;
409 obj.op_value.value = 't';
410 obj.op_value.label = rpt_strings.TEMPLATE_CONF_TRUE;
414 targetCmd.removeEventListener( 'command', __bool_value_event_handler, true );
416 tree.view.selection.select( item_pos );
420 __handler_cache = __bool_value_event_handler;
421 targetCmd.addEventListener( 'command', __bool_value_event_handler, true );
428 var promptstring = rpt_strings.TEMPLATE_CONF_NO_MATCH;
432 promptstring = rpt_strings.TEMPLATE_CONF_NOT_BETWEEN;
436 promptstring = rpt_strings.TEMPLATE_CONF_BETWEEN;
440 promptstring = rpt_strings.TEMPLATE_CONF_NOT_IN;
444 promptstring = rpt_strings.TEMPLATE_CONF_IN;
448 promptstring = dojo.string.substitute( rpt_strings.TEMPLATE_CONF_DEFAULT, [obj.op_label]);
452 function __default_value_event_handler () {
454 if (_v = prompt( promptstring, obj.op_value.value || '' )) {
460 obj.op_value.value = _v.split(/\s*,\s*/);
464 obj.op_value.value = _v;
468 obj.op_value.label = '"' + obj.op_value.value + '"';
471 targetCmd.removeEventListener( 'command', __default_value_event_handler, true );
473 tree.view.selection.select( item_pos );
477 __handler_cache = __default_value_event_handler;
478 targetCmd.addEventListener( 'command', __default_value_event_handler, true );
487 function populateOperatorContext () {
489 var active_tab = filterByAttribute(
490 $('used-source-fields-tabbox').getElementsByTagName('tab'),
495 var tabname = active_tab.getAttribute('id');
497 var tabpanel = $( tabname + 'panel' );
498 var tree = tabpanel.getElementsByTagName('tree')[0];
499 var items = getSelectedItems(tree);
502 for (var i in items) {
504 dtypes.push( item.getAttribute('datatype') );
507 var menu = $(tabname + '_op_menu');
508 while (menu.firstChild) menu.removeChild(menu.lastChild);
510 for (var i in OILS_RPT_FILTERS) {
511 var o = OILS_RPT_FILTERS[i];
515 onmouseup : "changeOperator({op:'"+i+"',label:'"+o.label+"'})"
520 var keys = getKeys(o.labels);
521 for ( var k in keys ) {
523 if ( grep(function(x){return key==x},dtypes).length ) {
526 { label : o.labels[key],
527 onmouseup : "changeOperator({op:'"+i+"',label:'"+o.labels[key]+"'});"
537 function populateTransformContext () {
539 var active_tab = filterByAttribute(
540 $('used-source-fields-tabbox').getElementsByTagName('tab'),
545 var tabname = active_tab.getAttribute('id');
547 var tabpanel = $( tabname + 'panel' );
548 var tree = tabpanel.getElementsByTagName('tree')[0];
549 var items = getSelectedItems(tree);
552 for (var i in items) {
554 var dtype = item.getAttribute('datatype');
555 var item_transforms = getTransforms({ datatype : dtype });
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];
563 var transformList = [];
564 for (var i in transforms) {
565 transformList.push( transforms[i] );
568 transformList.sort( sortHashLabels );
570 var menu = $(tabname + '_trans_menu');
571 while (menu.firstChild) menu.removeChild(menu.lastChild);
573 for (var i in transformList) {
574 var t = transformList[i];
576 if (tabname.match(/filter/)) {
577 if (tabname.match(/^agg/)) {
578 if (!t.aggregate) continue;
580 if (t.aggregate) continue;
586 { aggregate : t.aggregate,
591 onmouseup : "alterColumnTransform('"+t.name+"')"
597 menu.parentNode.setAttribute('disabled','false');
598 if (menu.childNodes.length == 0) {
599 menu.parentNode.setAttribute('disabled','true');
604 function renderSources (selected) {
606 var tree = $('used-sources');
607 var sources = $('used-sources-treetop');
608 var tabs = $('used-source-fields-tabbox').getElementsByTagName('tab');
611 while (sources.firstChild) sources.removeChild(sources.lastChild);
613 selected = getSelectedItems(tree);
614 if (!selected.length) {
615 selected = undefined;
616 while (sources.firstChild) sources.removeChild(sources.lastChild);
620 for (var j = 0; j < tabs.length; j++) {
622 var tabname = tab.getAttribute('id')
623 var tabpanel = $( tab.getAttribute('id') + 'panel' );
624 var fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
626 while (fieldtree.firstChild) fieldtree.removeChild(fieldtree.lastChild);
629 for (var relation_alias in rpt_rel_cache) {
630 if (!rpt_rel_cache[relation_alias].fields) continue;
636 return x.getAttribute('relation') == relation_alias;
643 $('used-sources-treetop').appendChild(
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
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 })
661 for each (var tabname in ['filter_tab','aggfilter_tab']) {
662 tabpanel = $( tabname + 'panel' );
663 fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
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(
669 { relation : relation_alias, datatype : datatype },
672 createTreeCell({ label : alias }),
673 createTreeCell({ label : colname }),
674 createTreeCell({ label : datatype }),
675 createTreeCell({ label : transform_label }),
676 createTreeCell({ label : transform })
681 fieldtree.lastChild.firstChild.appendChild(
682 createTreeCell({ op : op, label : op_label })
685 if (op_value.value != undefined) {
686 fieldtree.lastChild.firstChild.appendChild(
687 createTreeCell({ label : op_value.label })
695 tabpanel = $( 'dis_tabpanel' );
696 fieldtree = tabpanel.getElementsByTagName('treechildren')[0];
697 for each (var order in rpt_rel_cache.order_by) {
703 return x.getAttribute('relation') == order.relation;
710 with (rpt_rel_cache[order.relation].fields.dis_tab[order.field]) {
711 fieldtree.appendChild(
713 { relation : order.relation, datatype : datatype },
716 createTreeCell({ label : alias }),
717 createTreeCell({ label : colname }),
718 createTreeCell({ label : datatype }),
719 createTreeCell({ label : transform_label }),
720 createTreeCell({ label : transform })
725 fieldtree.lastChild.firstChild.appendChild(
726 createTreeCell({ op : op, label : op_label })
729 if (op_value.value != undefined) {
730 fieldtree.lastChild.firstChild.appendChild(
731 createTreeCell({ label : op_value.label })
741 filter_tab : 'where',
742 aggfilter_tab : 'having',
746 function save_template () {
751 core_class : $('sources-treetop').getElementsByTagName('treeitem')[0].getAttribute('idlclass'),
759 for (var relname in rpt_rel_cache) {
760 var relation = rpt_rel_cache[relname];
761 if (!relation.fields) continue;
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 );
771 // now the from clause
772 fleshFromPath( template, relation );
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 );
779 template.rel_cache = rpt_rel_cache;
781 //prompt( 'template', js2JSON( template ) );
783 // and the saving throw ...
785 var session = cgi.param('ses');
786 fetchUser( session );
789 tmpl.name( $('template-name').value );
790 tmpl.description( $('template-description').value );
791 tmpl.owner(USER.id());
792 tmpl.folder(cgi.param('folder'));
793 tmpl.data(js2JSON(template));
795 if(!confirm(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_CONFIRM_SAVE, [tmpl.name(), tmpl.description()] )))
798 var req = new Request('open-ils.reporter:open-ils.reporter.template.create', session, tmpl);
799 req.request.alertEvent = false;
802 var res = r.getResultObject();
803 if(checkILSEvent(res)) {
806 if( res && res != '0' ) {
807 confirm(dojo.string.substitute( rpt_strings.TEMPLATE_CONF_SUCCESS_SAVE, [tmpl.name()] ));
808 _l('../oils_rpt.xhtml');
817 function fleshFromPath ( template, rel ) {
818 var table_path = rel.path.split( /\./ );
819 if (table_path.length > 1 || rel.path.indexOf('-') > -1) table_path.push( rel.idlclass );
823 var current_path = '';
824 var current_obj = template.from;
826 while (link = table_path.shift()) {
827 if (current_path) current_path += '-';
828 current_path += link;
830 var leaf = table_path.length == 0 ? true : false;
832 current_obj.path = current_path;
833 current_obj.table = getSourceDefinition( link.split(/-/)[0] );
835 if (prev_link != '') {
836 var prev_class = getIDLClass( prev_link.split(/-/)[0] );
837 var prev_field = prev_link.split(/-/)[1];
839 var current_link = getIDLLink( prev_class, prev_field );
840 current_obj.key = current_link.getAttribute('key');
844 current_link.getAttribute('reltype') != 'has_a' ||
845 prev_type == 'left' ||
846 rel.reltype != 'has_a'
848 // getKeys(rel.fields.filter_tab).length == 0 &&
849 // getKeys(rel.fields.aggfitler_tab).length == 0
851 ) current_obj.type = 'left';
853 prev_type = current_obj.type;
857 current_obj.label = rel.label;
858 current_obj.alias = rel.alias;
859 current_obj.idlclass = rel.idlclass;
860 current_obj.template_path = rel.path;
862 var current_class = getIDLClass( link.split(/-/)[0] );
863 var join_field = link.split(/-/)[1];
864 var join_link = getIDLLink(current_class, join_field);
866 if (join_link.getAttribute('reltype') != 'has_a') {
867 var fields_el = current_class.getElementsByTagName('fields')[0];
869 fields_el.getAttributeNS(persistNS, 'primary') +
870 '-' + join_link.getAttribute('class') +
871 '-' + join_link.getAttribute('key');
874 if (!current_obj.alias) current_obj.alias = hex_md5( current_path ) ;
875 join_field += '-' + current_obj.alias;
877 if (!current_obj.join) current_obj.join = {};
878 if (!current_obj.join[join_field]) current_obj.join[join_field] = {};
880 if (current_obj.type == 'left') current_obj.join[join_field].type = 'left';
882 current_obj = current_obj.join[join_field];
891 function fleshTemplateField ( template, rel, tab_name, field ) {
893 if (!rel.fields[tab_name] || !rel.fields[tab_name][field]) return;
895 var tab = rel.fields[tab_name];
897 var table_path = rel.path.split( /\./ );
898 if (table_path.length > 1 || rel.path.indexOf('-') > -1)
899 table_path.push( rel.idlclass );
901 table_path.push( field );
903 var field_path = table_path.join('-');
906 alias : tab[field].alias,
909 transform : tab[field].transform,
910 transform_label : tab[field].transform_label
916 if (tab_name.match(/filter/)) {
917 element.condition = {};
918 if (tab[field].op == 'is' || tab[field].op == 'is not' || tab[field].op == 'is blank' || tab[field].op == 'is not blank') {
919 element.condition[tab[field].op] = null;
921 element.condition[tab[field].op] =
922 tab[field].op_value.value ?
923 tab[field].op_value.value :
924 '::P' + param_count++;
928 template[tab_use[tab_name]].push(element);