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);
16 DOM.oils_rpt_builder_save_template.onclick = oilsReportBuilderSave;
19 function oilsReportBuilderReset() {
20 var n = (oilsRpt) ? oilsRpt.name : "";
21 oilsRpt = new oilsReport();
23 oilsRptDisplaySelector = DOM.oils_rpt_display_selector;
24 oilsRptFilterSelector = DOM.oils_rpt_filter_selector;
25 oilsRptHavingSelector = DOM.oils_rpt_agg_filter_selector;
26 removeChildren(oilsRptDisplaySelector);
27 removeChildren(oilsRptFilterSelector);
28 removeChildren(oilsRptHavingSelector);
29 //removeChildren(oilsRptOrderBySelector);
33 function oilsReportBuilderSave() {
36 tmpl.name(DOM.oils_rpt_builder_new_name.value);
37 tmpl.description(DOM.oils_rpt_builder_new_desc.value);
38 tmpl.owner(USER.id());
39 tmpl.folder(new CGI().param('folder'));
40 tmpl.data(js2JSON(oilsRpt.def));
42 if(!confirm('Name : '+tmpl.name() + '\nDescription: ' + tmpl.description()+'\nSave Template?'))
49 var req = new Request(OILS_RPT_CREATE_TEMPLATE, SESSION, tmpl);
52 var res = r.getResultObject();
53 if( res && res != '0' ) {
54 oilsRptAlertSuccess();
65 /* adds an item to the display window */
66 function oilsAddRptDisplayItem(path, name, tform, params) {
67 if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) )
70 /* add the selected columns to the report output */
71 name = (name) ? name : oilsRptPathCol(path);
72 if( !tform ) tform = 'Bare';
74 var aggregate = oilsRptGetIsAgg(tform);
76 /* add this item to the select blob */
78 relation: hex_md5(oilsRptPathRel(path)),
81 column: { transform: tform, colname: oilsRptPathCol(path) }
84 if( params ) sel.column.params = params;
86 if(!oilsRptGetIsAgg(tform)) {
89 for( var i = 0; i < oilsRpt.def.select.length; i++ ) {
90 var item = oilsRpt.def.select[i];
91 if( !added && oilsRptGetIsAgg( item.column.transform ) ) {
97 if(!added) select.push(sel);
98 oilsRpt.def.select = select;
100 oilsRpt.def.select.push(sel);
104 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
108 function oilsRptGetIsAgg(tform) {
109 return OILS_RPT_TRANSFORMS[tform].aggregate;
112 var sel = $n(DOM.oils_rpt_tform_table,'selector');
113 for( var i = 0; i < sel.options.length; i++ ) {
114 var opt = sel.options[i];
115 if( opt.getAttribute('value') == tform )
116 return opt.getAttribute('aggregate');
120 /* takes a column path and builds a from-clause object for the path */
121 function oilsRptBuildFromClause(path) {
123 /* the path is the full path (relation) from the source
124 object to the column in question (e.g. au-home_ou-aou-name)*/
125 var parts = path.split(/-/);
127 /* the final from clause */
130 /* reference to the current position in the from clause */
135 /* walk the path, fleshing the from clause as we go */
136 for( var i = 0; i < parts.length; i += 2 ) {
138 var cls = parts[i]; /* class name (id) */
139 var col = parts[i+1]; /* column name */
141 /* a "node" is a class description from the IDL, it
142 contains relevant info, plus a list of "fields",
144 var node = oilsIDL[cls];
145 var pkey = oilsRptFindField(node, node.pkey);
147 /* a "field" is a parsed version of a column from the IDL,
148 contains datatype, column name, etc. */
149 var field = oilsRptFindField(node, col);
151 /* re-construct the path as we go so
152 we know what all we've seen thus far */
153 newpath = (newpath) ? newpath + '-'+ cls : cls;
155 /* extract relevant info */
156 tobj.table = node.table;
158 tobj.alias = hex_md5(newpath);
160 _debug('field type is ' + field.type);
161 if( i == (parts.length - 2) ) break;
163 /* we still have columns left in the path, keep adding join's */
165 if(field.reltype != 'has_a')
166 col = pkey.name + '-' + col;
173 if( field.type == 'link' )
174 tobj.key = field.key;
176 newpath = newpath + '-'+ path_col;
179 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
184 /* removes a specific item from the display window */
185 function oilsDelDisplayItem(val) {
186 oilsDelSelectorItem(oilsRptDisplaySelector, val);
189 /* removes selected items from the display window */
190 function oilsDelSelectedDisplayItems() {
191 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
193 _debug('deleting list: ' + list);
195 /* remove the de-selected columns from the report output */
196 oilsRpt.def.select = grep( oilsRpt.def.select,
198 for( var j = 0; j < list.length; j++ ) {
199 var d = list[j]; /* path */
202 _debug('in delete, looking at list = '+d+' : col = ' +
203 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
205 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
213 if(!oilsRpt.def.select) oilsRpt.def.select = [];
215 oilsRptPruneFromList(list);
218 for( var j = 0; j < list.length; j++ ) {
219 debug('seeing if we can prune from clause with relation = ' + hex_md5(oilsRptPathRel(list[j])));
220 if( !grep(oilsRpt.def.select,
221 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
222 && !grep(oilsRpt.def.where,
223 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
224 && !grep(oilsRpt.def.having,
225 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
227 _debug('pruning from clause');
228 oilsRptPruneFromClause(oilsRptPathRel(list[j]));
236 function oilsRptPruneFromList(pathlist) {
238 for( var j = 0; j < pathlist.length; j++ ) {
239 /* if there are no items left in the "select", "where", or "having" clauses
240 for the given relation, trim this relation from the "from" clause */
241 var path = pathlist[j];
242 var encrel = hex_md5(oilsRptPathRel(path));
244 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
246 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
248 if( !grep(oilsRpt.def.select, func) &&
249 !grep(oilsRpt.def.where, func) &&
250 !grep(oilsRpt.def.having, func) ) {
252 oilsRptPruneFromClause(oilsRptPathRel(pathlist[j]));
258 /* for each item in the path list, remove the associated data
259 from the "from" clause */
261 function oilsRptPruneFromClause(relation, node) {
262 _debug("removing relation from 'from' clause: " + relation);
263 if(!node) node = oilsRpt.def.from.join;
264 if(!node) return false;
266 for( var i in node ) {
267 _debug("from prune looking at node "+node[i].path);
268 // first, descend into the tree, and prune leaves first
270 oilsRptPruneFromClause(relation, node[i].join);
271 if(oilsRptObjectKeys(node[i].join).length == 0)
278 var key = oilsRptObjectKeys(node)[0];
279 var from_alias = node[key].alias;
280 var func = function(n){ return (n.relation == from_alias)};
282 _debug("pruning from clause with alias "+ from_alias);
284 if( !grep(oilsRpt.def.select, func) &&
285 !grep(oilsRpt.def.where, func) &&
286 !grep(oilsRpt.def.having, func) ) {
288 // if we're at an unused empty leaf, remove it
297 function oilsRptMkFilterTags(path, tform, filter) {
298 var name = oilsRptMakeLabel(path);
299 if(tform) name += ' ('+tform+')';
300 name += ' "' + filter + '"';
301 var epath = path + ':'+filter+':';
302 if(tform) epath += tform;
304 return [ name, epath ];
308 function oilsAddRptFilterItem(path, tform, filter) {
309 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
311 var name = oilsRptMkFilterTags(path, tform, filter);
315 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
319 relation: hex_md5(oilsRptPathRel(path)),
321 column: { transform: tform, colname: oilsRptPathCol(path) },
324 if( filter == 'is' || filter == 'is not' )
325 where.condition[filter] = null;
326 else where.condition[filter] = oilsRptNextParam();
329 case 'substring' : where.column.params = oilsRptNextParam();
332 oilsRpt.def.where.push(where);
333 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
338 function oilsAddRptHavingItem(path, tform, filter) {
339 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
341 var name = oilsRptMkFilterTags(path, tform, filter);
345 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
349 relation: hex_md5(oilsRptPathRel(path)),
351 column: { transform: tform, colname: oilsRptPathCol(path) },
354 if( filter == 'is' || filter == 'is not' )
355 having.condition[filter] = null;
356 else having.condition[filter] = oilsRptNextParam();
359 case 'substring' : having.column.params = oilsRptNextParam();
362 oilsRpt.def.having.push(having);
363 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
369 function oilsDelSelectedFilterItems() {
370 _oilsDelSelectedFilterItems('where');
372 function oilsDelSelectedAggFilterItems() {
373 _oilsDelSelectedFilterItems('having');
376 function _oilsDelSelectedFilterItems(type) {
378 /* the values in this list are formed: <path>:<operation>:<transform> */
379 var list = oilsDelSelectedItems(oilsRptFilterSelector);
381 for( var i = 0; i < list.length; i++ ) {
382 var enc_path = list[i];
383 var data = oilsRptParseFilterEncPath(enc_path);
384 oilsRpt.def[type] = grep(
387 return oilsRptFilterDataMatches(
388 f, data.path, data.operation, data.tform );
393 if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
394 oilsRptPruneFromList(list);
398 function oilsRptParseFilterEncPath(item) {
400 path: item.replace(/:.*/,''),
401 operation: item.replace(/.*:(.*):.*/,'$1'),
402 tform: item.replace(/.*?:.*?:(.*)/,'$1')
407 function oilsRptFilterDataMatches(filter, path, operation, tform) {
408 var rel = hex_md5(oilsRptPathRel(path));
409 var col = oilsRptPathCol(path);
411 if( col == filter.column.colname &&
412 rel == filter.relation &&
413 tform == filter.column.transform &&
414 operation == oilsRptObjectKeys(filter)[0] ) return true;
420 function oilsRptFilterGrep(flist, filter) {
422 for( var j = 0; j < flist.length; j++ ) {
425 var col = filter.column;
426 var frel = hex_md5(oilsRptPathRel(fil.path));
427 var fcol = oilsRptPathCol(fil.path);
429 var op = oilsRptObjectKeys(filter.condition)[0];
431 if( frel == filter.relation &&
432 fcol == col.colname &&
433 fil.operation == op &&
434 fil.tform == col.transform ) {
442 /* adds an item to the display window */
443 function oilsAddRptAggFilterItem(val) {
444 oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
447 /* removes a specific item from the display window */
448 function oilsDelAggFilterItem(val) {
449 oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
455 function ___oilsDelSelectedAggFilterItems() {
456 var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
457 oilsRpt.def.having = grep( oilsRpt.def.having,
459 for( var j = 0; j < list.length; j++ ) {
463 if( typeof col != 'string' )
464 for( var c in col ) col = col[c];
466 if( typeof col != 'string' ) col = col[0];
468 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
470 // var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
472 if( param ) delete oilsRpt.params[param];
480 if(!oilsRpt.def.having) oilsRpt.def.having = [];
481 oilsRptPruneFromList(list);
487 /* adds an item to the display window */
488 function oilsAddSelectorItem(sel, val, name) {
489 name = (name) ? name : oilsRptMakeLabel(val);
490 for( var i = 0; i < sel.options.length; i++ ) {
491 var opt = sel.options[i];
492 if( opt.value == val ) return false;
494 insertSelectorVal( sel, -1, name, val );
499 /* removes a specific item from the display window */
500 function oilsDelSelectorItem(sel, val) {
501 var opts = sel.options;
502 for( var i = 0; i < opts.length; i++ ) {
504 if( opt.value == val ) {
505 if( i == opts.length - 1 )
507 else opts[i] = opts[i+1];
513 /* removes selected items from the display window */
514 function oilsDelSelectedItems(sel) {
515 var list = getSelectedList(sel);
516 for( var i = 0; i < list.length; i++ )
517 oilsDelSelectorItem(sel, list[i]);
522 /* hides the different field editor tabs */
523 function oilsRptHideEditorDivs() {
524 hideMe(DOM.oils_rpt_tform_div);
525 hideMe(DOM.oils_rpt_filter_div);
526 hideMe(DOM.oils_rpt_agg_filter_div);
527 hideMe(DOM.oils_rpt_order_by_div);
532 This draws the 3-tabbed window containing the transform,
533 filter, and aggregate filter picker window
535 function oilsRptDrawDataWindow(path) {
536 var col = oilsRptPathCol(path);
537 var cls = oilsRptPathClass(path);
538 var field = oilsRptFindField(oilsIDL[cls], col);
540 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
541 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
543 _debug("setting update data window for column "+col+' on class '+cls);
545 var div = DOM.oils_rpt_column_editor;
546 /* set a preliminary top position so the page won't bounce around */
547 div.setAttribute('style','top:'+oilsMouseX+'px');
549 /* unhide the div so we can determine the dimensions */
552 /* don't let them see the floating div until the position is fully determined */
553 div.style.visibility='hidden';
555 oilsRptDrawTransformWindow(path, col, cls, field);
556 oilsRptDrawFilterWindow(path, col, cls, field);
557 oilsRptDrawHavingWindow(path, col, cls, field);
558 oilsRptDrawOrderByWindow(path, col, cls, field);
560 buildFloatingDiv(div, 600);
562 /* now let them see it */
563 div.style.visibility='visible';
564 oilsRptSetDataWindowActions(div);
568 function oilsRptSetDataWindowActions(div) {
569 /* give the tab links behavior */
570 DOM.oils_rpt_tform_tab.onclick =
571 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_tform_div)};
572 DOM.oils_rpt_filter_tab.onclick =
573 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_filter_div)};
574 DOM.oils_rpt_agg_filter_tab.onclick =
575 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_agg_filter_div)};
577 DOM.oils_rpt_order_by_tab.onclick =
579 oilsRptHideEditorDivs();
580 oilsRptDrawOrderByWindow();
581 unHideMe(DOM.oils_rpt_order_by_div);
584 DOM.oils_rpt_tform_tab.onclick();
585 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
589 function oilsRptDrawFilterWindow(path, col, cls, field) {
591 var tformPicker = new oilsRptTformPicker( {
592 node : DOM.oils_rpt_filter_tform_table,
593 datatype : field.datatype,
598 var filterPicker = new oilsRptFilterPicker({
599 node : DOM.oils_rpt_filter_op_table,
600 datatype : field.datatype
604 DOM.oils_rpt_filter_submit.onclick = function() {
605 oilsAddRptFilterItem(
606 path, tformPicker.getSelected(), filterPicker.getSelected());
611 function oilsRptDrawHavingWindow(path, col, cls, field) {
612 var tformPicker = new oilsRptTformPicker( {
613 node : DOM.oils_rpt_agg_filter_tform_table,
614 datatype : field.datatype,
619 var filterPicker = new oilsRptFilterPicker({
620 node : DOM.oils_rpt_agg_filter_op_table,
621 datatype : field.datatype
625 DOM.oils_rpt_agg_filter_submit.onclick = function() {
626 oilsAddRptHavingItem(
627 path, tformPicker.getSelected(), filterPicker.getSelected());
631 /* draws the transform window */
632 function oilsRptDrawTransformWindow(path, col, cls, field) {
633 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
634 var dtype = field.datatype;
636 var tformPicker = new oilsRptTformPicker( {
637 node : DOM.oils_rpt_tform_table,
638 datatype : field.datatype,
639 non_aggregate : true,
644 DOM.oils_rpt_tform_submit.onclick =
646 oilsAddRptDisplayItem(path,
647 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
650 DOM.oils_rpt_tform_label_input.focus();
651 DOM.oils_rpt_tform_label_input.select();
653 _debug("Building transform window for datatype "+dtype);
657 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
658 function oilsRptDrawOrderByWindow() {
659 var sel = DOM.oils_rpt_order_by_selector;
661 DOM.oils_rpt_order_by_submit.onclick = function() {
662 oilsRptAddOrderBy(getSelectorVal(sel));
665 var cols = oilsRpt.def.select;
666 for( var i = 0; i < cols.length; i++ ) {
668 insertSelectorVal(sel, -1, obj.alias, obj.path);
672 function oilsRptAddOrderBy(path) {
673 var rel = hex_md5(oilsRptPathRel(path));
674 var order_by = oilsRpt.def.order_by;
676 /* if this item is already in the order by remove it and overwrite it */
677 order_by = grep(oilsRpt.def.order_by,
678 function(i) {return (i.path != path)});
680 if(!order_by) order_by = [];
682 /* find the column definition in the select blob */
683 var obj = grep(oilsRpt.def.select,
684 function(i) {return (i.path == path)});
690 relation : obj.relation,
692 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
695 oilsRpt.def.order_by = order_by;