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);
32 function oilsReportBuilderSave() {
35 tmpl.name(DOM.oils_rpt_builder_new_name.value);
36 tmpl.description(DOM.oils_rpt_builder_new_desc.value);
37 tmpl.owner(USER.id());
38 tmpl.folder(new CGI().param('folder'));
39 tmpl.data(js2JSON(oilsRpt.def));
41 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();
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)));
183 /* removes a specific item from the display window */
184 function oilsDelDisplayItem(val) {
185 oilsDelSelectorItem(oilsRptDisplaySelector, val);
188 /* removes selected items from the display window */
189 function oilsDelSelectedDisplayItems() {
190 var list = oilsDelSelectedItems(oilsRptDisplaySelector);
192 _debug('deleting list: ' + list);
194 /* remove the de-selected columns from the report output */
195 oilsRpt.def.select = grep( oilsRpt.def.select,
197 for( var j = 0; j < list.length; j++ ) {
198 var d = list[j]; /* path */
201 _debug('in delete, looking at list = '+d+' : col = ' +
202 col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
204 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
212 if(!oilsRpt.def.select) oilsRpt.def.select = [];
214 for( var j = 0; j < list.length; j++ ) {
215 /* if there are no items left in the "select", "where", or "having" clauses
216 for the given relation, trim this relation from the "from" clause */
217 debug('seeing if we can prune from clause with relation = ' + hex_md5(oilsRptPathRel(list[j])));
218 if( !grep(oilsRpt.def.select,
219 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
220 && !grep(oilsRpt.def.where,
221 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
222 && !grep(oilsRpt.def.having,
223 function(i){ return (i.relation == hex_md5(oilsRptPathRel(list[j]))); })
225 _debug('pruning from clause');
226 oilsRptPruneFromClause(oilsRptPathRel(list[j]));
234 /* for each item in the path list, remove the associated data
235 from the "from" clause */
237 function oilsRptPruneFromClause(relation, node) {
238 _debug("removing relation from 'from' clause " + relation);
239 if(!node) node = oilsRpt.def.from.join;
241 for( var i in node ) {
242 _debug("looking at node "+node[i].path);
243 // first, descend into the tree, and prune leaves first
245 oilsRptPruneFromClause(relation, node[i].join);
246 if(oilsRptObjectKeys(node[i].join).length == 0) delete node[i].join;
250 _debug(js2JSON(node));
252 // if we're at an unused empty leaf, remove it
255 var key = oilsRptObjectKeys(node)[0];
256 _debug("pruning from clause with "+node[key].alias);
258 if( !grep(oilsRpt.def.select,
259 function(n){ _debug(n.relation); return (n.relation == node[key].alias)})
260 && !grep(oilsRpt.def.where,
261 function(n){ _debug(n.relation); return (n.relation == node[key].alias)})
262 && !grep(oilsRpt.def.having,
263 function(n){ _debug(n.relation); return (n.relation == node[key].alias)})
273 function oilsRptMkFilterTags(path, tform, filter) {
274 var name = oilsRptMakeLabel(path);
275 if(tform) name += ' ('+tform+')';
276 name += ' "' + filter + '"';
277 var epath = path + ':'+filter+':';
278 if(tform) epath += tform;
280 return [ name, epath ];
284 function oilsAddRptFilterItem(path, tform, filter) {
285 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
287 var name = oilsRptMkFilterTags(path, tform, filter);
291 if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
295 relation: hex_md5(oilsRptPathRel(path)),
297 column: { transform: tform, colname: oilsRptPathCol(path) },
300 if( filter == 'is' || filter == 'is not' )
301 where.condition[filter] = null;
302 else where.condition[filter] = oilsRptNextParam();
305 case 'substring' : where.column.params = oilsRptNextParam();
308 oilsRpt.def.where.push(where);
309 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
314 function oilsAddRptHavingItem(path, tform, filter) {
315 _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
317 var name = oilsRptMkFilterTags(path, tform, filter);
321 if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
325 relation: hex_md5(oilsRptPathRel(path)),
327 column: { transform: tform, colname: oilsRptPathCol(path) },
330 if( filter == 'is' || filter == 'is not' )
331 having.condition[filter] = null;
332 else having.condition[filter] = oilsRptNextParam();
335 case 'substring' : having.column.params = oilsRptNextParam();
338 oilsRpt.def.having.push(having);
339 mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
345 /* removes selected items from the display window */
346 function oilsDelSelectedFilterItems() {
348 /* the values in this list are formed: <path>:<operation>:<transform> */
349 var list = oilsDelSelectedItems(oilsRptFilterSelector);
353 for( var i = 0; i < list.length; i++ ) {
356 path: item.replace(/:.*/,''),
357 operation: item.replace(/.*:(.*):.*/,'$1'),
358 tform: item.replace(/.*?:.*?:(.*)/,'$1')
363 /* XXX refactor the below to take operation and transform into account
364 since the same path can be used multiple times as long as a different
365 filter and/or transform is used */
367 /* remove the de-selected columns from the report output */
368 oilsRpt.def.where = grep( oilsRpt.def.where,
370 for( var j = 0; j < flist.length; j++ ) {
373 var frel = oilsRptPathRel(fil.path);
374 var fcol = oilsRptPathCol(fil.path);
376 var op = oilsRptObjectKeys(i.condition)[0];
378 if( frel == i.relation &&
379 fcol == col.colname &&
380 fil.operation == op &&
381 fil.tform == col.transform ) {
382 /* we have found a where clause with the same
383 relation, column, operation and transform */
385 /* we aren't setting params on template build.. */
386 //var param = (i.column.params) ? i.columns.params.match(/::P\d*/) : null;
387 //if( param ) delete oilsRpt.params[param];
388 //param = (i.condition[op]) ? i.condition[op].match(/::P\d*/) : null;
389 //if( param ) delete oilsRpt.params[param];
398 if(!oilsRpt.def.where)
399 oilsRpt.def.where = [];
402 for( var j = 0; j < flist.length; j++ ) {
403 var path = flist[j].path;
404 var rel = oilsRptPathRel(path);
405 /* if there are no items left in the "select", "where", or "having" clauses
406 for the given relation, trim this relation from the "from" clause */
408 var func = function(i){ return (i.relation == rel); };
410 if( !grep(oilsRpt.def.select, func) &&
411 !grep(oilsRpt.def.where, func) &&
412 !grep(oilsRpt.def.having, func) ) {
414 _debug("pruning item with path "+ path + ' and relation '+ rel);
416 oilsRptPruneFromClause(oilsRptPathRel(path));
423 /* adds an item to the display window */
424 function oilsAddRptAggFilterItem(val) {
425 oilsAddSelectorItem(oilsRptAggFilterSelector, val);
428 /* removes a specific item from the display window */
429 function oilsDelAggFilterItem(val) {
430 oilsDelSelectorItem(oilsRptAggFilterSelector, val);
433 /* removes selected items from the display window */
434 function oilsDelSelectedAggFilterItems() {
435 var list = oilsDelSelectedItems(oilsRptAggFilterSelector);
437 /* remove the de-selected columns from the report output */
438 oilsRpt.def.having = grep( oilsRpt.def.having,
440 for( var j = 0; j < list.length; j++ ) {
444 /* if this columsn has a transform,
445 it will be an object { tform => column } */
446 if( typeof col != 'string' )
447 for( var c in col ) col = col[c];
449 /* if this transform requires params, the column
450 will be the first item in the param set array */
451 if( typeof col != 'string' ) col = col[0];
453 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
454 var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
455 if( param ) delete oilsRpt.params[param];
463 if(!oilsRpt.def.having) {
464 oilsRpt.def.having = [];
465 oilsReportBuilderReset();
468 for( var j = 0; j < list.length; j++ )
469 /* if there are no items left in the "select", "where", or "having" clauses
470 for the given relation, trim this relation from the "from" clause */
471 if( !grep(oilsRpt.def.select,
472 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
473 && !grep(oilsRpt.def.where,
474 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
475 && !grep(oilsRpt.def.having,
476 function(i){ return (i.relation == oilsRptPathRel(list[j])); })
477 ) oilsRptPruneFromClause(oilsRptPathRel(list[j]));
484 /* adds an item to the display window */
485 function oilsAddSelectorItem(sel, val, name) {
486 name = (name) ? name : oilsRptMakeLabel(val);
487 _debug("adding selector item "+name+' = ' +val);
488 for( var i = 0; i < sel.options.length; i++ ) {
489 var opt = sel.options[i];
490 if( opt.value == val ) return false;
492 insertSelectorVal( sel, -1, name, val );
497 /* removes a specific item from the display window */
498 function oilsDelSelectorItem(sel, val) {
499 _debug("deleting selector item "+val);
500 var opts = sel.options;
501 for( var i = 0; i < opts.length; i++ ) {
503 if( opt.value == val ) {
504 if( i == opts.length - 1 )
506 else opts[i] = opts[i+1];
512 /* removes selected items from the display window */
513 function oilsDelSelectedItems(sel) {
514 var list = getSelectedList(sel);
515 for( var i = 0; i < list.length; i++ )
516 oilsDelSelectorItem(sel, list[i]);
521 /* hides the different field editor tabs */
522 function oilsRptHideEditorDivs() {
523 hideMe(DOM.oils_rpt_tform_div);
524 hideMe(DOM.oils_rpt_filter_div);
525 hideMe(DOM.oils_rpt_agg_filter_div);
530 This draws the 3-tabbed window containing the transform,
531 filter, and aggregate filter picker window
533 function oilsRptDrawDataWindow(path) {
534 var col = oilsRptPathCol(path);
535 var cls = oilsRptPathClass(path);
536 var field = oilsRptFindField(oilsIDL[cls], col);
538 appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
539 appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
541 _debug("setting update data window for column "+col+' on class '+cls);
543 var div = DOM.oils_rpt_column_editor;
544 /* set a preliminary top position so the page won't bounce around */
545 div.setAttribute('style','top:'+oilsMouseX+'px');
547 /* unhide the div so we can determine the dimensions */
550 /* don't let them see the floating div until the position is fully determined */
551 div.style.visibility='hidden';
553 oilsRptDrawTransformWindow(path, col, cls, field);
554 oilsRptDrawFilterWindow(path, col, cls, field);
555 oilsRptDrawHavingWindow(path, col, cls, field);
557 //oilsRptSetFilters(field.datatype);
559 //oilsRptDoFilterWidgets();
561 //DOM.oils_rpt_filter_tform_selector.onchange = oilsRptDoFilterWidgets;
563 buildFloatingDiv(div, 600);
565 /* now let them see it */
566 div.style.visibility='visible';
568 oilsRptSetDataWindowActions(div);
572 function oilsRptSetDataWindowActions(div) {
573 /* give the tab links behavior */
574 DOM.oils_rpt_tform_tab.onclick =
575 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_tform_div)};
576 DOM.oils_rpt_filter_tab.onclick =
577 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_filter_div)};
578 DOM.oils_rpt_agg_filter_tab.onclick =
579 function(){oilsRptHideEditorDivs();unHideMe(DOM.oils_rpt_agg_filter_div)};
581 DOM.oils_rpt_tform_tab.onclick();
582 DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
586 function oilsRptDrawFilterWindow(path, col, cls, field) {
588 var tformPicker = new oilsRptTformPicker( {
589 node : DOM.oils_rpt_filter_tform_table,
590 datatype : field.datatype,
595 var filterPicker = new oilsRptFilterPicker({
596 node : DOM.oils_rpt_filter_op_table,
597 datatype : field.datatype
601 DOM.oils_rpt_filter_submit.onclick = function() {
602 oilsAddRptFilterItem(
603 path, tformPicker.getSelected(), filterPicker.getSelected());
608 function oilsRptDrawHavingWindow(path, col, cls, field) {
609 var tformPicker = new oilsRptTformPicker( {
610 node : DOM.oils_rpt_agg_filter_tform_table,
611 datatype : field.datatype,
616 var filterPicker = new oilsRptFilterPicker({
617 node : DOM.oils_rpt_agg_filter_op_table,
618 datatype : field.datatype
622 DOM.oils_rpt_agg_filter_submit.onclick = function() {
623 oilsAddRptHavingItem(
624 path, tformPicker.getSelected(), filterPicker.getSelected());
628 /* draws the transform window */
629 function oilsRptDrawTransformWindow(path, col, cls, field) {
630 DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
631 var dtype = field.datatype;
633 var tformPicker = new oilsRptTformPicker( {
634 node : DOM.oils_rpt_tform_table,
635 datatype : field.datatype,
636 non_aggregate : true,
641 DOM.oils_rpt_tform_submit.onclick =
643 oilsAddRptDisplayItem(path,
644 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
648 DOM.oils_rpt_tform_label_input.focus();
649 DOM.oils_rpt_tform_label_input.select();
651 _debug("Building transform window for datatype "+dtype);