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;
228 newpath = newpath + '-'+ path_col;
231 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
235 function oilsMoveUpDisplayItems() {
236 var sel = oilsRptDisplaySelector;
237 var idx = sel.selectedIndex;
238 if( idx == 0 ) return;
239 var opt = sel.options[idx];
240 sel.options[idx] = null;
242 var val = opt.getAttribute('value');
243 insertSelectorVal(sel, idx, opt.innerHTML, val);
244 sel.options[idx].selected = true;
246 var arr = oilsRpt.def.select;
247 for( var i = 0; i < arr.length; i++ ) {
248 if( arr[i].path == val ) {
249 var other = arr[i-1];
258 function oilsMoveDownDisplayItems() {
259 var sel = oilsRptDisplaySelector;
260 var idx = sel.selectedIndex;
261 if( idx == sel.options.length - 1 ) return;
262 var opt = sel.options[idx];
263 sel.options[idx] = null;
265 var val = opt.getAttribute('value');
266 insertSelectorVal(sel, idx, opt.innerHTML, val);
267 sel.options[idx].selected = true;
269 var arr = oilsRpt.def.select;
270 for( var i = 0; i < arr.length; i++ ) {
271 if( arr[i].path == val ) {
272 var other = arr[i+1];
282 /* removes a specific item from the display window */
284 function oilsDelDisplayItem(val) {
285 oilsDelSelectorItem(oilsRptDisplaySelector, val);
289 /* removes selected items from the display window */
290 function oilsDelSelectedDisplayItems() {
291 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
293 _debug('deleting list: ' + list);
295 /* remove the de-selected columns from the report output */
296 oilsRpt.def.select = grep( oilsRpt.def.select,
298 for( var j = 0; j < list.length; j++ ) {
299 var d = list[j]; /* path */
302 _debug('in delete, looking at list = '+d+' : col = ' +
303 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
305 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
313 if(!oilsRpt.def.select) oilsRpt.def.select = [];
315 oilsRptPruneFromList(list);
318 for( var j = 0; j < list.length; j++ ) {
319 debug('seeing if we can prune from clause with relation = ' + hex_md5(oilsRptPathRel(list[j])));
320 if( !grep(oilsRpt.def.select,
321 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
322 && !grep(oilsRpt.def.where,
323 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
324 && !grep(oilsRpt.def.having,
325 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
327 _debug('pruning from clause');
328 oilsRptPruneFromClause(oilsRptPathRel(list[j]));
336 function oilsRptPruneFromList(pathlist) {
338 for( var j = 0; j < pathlist.length; j++ ) {
339 /* if there are no items left in the "select", "where", or "having" clauses
340 for the given relation, trim this relation from the "from" clause */
341 var path = pathlist[j];
342 var encrel = hex_md5(oilsRptPathRel(path));
344 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
346 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
348 if( !grep(oilsRpt.def.select, func) &&
349 !grep(oilsRpt.def.where, func) &&
350 !grep(oilsRpt.def.having, func) ) {
352 oilsRptPruneFromClause(oilsRptPathRel(pathlist[j]));
358 /* for each item in the path list, remove the associated data
359 from the "from" clause */
361 function oilsRptPruneFromClause(relation, node) {
362 _debug("removing relation from 'from' clause: " + relation);
363 if(!node) node = oilsRpt.def.from.join;
364 if(!node) return false;
366 for( var i in node ) {
367 _debug("from prune looking at node "+node[i].path);
368 // first, descend into the tree, and prune leaves first
370 oilsRptPruneFromClause(relation, node[i].join);
371 if(oilsRptObjectKeys(node[i].join).length == 0)
378 var key = oilsRptObjectKeys(node)[0];
379 var from_alias = node[key].alias;
380 var func = function(n){ return (n.relation == from_alias)};
382 _debug("pruning from clause with alias "+ from_alias);
384 if( !grep(oilsRpt.def.select, func) &&
385 !grep(oilsRpt.def.where, func) &&
386 !grep(oilsRpt.def.having, func) ) {
388 // if we're at an unused empty leaf, remove it
397 function oilsRptMkFilterTags(path, tform, filter) {
398 var name = oilsRptMakeLabel(path);
399 if(tform) name += ' ('+tform+')';
400 name += ' "' + filter + '"';
401 var epath = path + ':'+filter+':';
402 if(tform) epath += tform;
404 return [ name, epath ];
408 function oilsAddRptFilterItem(path, tform, filter) {
409 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
411 var name = oilsRptMkFilterTags(path, tform, filter);
415 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
419 relation: hex_md5(oilsRptPathRel(path)),
421 column: { transform: tform, colname: oilsRptPathCol(path) },
424 if( filter == 'is' || filter == 'is not' )
425 where.condition[filter] = null;
426 else where.condition[filter] = oilsRptNextParam();
429 case 'substring' : where.column.params = oilsRptNextParam();
432 oilsRpt.def.where.push(where);
433 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
438 function oilsAddRptHavingItem(path, tform, filter) {
439 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
441 var name = oilsRptMkFilterTags(path, tform, filter);
445 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
449 relation: hex_md5(oilsRptPathRel(path)),
451 column: { transform: tform, colname: oilsRptPathCol(path) },
454 if( filter == 'is' || filter == 'is not' )
455 having.condition[filter] = null;
456 else having.condition[filter] = oilsRptNextParam();
459 case 'substring' : having.column.params = oilsRptNextParam();
462 oilsRpt.def.having.push(having);
463 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
469 function oilsDelSelectedFilterItems() {
470 _oilsDelSelectedFilterItems('where');
472 function oilsDelSelectedAggFilterItems() {
473 _oilsDelSelectedFilterItems('having');
476 function _oilsDelSelectedFilterItems(type) {
478 /* the values in this list are formed: <path>:<operation>:<transform> */
479 var list = oilsDelSelectedItems(oilsRptFilterSelector);
481 for( var i = 0; i < list.length; i++ ) {
482 var enc_path = list[i];
483 var data = oilsRptParseFilterEncPath(enc_path);
484 oilsRpt.def[type] = grep(
487 return oilsRptFilterDataMatches(
488 f, data.path, data.operation, data.tform );
493 if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
494 oilsRptPruneFromList(list);
498 function oilsRptParseFilterEncPath(item) {
500 path: item.replace(/:.*/,''),
501 operation: item.replace(/.*:(.*):.*/,'$1'),
502 tform: item.replace(/.*?:.*?:(.*)/,'$1')
507 function oilsRptFilterDataMatches(filter, path, operation, tform) {
508 var rel = hex_md5(oilsRptPathRel(path));
509 var col = oilsRptPathCol(path);
511 if( col == filter.column.colname &&
512 rel == filter.relation &&
513 tform == filter.column.transform &&
514 operation == oilsRptObjectKeys(filter)[0] ) return true;
520 function oilsRptFilterGrep(flist, filter) {
522 for( var j = 0; j < flist.length; j++ ) {
525 var col = filter.column;
526 var frel = hex_md5(oilsRptPathRel(fil.path));
527 var fcol = oilsRptPathCol(fil.path);
529 var op = oilsRptObjectKeys(filter.condition)[0];
531 if( frel == filter.relation &&
532 fcol == col.colname &&
533 fil.operation == op &&
534 fil.tform == col.transform ) {
542 /* adds an item to the display window */
543 function oilsAddRptAggFilterItem(val) {
544 oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
547 /* removes a specific item from the display window */
548 function oilsDelAggFilterItem(val) {
549 oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
555 function ___oilsDelSelectedAggFilterItems() {
556 var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
557 oilsRpt.def.having = grep( oilsRpt.def.having,
559 for( var j = 0; j < list.length; j++ ) {
563 if( typeof col != 'string' )
564 for( var c in col ) col = col[c];
566 if( typeof col != 'string' ) col = col[0];
568 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
570 // var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
572 if( param ) delete oilsRpt.params[param];
580 if(!oilsRpt.def.having) oilsRpt.def.having = [];
581 oilsRptPruneFromList(list);
587 /* adds an item to the display window */
588 function oilsAddSelectorItem(sel, val, name) {
589 name = (name) ? name : oilsRptMakeLabel(val);
590 for( var i = 0; i < sel.options.length; i++ ) {
591 var opt = sel.options[i];
592 if( opt.value == val ) return false;
594 var opt = insertSelectorVal( sel, -1, name, val );
595 opt.setAttribute('title', name);
600 /* removes a specific item from the display window */
601 function oilsDelSelectorItem(sel, val) {
602 var opts = sel.options;
603 for( var i = 0; i < opts.length; i++ ) {
605 if( opt.value == val ) {
606 if( i == opts.length - 1 )
608 else opts[i] = opts[i+1];
614 /* removes selected items from the display window */
615 function oilsDelSelectedItems(sel) {
616 var list = getSelectedList(sel);
617 for( var i = 0; i < list.length; i++ )
618 oilsDelSelectorItem(sel, list[i]);
623 /* hides the different field editor tabs */
624 function oilsRptHideEditorDivs() {
625 hideMe(DOM.oils_rpt_tform_div);
626 hideMe(DOM.oils_rpt_filter_div);
627 hideMe(DOM.oils_rpt_agg_filter_div);
628 hideMe(DOM.oils_rpt_order_by_div);
630 removeCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
631 removeCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
632 removeCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
637 This draws the 3-tabbed window containing the transform,
638 filter, and aggregate filter picker window
640 function oilsRptDrawDataWindow(path) {
641 var col = oilsRptPathCol(path);
642 var cls = oilsRptPathClass(path);
643 var field = oilsRptFindField(oilsIDL[cls], col);
645 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
646 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
648 _debug("setting update data window for column "+col+' on class '+cls);
650 var div = DOM.oils_rpt_column_editor;
651 /* set a preliminary top position so the page won't bounce around */
655 //div.setAttribute('style','top:'+oilsMouseX+'px');
657 /* unhide the div so we can determine the dimensions */
660 /* don't let them see the floating div until the position is fully determined */
661 div.style.visibility='hidden';
663 oilsRptDrawTransformWindow(path, col, cls, field);
664 oilsRptDrawFilterWindow(path, col, cls, field);
665 oilsRptDrawHavingWindow(path, col, cls, field);
666 oilsRptDrawOrderByWindow(path, col, cls, field);
668 //buildFloatingDiv(div, 600);
670 //window.scrollTo(0,0);
671 window.scrollTo(0, 60);
673 /* now let them see it */
674 div.style.visibility='visible';
675 oilsRptSetDataWindowActions(div);
679 function oilsRptSetDataWindowActions(div) {
680 /* give the tab links behavior */
683 DOM.oils_rpt_tform_tab.onclick =
685 oilsRptHideEditorDivs();
686 unHideMe(DOM.oils_rpt_tform_div)
687 addCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
690 DOM.oils_rpt_filter_tab.onclick =
692 oilsRptHideEditorDivs();
693 unHideMe(DOM.oils_rpt_filter_div)
694 addCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
696 DOM.oils_rpt_agg_filter_tab.onclick =
698 oilsRptHideEditorDivs();
699 unHideMe(DOM.oils_rpt_agg_filter_div)
700 addCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
704 DOM.oils_rpt_order_by_tab.onclick =
706 oilsRptHideEditorDivs();
707 oilsRptDrawOrderByWindow();
708 unHideMe(DOM.oils_rpt_order_by_div);
712 DOM.oils_rpt_tform_tab.onclick();
713 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
717 function oilsRptDrawFilterWindow(path, col, cls, field) {
719 var tformPicker = new oilsRptTformPicker( {
720 node : DOM.oils_rpt_filter_tform_table,
721 datatype : field.datatype,
726 var filterPicker = new oilsRptFilterPicker({
727 node : DOM.oils_rpt_filter_op_table,
728 datatype : field.datatype
732 DOM.oils_rpt_filter_submit.onclick = function() {
733 oilsAddRptFilterItem(
734 path, tformPicker.getSelected(), filterPicker.getSelected());
739 function oilsRptDrawHavingWindow(path, col, cls, field) {
740 var tformPicker = new oilsRptTformPicker( {
741 node : DOM.oils_rpt_agg_filter_tform_table,
742 datatype : field.datatype,
747 var filterPicker = new oilsRptFilterPicker({
748 node : DOM.oils_rpt_agg_filter_op_table,
749 datatype : field.datatype
753 DOM.oils_rpt_agg_filter_submit.onclick = function() {
754 oilsAddRptHavingItem(
755 path, tformPicker.getSelected(), filterPicker.getSelected());
759 /* draws the transform window */
760 function oilsRptDrawTransformWindow(path, col, cls, field) {
761 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
762 var dtype = field.datatype;
764 var tformPicker = new oilsRptTformPicker( {
765 node : DOM.oils_rpt_tform_table,
766 datatype : field.datatype,
767 non_aggregate : true,
772 DOM.oils_rpt_tform_submit.onclick =
774 oilsAddRptDisplayItem(path,
775 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
778 DOM.oils_rpt_tform_label_input.focus();
779 DOM.oils_rpt_tform_label_input.select();
781 _debug("Building transform window for datatype "+dtype);
785 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
786 function oilsRptDrawOrderByWindow() {
787 var sel = DOM.oils_rpt_order_by_selector;
789 DOM.oils_rpt_order_by_submit.onclick = function() {
790 oilsRptAddOrderBy(getSelectorVal(sel));
793 var cols = oilsRpt.def.select;
794 for( var i = 0; i < cols.length; i++ ) {
796 insertSelectorVal(sel, -1, obj.alias, obj.path);
800 function oilsRptAddOrderBy(path) {
801 var rel = hex_md5(oilsRptPathRel(path));
802 var order_by = oilsRpt.def.order_by;
804 /* if this item is already in the order by remove it and overwrite it */
805 order_by = grep(oilsRpt.def.order_by,
806 function(i) {return (i.path != path)});
808 if(!order_by) order_by = [];
810 /* find the column definition in the select blob */
811 var obj = grep(oilsRpt.def.select,
812 function(i) {return (i.path == path)});
818 relation : obj.relation,
820 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
823 oilsRpt.def.order_by = order_by;