Merge branch 'feature/widgets' into feature/progress_report

pull/6827/head
jwollert 14 years ago
commit 05b7b0ffbe
  1. 1
      assets/javascripts/reporting.js
  2. 13
      assets/javascripts/reporting/filters.js
  3. 11
      assets/javascripts/reporting/restore_query.js
  4. 82
      assets/stylesheets/reporting.css
  5. 16
      lib/report/chainable.rb
  6. 6
      lib/report/controller.rb
  7. 4
      lib/report/filter.rb
  8. 4
      lib/report/group_by.rb
  9. 2
      lib/report/operator.rb
  10. 4
      lib/report/query_utils.rb
  11. 2
      lib/report/walker.rb
  12. 2
      lib/widget/controls/query_name.rb
  13. 10
      lib/widget/controls/save_as.rb
  14. 4
      lib/widget/filters.rb
  15. 3
      lib/widget/filters/remove_button.rb
  16. 2
      lib/widget/filters/text_box.rb
  17. 2
      lib/widget/settings.rb
  18. 82
      lib/widget/table.rb
  19. 4
      lib/widget/table/report_table.rb

@ -78,3 +78,4 @@ Reporting.require("table");
// }
//
// // defineElementGetter();

@ -44,15 +44,16 @@ Reporting.Filters = {
var field_el = $('tr_' + field);
if (field_el !== null) {
// the following command might be included into the callback_function (which is called after the ajax request) later
$('rm_' + field).value = field;
var display_functor;
if (options.show_filter) {
display_functor = options.slowly ? Effect.Appear : Element.show;
(options.slowly ? Effect.Appear : Element.show)(field_el);
Reporting.Filters.load_available_values_for_filter(field, options.callback_func);
$('rm_' + field).value = field; // set the value, so the serialized form will return this filter
} else {
display_functor = options.slowly ? Effect.Fade : Element.hide;
(options.slowly ? Effect.Fade : Element.hide)(field_el);
field_el.removeAttribute('data-selected');
$('rm_' + field).value = ""; // reset the value, so the serialized form will not return this filter
}
display_functor(field_el);
Reporting.Filters.operator_changed(field, $("operators_" + field));
Reporting.Filters.display_category($(field_el.getAttribute("data-label")));
}
@ -133,7 +134,7 @@ Reporting.Filters = {
return $("filter_table").childElements().first().select('tr').select(function (tr) {
return tr.visible() === true;
}).collect(function (filter) {
return filter.className;
return filter.getAttribute("data-filter-name");
});
},
@ -150,7 +151,7 @@ Reporting.onload(function () {
});
$$(".filter_rem").each(function (e) {
e.observe("click", function () {
var filter_name = this.getAttribute("data-filter-name");
var filter_name = this.up('tr').getAttribute("data-filter-name");
Reporting.Filters.remove_filter(filter_name);
});
});

@ -60,9 +60,20 @@ Reporting.RestoreQuery = {
var name = $(group_by).getAttribute("value");
Reporting.RestoreQuery.show_group_by(name, $('group_by_' + axis + 's'));
});
},
restore_filters: function () {
// FIXME: rm_xxx values for filters have to be set after re-displaying them
$$("tr[data-selected=true]").each(function (e) {
var rm_box = e.select("input[id^=rm]").first();
var filter_name = e.getAttribute("data-filter-name");
rm_box.value = filter_name;
Reporting.Filters.select_option_enabled($("add_filter_select"), filter_name, false);
});
}
};
Reporting.onload(function () {
Reporting.RestoreQuery.restore_group_bys();
Reporting.RestoreQuery.restore_filters();
});

@ -100,21 +100,6 @@
vertical-align: top;
}
/* Aligning filter elements at the top. */
.new_report fieldset#filters table td {
vertical-align: top;
border-spacing: 5px 5px;
border-color: white;
border-style: solid;
border-width: 2px 0px 0px;
}
.new_report fieldset#filters table td > label {
left: 3px;
top: 3px;
position: relative;
}
/* Overwriting styling for headlines within the query. */
/* TODO: Font-size seems to be a bit odd. Needs some love. */
.new_report fieldset h3 {
@ -183,11 +168,10 @@
}
.filter_rem {
color: transparent;
overflow: hidden;
cursor: pointer;
background-repeat: no-repeat;
background-color: transparent;
background-position: 50%;
background: no-repeat center center transparent;
height: 16px;
width: 16px;
border-style: none;
@ -208,11 +192,11 @@
margin-top: 6px;
}
.new_report fieldset#filters table tr.filter:hover {
fieldset#filter-settings table tr.filter:hover {
background: #aaa;
}
.new_report fieldset#filters table tr.filter {
fieldset#filter-settings table tr.filter {
color: #000;
background: #ededed;
-webkit-border-radius: 5px;
@ -220,6 +204,22 @@
border-radius: 5px;
}
/* Aligning filter elements at the top. */
fieldset#filter-settings table td {
vertical-align: top;
border-spacing: 5px 5px;
border-color: white;
border-style: solid;
border-width: 2px 0px 0px;
padding: 2px;
vertical-align: middle;
}
fieldset#filter-settings table td > label {
left: 3px;
top: 3px;
position: relative;
}
.drag_element {
/*cursor: move;*/
@ -356,7 +356,38 @@ td:hover .drill_down, th:hover .drill_down {
margin: 2px;
}
div#button_form {
.buttons .apply {
background-color: #9a9a9a;
border: none;
cursor: pointer;
margin: 0px;
overflow: visible;
text-align: center;
white-space: nowrap;
-moz-border-radius: 3px;
border-radius: 3px;
padding: 4px;
}
.buttons .apply:hover {
background-color: #666666;
}
.buttons .apply span em {
color: white;
display: block;
font-size: 11px;
font-style: normal;
font-weight: bold;
line-height: 17px;
}
.buttons .apply span {
display: inline-block;
margin: 0px;
}
div.button_form {
/* TODO IE Compatibility! */
background-color: white;
border: 1px solid grey;
@ -365,17 +396,20 @@ div#button_form {
left: 100px;
position: absolute;
padding: 5px;
margin-top: -10px;
}
div#button_form * input#name {
div.button_form * input#name {
width: 200px
}
div#button_form * input[type="button"] {
div.button_form * input[type="button"] {
float: right;
} br { clear: right; }
div.button_form p * {
margin: 2px;
}
/***** Ajax indicator ******/
#ajax-indicator {
font-family: Verdana, sans-serif;

@ -301,5 +301,21 @@ class Report < ActiveRecord::Base
self.class.field
end
def mapping
self.class.method(:mapping).to_proc
end
def self.mapping(value)
value.to_s
end
def self.mapping_for(field)
@field_map ||= (engine::Filter.all + engine.GroupBy.all).inject(Hash.new {|h,k| h[k] = []}) do |hash,cbl|
hash[cbl.field] << cbl.mapping
end
@field_map[field]
end
end
end

@ -9,7 +9,7 @@ module Report::Controller
before_filter :determine_engine
before_filter :prepare_query, :only => [:index, :create]
before_filter :find_optional_report, :only => [:index, :show, :update, :delete]
before_filter :find_optional_report, :only => [:index, :show, :update, :delete, :rename]
end
end
@ -187,14 +187,14 @@ module Report::Controller
##
# Prepare the query from the request
def prepare_query
determine_filter_settings
determine_settings
@query = build_query(session[report_engine.name.underscore.to_sym][:filters], session[report_engine.name.underscore.to_sym][:groups])
end
##
# Determine the query settings the current request and save it to
# the session.
def determine_filter_settings
def determine_settings
if force_default?
filters = default_filter_parameters
groups = default_group_parameters

@ -9,6 +9,10 @@ class Report::Filter
@all ||= Set[]
end
def self.reset!
@all = nil
end
def self.all_grouped
all.group_by { |f| f.applies_for }.to_a.sort { |a,b| a.first.to_s <=> b.first.to_s }
end

@ -12,6 +12,10 @@ class Report::GroupBy
Set[engine::GroupBy::SingletonValue]
end
def self.reset!
@all = nil
end
def self.all_grouped
all.group_by { |f| f.applies_for }.to_a.sort { |a,b| a.first.to_s <=> b.first.to_s }
end

@ -37,7 +37,7 @@ class Report::Operator
new "w", :arity => 0, :label => :label_this_week do
def modify(query, field, offset = nil)
offset ||= 0
from = Time.now.at_beginning_of_week - ((l(:general_first_day_of_week).to_i % 7) + 1).days
from = Time.now.at_beginning_of_week - ((I18n.t(:general_first_day_of_week).to_i % 7) + 1).days
from -= offset.days
'<>d'.to_operator.modify query, field, from, from + 7.days
end

@ -46,6 +46,10 @@ module Report::QueryUtils
ActiveRecord::Base.connection.quote_string(str)
end
def current_language
::I18n.locale
end
##
# Creates a SQL fragment representing a collection/array.
#

@ -17,12 +17,10 @@ class Report::Walker
end
def for_empty_cell(&block)
puts __method__ unless block_given?
access_block(:empty_cell, &block) || access_block(:cell)
end
def access_block(name, &block)
puts method.center(80, '= '), caller[0..1] unless block_given?
@blocks ||= {}
@blocks[name] = block if block
@blocks[name]

@ -2,7 +2,7 @@ class Widget::Controls::QueryName < Widget::Base
def render
options = { :id => "query_saved_name", "data-translations" => translations }
if @query.new_record?
name = l(:label_save_this_query)
name = l(:label_new_report)
icon = ""
else
name = @query.name

@ -2,19 +2,21 @@ class Widget::Controls::SaveAs < Widget::Base
def render
if @query.new_record?
link_name = l(:button_save)
icon = "icon-save"
else
link_name = l(:button_save_as)
icon = "icon-save-as"
end
button = link_to link_name, "#",
:class => 'breadcrumb_icon icon-save-as',
:id => 'query-icon-save-as', :title => l(:button_save_as)
:class => "breadcrumb_icon #{icon}",
:id => 'query-icon-save-as', :title => link_name
button + render_popup
end
def render_popup_form
name = content_tag :p do
label_tag(:query_name, l(:field_name)) +
text_field_tag(:query_name, @query.name || l(:label_default))
text_field_tag(:query_name, @query.name)
end
box = content_tag :p do
label_tag(:query_is_public, l(:field_is_public)) +
@ -27,7 +29,7 @@ class Widget::Controls::SaveAs < Widget::Base
content_tag(:p) do
save = link_to content_tag(:span, content_tag(:em, l(:button_save))), "#",
:id => "query-icon-save-button",
:class => "button save",
:class => "button reporting_button save",
:"data-target" => url_for(:action => 'create', :set_filter => '1')
cancel = link_to l(:button_cancel), "#",
:id => "query-icon-save-as-cancel",

@ -34,7 +34,9 @@ class Widget::Filters < Widget::Base
def render_filters
active_filters = @query.filters.select { |f| f.class.display? }
engine::Filter.all.collect do |filter|
opts = {:id => "tr_#{filter.underscore_name}", :class => "#{filter.underscore_name}"}
opts = {:id => "tr_#{filter.underscore_name}",
:class => "#{filter.underscore_name} filter",
:"data-filter-name" => filter.underscore_name }
active_instance = active_filters.detect { |f| f.class == filter }
if active_instance
opts[:"data-selected"] = true

@ -3,8 +3,7 @@ class Widget::Filters::RemoveButton < Widget::Filters::Base
content_tag :td, :width => "25px" do
tag :input, :id => "rm_#{filter_class.underscore_name}",
:name => "fields[]", :type => "button", :value => "",
:class => "icon filter_rem icon-filter-rem",
:"data-filter-name" => filter_class.underscore_name
:class => "icon filter_rem icon-filter-rem"
end
end
end

@ -3,7 +3,7 @@ class Widget::Filters::TextBox < Widget::Filters::Base
content_tag :td do
content_tag :div, :id => "#{filter_class.underscore_name}_arg_1", :class => "filter_values" do
text_field_tag("values[#{filter_class.underscore_name}]", "",
:size => 150,
:size => "6",
:class => "select-small",
:id => "#{filter_class.underscore_name}_arg_1_val",
:'data-filter-name' => filter_class.underscore_name)

@ -1,6 +1,6 @@
class Widget::Settings < Widget::Base
def render
form_tag("#", {:id => 'query_form', :method => :post}) do |query_form|
form_tag("#", {:id => 'query_form', :method => :post}) do
content_tag :div, :id => "query_form_content" do
fieldsets = render_widget Widget::Settings::Fieldset, @query, { :type => "filter" } do

@ -1,24 +1,76 @@
class Widget::Table < Widget::Base
extend Report::InheritedAttribute
include ReportingHelper # FIXME ugs in the ugly. have to think of something else for mapping stuff
inherited_attribute :debug, :default => false
attr_accessor :debug
attr_accessor :fields
attr_accessor :mapping
def initialize(query, options = {})
def initialize(query)
raise ArgumentError, "Tables only work on Reports!" unless query.is_a? Report
super(query)
super
end
def debug?
!!debug
end
def show_result(*args)
map :show_result, *args
end
def show_row(*args)
map :show_row, *args
end
def label_for(*args)
map :label, *args
end
def entry_for(*args)
map :entry, *args
end
def edit_content(*args)
map :edit, *args
end
def debug_fields(*args)
map :debug_fields, *args
end
def raw_result(result)
mapped = mapping[:raw_result]
if mapped
mapped.call self, result
else
show_result(result, 0)
end
end
def show_field(field, *args)
mapped = mapping[:show_field]
if mapped
mapped.call self, field, *args
else
engine::Chainable.mapping_for(field).first.call field, *args
end
end
def map(to_map, *args)
fail "Table Widget #{self.class} needs a mapping for :#{to_map}" unless mapping[to_map]
mapping[to_map.to_sym].call self, *args
end
def render_with_options(options = {}, &block)
@fields ||= (options[:fields] || @query.result.important_fields)
@debug ||= (options[:debug] || false)
@mapping ||= options[:mapping]
fail "mappings need to respond to #call" if mapping.values.any? { |val| not val.respond_to? :call }
canvas = options[:to] ? options[:to] << "\n" : ""
canvas << render(&block)
end
def table_widget
def fancy_table
if @query.depth_of(:row) == 0
@query.row(:singleton_value)
elsif @query.depth_of(:column) == 0
@ -27,14 +79,28 @@ class Widget::Table < Widget::Base
Widget::Table::ReportTable
end
def simple_table
Widget::Table::SimpleTable
end
def entry_table
Widget::Table::EntryTable
end
def render
content_tag :div, :id => "result-table" do
if @query.group_bys.empty? || @query.result.count <= 0
content_tag :p, l(:label_no_data), :class => "nodata"
options = { :debug => debug?, :mapping => @mapping, :fields => @fields }
return content_tag :p, l(:label_no_data), :class => "nodata" if @query.result.count <= 0
if @query.group_bys.empty?
render_widget entry_table, @query, options
elsif @query.group_bys.size == 1
render_widget simple_table, @query, options
else
render_widget table_widget, @query, { :debug => debug? }
render_widget fancy_table, @query, options
end
end
end
end

@ -2,9 +2,9 @@ class Widget::Table::ReportTable < Widget::Table
attr_accessor :walker
def initialize(report, options = {})
def initialize(query)
super
@walker = @query.walker
@walker = query.walker
end
def render

Loading…
Cancel
Save