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?'))
48 var req = new Request(OILS_RPT_CREATE_TEMPLATE, SESSION, tmpl);
51 var res = r.getResultObject();
52 if( res && res != '0' ) {
53 oilsRptAlertSuccess();
64 /* adds an item to the display window */
65 function oilsAddRptDisplayItem(path, name, tform, params) {
66 if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) )
69 /* add the selected columns to the report output */
70 name = (name) ? name : oilsRptPathCol(path);
71 if( !tform ) tform = 'Bare';
73 var aggregate = oilsRptGetIsAgg(tform);
75 /* add this item to the select blob */
77 relation: hex_md5(oilsRptPathRel(path)),
80 column: { transform: tform, colname: oilsRptPathCol(path) }
83 if( params ) sel.column.params = params;
85 if(!oilsRptGetIsAgg(tform)) {
88 for( var i = 0; i < oilsRpt.def.select.length; i++ ) {
89 var item = oilsRpt.def.select[i];
90 if( !added && oilsRptGetIsAgg( item.column.transform ) ) {
96 if(!added) select.push(sel);
97 oilsRpt.def.select = select;
99 oilsRpt.def.select.push(sel);
103 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
107 function oilsRptGetIsAgg(tform) {
108 return OILS_RPT_TRANSFORMS[tform].aggregate;
111 var sel = $n(DOM.oils_rpt_tform_table,'selector');
112 for( var i = 0; i < sel.options.length; i++ ) {
113 var opt = sel.options[i];
114 if( opt.getAttribute('value') == tform )
115 return opt.getAttribute('aggregate');
119 /* takes a column path and builds a from-clause object for the path */
120 function oilsRptBuildFromClause(path) {
122 /* the path is the full path (relation) from the source
123 object to the column in question (e.g. au-home_ou-aou-name)*/
124 var parts = path.split(/-/);
126 /* the final from clause */
129 /* reference to the current position in the from clause */
134 /* walk the path, fleshing the from clause as we go */
135 for( var i = 0; i < parts.length; i += 2 ) {
137 var cls = parts[i]; /* class name (id) */
138 var col = parts[i+1]; /* column name */
140 /* a "node" is a class description from the IDL, it
141 contains relevant info, plus a list of "fields",
143 var node = oilsIDL[cls];
144 var pkey = oilsRptFindField(node, node.pkey);
146 /* a "field" is a parsed version of a column from the IDL,
147 contains datatype, column name, etc. */
148 var field = oilsRptFindField(node, col);
150 /* re-construct the path as we go so
151 we know what all we've seen thus far */
152 newpath = (newpath) ? newpath + '-'+ cls : cls;
154 /* extract relevant info */
155 tobj.table = node.table;
157 tobj.alias = hex_md5(newpath);
159 _debug('field type is ' + field.type);
160 if( i == (parts.length - 2) ) break;
162 /* we still have columns left in the path, keep adding join's */
164 if(field.reltype != 'has_a')
165 col = pkey.name + '-' + col;
172 if( field.type == 'link' )
173 tobj.key = field.key;
175 newpath = newpath + '-'+ path_col;
178 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
182 function oilsMoveUpDisplayItems() {
183 var sel = oilsRptDisplaySelector;
184 var idx = sel.selectedIndex;
185 if( idx == 0 ) return;
186 var opt = sel.options[idx];
187 sel.options[idx] = null;
189 var val = opt.getAttribute('value');
190 insertSelectorVal(sel, idx, opt.innerHTML, val);
191 sel.options[idx].selected = true;
193 var arr = oilsRpt.def.select;
194 for( var i = 0; i < arr.length; i++ ) {
195 if( arr[i].path == val ) {
196 var other = arr[i-1];
205 function oilsMoveDownDisplayItems() {
206 var sel = oilsRptDisplaySelector;
207 var idx = sel.selectedIndex;
208 if( idx == sel.options.length - 1 ) return;
209 var opt = sel.options[idx];
210 sel.options[idx] = null;
212 var val = opt.getAttribute('value');
213 insertSelectorVal(sel, idx, opt.innerHTML, val);
214 sel.options[idx].selected = true;
216 var arr = oilsRpt.def.select;
217 for( var i = 0; i < arr.length; i++ ) {
218 if( arr[i].path == val ) {
219 var other = arr[i+1];
229 /* removes a specific item from the display window */
231 function oilsDelDisplayItem(val) {
232 oilsDelSelectorItem(oilsRptDisplaySelector, val);
236 /* removes selected items from the display window */
237 function oilsDelSelectedDisplayItems() {
238 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
240 _debug('deleting list: ' + list);
242 /* remove the de-selected columns from the report output */
243 oilsRpt.def.select = grep( oilsRpt.def.select,
245 for( var j = 0; j < list.length; j++ ) {
246 var d = list[j]; /* path */
249 _debug('in delete, looking at list = '+d+' : col = ' +
250 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
252 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
260 if(!oilsRpt.def.select) oilsRpt.def.select = [];
262 oilsRptPruneFromList(list);
265 for( var j = 0; j < list.length; j++ ) {
266 debug('seeing if we can prune from clause with relation = ' + hex_md5(oilsRptPathRel(list[j])));
267 if( !grep(oilsRpt.def.select,
268 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
269 && !grep(oilsRpt.def.where,
270 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
271 && !grep(oilsRpt.def.having,
272 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
274 _debug('pruning from clause');
275 oilsRptPruneFromClause(oilsRptPathRel(list[j]));
283 function oilsRptPruneFromList(pathlist) {
285 for( var j = 0; j < pathlist.length; j++ ) {
286 /* if there are no items left in the "select", "where", or "having" clauses
287 for the given relation, trim this relation from the "from" clause */
288 var path = pathlist[j];
289 var encrel = hex_md5(oilsRptPathRel(path));
291 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
293 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
295 if( !grep(oilsRpt.def.select, func) &&
296 !grep(oilsRpt.def.where, func) &&
297 !grep(oilsRpt.def.having, func) ) {
299 oilsRptPruneFromClause(oilsRptPathRel(pathlist[j]));
305 /* for each item in the path list, remove the associated data
306 from the "from" clause */
308 function oilsRptPruneFromClause(relation, node) {
309 _debug("removing relation from 'from' clause: " + relation);
310 if(!node) node = oilsRpt.def.from.join;
311 if(!node) return false;
313 for( var i in node ) {
314 _debug("from prune looking at node "+node[i].path);
315 // first, descend into the tree, and prune leaves first
317 oilsRptPruneFromClause(relation, node[i].join);
318 if(oilsRptObjectKeys(node[i].join).length == 0)
325 var key = oilsRptObjectKeys(node)[0];
326 var from_alias = node[key].alias;
327 var func = function(n){ return (n.relation == from_alias)};
329 _debug("pruning from clause with alias "+ from_alias);
331 if( !grep(oilsRpt.def.select, func) &&
332 !grep(oilsRpt.def.where, func) &&
333 !grep(oilsRpt.def.having, func) ) {
335 // if we're at an unused empty leaf, remove it
344 function oilsRptMkFilterTags(path, tform, filter) {
345 var name = oilsRptMakeLabel(path);
346 if(tform) name += ' ('+tform+')';
347 name += ' "' + filter + '"';
348 var epath = path + ':'+filter+':';
349 if(tform) epath += tform;
351 return [ name, epath ];
355 function oilsAddRptFilterItem(path, tform, filter) {
356 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
358 var name = oilsRptMkFilterTags(path, tform, filter);
362 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
366 relation: hex_md5(oilsRptPathRel(path)),
368 column: { transform: tform, colname: oilsRptPathCol(path) },
371 if( filter == 'is' || filter == 'is not' )
372 where.condition[filter] = null;
373 else where.condition[filter] = oilsRptNextParam();
376 case 'substring' : where.column.params = oilsRptNextParam();
379 oilsRpt.def.where.push(where);
380 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
385 function oilsAddRptHavingItem(path, tform, filter) {
386 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
388 var name = oilsRptMkFilterTags(path, tform, filter);
392 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
396 relation: hex_md5(oilsRptPathRel(path)),
398 column: { transform: tform, colname: oilsRptPathCol(path) },
401 if( filter == 'is' || filter == 'is not' )
402 having.condition[filter] = null;
403 else having.condition[filter] = oilsRptNextParam();
406 case 'substring' : having.column.params = oilsRptNextParam();
409 oilsRpt.def.having.push(having);
410 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
416 function oilsDelSelectedFilterItems() {
417 _oilsDelSelectedFilterItems('where');
419 function oilsDelSelectedAggFilterItems() {
420 _oilsDelSelectedFilterItems('having');
423 function _oilsDelSelectedFilterItems(type) {
425 /* the values in this list are formed: <path>:<operation>:<transform> */
426 var list = oilsDelSelectedItems(oilsRptFilterSelector);
428 for( var i = 0; i < list.length; i++ ) {
429 var enc_path = list[i];
430 var data = oilsRptParseFilterEncPath(enc_path);
431 oilsRpt.def[type] = grep(
434 return oilsRptFilterDataMatches(
435 f, data.path, data.operation, data.tform );
440 if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
441 oilsRptPruneFromList(list);
445 function oilsRptParseFilterEncPath(item) {
447 path: item.replace(/:.*/,''),
448 operation: item.replace(/.*:(.*):.*/,'$1'),
449 tform: item.replace(/.*?:.*?:(.*)/,'$1')
454 function oilsRptFilterDataMatches(filter, path, operation, tform) {
455 var rel = hex_md5(oilsRptPathRel(path));
456 var col = oilsRptPathCol(path);
458 if( col == filter.column.colname &&
459 rel == filter.relation &&
460 tform == filter.column.transform &&
461 operation == oilsRptObjectKeys(filter)[0] ) return true;
467 function oilsRptFilterGrep(flist, filter) {
469 for( var j = 0; j < flist.length; j++ ) {
472 var col = filter.column;
473 var frel = hex_md5(oilsRptPathRel(fil.path));
474 var fcol = oilsRptPathCol(fil.path);
476 var op = oilsRptObjectKeys(filter.condition)[0];
478 if( frel == filter.relation &&
479 fcol == col.colname &&
480 fil.operation == op &&
481 fil.tform == col.transform ) {
489 /* adds an item to the display window */
490 function oilsAddRptAggFilterItem(val) {
491 oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
494 /* removes a specific item from the display window */
495 function oilsDelAggFilterItem(val) {
496 oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
502 function ___oilsDelSelectedAggFilterItems() {
503 var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
504 oilsRpt.def.having = grep( oilsRpt.def.having,
506 for( var j = 0; j < list.length; j++ ) {
510 if( typeof col != 'string' )
511 for( var c in col ) col = col[c];
513 if( typeof col != 'string' ) col = col[0];
515 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
517 // var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
519 if( param ) delete oilsRpt.params[param];
527 if(!oilsRpt.def.having) oilsRpt.def.having = [];
528 oilsRptPruneFromList(list);
534 /* adds an item to the display window */
535 function oilsAddSelectorItem(sel, val, name) {
536 name = (name) ? name : oilsRptMakeLabel(val);
537 for( var i = 0; i < sel.options.length; i++ ) {
538 var opt = sel.options[i];
539 if( opt.value == val ) return false;
541 insertSelectorVal( sel, -1, name, val );
546 /* removes a specific item from the display window */
547 function oilsDelSelectorItem(sel, val) {
548 var opts = sel.options;
549 for( var i = 0; i < opts.length; i++ ) {
551 if( opt.value == val ) {
552 if( i == opts.length - 1 )
554 else opts[i] = opts[i+1];
560 /* removes selected items from the display window */
561 function oilsDelSelectedItems(sel) {
562 var list = getSelectedList(sel);
563 for( var i = 0; i < list.length; i++ )
564 oilsDelSelectorItem(sel, list[i]);
569 /* hides the different field editor tabs */
570 function oilsRptHideEditorDivs() {
571 hideMe(DOM.oils_rpt_tform_div);
572 hideMe(DOM.oils_rpt_filter_div);
573 hideMe(DOM.oils_rpt_agg_filter_div);
574 hideMe(DOM.oils_rpt_order_by_div);
579 This draws the 3-tabbed window containing the transform,
580 filter, and aggregate filter picker window
582 function oilsRptDrawDataWindow(path) {
583 var col = oilsRptPathCol(path);
584 var cls = oilsRptPathClass(path);
585 var field = oilsRptFindField(oilsIDL[cls], col);
587 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
588 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
590 _debug("setting update data window for column "+col+' on class '+cls);
592 var div = DOM.oils_rpt_column_editor;
593 /* set a preliminary top position so the page won't bounce around */
594 div.setAttribute('style','top:'+oilsMouseX+'px');
596 /* unhide the div so we can determine the dimensions */
599 /* don't let them see the floating div until the position is fully determined */
600 div.style.visibility='hidden';
602 oilsRptDrawTransformWindow(path, col, cls, field);
603 oilsRptDrawFilterWindow(path, col, cls, field);
604 oilsRptDrawHavingWindow(path, col, cls, field);
605 oilsRptDrawOrderByWindow(path, col, cls, field);
607 buildFloatingDiv(div, 600);
609 /* now let them see it */
610 div.style.visibility='visible';
611 oilsRptSetDataWindowActions(div);
615 function oilsRptSetDataWindowActions(div) {
616 /* give the tab links behavior */
617 DOM.oils_rpt_tform_tab.onclick =
618 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_tform_div)};
619 DOM.oils_rpt_filter_tab.onclick =
620 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_filter_div)};
621 DOM.oils_rpt_agg_filter_tab.onclick =
622 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_agg_filter_div)};
625 DOM.oils_rpt_order_by_tab.onclick =
627 oilsRptHideEditorDivs();
628 oilsRptDrawOrderByWindow();
629 unHideMe(DOM.oils_rpt_order_by_div);
633 DOM.oils_rpt_tform_tab.onclick();
634 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
638 function oilsRptDrawFilterWindow(path, col, cls, field) {
640 var tformPicker = new oilsRptTformPicker( {
641 node : DOM.oils_rpt_filter_tform_table,
642 datatype : field.datatype,
647 var filterPicker = new oilsRptFilterPicker({
648 node : DOM.oils_rpt_filter_op_table,
649 datatype : field.datatype
653 DOM.oils_rpt_filter_submit.onclick = function() {
654 oilsAddRptFilterItem(
655 path, tformPicker.getSelected(), filterPicker.getSelected());
660 function oilsRptDrawHavingWindow(path, col, cls, field) {
661 var tformPicker = new oilsRptTformPicker( {
662 node : DOM.oils_rpt_agg_filter_tform_table,
663 datatype : field.datatype,
668 var filterPicker = new oilsRptFilterPicker({
669 node : DOM.oils_rpt_agg_filter_op_table,
670 datatype : field.datatype
674 DOM.oils_rpt_agg_filter_submit.onclick = function() {
675 oilsAddRptHavingItem(
676 path, tformPicker.getSelected(), filterPicker.getSelected());
680 /* draws the transform window */
681 function oilsRptDrawTransformWindow(path, col, cls, field) {
682 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
683 var dtype = field.datatype;
685 var tformPicker = new oilsRptTformPicker( {
686 node : DOM.oils_rpt_tform_table,
687 datatype : field.datatype,
688 non_aggregate : true,
693 DOM.oils_rpt_tform_submit.onclick =
695 oilsAddRptDisplayItem(path,
696 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
699 DOM.oils_rpt_tform_label_input.focus();
700 DOM.oils_rpt_tform_label_input.select();
702 _debug("Building transform window for datatype "+dtype);
706 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
707 function oilsRptDrawOrderByWindow() {
708 var sel = DOM.oils_rpt_order_by_selector;
710 DOM.oils_rpt_order_by_submit.onclick = function() {
711 oilsRptAddOrderBy(getSelectorVal(sel));
714 var cols = oilsRpt.def.select;
715 for( var i = 0; i < cols.length; i++ ) {
717 insertSelectorVal(sel, -1, obj.alias, obj.path);
721 function oilsRptAddOrderBy(path) {
722 var rel = hex_md5(oilsRptPathRel(path));
723 var order_by = oilsRpt.def.order_by;
725 /* if this item is already in the order by remove it and overwrite it */
726 order_by = grep(oilsRpt.def.order_by,
727 function(i) {return (i.path != path)});
729 if(!order_by) order_by = [];
731 /* find the column definition in the select blob */
732 var obj = grep(oilsRpt.def.select,
733 function(i) {return (i.path == path)});
739 relation : obj.relation,
741 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
744 oilsRpt.def.order_by = order_by;