1 /** initializes reports, some basid display settings,
2 * grabs and builds the IDL tree
4 function oilsInitReportBuilder() {
5 if(!oilsInitReports()) return false;
6 oilsReportBuilderReset();
7 DOM.oils_rpt_table.onclick =
8 function(){hideMe(DOM.oils_rpt_column_editor)};
11 hideMe(DOM.oils_rpt_tree_loading);
12 unHideMe(DOM.oils_rpt_table);
13 oilsRptBuilderDrawClone(new CGI().param('ct'));
17 DOM.oils_rpt_builder_save_template.onclick = oilsReportBuilderSave;
20 function oilsRptBuilderDrawClone(templateId) {
21 if(!templateId) return;
22 unHideMe(DOM.oils_rpt_builder_cloning);
24 oilsRptFetchTemplate(templateId,
25 function(template) { oilsRptBuilderDrawClone2(template);}
30 function oilsRptBuilderDrawClone2(template) {
32 appendClear( DOM.oils_rpt_build_cloning_name, template.name() );
33 DOM.oils_rpt_builder_new_name.value = template.name();
34 DOM.oils_rpt_builder_new_desc.value = template.description();
36 _debug(formatJSON(template.data()));
38 /* manually shove data into the display selectors */
39 var def = JSON2js(template.data());
41 var table = def.from.table;
43 for( var i in oilsIDL ) {
45 if( node.table == table ) {
46 setSelector(DOM.oils_rpt_builder_type_selector, node.name);
47 DOM.oils_rpt_builder_type_selector.onchange();
54 oilsAddRptDisplayItem(item.path, item.alias, item.column.transform)});
58 oilsAddRptFilterItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
62 oilsAddRptHavingItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
64 oilsRpt.setTemplate(template);
67 function oilsReportBuilderReset() {
68 var n = (oilsRpt) ? oilsRpt.name : "";
69 oilsRpt = new oilsReport();
71 oilsRptDisplaySelector = DOM.oils_rpt_display_selector;
72 oilsRptFilterSelector = DOM.oils_rpt_filter_selector;
73 oilsRptHavingSelector = DOM.oils_rpt_agg_filter_selector;
74 removeChildren(oilsRptDisplaySelector);
75 removeChildren(oilsRptFilterSelector);
76 removeChildren(oilsRptHavingSelector);
77 //removeChildren(oilsRptOrderBySelector);
81 function oilsReportBuilderSave() {
84 tmpl.name(DOM.oils_rpt_builder_new_name.value);
85 tmpl.description(DOM.oils_rpt_builder_new_desc.value);
86 tmpl.owner(USER.id());
87 tmpl.folder(new CGI().param('folder'));
88 tmpl.data(js2JSON(oilsRpt.def));
90 if(!confirm('Name : '+tmpl.name() + '\nDescription: ' + tmpl.description()+'\nSave Template?'))
96 var req = new Request(OILS_RPT_CREATE_TEMPLATE, SESSION, tmpl);
97 req.request.alertEvent = false;
100 var res = r.getResultObject();
101 if(checkILSEvent(res)) {
104 if( res && res != '0' ) {
105 oilsRptAlertSuccess();
106 _l('oils_rpt.xhtml');
117 /* adds an item to the display window */
118 function oilsAddRptDisplayItem(path, name, tform, params) {
119 if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) )
122 /* add the selected columns to the report output */
123 name = (name) ? name : oilsRptPathCol(path);
124 if( !tform ) tform = 'Bare';
126 var aggregate = oilsRptGetIsAgg(tform);
128 /* add this item to the select blob */
130 relation: hex_md5(oilsRptPathRel(path)),
133 column: { transform: tform, colname: oilsRptPathCol(path) }
136 if( params ) sel.column.params = params;
138 if(!oilsRptGetIsAgg(tform)) {
141 for( var i = 0; i < oilsRpt.def.select.length; i++ ) {
142 var item = oilsRpt.def.select[i];
143 if( !added && oilsRptGetIsAgg( item.column.transform ) ) {
149 if(!added) select.push(sel);
150 oilsRpt.def.select = select;
152 oilsRpt.def.select.push(sel);
156 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
160 function oilsRptGetIsAgg(tform) {
161 return OILS_RPT_TRANSFORMS[tform].aggregate;
164 var sel = $n(DOM.oils_rpt_tform_table,'selector');
165 for( var i = 0; i < sel.options.length; i++ ) {
166 var opt = sel.options[i];
167 if( opt.getAttribute('value') == tform )
168 return opt.getAttribute('aggregate');
172 /* takes a column path and builds a from-clause object for the path */
173 function oilsRptBuildFromClause(path) {
175 /* the path is the full path (relation) from the source
176 object to the column in question (e.g. au-home_ou-aou-name)*/
177 var parts = path.split(/-/);
179 /* the final from clause */
182 /* reference to the current position in the from clause */
187 /* walk the path, fleshing the from clause as we go */
188 for( var i = 0; i < parts.length; i += 2 ) {
190 var cls = parts[i]; /* class name (id) */
191 var col = parts[i+1]; /* column name */
193 /* a "node" is a class description from the IDL, it
194 contains relevant info, plus a list of "fields",
196 var node = oilsIDL[cls];
197 var pkey = oilsRptFindField(node, node.pkey);
199 /* a "field" is a parsed version of a column from the IDL,
200 contains datatype, column name, etc. */
201 var field = oilsRptFindField(node, col);
203 /* re-construct the path as we go so
204 we know what all we've seen thus far */
205 newpath = (newpath) ? newpath + '-'+ cls : cls;
207 /* extract relevant info */
208 tobj.table = node.table;
210 tobj.alias = hex_md5(newpath);
212 _debug('field type is ' + field.type);
213 if( i == (parts.length - 2) ) break;
215 /* we still have columns left in the path, keep adding join's */
217 if(field.reltype != 'has_a')
218 col = pkey.name + '-' + col;
225 if( field.type == 'link' ) {
226 tobj.key = field.key;
227 if( field.reltype == 'has_many' || field.reltype == 'might_have' )
231 newpath = newpath + '-'+ path_col;
234 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
238 function oilsMoveUpDisplayItems() {
239 var sel = oilsRptDisplaySelector;
240 var idx = sel.selectedIndex;
241 if( idx == 0 ) return;
242 var opt = sel.options[idx];
243 sel.options[idx] = null;
245 var val = opt.getAttribute('value');
246 insertSelectorVal(sel, idx, opt.innerHTML, val);
247 sel.options[idx].selected = true;
249 var arr = oilsRpt.def.select;
250 for( var i = 0; i < arr.length; i++ ) {
251 if( arr[i].path == val ) {
252 var other = arr[i-1];
261 function oilsMoveDownDisplayItems() {
262 var sel = oilsRptDisplaySelector;
263 var idx = sel.selectedIndex;
264 if( idx == sel.options.length - 1 ) return;
265 var opt = sel.options[idx];
266 sel.options[idx] = null;
268 var val = opt.getAttribute('value');
269 insertSelectorVal(sel, idx, opt.innerHTML, val);
270 sel.options[idx].selected = true;
272 var arr = oilsRpt.def.select;
273 for( var i = 0; i < arr.length; i++ ) {
274 if( arr[i].path == val ) {
275 var other = arr[i+1];
285 /* removes a specific item from the display window */
287 function oilsDelDisplayItem(val) {
288 oilsDelSelectorItem(oilsRptDisplaySelector, val);
292 /* removes selected items from the display window */
293 function oilsDelSelectedDisplayItems() {
294 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
296 _debug('deleting list: ' + list);
298 /* remove the de-selected columns from the report output */
299 oilsRpt.def.select = grep( oilsRpt.def.select,
301 for( var j = 0; j < list.length; j++ ) {
302 var d = list[j]; /* path */
305 _debug('in delete, looking at list = '+d+' : col = ' +
306 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
308 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
316 if(!oilsRpt.def.select) oilsRpt.def.select = [];
318 oilsRptPruneFromList(list);
321 for( var j = 0; j < list.length; j++ ) {
322 debug('seeing if we can prune from clause with relation = ' + hex_md5(oilsRptPathRel(list[j])));
323 if( !grep(oilsRpt.def.select,
324 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
325 && !grep(oilsRpt.def.where,
326 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
327 && !grep(oilsRpt.def.having,
328 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
330 _debug('pruning from clause');
331 oilsRptPruneFromClause(oilsRptPathRel(list[j]));
339 function oilsRptPruneFromList(pathlist) {
341 for( var j = 0; j < pathlist.length; j++ ) {
342 /* if there are no items left in the "select", "where", or "having" clauses
343 for the given relation, trim this relation from the "from" clause */
344 var path = pathlist[j];
345 var encrel = hex_md5(oilsRptPathRel(path));
347 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
349 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
351 if( !grep(oilsRpt.def.select, func) &&
352 !grep(oilsRpt.def.where, func) &&
353 !grep(oilsRpt.def.having, func) ) {
355 debug('looks like we can prune ' + path);
357 oilsRptPruneFromClause(oilsRptPathRel(pathlist[j]));
363 /* for each item in the path list, remove the associated data
364 from the "from" clause */
366 function oilsRptPruneFromClause(relation, node) {
368 var keys = oilsRptObjectKeys(node);
369 _debug("trying to remove relation: " + relation+'\n\tthis object has keys: '+keys);
371 if(!node) node = oilsRpt.def.from.join;
372 if(!node) return false;
374 for( var i in node ) {
375 var child_node = node[i];
376 _debug("\tanalyzing child node: "+child_node.path);
378 // first, descend into the tree, and prune leaves
379 if( child_node.join ) {
381 oilsRptPruneFromClause(relation, child_node.join);
382 var join_keys = oilsRptObjectKeys(child_node.join);
383 _debug("\tchild has a sub-join for items : ["+ join_keys+"]");
385 if(join_keys.length == 0) {
386 _debug("\tdeleting join for object "+i);
387 delete child_node.join;
391 if( !child_node.join ) {
393 _debug("\tchild node has no sub-join, seeing if we should delete it");
395 var from_alias = child_node.alias;
396 var func = function(n){ return (n.relation == from_alias)};
398 if( !grep(oilsRpt.def.select, func) &&
399 !grep(oilsRpt.def.where, func) &&
400 !grep(oilsRpt.def.having, func) ) {
402 /* we are not used by any other clauses */
403 _debug("\tdeleting node with relation: "+ from_alias);
413 function oilsRptMkFilterTags(path, tform, filter) {
414 var name = oilsRptMakeLabel(path);
415 if(tform) name += ' ('+tform+')';
416 name += ' "' + filter + '"';
417 var epath = path + ':'+filter+':';
418 if(tform) epath += tform;
420 return [ name, epath ];
424 function oilsAddRptFilterItem(path, tform, filter) {
425 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
427 var name = oilsRptMkFilterTags(path, tform, filter);
431 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
435 relation: hex_md5(oilsRptPathRel(path)),
437 column: { transform: tform, colname: oilsRptPathCol(path) },
440 if( filter == 'is' || filter == 'is not' )
441 where.condition[filter] = null;
442 else where.condition[filter] = oilsRptNextParam();
445 case 'substring' : where.column.params = oilsRptNextParam();
448 oilsRpt.def.where.push(where);
449 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
454 function oilsAddRptHavingItem(path, tform, filter) {
455 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
457 var name = oilsRptMkFilterTags(path, tform, filter);
461 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
465 relation: hex_md5(oilsRptPathRel(path)),
467 column: { transform: tform, colname: oilsRptPathCol(path) },
470 if( filter == 'is' || filter == 'is not' )
471 having.condition[filter] = null;
472 else having.condition[filter] = oilsRptNextParam();
475 case 'substring' : having.column.params = oilsRptNextParam();
478 oilsRpt.def.having.push(having);
479 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
485 function oilsDelSelectedFilterItems() {
486 _oilsDelSelectedFilterItems('where');
488 function oilsDelSelectedAggFilterItems() {
489 _oilsDelSelectedFilterItems('having');
492 function _oilsDelSelectedFilterItems(type) {
494 /* the values in this list are formed: <path>:<operation>:<transform> */
495 var list = oilsDelSelectedItems(oilsRptFilterSelector);
497 for( var i = 0; i < list.length; i++ ) {
498 var enc_path = list[i];
499 var data = oilsRptParseFilterEncPath(enc_path);
500 oilsRpt.def[type] = grep(
503 return oilsRptFilterDataMatches(
504 f, data.path, data.operation, data.tform );
509 if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
510 oilsRptPruneFromList(list);
514 function oilsRptParseFilterEncPath(item) {
516 path: item.replace(/:.*/,''),
517 operation: item.replace(/.*:(.*):.*/,'$1'),
518 tform: item.replace(/.*?:.*?:(.*)/,'$1')
523 function oilsRptFilterDataMatches(filter, path, operation, tform) {
524 var rel = hex_md5(oilsRptPathRel(path));
525 var col = oilsRptPathCol(path);
527 if( col == filter.column.colname &&
528 rel == filter.relation &&
529 tform == filter.column.transform &&
530 operation == oilsRptObjectKeys(filter)[0] ) return true;
536 function oilsRptFilterGrep(flist, filter) {
538 for( var j = 0; j < flist.length; j++ ) {
541 var col = filter.column;
542 var frel = hex_md5(oilsRptPathRel(fil.path));
543 var fcol = oilsRptPathCol(fil.path);
545 var op = oilsRptObjectKeys(filter.condition)[0];
547 if( frel == filter.relation &&
548 fcol == col.colname &&
549 fil.operation == op &&
550 fil.tform == col.transform ) {
558 /* adds an item to the display window */
559 function oilsAddRptAggFilterItem(val) {
560 oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
563 /* removes a specific item from the display window */
564 function oilsDelAggFilterItem(val) {
565 oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
571 function ___oilsDelSelectedAggFilterItems() {
572 var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
573 oilsRpt.def.having = grep( oilsRpt.def.having,
575 for( var j = 0; j < list.length; j++ ) {
579 if( typeof col != 'string' )
580 for( var c in col ) col = col[c];
582 if( typeof col != 'string' ) col = col[0];
584 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
586 // var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
588 if( param ) delete oilsRpt.params[param];
596 if(!oilsRpt.def.having) oilsRpt.def.having = [];
597 oilsRptPruneFromList(list);
603 /* adds an item to the display window */
604 function oilsAddSelectorItem(sel, val, name) {
605 name = (name) ? name : oilsRptMakeLabel(val);
606 for( var i = 0; i < sel.options.length; i++ ) {
607 var opt = sel.options[i];
608 if( opt.value == val ) return false;
610 var opt = insertSelectorVal( sel, -1, name, val );
611 opt.setAttribute('title', name);
616 /* removes a specific item from the display window */
617 function oilsDelSelectorItem(sel, val) {
618 var opts = sel.options;
619 for( var i = 0; i < opts.length; i++ ) {
621 if( opt.value == val ) {
622 if( i == opts.length - 1 )
624 else opts[i] = opts[i+1];
630 /* removes selected items from the display window */
631 function oilsDelSelectedItems(sel) {
632 var list = getSelectedList(sel);
633 for( var i = 0; i < list.length; i++ )
634 oilsDelSelectorItem(sel, list[i]);
639 /* hides the different field editor tabs */
640 function oilsRptHideEditorDivs() {
641 hideMe(DOM.oils_rpt_tform_div);
642 hideMe(DOM.oils_rpt_filter_div);
643 hideMe(DOM.oils_rpt_agg_filter_div);
644 hideMe(DOM.oils_rpt_order_by_div);
646 removeCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
647 removeCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
648 removeCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
653 This draws the 3-tabbed window containing the transform,
654 filter, and aggregate filter picker window
656 function oilsRptDrawDataWindow(path) {
657 var col = oilsRptPathCol(path);
658 var cls = oilsRptPathClass(path);
659 var field = oilsRptFindField(oilsIDL[cls], col);
661 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
662 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
664 _debug("setting update data window for column "+col+' on class '+cls);
666 var div = DOM.oils_rpt_column_editor;
667 /* set a preliminary top position so the page won't bounce around */
671 //div.setAttribute('style','top:'+oilsMouseX+'px');
673 /* unhide the div so we can determine the dimensions */
676 /* don't let them see the floating div until the position is fully determined */
677 div.style.visibility='hidden';
679 oilsRptDrawTransformWindow(path, col, cls, field);
680 oilsRptDrawFilterWindow(path, col, cls, field);
681 oilsRptDrawHavingWindow(path, col, cls, field);
682 oilsRptDrawOrderByWindow(path, col, cls, field);
684 //buildFloatingDiv(div, 600);
686 //window.scrollTo(0,0);
687 window.scrollTo(0, 60);
689 /* now let them see it */
690 div.style.visibility='visible';
691 oilsRptSetDataWindowActions(div);
695 function oilsRptSetDataWindowActions(div) {
696 /* give the tab links behavior */
699 DOM.oils_rpt_tform_tab.onclick =
701 oilsRptHideEditorDivs();
702 unHideMe(DOM.oils_rpt_tform_div)
703 addCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
706 DOM.oils_rpt_filter_tab.onclick =
708 oilsRptHideEditorDivs();
709 unHideMe(DOM.oils_rpt_filter_div)
710 addCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
712 DOM.oils_rpt_agg_filter_tab.onclick =
714 oilsRptHideEditorDivs();
715 unHideMe(DOM.oils_rpt_agg_filter_div)
716 addCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
720 DOM.oils_rpt_order_by_tab.onclick =
722 oilsRptHideEditorDivs();
723 oilsRptDrawOrderByWindow();
724 unHideMe(DOM.oils_rpt_order_by_div);
728 DOM.oils_rpt_tform_tab.onclick();
729 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
733 function oilsRptDrawFilterWindow(path, col, cls, field) {
735 var tformPicker = new oilsRptTformPicker( {
736 node : DOM.oils_rpt_filter_tform_table,
737 datatype : field.datatype,
742 var filterPicker = new oilsRptFilterPicker({
743 node : DOM.oils_rpt_filter_op_table,
744 datatype : field.datatype
748 DOM.oils_rpt_filter_submit.onclick = function() {
749 oilsAddRptFilterItem(
750 path, tformPicker.getSelected(), filterPicker.getSelected());
755 function oilsRptDrawHavingWindow(path, col, cls, field) {
756 var tformPicker = new oilsRptTformPicker( {
757 node : DOM.oils_rpt_agg_filter_tform_table,
758 datatype : field.datatype,
763 var filterPicker = new oilsRptFilterPicker({
764 node : DOM.oils_rpt_agg_filter_op_table,
765 datatype : field.datatype
769 DOM.oils_rpt_agg_filter_submit.onclick = function() {
770 oilsAddRptHavingItem(
771 path, tformPicker.getSelected(), filterPicker.getSelected());
775 /* draws the transform window */
776 function oilsRptDrawTransformWindow(path, col, cls, field) {
777 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
778 var dtype = field.datatype;
780 var tformPicker = new oilsRptTformPicker( {
781 node : DOM.oils_rpt_tform_table,
782 datatype : field.datatype,
783 non_aggregate : true,
788 DOM.oils_rpt_tform_submit.onclick =
790 oilsAddRptDisplayItem(path,
791 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
794 DOM.oils_rpt_tform_label_input.focus();
795 DOM.oils_rpt_tform_label_input.select();
797 _debug("Building transform window for datatype "+dtype);
801 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
802 function oilsRptDrawOrderByWindow() {
803 var sel = DOM.oils_rpt_order_by_selector;
805 DOM.oils_rpt_order_by_submit.onclick = function() {
806 oilsRptAddOrderBy(getSelectorVal(sel));
809 var cols = oilsRpt.def.select;
810 for( var i = 0; i < cols.length; i++ ) {
812 insertSelectorVal(sel, -1, obj.alias, obj.path);
816 function oilsRptAddOrderBy(path) {
817 var rel = hex_md5(oilsRptPathRel(path));
818 var order_by = oilsRpt.def.order_by;
820 /* if this item is already in the order by remove it and overwrite it */
821 order_by = grep(oilsRpt.def.order_by,
822 function(i) {return (i.path != path)});
824 if(!order_by) order_by = [];
826 /* find the column definition in the select blob */
827 var obj = grep(oilsRpt.def.select,
828 function(i) {return (i.path == path)});
834 relation : obj.relation,
836 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
839 oilsRpt.def.order_by = order_by;