diff --git a/app/controllers/cost_reports_controller.rb b/app/controllers/cost_reports_controller.rb
index d0973af10e..91f58aa69e 100644
--- a/app/controllers/cost_reports_controller.rb
+++ b/app/controllers/cost_reports_controller.rb
@@ -27,6 +27,16 @@ class CostReportsController < ApplicationController
redirect_to :action => :index
end
+ def available_values
+ filter = filter_class(params[:filter_name].to_s)
+ render_404 unless filter
+ @available_values = filter.available_values
+
+ respond_to do |format|
+ format.html { render :layout => !request.xhr? }
+ end
+ end
+
##
# Determines if the request contains filters to set
def set_filter? #FIXME: rename to set_query?
diff --git a/app/helpers/reporting_helper.rb b/app/helpers/reporting_helper.rb
index 46368d2714..1f2ffc1958 100644
--- a/app/helpers/reporting_helper.rb
+++ b/app/helpers/reporting_helper.rb
@@ -144,4 +144,14 @@ module ReportingHelper
def show_row(row)
link_to_details(row) << row.render { |k,v| show_field(k,v) }
end
+
+ ##
+ # Finds the Filter-Class for as specific filter name while being careful with the filter_name parameter as it is user input.
+ def filter_class(filter_name)
+ klass = CostQuery::Filter.const_get(filter_name.to_s.camelize)
+ return klass if klass.is_a? Class
+ nil
+ rescue NameError
+ return nil
+ end
end
\ No newline at end of file
diff --git a/app/views/cost_reports/available_values.rhtml b/app/views/cost_reports/available_values.rhtml
new file mode 100644
index 0000000000..4723e04c5d
--- /dev/null
+++ b/app/views/cost_reports/available_values.rhtml
@@ -0,0 +1,5 @@
+<% @available_values.each do |name, id, *args| %>
+ <%= render :partial => 'cost_reports/filters/available_value',
+ :locals => { :name => name, :id => id, :level => args.first },
+ :layout => !request.xhr? %>
+<% end %>
diff --git a/app/views/cost_reports/filters/_available_value.rhtml b/app/views/cost_reports/filters/_available_value.rhtml
new file mode 100644
index 0000000000..5dafad42e5
--- /dev/null
+++ b/app/views/cost_reports/filters/_available_value.rhtml
@@ -0,0 +1,11 @@
+<%#
+ This partial requires the following locals:
+ name String: The displayed name of the option
+ id Integer: The id the option refers to
+ level Integer: The indendation level of this option
+%>
+
+<% name_prefix = ((level && level > 0) ? (' ' * 2 * level + '» ') : '') %>
+
\ No newline at end of file
diff --git a/app/views/cost_reports/filters/_multi_values.rhtml b/app/views/cost_reports/filters/_multi_values.rhtml
index 15b7fb9e9c..5b43b2f184 100644
--- a/app/views/cost_reports/filters/_multi_values.rhtml
+++ b/app/views/cost_reports/filters/_multi_values.rhtml
@@ -14,13 +14,7 @@
id="<%= element[:filter_name] %>_arg_1_val"
class="select-small"
multiple="multiple"> <%# multiple will be disabled/enabled later by JavaScript anyhow. We need to specify multiple here because of a IE6-bug. %>
- <% element[:values].each do |name, id, *args| %>
- <% level = args.first #nesting_level is optional for values %>
- <% name_prefix = ((level && level > 0) ? (' ' * 2 * level + '» ') : '') %>
-
- <% end %>
+ <%# content will be inserted on filter activation %>
<%= link_to_function image_tag('bullet_toggle_plus.png'), "toggle_multi_select($('#{element[:filter_name]}_arg_1_val'));", :style => "vertical-align: bottom;" %>
diff --git a/assets/javascripts/reporting.js b/assets/javascripts/reporting.js
index 4c6923e89e..aab442d1e7 100644
--- a/assets/javascripts/reporting.js
+++ b/assets/javascripts/reporting.js
@@ -89,6 +89,7 @@ function show_filter(field) {
var field_el = $('tr_' + field);
register_remove_hover(field);
if (field_el !== null) {
+ load_available_values_for_filter(field);
field_el.show();
toggle_filter(field);
$('rm_' + field).value = field;
@@ -270,6 +271,54 @@ function disable_all_group_bys() {
});
}
+function serialize_filter_and_group_by() {
+ var ret_str = Form.serialize('query_form');
+ var rows = Sortable.serialize('group_rows');
+ var columns = Sortable.serialize('group_columns');
+ if (rows !== null && rows != "") {
+ ret_str += "&" + rows;
+ }
+ if(columns !== null && columns != "") {
+ ret_str += "&" + columns;
+ }
+ return ret_str;
+}
+
+function init_group_bys() {
+ var options = {
+ tag:'span',
+ overlap:'horizontal',
+ constraint:'horizontal',
+ containment: ['group_columns','group_rows'],
+ //only: "group_by",
+ dropOnEmpty: true,
+ format: /^(.*)$/,
+ hoverclass: 'drag_container_accept'
+ };
+ Sortable.create('group_columns', options);
+ Sortable.create('group_rows', options);
+}
+
+function load_available_values_for_filter(filter_name) {
+ var select;
+ select = $('' + filter_name + '_arg_1_val');
+ if (select.childElements().length == 0) {
+ new Ajax.Updater({ success: select }, '/cost_reports/available_values', {
+ parameters: { filter_name: filter_name },
+ insertion: 'bottom',
+ evalScripts: false,
+ onCreate: function (a,b) {
+ $('operators_' + filter_name).disable();
+ $('' + filter_name + '_arg_1_val').disable();
+ },
+ onComplete: function (a,b) {
+ $('operators_' + filter_name).enable();
+ $('' + filter_name + '_arg_1_val').enable();
+ }
+ });
+ }
+}
+
function defineElementGetter() {
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)