1 /** initializes reports, some basid display settings,
2 * grabs and builds the IDL tree
4 function oilsInitReportBuilder() {
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);
17 function oilsReportBuilderReset() {
18 var n = (oilsRpt) ? oilsRpt.name : "";
19 oilsRpt = new oilsReport();
21 oilsRptDisplaySelector = DOM.oils_rpt_display_selector;
22 oilsRptFilterSelector = DOM.oils_rpt_filter_selector;
23 oilsRptAggFilterSelector= DOM.oils_rpt_agg_filter_selector;
24 removeChildren(oilsRptDisplaySelector);
25 removeChildren(oilsRptFilterSelector);
26 removeChildren(oilsRptAggFilterSelector);
32 /* adds an item to the display window */
33 function oilsAddRptDisplayItem(path, name, tform, params) {
34 if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) )
37 /* add the selected columns to the report output */
38 name = (name) ? name : oilsRptPathCol(path);
39 if( !tform ) tform = 'Bare';
41 /* add this item to the select blob */
43 relation: oilsRptPathRel(path),
45 column: { transform: tform, colname: oilsRptPathCol(path) }
48 if( params ) sel.column.params = params;
49 oilsRpt.def.select.push(sel);
51 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
55 /* takes a column path and builds a from-clause object for the path */
56 function oilsRptBuildFromClause(path) {
58 /* the path is the full path (relation) from the source
59 object to the column in question (e.g. au-home_ou-aou-name)*/
60 var parts = path.split(/-/);
62 /* the final from clause */
65 /* reference to the current position in the from clause */
70 /* walk the path, fleshing the from clause as we go */
71 for( var i = 0; i < parts.length; i += 2 ) {
73 var cls = parts[i]; /* class name (id) */
74 var col = parts[i+1]; /* column name */
76 /* a "node" is a class description from the IDL, it
77 contains relevant info, plus a list of "fields",
79 var node = oilsIDL[cls];
80 var pkey = oilsRptFindField(node, node.pkey);
82 /* a "field" is a parsed version of a column from the IDL,
83 contains datatype, column name, etc. */
84 var field = oilsRptFindField(node, col);
86 /* re-construct the path as we go so
87 we know what all we've seen thus far */
88 newpath = (newpath) ? newpath + '-'+ cls : cls;
90 /* extract relevant info */
91 tobj.table = node.table;
93 _debug('field type is ' + field.type);
94 if( i == (parts.length - 2) ) break;
96 /* we still have columns left in the path, keep adding join's */
98 if(field.reltype != 'has_a')
99 col = pkey.name + '-' + col;
106 if( field.type == 'link' )
107 tobj.key = field.key;
109 newpath = newpath + '-'+ path_col;
112 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
117 /* removes a specific item from the display window */
118 function oilsDelDisplayItem(val) {
119 oilsDelSelectorItem(oilsRptDisplaySelector, val);
122 /* removes selected items from the display window */
123 function oilsDelSelectedDisplayItems() {
124 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
126 /* remove the de-selected columns from the report output */
127 oilsRpt.def.select = grep( oilsRpt.def.select,
129 for( var j = 0; j < list.length; j++ ) {
133 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col.colname ) {
134 //var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
135 // if( param ) delete oilsRpt.params[param];
143 if(!oilsRpt.def.select) {
144 oilsRpt.def.select = [];
145 //oilsReportBuilderReset();
148 for( var j = 0; j < list.length; j++ )
149 /* if there are no items left in the "select", "where", or "having" clauses
150 for the given relation, trim this relation from the "from" clause */
151 if( !grep(oilsRpt.def.select,
152 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
153 && !grep(oilsRpt.def.where,
154 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
155 && !grep(oilsRpt.def.having,
156 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
157 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
163 /* for each item in the path list, remove the associated data
164 from the "from" clause */
166 function oilsRptPruneFromClause(relation, node) {
167 _debug("removing relation from 'from' clause " + relation);
168 if(!node) node = oilsRpt.def.from.join;
169 for( var i in node ) {
170 if( node[i].alias == relation ) {
172 /* if we have subtrees, don't delete our tree node */
180 if( oilsRptPruneFromClause(relation, node[i].join ) ) {
181 if(oilsRptObjectKeys(node[i].join).length == 0) {
183 /* if there are no items in the select clause with a relation matching
184 this nodes alias, we can safely remove this node from the tree */
185 if(!grep(oilsRpt.def.select,function(r){return (r.relation==node[i].alias)}))
196 function oilsRptFilterName(path, tform, filter) {
199 /* adds an item to the display window */
200 function oilsAddRptFilterItem(path, tform, filter) {
201 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
203 var name = oilsRptMakeLabel(path);
204 if(tform) name += ' ('+tform+')';
205 name += ' "' + filter + '"';
207 var epath = path + ':'+filter+':';
208 if(tform) epath += tform;
211 if( ! oilsAddSelectorItem(oilsRptFilterSelector, path, name) )
215 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
219 relation: oilsRptPathRel(path),
220 column: { transform: tform, colname: oilsRptPathCol(path) },
223 where.condition[filter] = oilsRptNextParam();
226 case 'substring' : where.column.params = oilsRptNextParam();
229 oilsRpt.def.where.push(where);
230 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
234 /* removes a specific item from the display window */
235 //function oilsDelFilterItem(path) {
236 //oilsDelSelectorItem(oilsRptFilterSelector, path);
239 /* removes selected items from the display window */
240 function oilsDelSelectedFilterItems() {
242 /* the values in this list are formed: <path>:<operation>:<tform (optional)> */
243 var list = oilsDelSelectedItems(oilsRptFilterSelector);
247 for( var i = 0; i < list.length; i++ ) {
250 path: item.replace(/:.*/,''),
251 filter: item.replace(/.*:(.*):.*/,'$1'),
252 tform: item.replace(/.*?:.*?:(.*)/,'$1')
257 /* XXX refactor the below to take operation and transform into account
258 since the same path can be used multiple times as long as a different
259 filter and/or transform is used */
261 /* remove the de-selected columns from the report output */
262 oilsRpt.def.where = grep( oilsRpt.def.where,
264 for( var j = 0; j < list.length; j++ ) {
268 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col.colname ) {
269 var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
270 if( param ) delete oilsRpt.params[param];
278 if(!oilsRpt.def.where) {
279 oilsRpt.def.where = [];
280 //oilsReportBuilderReset();
283 for( var j = 0; j < list.length; j++ )
284 /* if there are no items left in the "select", "where", or "having" clauses
285 for the given relation, trim this relation from the "from" clause */
286 if( !grep(oilsRpt.def.select,
287 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
288 && !grep(oilsRpt.def.where,
289 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
290 && !grep(oilsRpt.def.having,
291 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
292 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
298 /* adds an item to the display window */
299 function oilsAddRptAggFilterItem(val) {
300 oilsAddSelectorItem(oilsRptAggFilterSelector, val);
303 /* removes a specific item from the display window */
304 function oilsDelAggFilterItem(val) {
305 oilsDelSelectorItem(oilsRptAggFilterSelector, val);
308 /* removes selected items from the display window */
309 function oilsDelSelectedAggFilterItems() {
310 var list = oilsDelSelectedItems(oilsRptAggFilterSelector);
312 /* remove the de-selected columns from the report output */
313 oilsRpt.def.having = grep( oilsRpt.def.having,
315 for( var j = 0; j < list.length; j++ ) {
319 /* if this columsn has a transform,
320 it will be an object { tform => column } */
321 if( typeof col != 'string' )
322 for( var c in col ) col = col[c];
324 /* if this transform requires params, the column
325 will be the first item in the param set array */
326 if( typeof col != 'string' ) col = col[0];
328 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
329 var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
330 if( param ) delete oilsRpt.params[param];
338 if(!oilsRpt.def.having) {
339 oilsRpt.def.having = [];
340 oilsReportBuilderReset();
343 for( var j = 0; j < list.length; j++ )
344 /* if there are no items left in the "select", "where", or "having" clauses
345 for the given relation, trim this relation from the "from" clause */
346 if( !grep(oilsRpt.def.select,
347 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
348 && !grep(oilsRpt.def.where,
349 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
350 && !grep(oilsRpt.def.having,
351 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
352 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
359 /* adds an item to the display window */
360 function oilsAddSelectorItem(sel, val, name) {
361 name = (name) ? name : oilsRptMakeLabel(val);
362 _debug("adding selector item "+name+' = ' +val);
363 for( var i = 0; i < sel.options.length; i++ ) {
364 var opt = sel.options[i];
365 if( opt.value == val ) return false;
367 insertSelectorVal( sel, -1, name, val );
372 /* removes a specific item from the display window */
373 function oilsDelSelectorItem(sel, val) {
374 _debug("deleting selector item "+val);
375 var opts = sel.options;
376 for( var i = 0; i < opts.length; i++ ) {
378 if( opt.value == val ) {
379 if( i == opts.length - 1 )
381 else opts[i] = opts[i+1];
387 /* removes selected items from the display window */
388 function oilsDelSelectedItems(sel) {
389 var list = getSelectedList(sel);
390 for( var i = 0; i < list.length; i++ )
391 oilsDelSelectorItem(sel, list[i]);
396 /* hides the different field editor tabs */
397 function oilsRptHideEditorDivs() {
398 hideMe(DOM.oils_rpt_tform_div);
399 hideMe(DOM.oils_rpt_filter_div);
400 hideMe(DOM.oils_rpt_agg_filter_div);
405 This draws the 3-tabbed window containing the transform,
406 filter, and aggregate filter picker window
408 function oilsRptDrawDataWindow(path) {
409 var col = oilsRptPathCol(path);
410 var cls = oilsRptPathClass(path);
411 var field = oilsRptFindField(oilsIDL[cls], col);
413 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
414 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
416 _debug("setting update data window for column "+col+' on class '+cls);
418 var div = DOM.oils_rpt_column_editor;
419 /* set a preliminary top position so the page won't bounce around */
420 div.setAttribute('style','top:'+oilsMouseX+'px');
422 /* unhide the div so we can determine the dimensions */
425 /* don't let them see the floating div until the position is fully determined */
426 div.style.visibility='hidden';
428 oilsRptDrawTransformWindow(path, col, cls, field);
429 oilsRptDrawFilterWindow(path, col, cls, field);
431 //oilsRptSetFilters(field.datatype);
433 //oilsRptDoFilterWidgets();
435 //DOM.oils_rpt_filter_tform_selector.onchange = oilsRptDoFilterWidgets;
437 buildFloatingDiv(div, 600);
439 /* now let them see it */
440 div.style.visibility='visible';
442 oilsRptSetDataWindowActions(div);
446 function oilsRptSetDataWindowActions(div) {
447 /* give the tab links behavior */
448 DOM.oils_rpt_tform_tab.onclick =
449 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_tform_div)};
450 DOM.oils_rpt_filter_tab.onclick =
451 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_filter_div)};
452 DOM.oils_rpt_agg_filter_tab.onclick =
453 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_agg_filter_div)};
455 DOM.oils_rpt_tform_tab.onclick();
456 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
460 function oilsRptDrawFilterWindow(path, col, cls, field) {
462 var fsel = $n(DOM.oils_rpt_filter_op_table,'selector');
463 for( var i = 0; i < fsel.options.length; i++ ){
464 var opt = fsel.options[i];
465 var dt = opt.getAttribute('datatype');
468 /* add a special case for boolean objects, since the only
469 operation that makes sense is "=" */
470 if( field.datatype == 'bool' ) {
472 if( opt.getAttribute('value') == '=' )
476 if( dt && dt != field.datatype )
483 DOM.oils_rpt_filter_submit.onclick = function() {
484 var tsel = $n(DOM.oils_rpt_filter_tform_table,'selector');
485 var tform = getSelectorVal(tsel);
486 var filter = getSelectorVal(fsel);
487 oilsAddRptFilterItem(path, tform, filter);
489 oilsRptShowFilters($n(DOM.oils_rpt_filter_tform_table,'selector'), field.datatype, false, true);
492 oilsRptCurrentFilterTform = new oilsRptTFormManager(DOM.oils_rpt_filter_tform_table);
493 oilsRptCurrentFilterTform.build(field.datatype, false, true);
494 oilsRptCurrentFilterOpManager = new oilsRptOpManager(DOM.oils_rpt_filter_op_table);
498 function oilsRptShowFilters( selector, dtype, show_agg, show_noagg ) {
499 for( var i = 0; i < selector.options.length; i++ ) {
500 var opt = selector.options[i];
501 var t = opt.getAttribute('datatype');
502 if( t && t != dtype ){
505 var ag = opt.getAttribute('aggregate');
508 else if( ag && ! show_agg )
510 else if( !ag && show_noagg )
518 /* draws the transform window */
519 function oilsRptDrawTransformWindow(path, col, cls, field) {
520 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
521 var dtype = field.datatype;
523 DOM.oils_rpt_tform_submit.onclick =
525 var sel = $n(DOM.oils_rpt_tform_table,'selector');
526 var tform = getSelectorVal(sel);
527 oilsAddRptDisplayItem(path, DOM.oils_rpt_tform_label_input.value, tform )
531 DOM.oils_rpt_tform_label_input.focus();
532 DOM.oils_rpt_tform_label_input.select();
535 oilsRptCurrentTform = new oilsRptTFormManager(DOM.oils_rpt_tform_table);
536 oilsRptCurrentTform.build(dtype, true, true);
539 _debug($n(DOM.oils_rpt_tform_table,'selector'));
541 oilsRptShowFilters($n(DOM.oils_rpt_tform_table,'selector'), dtype, true, true);
544 oilsRptHideTformFields();
545 oilsRptUnHideTformFields(dtype);
548 _debug("Building transform window for datatype "+dtype);
551 unHideMe($('oils_rpt_tform_'+dtype+'_div'));
552 $('oils_rpt_tform_all_raw').checked = true;
557 function oilsRptHideTformFields() {
558 var rows = DOM.oils_rpt_tform_tbody.childNodes;
559 for( var i = 0; i < rows.length; i++ )
560 if( rows[i] && rows[i].nodeType == 1 )
564 function oilsRptUnHideTformFields(dtype) {
565 var rows = DOM.oils_rpt_tform_tbody.childNodes;
566 for( var i = 0; i < rows.length; i++ ) {
568 if( row && row.nodeType == 1 &&
569 (row.getAttribute('datatype')=='all'
570 || row.getAttribute('datatype') == dtype)) {
577 function oilsRptGetTform(datatype) {
578 for( var i in oilsRptTransforms[datatype] )
579 if( $('oils_rpt_tform_'+datatype+'_'+oilsRptTransforms[datatype][i]).checked )
580 return oilsRptTransforms[datatype][i];
581 for( var i in oilsRptTransforms.all )
582 if( $('oils_rpt_tform_all_'+oilsRptTransforms.all[i]).checked )
583 return oilsRptTransforms.all[i];
590 function getRptTformParams(type, tform) {
596 DOM.oils_rpt_tform_string_substring_offset.value,
597 DOM.oils_rpt_tform_string_substring_length.value];
604 /* given a transform selector, this displays the appropriate
605 transforms for the given datatype.
606 if aggregate is true, is displays the aggregate transforms */
608 function oilsRptSetTransforms(sel, dtype, show_agg, show_noagg) {
609 for( var i = 0; i < sel.options.length; i++ ) {
610 var opt = sel.options[i];
611 var t = opt.getAttribute('datatype');
612 if( t && t != dtype ){
615 var ag = opt.getAttribute('aggregate');
618 else if( ag && ! show_agg )
620 else if( !ag && show_noagg )
630 /* displays the correct filter-transforms for the given datatype */
632 function oilsRptSetFilters(dtype) {
634 DOM.oils_rpt_filter_submit.onclick = function() {
635 var data = oilsRptDoFilterWidgets();
636 alert(js2JSON(data));
639 var sel = DOM.oils_rpt_filter_tform_selector;
640 for( var i = 0; i < sel.options.length; i++ ) {
641 var opt = sel.options[i];
642 _debug(opt.getAttribute('op'));
643 var t = opt.getAttribute('datatype');
644 if( t && t != dtype ) hideMe(opt);
650 /* hides all of the filter widgets */
651 function oilsRptHideFilterWidgets(node) {
653 node = DOM.oils_rpt_filter_tform_widget_td;
654 if( node.nodeType != 1 ) return;
655 if( node.getAttribute('widget') ) {
658 var cs = node.childNodes;
659 for( var i = 0; cs && i < cs.length; i++ )
660 oilsRptHideFilterWidgets(cs[i]);
664 /* what does this need to do? */
665 function oilsRptSetFilterOpActions() {
670 /* hides/unhides the appropriate widgets and returns the parameter
671 array appropriate for the selected widget */
672 function oilsRptDoFilterWidgets() {
673 filter = getSelectorVal(DOM.oils_rpt_filter_tform_selector);
674 oilsRptHideFilterWidgets();
681 /* generic transforms */
683 if(!op) op = 'equals';
687 if(!op) op = 'ilike';
699 if(!op) op = 'not in';
701 if(!op) op = 'between';
703 if(!op) op = 'not between';
704 unHideMe(DOM.oils_rpt_filter_tform_input);
705 params = [DOM.oils_rpt_filter_tform_input.value];
708 /* timestamp transforms */
710 if(!op) op = 'between';
711 case 'date_not_between':
712 if(!op) op = 'not between';
715 unHideMe(DOM.oils_rpt_filter_tform_date_1);
716 unHideMe(DOM.oils_rpt_filter_tform_date_2);
717 unHideMe(DOM.oils_rpt_filter_tform_date_hint);
718 DOM.oils_rpt_filter_tform_date_1.value = mkYearMonDay();
719 DOM.oils_rpt_filter_tform_date_2.value = mkYearMonDay();
721 DOM.oils_rpt_filter_tform_date_1.value,
722 DOM.oils_rpt_filter_tform_date_2.value
728 if(!tform) tform = 'dow';
729 case 'dow_not_between':
730 if(!op) op = 'not between';
731 if(!tform) tform = 'dow';
736 if(!tform) tform = 'dom';
737 case 'dom_not_between':
738 if(!op) op = 'not between';
739 if(!tform) tform = 'dom';
742 case 'month_between':
744 if(!tform) tform = 'moy';
745 case 'month_not_between':
746 if(!op) op = 'not between';
747 if(!tform) tform = 'moy';
750 case 'quarter_between':
752 if(!tform) tform = 'qoy';
753 case 'quarter_not_between':
754 if(!op) op = 'not between';
755 if(!tform) tform = 'qoy';
759 if(!op) op = 'between';
760 if(!tform) tform = 'year_trunc';
761 case 'year_not_between':
762 if(!op) op = 'not between';
763 if(!tform) tform = 'year_trunc';
767 if(!op) op = 'between';
768 if(!tform) tform = 'age';
769 case 'age_not_between':
770 if(!op) op = 'not between';
771 if(!tform) tform = 'age';
774 /* string transforms */
776 if(!tform) tform = 'substring';
781 if(!tform) tform = 'dow';
785 if(!tform) tform = 'dow';
787 /* numeric transforms */
790 if(!tform) tform = 'dow';
794 if(!tform) tform = 'dow';
797 return { op : op, params : params, tform : tform };