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)};
9 //oilsRptBuildCalendars();
12 hideMe(DOM.oils_rpt_tree_loading);
13 unHideMe(DOM.oils_rpt_table);
18 function oilsReportBuilderReset() {
19 var n = (oilsRpt) ? oilsRpt.name : "";
20 oilsRpt = new oilsReport();
22 oilsRptDisplaySelector = DOM.oils_rpt_display_selector;
23 oilsRptFilterSelector = DOM.oils_rpt_filter_selector;
24 oilsRptAggFilterSelector= DOM.oils_rpt_agg_filter_selector;
25 removeChildren(oilsRptDisplaySelector);
26 removeChildren(oilsRptFilterSelector);
27 removeChildren(oilsRptAggFilterSelector);
34 function oilsRptBuildCalendars() {
36 inputField : "oils_rpt_filter_tform_timestamp_input", // id of the input field
37 ifFormat : "%Y-%m-%d", // format of the input field
38 button : "oils_rpt_filter_tform_timestamp_cal", // trigger for the calendar (button ID)
39 align : "Tl", // alignment (defaults to "Bl")
43 inputField : "oils_rpt_filter_tform_timestamp_input_2", // id of the input field
44 ifFormat : "%Y-%m-%d", // format of the input field
45 button : "oils_rpt_filter_tform_timestamp_cal2", // trigger for the calendar (button ID)
46 align : "Tl", // alignment (defaults to "Bl")
53 /* adds an item to the display window */
54 function oilsAddRptDisplayItem(path, name, tform, params) {
55 if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) )
58 /* add the selected columns to the report output */
59 name = (name) ? name : oilsRptPathCol(path);
60 if( !tform ) tform = 'Bare';
62 /* add this item to the select blob */
64 relation: oilsRptPathRel(path),
66 column: { transform: tform, colname: oilsRptPathCol(path) }
69 if( params ) sel.column.params = params;
70 oilsRpt.def.select.push(sel);
72 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
76 /* takes a column path and builds a from-clause object for the path */
77 function oilsRptBuildFromClause(path) {
79 /* the path is the full path (relation) from the source
80 object to the column in question (e.g. au-home_ou-aou-name)*/
81 var parts = path.split(/-/);
83 /* the final from clause */
86 /* reference to the current position in the from clause */
91 /* walk the path, fleshing the from clause as we go */
92 for( var i = 0; i < parts.length; i += 2 ) {
94 var cls = parts[i]; /* class name (id) */
95 var col = parts[i+1]; /* column name */
97 /* a "node" is a class description from the IDL, it
98 contains relevant info, plus a list of "fields",
100 var node = oilsIDL[cls];
101 var pkey = oilsRptFindField(node, node.pkey);
103 /* a "field" is a parsed version of a column from the IDL,
104 contains datatype, column name, etc. */
105 var field = oilsRptFindField(node, col);
107 /* re-construct the path as we go so
108 we know what all we've seen thus far */
109 newpath = (newpath) ? newpath + '-'+ cls : cls;
111 /* extract relevant info */
112 tobj.table = node.table;
113 tobj.alias = newpath;
114 _debug('field type is ' + field.type);
115 if( i == (parts.length - 2) ) break;
117 /* we still have columns left in the path, keep adding join's */
119 if(field.reltype != 'has_a')
120 col = pkey.name + '-' + col;
127 if( field.type == 'link' )
128 tobj.key = field.key;
130 newpath = newpath + '-'+ path_col;
133 _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
138 /* removes a specific item from the display window */
139 function oilsDelDisplayItem(val) {
140 oilsDelSelectorItem(oilsRptDisplaySelector, val);
143 /* removes selected items from the display window */
144 function oilsDelSelectedDisplayItems() {
145 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
147 /* remove the de-selected columns from the report output */
148 oilsRpt.def.select = grep( oilsRpt.def.select,
150 for( var j = 0; j < list.length; j++ ) {
154 /* if this columsn has a transform,
155 it will be an object { tform => column } */
156 if( typeof col != 'string' )
157 for( var c in col ) col = col[c];
159 /* if this transform requires params, the column
160 will be the first item in the param set array */
161 if( typeof col != 'string' ) col = col[0];
163 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
164 var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
165 if( param ) delete oilsRpt.params[param];
173 if(!oilsRpt.def.select) {
174 oilsRpt.def.select = [];
175 oilsReportBuilderReset();
178 for( var j = 0; j < list.length; j++ )
179 /* if there are no items left in the "select", "where", or "having" clauses
180 for the given relation, trim this relation from the "from" clause */
181 if( !grep(oilsRpt.def.select,
182 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
183 && !grep(oilsRpt.def.where,
184 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
185 && !grep(oilsRpt.def.having,
186 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
187 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
193 /* for each item in the path list, remove the associated data
194 from the "from" clause */
196 function oilsRptPruneFromClause(relation, node) {
197 _debug("removing relation from 'from' clause " + relation);
198 if(!node) node = oilsRpt.def.from.join;
199 for( var i in node ) {
200 if( node[i].alias == relation ) {
202 /* if we have subtrees, don't delete our tree node */
210 if( oilsRptPruneFromClause(relation, node[i].join ) ) {
211 if(oilsRptObjectKeys(node[i].join).length == 0) {
213 /* if there are no items in the select clause with a relation matching
214 this nodes alias, we can safely remove this node from the tree */
215 if(!grep(oilsRpt.def.select,function(r){return (r.relation==node[i].alias)}))
226 /* adds an item to the display window */
227 function oilsAddRptFilterItem(val) {
228 oilsAddSelectorItem(oilsRptFilterSelector, val);
231 /* removes a specific item from the display window */
232 function oilsDelFilterItem(val) {
233 oilsDelSelectorItem(oilsRptFilterSelector, val);
236 /* removes selected items from the display window */
237 function oilsDelSelectedFilterItems() {
238 var list = oilsDelSelectedItems(oilsRptFilterSelector);
240 /* remove the de-selected columns from the report output */
241 oilsRpt.def.where = grep( oilsRpt.def.where,
243 for( var j = 0; j < list.length; j++ ) {
247 /* if this columsn has a transform,
248 it will be an object { tform => column } */
249 if( typeof col != 'string' )
250 for( var c in col ) col = col[c];
252 /* if this transform requires params, the column
253 will be the first item in the param set array */
254 if( typeof col != 'string' ) col = col[0];
256 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
257 var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
258 if( param ) delete oilsRpt.params[param];
266 if(!oilsRpt.def.where) {
267 oilsRpt.def.where = [];
268 oilsReportBuilderReset();
271 for( var j = 0; j < list.length; j++ )
272 /* if there are no items left in the "select", "where", or "having" clauses
273 for the given relation, trim this relation from the "from" clause */
274 if( !grep(oilsRpt.def.select,
275 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
276 && !grep(oilsRpt.def.where,
277 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
278 && !grep(oilsRpt.def.having,
279 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
280 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
286 /* adds an item to the display window */
287 function oilsAddRptAggFilterItem(val) {
288 oilsAddSelectorItem(oilsRptAggFilterSelector, val);
291 /* removes a specific item from the display window */
292 function oilsDelAggFilterItem(val) {
293 oilsDelSelectorItem(oilsRptAggFilterSelector, val);
296 /* removes selected items from the display window */
297 function oilsDelSelectedAggFilterItems() {
298 var list = oilsDelSelectedItems(oilsRptAggFilterSelector);
300 /* remove the de-selected columns from the report output */
301 oilsRpt.def.having = grep( oilsRpt.def.having,
303 for( var j = 0; j < list.length; j++ ) {
307 /* if this columsn has a transform,
308 it will be an object { tform => column } */
309 if( typeof col != 'string' )
310 for( var c in col ) col = col[c];
312 /* if this transform requires params, the column
313 will be the first item in the param set array */
314 if( typeof col != 'string' ) col = col[0];
316 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
317 var param = (i.alias) ? i.alias.match(/::PARAM\d*/) : null;
318 if( param ) delete oilsRpt.params[param];
326 if(!oilsRpt.def.having) {
327 oilsRpt.def.having = [];
328 oilsReportBuilderReset();
331 for( var j = 0; j < list.length; j++ )
332 /* if there are no items left in the "select", "where", or "having" clauses
333 for the given relation, trim this relation from the "from" clause */
334 if( !grep(oilsRpt.def.select,
335 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
336 && !grep(oilsRpt.def.where,
337 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
338 && !grep(oilsRpt.def.having,
339 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
340 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
347 /* adds an item to the display window */
348 function oilsAddSelectorItem(sel, val, name) {
349 name = (name) ? name : oilsRptMakeLabel(val);
350 _debug("adding selector item "+name+' = ' +val);
351 for( var i = 0; i < sel.options.length; i++ ) {
352 var opt = sel.options[i];
353 if( opt.value == val ) return false;
355 insertSelectorVal( sel, -1, name, val );
360 /* removes a specific item from the display window */
361 function oilsDelSelectorItem(sel, val) {
362 _debug("deleting selector item "+val);
363 var opts = sel.options;
364 for( var i = 0; i < opts.length; i++ ) {
366 if( opt.value == val ) {
367 if( i == opts.length - 1 )
369 else opts[i] = opts[i+1];
375 /* removes selected items from the display window */
376 function oilsDelSelectedItems(sel) {
377 var list = getSelectedList(sel);
378 for( var i = 0; i < list.length; i++ )
379 oilsDelSelectorItem(sel, list[i]);
384 /* hides the different field editor tabs */
385 function oilsRptHideEditorDivs() {
386 hideMe(DOM.oils_rpt_tform_div);
387 hideMe(DOM.oils_rpt_filter_div);
388 hideMe(DOM.oils_rpt_agg_filter_div);
393 This draws the 3-tabbed window containing the transform,
394 filter, and aggregate filter picker window
396 function oilsRptDrawDataWindow(path) {
397 var col = oilsRptPathCol(path);
398 var cls = oilsRptPathClass(path);
399 var field = oilsRptFindField(oilsIDL[cls], col);
401 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
402 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
404 _debug("setting update data window for column "+col+' on class '+cls);
406 var div = DOM.oils_rpt_column_editor;
407 /* set a preliminary top position so the page won't bounce around */
408 div.setAttribute('style','top:'+oilsMouseX+'px');
410 /* unhide the div so we can determine the dimensions */
413 /* don't let them see the floating div until the position is fully determined */
414 div.style.visibility='hidden';
416 oilsRptDrawTransformWindow(path, col, cls, field);
417 oilsRptDrawFilterWindow(path, col, cls, field);
419 //oilsRptSetFilters(field.datatype);
421 //oilsRptDoFilterWidgets();
423 //DOM.oils_rpt_filter_tform_selector.onchange = oilsRptDoFilterWidgets;
425 buildFloatingDiv(div, 600);
427 /* now let them see it */
428 div.style.visibility='visible';
430 oilsRptSetDataWindowActions(div);
434 function oilsRptSetDataWindowActions(div) {
435 /* give the tab links behavior */
436 DOM.oils_rpt_tform_tab.onclick =
437 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_tform_div)};
438 DOM.oils_rpt_filter_tab.onclick =
439 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_filter_div)};
440 DOM.oils_rpt_agg_filter_tab.onclick =
441 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_agg_filter_div)};
443 DOM.oils_rpt_tform_tab.onclick();
444 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
448 function oilsRptDrawFilterWindow(path, col, cls, field) {
449 oilsRptCurrentFilterTform = new oilsRptTFormManager(DOM.oils_rpt_filter_tform_table);
450 oilsRptCurrentFilterTform.build(field.datatype, false, true);
451 oilsRptCurrentFilterOpManager = new oilsRptOpManager(DOM.oils_rpt_filter_op_table);
455 /* draws the transform window */
456 function oilsRptDrawTransformWindow(path, col, cls, field) {
457 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
458 var dtype = field.datatype;
460 DOM.oils_rpt_tform_submit.onclick =
463 var tform = oilsRptGetTform(dtype);
464 _debug('found tform: ' + js2JSON(tform));
465 var params = getRptTformParams(dtype, tform);
466 _debug('found tform params: ' + js2JSON(params));
467 tform = (tform == 'raw') ? null : tform;
470 var tform = oilsRptCurrentTform.getCurrentTForm();
471 oilsAddRptDisplayItem(path, DOM.oils_rpt_tform_label_input.value, tform.value, tform.params )
475 DOM.oils_rpt_tform_label_input.focus();
476 DOM.oils_rpt_tform_label_input.select();
478 oilsRptCurrentTform = new oilsRptTFormManager(DOM.oils_rpt_tform_table);
479 oilsRptCurrentTform.build(dtype, true, true);
482 oilsRptHideTformFields();
483 oilsRptUnHideTformFields(dtype);
486 _debug("Building transiform window for datatype "+dtype);
489 unHideMe($('oils_rpt_tform_'+dtype+'_div'));
490 $('oils_rpt_tform_all_raw').checked = true;
495 function oilsRptHideTformFields() {
496 var rows = DOM.oils_rpt_tform_tbody.childNodes;
497 for( var i = 0; i < rows.length; i++ )
498 if( rows[i] && rows[i].nodeType == 1 )
502 function oilsRptUnHideTformFields(dtype) {
503 var rows = DOM.oils_rpt_tform_tbody.childNodes;
504 for( var i = 0; i < rows.length; i++ ) {
506 if( row && row.nodeType == 1 &&
507 (row.getAttribute('datatype')=='all'
508 || row.getAttribute('datatype') == dtype)) {
515 function oilsRptGetTform(datatype) {
516 for( var i in oilsRptTransforms[datatype] )
517 if( $('oils_rpt_tform_'+datatype+'_'+oilsRptTransforms[datatype][i]).checked )
518 return oilsRptTransforms[datatype][i];
519 for( var i in oilsRptTransforms.all )
520 if( $('oils_rpt_tform_all_'+oilsRptTransforms.all[i]).checked )
521 return oilsRptTransforms.all[i];
528 function getRptTformParams(type, tform) {
534 DOM.oils_rpt_tform_string_substring_offset.value,
535 DOM.oils_rpt_tform_string_substring_length.value];
542 /* given a transform selector, this displays the appropriate
543 transforms for the given datatype.
544 if aggregate is true, is displays the aggregate transforms */
546 function oilsRptSetTransforms(sel, dtype, show_agg, show_noagg) {
547 for( var i = 0; i < sel.options.length; i++ ) {
548 var opt = sel.options[i];
549 var t = opt.getAttribute('datatype');
550 if( t && t != dtype ){
553 var ag = opt.getAttribute('aggregate');
556 else if( ag && ! show_agg )
558 else if( !ag && show_noagg )
568 /* displays the correct filter-transforms for the given datatype */
570 function oilsRptSetFilters(dtype) {
572 DOM.oils_rpt_filter_submit.onclick = function() {
573 var data = oilsRptDoFilterWidgets();
574 alert(js2JSON(data));
577 var sel = DOM.oils_rpt_filter_tform_selector;
578 for( var i = 0; i < sel.options.length; i++ ) {
579 var opt = sel.options[i];
580 _debug(opt.getAttribute('op'));
581 var t = opt.getAttribute('datatype');
582 if( t && t != dtype ) hideMe(opt);
588 /* hides all of the filter widgets */
589 function oilsRptHideFilterWidgets(node) {
591 node = DOM.oils_rpt_filter_tform_widget_td;
592 if( node.nodeType != 1 ) return;
593 if( node.getAttribute('widget') ) {
596 var cs = node.childNodes;
597 for( var i = 0; cs && i < cs.length; i++ )
598 oilsRptHideFilterWidgets(cs[i]);
602 /* what does this need to do? */
603 function oilsRptSetFilterOpActions() {
608 /* hides/unhides the appropriate widgets and returns the parameter
609 array appropriate for the selected widget */
610 function oilsRptDoFilterWidgets() {
611 filter = getSelectorVal(DOM.oils_rpt_filter_tform_selector);
612 oilsRptHideFilterWidgets();
619 /* generic transforms */
621 if(!op) op = 'equals';
625 if(!op) op = 'ilike';
637 if(!op) op = 'not in';
639 if(!op) op = 'between';
641 if(!op) op = 'not between';
642 unHideMe(DOM.oils_rpt_filter_tform_input);
643 params = [DOM.oils_rpt_filter_tform_input.value];
646 /* timestamp transforms */
648 if(!op) op = 'between';
649 case 'date_not_between':
650 if(!op) op = 'not between';
653 unHideMe(DOM.oils_rpt_filter_tform_date_1);
654 unHideMe(DOM.oils_rpt_filter_tform_date_2);
655 unHideMe(DOM.oils_rpt_filter_tform_date_hint);
656 DOM.oils_rpt_filter_tform_date_1.value = mkYearMonDay();
657 DOM.oils_rpt_filter_tform_date_2.value = mkYearMonDay();
659 DOM.oils_rpt_filter_tform_date_1.value,
660 DOM.oils_rpt_filter_tform_date_2.value
666 if(!tform) tform = 'dow';
667 case 'dow_not_between':
668 if(!op) op = 'not between';
669 if(!tform) tform = 'dow';
674 if(!tform) tform = 'dom';
675 case 'dom_not_between':
676 if(!op) op = 'not between';
677 if(!tform) tform = 'dom';
680 case 'month_between':
682 if(!tform) tform = 'moy';
683 case 'month_not_between':
684 if(!op) op = 'not between';
685 if(!tform) tform = 'moy';
688 case 'quarter_between':
690 if(!tform) tform = 'qoy';
691 case 'quarter_not_between':
692 if(!op) op = 'not between';
693 if(!tform) tform = 'qoy';
697 if(!op) op = 'between';
698 if(!tform) tform = 'year_trunc';
699 case 'year_not_between':
700 if(!op) op = 'not between';
701 if(!tform) tform = 'year_trunc';
705 if(!op) op = 'between';
706 if(!tform) tform = 'age';
707 case 'age_not_between':
708 if(!op) op = 'not between';
709 if(!tform) tform = 'age';
712 /* string transforms */
714 if(!tform) tform = 'substring';
719 if(!tform) tform = 'dow';
723 if(!tform) tform = 'dow';
725 /* numeric transforms */
728 if(!tform) tform = 'dow';
732 if(!tform) tform = 'dow';
735 return { op : op, params : params, tform : tform };