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) {
31 appendClear( DOM.oils_rpt_build_cloning_name, template.name() );
32 DOM.oils_rpt_builder_new_name.value = template.name();
33 DOM.oils_rpt_builder_new_desc.value = template.description();
35 _debug(formatJSON(template.data()));
37 /* manually shove data into the display selectors */
38 var def = JSON2js(template.data());
40 var table = def.from.table;
42 for( var i in oilsIDL ) {
44 if( node.table == table ) {
45 setSelector(DOM.oils_rpt_builder_type_selector, node.name);
46 DOM.oils_rpt_builder_type_selector.onchange();
53 oilsAddRptDisplayItem(item.path, item.alias, item.column.transform)});
57 oilsAddRptFilterItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
61 oilsAddRptHavingItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
63 oilsRpt.setTemplate(template);
64 oilsRpt.templateObject = null; /* simplify debugging */
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;
137 oilsRptAddSelectList(sel, tform);
138 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
142 function oilsRptAddSelectList(obj, tform) {
143 if(!oilsRptGetIsAgg(tform)) {
146 for( var i = 0; i < oilsRpt.def.select.length; i++ ) {
147 var item = oilsRpt.def.select[i];
149 /* shove the item in question in front of the first agg tform */
150 if( !added && oilsRptGetIsAgg( item.column.transform ) ) {
157 /* if there is no existing agg tfrom to
158 insert in front of, add me on the end */
159 if(!added) select.push(obj);
161 oilsRpt.def.select = select;
164 /* re-draw the select display to get the order correct */
165 var sel = oilsRptDisplaySelector;
166 while( sel.options.length > 0 ) sel.options[0] = null;
167 iterate(oilsRpt.def.select,
169 _debug('re-inserting display item ' + item.path);
170 oilsAddSelectorItem(oilsRptDisplaySelector, item.path, item.alias) });
174 /* shove agg transforms onto the end */
175 oilsRpt.def.select.push(obj);
181 function oilsRptGetIsAgg(tform) {
182 return OILS_RPT_TRANSFORMS[tform].aggregate;
185 /* takes a column path and builds a from-clause object for the path */
186 function oilsRptBuildFromClause(path) {
188 /* the path is the full path (relation) from the source
189 object to the column in question (e.g. au-home_ou-aou-name)*/
190 var parts = path.split(/-/);
192 /* the final from clause */
195 /* reference to the current position in the from clause */
200 /* walk the path, fleshing the from clause as we go */
201 for( var i = 0; i < parts.length; i += 2 ) {
203 var cls = parts[i]; /* class name (id) */
204 var col = parts[i+1]; /* column name */
206 /* a "node" is a class description from the IDL, it
207 contains relevant info, plus a list of "fields",
209 var node = oilsIDL[cls];
210 var pkey = oilsRptFindField(node, node.pkey);
212 /* a "field" is a parsed version of a column from the IDL,
213 contains datatype, column name, etc. */
214 var field = oilsRptFindField(node, col);
216 /* re-construct the path as we go so
217 we know what all we've seen thus far */
218 newpath = (newpath) ? newpath + '-'+ cls : cls;
220 /* extract relevant info */
221 tobj.table = node.table;
223 tobj.alias = hex_md5(newpath);
225 _debug('field type is ' + field.type);
226 if( i == (parts.length - 2) ) break;
228 /* we still have columns left in the path, keep adding join's */
230 if(field.reltype != 'has_a')
231 col = pkey.name + '-' + col;
238 if( field.type == 'link' ) {
239 tobj.key = field.key;
240 if( field.reltype == 'has_many' || field.reltype == 'might_have' )
244 newpath = newpath + '-'+ path_col;
247 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
251 function oilsMoveUpDisplayItems() {
252 var sel = oilsRptDisplaySelector;
253 var idx = sel.selectedIndex;
254 if( idx == 0 ) return;
255 var opt = sel.options[idx];
256 sel.options[idx] = null;
258 var val = opt.getAttribute('value');
259 insertSelectorVal(sel, idx, opt.innerHTML, val);
260 sel.options[idx].selected = true;
262 var arr = oilsRpt.def.select;
263 for( var i = 0; i < arr.length; i++ ) {
264 if( arr[i].path == val ) {
265 var other = arr[i-1];
274 function oilsMoveDownDisplayItems() {
275 var sel = oilsRptDisplaySelector;
276 var idx = sel.selectedIndex;
277 if( idx == sel.options.length - 1 ) return;
278 var opt = sel.options[idx];
279 sel.options[idx] = null;
281 var val = opt.getAttribute('value');
282 insertSelectorVal(sel, idx, opt.innerHTML, val);
283 sel.options[idx].selected = true;
285 var arr = oilsRpt.def.select;
286 for( var i = 0; i < arr.length; i++ ) {
287 if( arr[i].path == val ) {
288 var other = arr[i+1];
298 /* removes a specific item from the display window */
300 function oilsDelDisplayItem(val) {
301 oilsDelSelectorItem(oilsRptDisplaySelector, val);
305 /* removes selected items from the display window */
306 function oilsDelSelectedDisplayItems() {
307 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
309 _debug('deleting list: ' + list);
311 /* remove the de-selected columns from the report output */
312 oilsRpt.def.select = grep( oilsRpt.def.select,
314 for( var j = 0; j < list.length; j++ ) {
315 var d = list[j]; /* path */
318 _debug('in delete, looking at list = '+d+' : col = ' +
319 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
321 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
329 if(!oilsRpt.def.select) oilsRpt.def.select = [];
330 oilsRptPruneFromList(list);
334 function oilsRptPruneFromList(pathlist) {
336 for( var j = 0; j < pathlist.length; j++ ) {
337 /* if there are no items left in the "select", "where", or "having" clauses
338 for the given relation, trim this relation from the "from" clause */
339 var path = pathlist[j];
340 var encrel = hex_md5(oilsRptPathRel(path));
342 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
344 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
346 if( !grep(oilsRpt.def.select, func) &&
347 !grep(oilsRpt.def.where, func) &&
348 !grep(oilsRpt.def.having, func) ) {
350 debug('looks like we can prune ' + path);
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) {
363 var keys = oilsRptObjectKeys(node);
364 _debug("trying to remove relation: " + relation+'\n\tthis object has keys: '+keys);
366 if(!node) node = oilsRpt.def.from.join;
367 if(!node) return false;
369 for( var i in node ) {
370 var child_node = node[i];
371 _debug("\tanalyzing child node: "+child_node.path);
373 // first, descend into the tree, and prune leaves
374 if( child_node.join ) {
376 oilsRptPruneFromClause(relation, child_node.join);
377 var join_keys = oilsRptObjectKeys(child_node.join);
378 _debug("\tchild has a sub-join for items : ["+ join_keys+"]");
380 if(join_keys.length == 0) {
381 _debug("\tdeleting join for object "+i);
382 delete child_node.join;
386 if( !child_node.join ) {
388 _debug("\tchild node has no sub-join, seeing if we should delete it");
390 var from_alias = child_node.alias;
391 var func = function(n){ return (n.relation == from_alias)};
393 if( !grep(oilsRpt.def.select, func) &&
394 !grep(oilsRpt.def.where, func) &&
395 !grep(oilsRpt.def.having, func) ) {
397 /* we are not used by any other clauses */
398 _debug("\tdeleting node with relation: "+ from_alias);
408 function oilsRptMkFilterTags(path, tform, filter) {
409 var name = oilsRptMakeLabel(path);
410 if(tform) name += ' ('+tform+')';
411 name += ' "' + filter + '"';
412 var epath = path + ':'+filter+':';
413 if(tform) epath += tform;
415 return [ name, epath ];
419 function oilsAddRptFilterItem(path, tform, filter) {
420 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
422 var name = oilsRptMkFilterTags(path, tform, filter);
426 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
430 relation: hex_md5(oilsRptPathRel(path)),
432 column: { transform: tform, colname: oilsRptPathCol(path) },
435 if( filter == 'is' || filter == 'is not' )
436 where.condition[filter] = null;
437 else where.condition[filter] = oilsRptNextParam();
440 case 'substring' : where.column.params = oilsRptNextParam();
443 oilsRpt.def.where.push(where);
444 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
449 function oilsAddRptHavingItem(path, tform, filter) {
450 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
452 var name = oilsRptMkFilterTags(path, tform, filter);
456 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
460 relation: hex_md5(oilsRptPathRel(path)),
462 column: { transform: tform, colname: oilsRptPathCol(path) },
465 if( filter == 'is' || filter == 'is not' )
466 having.condition[filter] = null;
467 else having.condition[filter] = oilsRptNextParam();
470 case 'substring' : having.column.params = oilsRptNextParam();
473 oilsRpt.def.having.push(having);
474 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
480 function oilsDelSelectedFilterItems() {
481 _oilsDelSelectedFilterItems('where');
483 function oilsDelSelectedAggFilterItems() {
484 _oilsDelSelectedFilterItems('having');
487 function _oilsDelSelectedFilterItems(type) {
489 /* the values in this list are formed: <path>:<operation>:<transform> */
490 var list = oilsDelSelectedItems(oilsRptFilterSelector);
492 for( var i = 0; i < list.length; i++ ) {
493 var enc_path = list[i];
494 var data = oilsRptParseFilterEncPath(enc_path);
495 oilsRpt.def[type] = grep(
498 return oilsRptFilterDataMatches(
499 f, data.path, data.operation, data.tform );
504 if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
505 oilsRptPruneFromList(list);
509 function oilsRptParseFilterEncPath(item) {
511 path: item.replace(/:.*/,''),
512 operation: item.replace(/.*:(.*):.*/,'$1'),
513 tform: item.replace(/.*?:.*?:(.*)/,'$1')
518 function oilsRptFilterDataMatches(filter, path, operation, tform) {
519 var rel = hex_md5(oilsRptPathRel(path));
520 var col = oilsRptPathCol(path);
522 if( col == filter.column.colname &&
523 rel == filter.relation &&
524 tform == filter.column.transform &&
525 operation == oilsRptObjectKeys(filter)[0] ) return true;
531 function oilsRptFilterGrep(flist, filter) {
533 for( var j = 0; j < flist.length; j++ ) {
536 var col = filter.column;
537 var frel = hex_md5(oilsRptPathRel(fil.path));
538 var fcol = oilsRptPathCol(fil.path);
540 var op = oilsRptObjectKeys(filter.condition)[0];
542 if( frel == filter.relation &&
543 fcol == col.colname &&
544 fil.operation == op &&
545 fil.tform == col.transform ) {
553 /* adds an item to the display window */
554 function oilsAddRptAggFilterItem(val) {
555 oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
558 /* removes a specific item from the display window */
559 function oilsDelAggFilterItem(val) {
560 oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
566 function ___oilsDelSelectedAggFilterItems() {
567 var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
568 oilsRpt.def.having = grep( oilsRpt.def.having,
570 for( var j = 0; j < list.length; j++ ) {
574 if( typeof col != 'string' )
575 for( var c in col ) col = col[c];
577 if( typeof col != 'string' ) col = col[0];
579 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
581 // var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
583 if( param ) delete oilsRpt.params[param];
591 if(!oilsRpt.def.having) oilsRpt.def.having = [];
592 oilsRptPruneFromList(list);
598 /* adds an item to the display window */
599 function oilsAddSelectorItem(sel, val, name) {
600 name = (name) ? name : oilsRptMakeLabel(val);
601 for( var i = 0; i < sel.options.length; i++ ) {
602 var opt = sel.options[i];
603 if( opt.value == val ) return false;
605 var opt = insertSelectorVal( sel, -1, name, val );
606 opt.setAttribute('title', name);
611 /* removes a specific item from the display window */
612 function oilsDelSelectorItem(sel, val) {
613 var opts = sel.options;
614 for( var i = 0; i < opts.length; i++ ) {
616 if( opt.value == val ) {
617 if( i == opts.length - 1 )
619 else opts[i] = opts[i+1];
625 /* removes selected items from the display window */
626 function oilsDelSelectedItems(sel) {
627 var list = getSelectedList(sel);
628 for( var i = 0; i < list.length; i++ )
629 oilsDelSelectorItem(sel, list[i]);
634 /* hides the different field editor tabs */
635 function oilsRptHideEditorDivs() {
636 hideMe(DOM.oils_rpt_tform_div);
637 hideMe(DOM.oils_rpt_filter_div);
638 hideMe(DOM.oils_rpt_agg_filter_div);
639 hideMe(DOM.oils_rpt_order_by_div);
641 removeCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
642 removeCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
643 removeCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
648 This draws the 3-tabbed window containing the transform,
649 filter, and aggregate filter picker window
651 function oilsRptDrawDataWindow(path) {
652 var col = oilsRptPathCol(path);
653 var cls = oilsRptPathClass(path);
654 var field = oilsRptFindField(oilsIDL[cls], col);
656 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
657 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
659 _debug("setting update data window for column "+col+' on class '+cls);
661 var div = DOM.oils_rpt_column_editor;
662 /* set a preliminary top position so the page won't bounce around */
666 //div.setAttribute('style','top:'+oilsMouseX+'px');
668 /* unhide the div so we can determine the dimensions */
671 /* don't let them see the floating div until the position is fully determined */
672 div.style.visibility='hidden';
674 oilsRptDrawTransformWindow(path, col, cls, field);
675 oilsRptDrawFilterWindow(path, col, cls, field);
676 oilsRptDrawHavingWindow(path, col, cls, field);
677 //oilsRptDrawOrderByWindow(path, col, cls, field);
679 //buildFloatingDiv(div, 600);
681 //window.scrollTo(0,0);
682 window.scrollTo(0, 60);
684 /* now let them see it */
685 div.style.visibility='visible';
686 oilsRptSetDataWindowActions(div);
690 function oilsRptSetDataWindowActions(div) {
691 /* give the tab links behavior */
694 DOM.oils_rpt_tform_tab.onclick =
696 oilsRptHideEditorDivs();
697 unHideMe(DOM.oils_rpt_tform_div)
698 addCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
701 DOM.oils_rpt_filter_tab.onclick =
703 oilsRptHideEditorDivs();
704 unHideMe(DOM.oils_rpt_filter_div)
705 addCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
707 DOM.oils_rpt_agg_filter_tab.onclick =
709 oilsRptHideEditorDivs();
710 unHideMe(DOM.oils_rpt_agg_filter_div)
711 addCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
715 DOM.oils_rpt_order_by_tab.onclick =
717 oilsRptHideEditorDivs();
718 oilsRptDrawOrderByWindow();
719 unHideMe(DOM.oils_rpt_order_by_div);
723 DOM.oils_rpt_tform_tab.onclick();
724 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
728 function oilsRptDrawFilterWindow(path, col, cls, field) {
730 var tformPicker = new oilsRptTformPicker( {
731 node : DOM.oils_rpt_filter_tform_table,
732 datatype : field.datatype,
737 var filterPicker = new oilsRptFilterPicker({
738 node : DOM.oils_rpt_filter_op_table,
739 datatype : field.datatype
743 DOM.oils_rpt_filter_submit.onclick = function() {
744 oilsAddRptFilterItem(
745 path, tformPicker.getSelected(), filterPicker.getSelected());
750 function oilsRptDrawHavingWindow(path, col, cls, field) {
751 var tformPicker = new oilsRptTformPicker( {
752 node : DOM.oils_rpt_agg_filter_tform_table,
753 datatype : field.datatype,
758 var filterPicker = new oilsRptFilterPicker({
759 node : DOM.oils_rpt_agg_filter_op_table,
760 datatype : field.datatype
764 DOM.oils_rpt_agg_filter_submit.onclick = function() {
765 oilsAddRptHavingItem(
766 path, tformPicker.getSelected(), filterPicker.getSelected());
770 /* draws the transform window */
771 function oilsRptDrawTransformWindow(path, col, cls, field) {
772 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
773 var dtype = field.datatype;
775 var tformPicker = new oilsRptTformPicker( {
776 node : DOM.oils_rpt_tform_table,
777 datatype : field.datatype,
778 non_aggregate : true,
783 DOM.oils_rpt_tform_submit.onclick =
785 oilsAddRptDisplayItem(path,
786 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
789 DOM.oils_rpt_tform_label_input.focus();
790 DOM.oils_rpt_tform_label_input.select();
792 _debug("Building transform window for datatype "+dtype);
796 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
797 function oilsRptDrawOrderByWindow() {
798 var sel = DOM.oils_rpt_order_by_selector;
800 DOM.oils_rpt_order_by_submit.onclick = function() {
801 oilsRptAddOrderBy(getSelectorVal(sel));
804 var cols = oilsRpt.def.select;
805 for( var i = 0; i < cols.length; i++ ) {
807 insertSelectorVal(sel, -1, obj.alias, obj.path);
811 function oilsRptAddOrderBy(path) {
812 var rel = hex_md5(oilsRptPathRel(path));
813 var order_by = oilsRpt.def.order_by;
815 /* if this item is already in the order by remove it and overwrite it */
816 order_by = grep(oilsRpt.def.order_by,
817 function(i) {return (i.path != path)});
819 if(!order_by) order_by = [];
821 /* find the column definition in the select blob */
822 var obj = grep(oilsRpt.def.select,
823 function(i) {return (i.path == path)});
829 relation : obj.relation,
831 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
834 oilsRpt.def.order_by = order_by;