Merge branch 'feature/widgets' into feature/multi_choice

pull/6827/head
Philipp Tessenow 14 years ago
commit 95773340d8
  1. BIN
      assets/images/arrow_B_down.gif
  2. BIN
      assets/images/arrow_B_left.gif
  3. BIN
      assets/images/arrow_B_right.gif
  4. BIN
      assets/images/arrow_B_up.gif
  5. BIN
      assets/images/arrow_D_down.gif
  6. BIN
      assets/images/arrow_D_left.gif
  7. BIN
      assets/images/arrow_D_right.gif
  8. BIN
      assets/images/arrow_D_up.gif
  9. BIN
      assets/images/button_hover.png
  10. BIN
      assets/images/button_inactive.png
  11. BIN
      assets/images/button_normal.png
  12. BIN
      assets/images/group_by_arrow_both.png
  13. BIN
      assets/images/group_by_arrow_both_hover_left.png
  14. BIN
      assets/images/group_by_arrow_both_hover_right.png
  15. BIN
      assets/images/group_by_arrow_both_remove.png
  16. BIN
      assets/images/group_by_arrow_left.png
  17. BIN
      assets/images/group_by_arrow_left_hover.png
  18. BIN
      assets/images/group_by_arrow_left_remove.png
  19. BIN
      assets/images/group_by_arrow_right.png
  20. BIN
      assets/images/group_by_arrow_right_hover.png
  21. 53
      assets/javascripts/reporting.js
  22. 28
      assets/javascripts/reporting/controls.js
  23. 4
      assets/javascripts/reporting/filters.js
  24. 195
      assets/javascripts/reporting/group_bys.js
  25. 57
      assets/javascripts/reporting/restore_query.js
  26. 151
      assets/javascripts/select_list_move_optgroup.js
  27. 100
      assets/stylesheets/reporting.css
  28. 4
      lib/report.rb
  29. 132
      lib/widget/group_bys.rb
  30. 114
      lib/widget/old_group_bys.rb

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -28,7 +28,7 @@ window.Reporting = {
} }
if ($("flash_" + type) !== null) { if ($("flash_" + type) !== null) {
$("flash_" + type).remove(); $("flash_" + type).remove();
}; }
var flash = document.createElement('div'); var flash = document.createElement('div');
flash.setAttribute('id', 'flash_' + type); flash.setAttribute('id', 'flash_' + type);
flash.setAttribute('onclick', '$(this).remove();'); flash.setAttribute('onclick', '$(this).remove();');
@ -62,54 +62,3 @@ Reporting.require("filters");
Reporting.require("group_bys"); Reporting.require("group_bys");
Reporting.require("restore_query"); Reporting.require("restore_query");
Reporting.require("controls"); Reporting.require("controls");
//
// function hide_category(tr_field) {
// var label = $(tr_field.getAttribute("data-label"));
// if (label !== null) {
// label.hide();
// }
// }
//
// function restore_select_values(select, values) {
// var i, j;
// if (values.length > 1) {
// make_select_accept_multiple_values(select);
// } else {
// make_select_accept_single_value(select);
// }
// for (i = 0; i < values.length; i += 1) {
// for (j = 0; j < select.options.length; j += 1) {
// if (select.options[j].value === values[i].toString()) {
// try {
// select.options[j].selected = true;
// break;
// } catch(e) {
// window.setTimeout('$("' + select.id + '").childElements()[' + j + '].selected = true;', 1);
// }
// }
// }
// }
// }
//
// function defineElementGetter() {
// if (document.getElementsByClassName === undefined) {
// document.getElementsByClassName = function (className)
// {
// var hasClassName, allElements, results, element, elementClass, i;
// hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
// allElements = document.getElementsByTagName("*");
// results = [];
// for (i = 0; (element = allElements[i]) !== null; i += 1) {
// elementClass = element.className;
// if (elementClass && elementClass.indexOf(className) !== -1 && hasClassName.test(elementClass)) {
// results.push(element);
// }
// }
// return results;
// };
// }
// }
//
// // defineElementGetter();

@ -70,22 +70,36 @@ Reporting.Controls = {
failureCallback = Reporting.Controls.default_failure_callback; failureCallback = Reporting.Controls.default_failure_callback;
} }
Reporting.clearFlash(); Reporting.clearFlash();
selectAllOptions('group_by_rows'); new Ajax.Request(
selectAllOptions('group_by_columns');
var updater = new Ajax.Request(
targetUrl, targetUrl,
{ asynchronous: true, { asynchronous: true,
evalScripts: true, evalScripts: true,
postBody: Form.serialize('query_form'), postBody: Reporting.Controls.serialize_settings_form(),
onSuccess: callback, onSuccess: callback,
onFailure: failureCallback}); onFailure: failureCallback });
},
serialize_settings_form: function() {
var ret_str, grouping_str;
ret_str = Form.serialize('query_form');
grouping_str = $w('rows columns').inject('', function(grouping, type) {
return grouping + $('group_by_' + type).select('.group_by_element').map(function(group_by) {
return 'groups[' + type + '][]=' + group_by.readAttribute('data-group-by');
}).inject('', function(all_group_str, group_str) {
return all_group_str + '&' + group_str;
});
});
if (grouping_str.length > 0) {
ret_str += grouping_str;
}
return ret_str;
}, },
attach_settings_callback: function (element, callback) { attach_settings_callback: function (element, callback) {
failureCallback = function (response) { failureCallback = function (response) {
$('result-table').update(""); $('result-table').update("");
Reporting.Controls.default_failure_callback(response); Reporting.Controls.default_failure_callback(response);
} };
element.observe("click", function (e) { element.observe("click", function (e) {
Reporting.Controls.send_settings_data(this.getAttribute("data-target"), callback, failureCallback); Reporting.Controls.send_settings_data(this.getAttribute("data-target"), callback, failureCallback);
e.preventDefault(); e.preventDefault();
@ -104,7 +118,7 @@ Reporting.Controls = {
}, },
default_failure_callback: function (response) { default_failure_callback: function (response) {
if ((response.status + "")[0] === "4") { if (response.status >= 400 && response.status < 500) {
Reporting.flash(response.responseText); Reporting.flash(response.responseText);
} else { } else {
Reporting.flash("There was an error getting the results. The administrator has been informed."); Reporting.flash("There was an error getting the results. The administrator has been informed.");

@ -243,7 +243,7 @@ Reporting.Filters = {
// Param: select [optional] - the select-box of the filter which should activate it's dependents // Param: select [optional] - the select-box of the filter which should activate it's dependents
activate_dependents: function (selectBox, callbackWhenFinished) { activate_dependents: function (selectBox, callbackWhenFinished) {
var dependents, active_filters, source; var dependents, active_filters, source;
if (selectBox === undefined || selectBox.type == 'change') { if (selectBox === undefined || selectBox.type.toLowerCase() == 'change') {
selectBox = this; selectBox = this;
} }
if (callbackWhenFinished === undefined) { if (callbackWhenFinished === undefined) {
@ -303,7 +303,7 @@ Reporting.Filters = {
{ {
asynchronous: true, asynchronous: true,
evalScripts: true, evalScripts: true,
postBody: Form.serialize('query_form'), postBody: Reporting.Controls.serialize_settings_form(),
onSuccess: function (response) { onSuccess: function (response) {
Reporting.clearFlash(); Reporting.clearFlash();
if (response.responseJSON !== undefined) { if (response.responseJSON !== undefined) {

@ -2,60 +2,179 @@
/*global window, $, $$, Reporting, Effect, Ajax, selectAllOptions, moveOptions, moveOptionUp, moveOptionDown */ /*global window, $, $$, Reporting, Effect, Ajax, selectAllOptions, moveOptions, moveOptionUp, moveOptionDown */
Reporting.GroupBys = { Reporting.GroupBys = {
attach_move_button: function (direction) { group_by_container_ids: function() {
var btn = $$(".buttons.group_by.move.move" + direction)[0]; return $w('group_by_columns group_by_rows');
},
var axis; sortable_options: function() {
if (direction === "Up" || direction === "Down") { return {
axis = "columns"; tag: 'span',
} else if (direction === "Left" || direction === "Right") { only: "drag_element",
axis = "rows"; overlap: 'horizontal',
} constraint:'horizontal',
containment: Reporting.GroupBys.group_by_container_ids(),
dropOnEmpty: true,
hoverclass: 'drag_container_accept',
onUpdate: Reporting.GroupBys.ordering_changed
};
},
var selected_container = $(btn.form).select("#group_by_" + axis)[0]; ordering_changed: function(container) {
var group_by_container = btn.form.group_by_container; container.select('.group_by_element').each(function(group_by) {
Reporting.GroupBys.update_arrow(group_by);
});
},
var source_container, target_container; recreate_sortables: function() {
if (direction === "Down" || direction === "Right") { Reporting.GroupBys.group_by_container_ids().each(function(id) {
source_container = selected_container; Sortable.create(id, Reporting.GroupBys.sortable_options());
target_container = group_by_container; });
} else if (direction === "Up" || direction === "Left") { },
target_container = selected_container;
source_container = group_by_container; initialize_drag_and_drop_areas: function() {
Reporting.GroupBys.recreate_sortables();
},
create_group_by: function(field) {
var group_by = new Element('span', {
'class': 'in_row drag_element group_by_element',
'data-group-by': field
});
group_by.identify(); // give it a unique id
return group_by;
},
group_by_hover_effect: function(event, do_hover) {
var group_by = $(Event.element(event));
// we possibly hit a tag inside the group_by, so go search the group_by then
if (!group_by.hasClassName('group_by_element')) {
group_by = group_by.up('.group_by_element');
}
if (group_by !== null) {
Reporting.GroupBys.group_by_hover(group_by, do_hover);
} }
},
btn.observe("click", function () { // on mouse_over of a group_by or it's label, change the color of the group_by
moveOptions(source_container, target_container); // also change the color of the arrows
init_group_by_hover_effects: function(elements) {
elements.each(function(element) {
['mouseover', 'mouseout'].each(function(event_type) {
element.observe(event_type, function(event) {
Reporting.GroupBys.group_by_hover_effect(event, event_type == 'mouseover');
});
});
}); });
}, },
attach_sort_button: function (direction, axis) { create_label: function(group_by, text) {
var btn = $$(".buttons.group_by.sort.sort" + direction + ".sort-" + axis)[0]; return new Element('label', {
var box = $(btn.form).select("#group_by_" + axis)[0]; 'class': 'in_row group_by_label',
btn.observe("click", function () { 'for': group_by.identify(),
if (direction === "Up") { 'id': group_by.identify() + '_label'
moveOptionUp(box); }).update(text);
} else { },
moveOptionDown(box);
} adding_group_by_enabled: function(field, state) {
$w('add_group_by_columns add_group_by_rows').each(function(container_id) {
Reporting.Filters.select_option_enabled($(container_id), field, state);
}); });
}, },
clear: function () { arrow_removal_hover: function(arrow, status) {
['group_by_columns', 'group_by_rows'].each(function (type) { if (status) {
selectAllOptions(type); $(arrow).addClassName('arrow_removal_hover');
moveOptions(type, 'group_by_container'); }
else {
$(arrow).removeClassName('arrow_removal_hover');
}
},
group_by_hover: function(group_by, state) {
var arrow, previous_groups_arrow;
arrow = $(group_by.identify() + '_arrow');
previous_groups_arrow = $(group_by.previous().identify() + '_arrow');
if (Reporting.GroupBys.is_last(group_by)) {
state ? arrow.addClassName('hover') : arrow.removeClassName('hover');
} else {
state ? arrow.addClassName('hover_left') : arrow.removeClassName('hover_left');
}
if (!Reporting.GroupBys.is_first(group_by)) {
state ? previous_groups_arrow.addClassName('hover_right') : previous_groups_arrow.removeClassName('hover_right');
}
},
remove_group_by: function(group_by) {
var previous_group = group_by.previous();
Reporting.GroupBys.adding_group_by_enabled(group_by.readAttribute('data-group-by'), true);
group_by.remove();
if (previous_group !== null && previous_group.hasClassName('group_by_element')) {
Reporting.GroupBys.update_arrow(previous_group);
}
},
init_arrow: function(group_by) {
var arrow = new Element('span', {
'class': 'arrow in_row arrow_left',
'id': group_by.identify() + '_arrow'
}); });
//initialize callbacks for hover-effects and removal of group_by
arrow.observe('mouseover', function() { Reporting.GroupBys.arrow_removal_hover(arrow, true) });
arrow.observe('mouseout', function() { Reporting.GroupBys.arrow_removal_hover(arrow, false) });
arrow.observe('mousedown', function() { Reporting.GroupBys.remove_group_by(arrow.up('.group_by_element')) });
return arrow;
},
// returns true if the given group is the first group in its container
is_first: function(group_by) {
return (($(group_by).previous() == null) || (!($(group_by).previous().className.include('group_by'))));
},
// returns true if the given group is the last group in its container
is_last: function(group_by) {
return (($(group_by).next() == null) || (!($(group_by).next().className.include('group_by'))));
},
update_arrow: function(group_by) {
if (Reporting.GroupBys.is_last(group_by)) {
$(group_by.identify() + "_arrow").className = "arrow in_row arrow_left";
} else {
$(group_by.identify() + "_arrow").className = "arrow in_row arrow_both";
}
},
add_group_by_from_select: function(select) {
var field, caption, container, selected_option;
field = $(select).getValue();
container = select.up('.drag_container');
selected_option = select.select("[value='" + field + "']").first();
caption = selected_option.readAttribute('data-label');
Reporting.GroupBys.add_group_by(field, caption, container);
select.select("[value='']").first().selected = true;
},
add_group_by: function(field, caption, container) {
var group_by, label;
group_by = Reporting.GroupBys.create_group_by(field);
container.appendChild(group_by);
label = Reporting.GroupBys.create_label(group_by, caption);
Reporting.GroupBys.init_group_by_hover_effects([group_by, label]);
group_by.appendChild(label);
group_by.appendChild(Reporting.GroupBys.init_arrow(group_by));
if (!(Reporting.GroupBys.is_first(group_by))) {
Reporting.GroupBys.update_arrow(group_by.previous());
}
Reporting.GroupBys.adding_group_by_enabled(field, false);
Reporting.GroupBys.recreate_sortables();
} }
}; };
Reporting.onload(function () { Reporting.onload(function () {
["Left", "Right", "Up", "Down"].each(function (dir) { Reporting.GroupBys.initialize_drag_and_drop_areas();
Reporting.GroupBys.attach_move_button(dir); $('add_group_by_rows').observe("change", function () {
Reporting.GroupBys.add_group_by_from_select(this);
}); });
["Up", "Down"].each(function (dir) { $('add_group_by_columns').observe("change", function () {
["rows", "columns"].each(function (axis) { Reporting.GroupBys.add_group_by_from_select(this);
Reporting.GroupBys.attach_sort_button(dir, axis);
});
}); });
}); });

@ -27,27 +27,6 @@ Reporting.RestoreQuery = {
} }
}, },
show_group_by: function (group_by, target) {
$('group_by_container').select("");
var source, group_option, i;
source = $("group_by_container");
group_option = null;
// find group_by option-tag in target select-box
for (i = 0; i < source.options.length; i += 1) {
if (source.options[i].value === group_by) {
group_option = source.options[i];
source.options[i] = null;
break;
}
}
// die if the appropriate option-tag can not be found
if (group_option === null) {
return;
}
// move the option-tag to the taget select-box while keepings its data
target.options[target.length] = group_option;
},
// This is called the first time the report loads. // This is called the first time the report loads.
// Params: // Params:
// elements: Array of visible filter-select-boxes that have dependents // elements: Array of visible filter-select-boxes that have dependents
@ -59,7 +38,7 @@ Reporting.RestoreQuery = {
// Filters which are <<inactive>> are probably dependents themselfes, so remove and forget them for now. // Filters which are <<inactive>> are probably dependents themselfes, so remove and forget them for now.
// This is OK as they get reloaded later // This is OK as they get reloaded later
dependent_filters.each(function(select) { dependent_filters.each(function(select) {
Reporting.Filters.remove_filter(select.up('tr').getAttribute("data-filter-name")); Reporting.Filters.remove_filter(select.up('tr').readAttribute("data-filter-name"));
}); });
// For each dependent filter we reload its dependent chain // For each dependent filter we reload its dependent chain
filters_to_load.each(function(selectBox) { filters_to_load.each(function(selectBox) {
@ -70,9 +49,9 @@ Reporting.RestoreQuery = {
}); });
sources.each(function(source) { sources.each(function(source) {
if (source.hasAttribute('data-initially-selected')) { if (source.hasAttribute('data-initially-selected')) {
selected_values = source.getAttribute('data-initially-selected').replace(/'/g, '"').evalJSON(true); selected_values = source.readAttribute('data-initially-selected').replace(/'/g, '"').evalJSON(true);
Reporting.Filters.select_values(source, selected_values); Reporting.Filters.select_values(source, selected_values);
Reporting.Filters.value_changed(source.up('tr').getAttribute("data-filter-name")); Reporting.Filters.value_changed(source.up('tr').readAttribute("data-filter-name"));
} }
}); });
if (sources.reject( function (select) { return select.value == '<<inactive>>' }).size() == 0) { if (sources.reject( function (select) { return select.value == '<<inactive>>' }).size() == 0) {
@ -85,20 +64,6 @@ Reporting.RestoreQuery = {
}); });
}, },
restore_group_bys: function () {
// Activate recent group_bys on loading
$('group_by_container').select("option")
.select(function (group_by) {
return $(group_by).hasAttribute("data-selected-axis");
}).sortBy(function (group_by) {
return $(group_by).getAttribute("data-selected-index");
}).each(function (group_by) {
var axis = $(group_by).getAttribute("data-selected-axis");
var name = $(group_by).getAttribute("value");
Reporting.RestoreQuery.show_group_by(name, $('group_by_' + axis + 's'));
});
},
restore_filters: function () { restore_filters: function () {
// FIXME: rm_xxx values for filters have to be set after re-displaying them // FIXME: rm_xxx values for filters have to be set after re-displaying them
$$("tr[data-selected=true]").each(function (e) { $$("tr[data-selected=true]").each(function (e) {
@ -111,6 +76,22 @@ Reporting.RestoreQuery = {
Reporting.RestoreQuery.initialize_load_dependent_filters($$('.filters-select[data-dependents]').findAll(function(select) { Reporting.RestoreQuery.initialize_load_dependent_filters($$('.filters-select[data-dependents]').findAll(function(select) {
return select.up('tr').visible() return select.up('tr').visible()
})); }));
},
restore_group_bys: function () {
Reporting.GroupBys.group_by_container_ids().each(function(id) {
var container, selected_groups;
container = $(id);
if (container.hasAttribute('data-initially-selected')) {
selected_groups = container.readAttribute('data-initially-selected').replace(/'/g, '"').evalJSON(true);
selected_groups.each(function(group_and_label) {
var group, label;
group = group_and_label[0];
label = group_and_label[1];
Reporting.GroupBys.add_group_by(group, label, container);
});
}
});
} }
}; };

@ -1,151 +0,0 @@
var NS4 = (navigator.appName === "Netscape" && parseInt(navigator.appVersion, 10) < 5);
function createOption(theText, theValue, theCategory) {
var newOpt = document.createElement('option');
newOpt.text = theText;
newOpt.value = theValue;
newOpt.setAttribute("data-category", theCategory);
return newOpt;
}
function addOption(theSel, newOpt)
{
var theCategory, opt_groups, i;
theCategory = newOpt.getAttribute("data-category");
theSel = $(theSel);
if (theCategory && (theSel.childElements().length > 0) && theSel.down(0).tagName === "OPTGROUP") { // add the opt to the given category
opt_groups = theSel.childElements();
for (i = 0; i < opt_groups.length; i += 1) {
if (opt_groups[i].getAttribute("data-category") === theCategory) {
opt_groups[i].appendChild(newOpt);
break;
}
}
}
else { // no category given, just add the opt to the end of the select list
theSel.appendChild(newOpt);
}
}
function swapOptions(theSel, index1, index2)
{
theSel = $(theSel);
var text, value, category;
text = theSel.options[index1].text;
value = theSel.options[index1].value;
category = theSel.options[index1].getAttribute("data-category");
theSel.options[index1].text = theSel.options[index2].text;
theSel.options[index1].value = theSel.options[index2].value;
theSel.options[index1].setAttribute("data-category", theSel.options[index2].getAttribute("data-category"));
theSel.options[index2].text = text;
theSel.options[index2].value = value;
theSel.options[index2].setAttribute("data-category", category);
}
function deleteOption(theSel, theIndex)
{
theSel = $(theSel);
var selLength = theSel.length;
if (selLength > 0)
{
theSel.options[theIndex] = null;
}
}
// Returns true if the given select-box has optgroups.
// We assume that a possibly present optgroup is the first child element of the select-box.
function has_optgroups(theSel) {
theSel = $(theSel);
return (theSel.childElements().length > 0) && (theSel.down(0).tagName === "OPTGROUP");
}
// Compares two option elements (return -1 if a < b, if not return 1).
// If those elements have a 'data-sort_by' attribute, we compare that attribute.
// If this is not the case we just compare their labels.
function compareOptions(a, b) {
var a_cmp, b_cmp;
a_cmp = a.getAttribute("data-sort_by") ? a.getAttribute("data-sort_by") : a.text.toLowerCase();
b_cmp = b.getAttribute("data-sort_by") ? b.getAttribute("data-sort_by") : b.text.toLowerCase();
return (a_cmp < b_cmp) ? -1 : 1;
}
// Sorts all elements of the given select-box.
// If that select-box contains optgroups, the options are sorted for each optgroup separately.
function sortOptions(theSel) {
theSel = $(theSel);
if (has_optgroups(theSel)) {
// handle each optgroup separately
theSel.childElements().each(function (group) {
var sorted_elements;
// get all elements of this optgroup and sort them
sorted_elements = $A(group.childElements()).sort(compareOptions);
// make optgroup empty
$A(group.childElements()).each(function (o) {
$(o).remove();
});
// insert sorted elements into opgroup
sorted_elements.each(function (o) {
$(group).insert({'bottom' : o});
});
});
}
else {
// there is no optgroup, so just sort the options
$A(theSel.options).sort(compareOptions).each(function (o, i) {
theSel.options[i] = o;
});
}
}
function moveOptions(theSelFrom, theSelTo)
{
var selLength, selectedText, selectedValues, selectedCategories, selectedCount, i;
theSelFrom = $(theSelFrom);
theSelTo = $(theSelTo);
selLength = theSelFrom.length;
selectedText = [];
selectedValues = [];
selectedCategories = [];
selectedCount = 0;
for (i = selLength - 1; i >= 0; i -= 1) {
if (theSelFrom.options[i].selected)
{
addOption(theSelTo, theSelFrom.options[i].cloneNode(true));
deleteOption(theSelFrom, i);
}
}
if (has_optgroups(theSelTo)) {
sortOptions(theSelTo);
}
if (NS4) {
history.go(0);
}
}
function moveOptionUp(theSel) {
theSel = $(theSel);
var index = theSel.selectedIndex;
if (index > 0) {
swapOptions(theSel, index - 1, index);
theSel.selectedIndex = index - 1;
}
}
function moveOptionDown(theSel) {
theSel = $(theSel);
var index = theSel.selectedIndex;
if (index < theSel.length - 1) {
swapOptions(theSel, index, index + 1);
theSel.selectedIndex = index + 1;
}
}
function selectAllOptions(select)
{
select = $(select);
for (var i = 0; i < select.options.length; i += 1) {
select.options[i].selected = true;
}
}

@ -117,65 +117,6 @@
border: none; border: none;
} }
.group_by {
background-color: transparent;
background-position: 50%;
background-repeat: no-repeat;
border: 1px solid #900;
height: 10px;
width: 10px;
margin: 1px;
}
.group_by:hover {
background-color: #EEE;
}
.move {
height: 25px;
width: 25px;
}
.sort {
height: 15px;
width: 15px;
}
.moveUp {
margin-top: 0px;
margin-bottom: 0px;
background-image: url(../images/arrow_D_up.gif);
}
.moveDown {
margin-top: 0px;
margin-bottom: 0px;
background-image: url(../images/arrow_D_down.gif);
}
.moveLeft {
margin-left: 0px;
margin-right: 0px;
background-image: url(../images/arrow_D_left.gif);
}
.moveRight {
margin-left: 0px;
margin-right: 0px;
background-image: url(../images/arrow_D_right.gif);
}
.sortUp {
margin-left: 0px;
margin-right: 0px;
background-image: url(../images/arrow_B_up.gif);
}
.sortDown {
margin-left: 0px;
margin-right: 0px;
background-image: url(../images/arrow_B_down.gif);
}
.remove-box { .remove-box {
height: 20px; height: 20px;
width: 20px; width: 20px;
@ -264,10 +205,7 @@ fieldset#filter-settings table td > label {
position: relative; position: relative;
} }
.drag_element { /* ----- group by --- */
/*cursor: move;*/
}
.in_row { .in_row {
float: left; float: left;
display: block; display: block;
@ -285,6 +223,16 @@ fieldset#filter-settings table td > label {
color: #fff; color: #fff;
} }
.group_by_element {
background-color: #3F9ED7;
background-position: 50%;
background-repeat: no-repeat;
}
.group_by_element:hover {
background-color: #398AD3;
}
.arrow { .arrow {
background-repeat: no-repeat; background-repeat: no-repeat;
height: 19px !important; height: 19px !important;
@ -295,31 +243,31 @@ fieldset#filter-settings table td > label {
} }
.arrow_both { .arrow_both {
background-image: url(../images/arrow_both.png); background-image: url(../images/group_by_arrow_both.png);
} }
.arrow_both_hover_left { .arrow_both.arrow_removal_hover {
background-image: url(../images/arrow_both_hover_left.png); background-image: url(../images/group_by_arrow_both_remove.png) !important;
} }
.arrow_both_remove { .arrow_both.hover_left {
background-image: url(../images/arrow_both_remove.png); background-image: url(../images/group_by_arrow_both_hover_left.png);
} }
.arrow_both_hover_right { .arrow_both.hover_right {
background-image: url(../images/arrow_both_hover_right.png); background-image: url(../images/group_by_arrow_both_hover_right.png);
} }
.arrow_left { .arrow_left {
background-image: url(../images/arrow_left.png); background-image: url(../images/group_by_arrow_left.png);
} }
.arrow_left_remove { .arrow_left.arrow_removal_hover {
background-image: url(../images/arrow_left_remove.png); background-image: url(../images/group_by_arrow_left_remove.png) !important;
} }
.arrow_left_hover { .arrow_left.hover {
background-image: url(../images/arrow_left_hover.png); background-image: url(../images/group_by_arrow_left_hover.png);
} }
.drag_container { .drag_container {
@ -344,6 +292,8 @@ fieldset#filter-settings table td > label {
/*border: 1px solid #BBBBBB;*/ /*border: 1px solid #BBBBBB;*/
} }
/* -- end group-by -- */
td .drill_down, th .drill_down { td .drill_down, th .drill_down {
font-size: 8px; font-size: 8px;
display: block; display: block;

@ -107,8 +107,8 @@ class Report < ActiveRecord::Base
@table = self.class::Table.new(self) @table = self.class::Table.new(self)
end end
def group_bys def group_bys(type=nil)
chain.select { |c| c.group_by? } chain.select { |c| c.group_by? && (type.nil? || c.type == type) }
end end
def filters def filters

@ -1,114 +1,46 @@
class Widget::GroupBys < Widget::Base class Widget::GroupBys < Widget::Base
extend ProactiveAutoloader extend ProactiveAutoloader
def render_row_1_with_columns def render_options(group_by_ary)
content_tag :tr do group_by_ary.sort_by do |group_by|
tr = content_tag :td, " ", :colspan => "2" l(group_by.label)
tr += content_tag :td, :align => "center", :valign => "right" do end.collect do |group_by|
render_up_down_buttons("columns") next unless group_by.selectable?
end content_tag :option, :value => group_by.underscore_name, :'data-label' => "#{l(group_by.label)}" do
tr += content_tag :td, :valign => "middle" do l(group_by.label)
content_tag(:h3, "Columns") + selected_group_bys("columns")
end end
end end.join.html_safe
end end
def render_row_2_with_up_down def render_group(type, initially_selected)
content_tag :tr do initially_selected = initially_selected.map do |group_by|
tr = content_tag :td, " " [group_by.class.underscore_name, l(group_by.class.label)]
tr += content_tag :td, :valign => "bottom", :style => "padding-bottom: 0;" do
content_tag :h3, "Rows"
end
tr += content_tag :td, " "
tr += content_tag :td, :align => "left", :valign => "left" do
render_move_buttons("columns", "Up", "Down")
end
end end
end content_tag :div,
:id => "group_by_#{type}",
def render_row_3_with_rows_and_group_bys :class => 'drag_target drag_container',
content_tag :tr do :'data-initially-selected' => initially_selected.to_json.gsub('"', "'") do
tr = content_tag :td, :align => "center", :valign => "top" do content_tag :select, :id => "add_group_by_#{type}", :class => 'select-small' do
render_up_down_buttons("rows") content = tag :option, :value => ''
end content += engine::GroupBy.all_grouped.sort_by do |label, group_by_ary|
tr += content_tag :td ,:style => "padding-left: 0pt;", :valign => "top" do l(label)
selected_group_bys("rows") end.collect do |label, group_by_ary|
end content_tag :optgroup, :label => l(label) do
tr += content_tag :td, :align => "center", :valign => "top" do render_options group_by_ary
render_move_buttons("rows", "Left", "Right", true) end
end end.join.html_safe
tr += content_tag :td do content
render_grouped_group_bys end.html_safe
end
end end
end end
#TODO: replace me with a drag&drop group_by selector
def render def render
content_tag :div do content_tag :div, :id => 'group_by_area' do
content_tag :table, :style => "border-collapse: collapse; border: 0pt none;", out = l(:label_columns)
:id => "group_by_table" do out += render_group 'columns', @query.group_bys(:column)
content_tag :tbody do out += l(:label_rows)
render_row_1_with_columns + out += render_group 'rows', @query.group_bys(:row)
render_row_2_with_up_down + out.html_safe
render_row_3_with_rows_and_group_bys
end
end
end
end
def selected_group_bys(axis)
content_tag :select, "", :style => "width: 180px;", :size => "4",
:name => "groups[#{axis}][]", :multiple => "multiple",
:id => "group_by_#{axis}"
end
def render_up_down_buttons(axis)
render_sort_button(axis, "Up") + tag(:br) + render_sort_button(axis, "Down")
end
def render_sort_button(axis, dir)
tag :input, :type => "button", :class => "buttons group_by sort sort#{dir} sort-#{axis}"
end
def render_move_buttons(axis, to, from, br = false)
canvas = render_move_option_button(axis, to)
canvas += tag(:br) if br
canvas + render_move_option_button(axis, from)
end
def render_move_option_button(axis, dir)
tag :input, :type => "button", :class => "buttons group_by move move#{dir}"
end
def render_grouped_group_bys
content_tag :select, :style => "width: 180px;", :size => "9", :multiple => "multiple", :id => "group_by_container" do
engine::GroupBy.all_grouped.sort_by do |label, group_by_ary|
l(label)
end.collect do |label, group_by_ary|
content_tag :optgroup, :label => l(label), :"data-category" => label.to_s do
render_group_bys_for(group_by_ary, label)
end
end.join.html_safe
end
end
def render_group_bys_for(group_by_ary, label)
group_by_ary.sort_by do |g|
l(g.label)
end.collect do |group_by|
next unless group_by.selectable?
render_group_by(group_by, :value => group_by.underscore_name, :"data-category" => label.to_s)
end.compact.join.html_safe
end
def render_group_by(group_by, option_tag_options)
if grby = @query.group_bys.detect {|g| g.class == group_by }
option_tag_options[:"data-selected-axis"] = grby.type.to_s
option_tag_options[:"data-selected-index"] = @query.group_bys.index(grby)
end
content_tag :option, option_tag_options do
l(group_by.label)
end end
end end
end end

@ -0,0 +1,114 @@
class Widget::OldGroupBys < Widget::Base
extend ProactiveAutoloader
def render_row_1_with_columns
content_tag :tr do
tr = content_tag :td, " ", :colspan => "2"
tr += content_tag :td, :align => "center", :valign => "right" do
render_up_down_buttons("columns")
end
tr += content_tag :td, :valign => "middle" do
content_tag(:h3, "Columns") + selected_group_bys("columns")
end
end
end
def render_row_2_with_up_down
content_tag :tr do
tr = content_tag :td, " "
tr += content_tag :td, :valign => "bottom", :style => "padding-bottom: 0;" do
content_tag :h3, "Rows"
end
tr += content_tag :td, " "
tr += content_tag :td, :align => "left", :valign => "left" do
render_move_buttons("columns", "Up", "Down")
end
end
end
def render_row_3_with_rows_and_group_bys
content_tag :tr do
tr = content_tag :td, :align => "center", :valign => "top" do
render_up_down_buttons("rows")
end
tr += content_tag :td ,:style => "padding-left: 0pt;", :valign => "top" do
selected_group_bys("rows")
end
tr += content_tag :td, :align => "center", :valign => "top" do
render_move_buttons("rows", "Left", "Right", true)
end
tr += content_tag :td do
render_grouped_group_bys
end
end
end
#TODO: replace me with a drag&drop group_by selector
def render
content_tag :div do
content_tag :table, :style => "border-collapse: collapse; border: 0pt none;",
:id => "group_by_table" do
content_tag :tbody do
render_row_1_with_columns +
render_row_2_with_up_down +
render_row_3_with_rows_and_group_bys
end
end
end
end
def selected_group_bys(axis)
content_tag :select, "", :style => "width: 180px;", :size => "4",
:name => "groups[#{axis}][]", :multiple => "multiple",
:id => "group_by_#{axis}"
end
def render_up_down_buttons(axis)
render_sort_button(axis, "Up") + tag(:br) + render_sort_button(axis, "Down")
end
def render_sort_button(axis, dir)
tag :input, :type => "button", :class => "buttons group_by sort sort#{dir} sort-#{axis}"
end
def render_move_buttons(axis, to, from, br = false)
canvas = render_move_option_button(axis, to)
canvas += tag(:br) if br
canvas + render_move_option_button(axis, from)
end
def render_move_option_button(axis, dir)
tag :input, :type => "button", :class => "buttons group_by move move#{dir}"
end
def render_grouped_group_bys
content_tag :select, :style => "width: 180px;", :size => "9", :multiple => "multiple", :id => "group_by_container" do
engine::GroupBy.all_grouped.sort_by do |label, group_by_ary|
l(label)
end.collect do |label, group_by_ary|
content_tag :optgroup, :label => l(label), :"data-category" => label.to_s do
render_group_bys_for(group_by_ary, label)
end
end.join.html_safe
end
end
def render_group_bys_for(group_by_ary, label)
group_by_ary.sort_by do |g|
l(g.label)
end.collect do |group_by|
next unless group_by.selectable?
render_group_by(group_by, :value => group_by.underscore_name, :"data-category" => label.to_s)
end.compact.join.html_safe
end
def render_group_by(group_by, option_tag_options)
if grby = @query.group_bys.detect {|g| g.class == group_by }
option_tag_options[:"data-selected-axis"] = grby.type.to_s
option_tag_options[:"data-selected-index"] = @query.group_bys.index(grby)
end
content_tag :option, option_tag_options do
l(group_by.label)
end
end
end
Loading…
Cancel
Save