Merge branch 'feature/widgets' of https://dev.finn.de/git/reporting-engine into feature/widgets

pull/6827/head
Tim Felgentreff 14 years ago
commit 50fb205ca8
  1. BIN
      assets/images/icon_info_red.gif
  2. 159
      assets/javascripts/cordinc_tooltip.js
  3. 55
      assets/stylesheets/help.css
  4. 3
      config/locales/de.yml
  5. 2
      config/locales/en.yml
  6. 16
      lib/report/chainable.rb
  7. 30
      lib/widget/base.rb
  8. 3
      lib/widget/controls/clear.rb
  9. 55
      lib/widget/controls/help.rb
  10. 2
      lib/widget/controls/save_as.rb
  11. 24
      lib/widget/filters.rb
  12. 15
      lib/widget/group_bys.rb
  13. 23
      lib/widget/settings.rb
  14. 8
      lib/widget/settings/fieldset.rb

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 B

@ -0,0 +1,159 @@
/*
* Copyright (c) 2009 Charles Cordingley (www.cordinc.com)
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* cordinc_tooltip.js, v1.0.2 - 27 August 2008
* For help see www.cordinc.com/projects/tooltips.html
*/
var Tooltip = Class.create({
initialize: function(target, tooltip) {
var options = Object.extend({
start_effect: function(element) {},
end_effect: function(element) {},
zindex: 1000,
offset: {x:0, y:0},
hook: {target:'topRight', tip:'bottomLeft'},
trigger: false,
DOM_location: false,
className: false,
delay: {}
}, arguments[2] || {});
this.target = $(target);
this.show_at = (options.show_at_id !== undefined) ? $(options.show_at_id) : undefined
this.tooltip = $(tooltip);
this.options = options;
this.event_target = this.options.trigger?$(this.options.trigger):this.target;
if (this.options.className) {
this.tooltip.addClassName(this.options.className);
}
this.tooltip.hide();
this.display=false;
this.mouse_over = this.displayTooltip.bindAsEventListener(this);
this.mouse_out = this.removeTooltip.bindAsEventListener(this);
this.event_target.observe("mouseover", this.mouse_over);
this.event_target.observe("mouseout", this.mouse_out);
},
displayTooltip: function(event){
event.stop();
if (this.display) {return;}
if (this.options.delay.start) {
var self = this;
this.timer_id = setTimeout(function(){self.timer_id = false; self.showTooltip(event);}, this.options.delay.start*1000);
} else {
this.showTooltip(event);
}
},
showTooltip: function(event) {
var show_at = (this.show_at !== undefined) ? this.show_at : this.target
this.display=true;
position = this.positionTooltip(event);
this.clone = this.tooltip.cloneNode(true);
parentId = this.options.DOM_location?$(this.options.DOM_location.parentId):show_at.parentNode;
successorId = this.options.DOM_location?$(this.options.DOM_location.successorId):show_at;
parentId.insertBefore(this.clone, successorId);
this.clone.setStyle({
position: 'absolute',
top: position.top + "px",
left: position.left + "px",
display: "inline",
zIndex:this.options.zindex,
/* fix for ur dashboard */
visibility: 'visible',
width: "400px"
});
if (this.options.start_effect) {
this.options.start_effect(this.clone);
}
},
positionTooltip: function(event) {
target_position = this.target.cumulativeOffset();
tooltip_dimensions = this.tooltip.getDimensions();
target_dimensions = this.target.getDimensions();
this.positionModify(target_position, target_dimensions, this.options.hook.target, 1);
this.positionModify(target_position, tooltip_dimensions, this.options.hook.tip, -1);
target_position.top += this.options.offset.y;
target_position.left += this.options.offset.x;
return target_position;
},
positionModify: function(position, box, corner, neg) {
if (corner == 'topRight') {
position.left += box.width*neg;
} else if (corner == 'topLeft') {
} else if (corner == 'bottomLeft') {
position.top += box.height*neg;
} else if (corner == 'bottomRight') {
position.top += box.height*neg;
position.left += box.width*neg;
} else if (corner == 'topMid') {
position.left += (box.width/2)*neg;
} else if (corner == 'leftMid') {
position.top += (box.height/2)*neg;
} else if (corner == 'bottomMid') {
position.top += box.height*neg;
position.left += (box.width/2)*neg;
} else if (corner == 'rightMid') {
position.top += (box.height/2)*neg;
position.left += box.width*neg;
}
},
removeTooltip: function(event) {
if (this.timer_id) {
clearTimeout(this.timer_id);
this.timer_id = false;
return;
}
if (this.options.end_effect) {
this.options.end_effect(this.clone);
}
if (this.options.delay.end) {
var self = this;
setTimeout(function(){self.clearTooltip();}, this.options.delay.end*1000);
} else {
this.clearTooltip();
}
},
clearTooltip: function() {
if (this.clone !== undefined && this.clone !== null) {
this.clone.remove();
this.clone = null;
this.display=false;
}
},
destroy: function() {
this.event_target.stopObserving("mouseover", this.mouse_over);
this.event_target.stopObserving("mouseout", this.mouse_out);
this.clearTooltip();
}
})

@ -0,0 +1,55 @@
.help {
margin-left: 5px;
margin-right: 5px;
}
.tooltip {
position: absolute;
margin-top: 3px;
margin-bottom: 3px;
padding: 3px;
width: 400px;
z-index: 256;
color: #000000;
border: 1px solid #000000;
background: #FFFFCC;
font: 12px Verdana, sans-serif;
text-align: left;
padding: -50px;
line-height: 16px;
font-size: 11px;
}
.filter-icon {
}
.filter-tip {
}
.group-by-icon {
float: right;
margin-right: 5px;
}
.group-by-tip {
margin-top: -300px;
margin-left: -475px;
}
.filter-legend-icon {
}
.filter-legend-tip {
margin-left: 10px;
}
.group_by-legend-icon {
}
.group_by-legend-tip {
margin-left: 10px;
}

@ -18,7 +18,10 @@ de:
label_sum: Summe label_sum: Summe
label_none: "(Keine Angabe)" label_none: "(Keine Angabe)"
label_help: Hilfe
description_drill_down: Details anzeigen description_drill_down: Details anzeigen
validation_failure_date: "ist kein gültiges Datum" validation_failure_date: "ist kein gültiges Datum"
validation_failure_integer: "ist keine ganze Zahl" validation_failure_integer: "ist keine ganze Zahl"

@ -18,6 +18,8 @@ en:
label_sum: Sum label_sum: Sum
label_none: "(no data)" label_none: "(no data)"
label_help: Help
description_drill_down: Show details description_drill_down: Show details
validation_failure_date: "is not a valid date" validation_failure_date: "is not a valid date"

@ -309,7 +309,6 @@ class Report < ActiveRecord::Base
value.to_s value.to_s
end end
def self.mapping_for(field) def self.mapping_for(field)
@field_map ||= (engine::Filter.all + engine.GroupBy.all).inject(Hash.new {|h,k| h[k] = []}) do |hash,cbl| @field_map ||= (engine::Filter.all + engine.GroupBy.all).inject(Hash.new {|h,k| h[k] = []}) do |hash,cbl|
hash[cbl.field] << cbl.mapping hash[cbl.field] << cbl.mapping
@ -317,5 +316,20 @@ class Report < ActiveRecord::Base
@field_map[field] @field_map[field]
end end
def help_text
self.class.help_text
end
##
# Sets a help text to be displayed for this kind of Chainable.
def self.help_text=(sym)
@help_text = sym
end
def self.help_text(sym = nil)
@help_text = sym if sym
@help_text
end
end end
end end

@ -11,10 +11,40 @@ class Widget::Base < Widget
end end
def render_with_options(options = {}, &block) def render_with_options(options = {}, &block)
self.help_text = options[:help_text]
if canvas = options[:to] if canvas = options[:to]
canvas << "\n" << render(&block) canvas << "\n" << render(&block)
else else
render(&block) render(&block)
end end
end end
##
# An optional help text. If defined the Help Widget
# displaying the given text is going to be placed
# next to this Widget, if it supports that.
def help_text
@help_text
end
def help_text=(text)
@help_text = text
end
##
# Appends the Help Widget with this Widget's help text
# if it is defined to the input.
# If the help text is not defined the input is returned.
def maybe_with_help(html, options = {})
text = options[:text]
text ||= help_text unless options[:ignore_default]
if text
help = render_widget Widget::Controls::Help, text do
options
end
html + help
else
html
end
end
end end

@ -1,5 +1,6 @@
class Widget::Controls::Clear < Widget::Base class Widget::Controls::Clear < Widget::Base
def render def render
link_to content_tag(:span, content_tag(:em, l(:"button_clear"), :class => "button-icon icon-clear")), '#', :id => 'query-link-clear', :class => 'button secondary' html = link_to content_tag(:span, content_tag(:em, l(:"button_clear"), :class => "button-icon icon-clear")), '#', :id => 'query-link-clear', :class => 'button secondary'
maybe_with_help html
end end
end end

@ -0,0 +1,55 @@
##
# Usgae: render_widget Widget::Controls::Help, :text
#
# Where :text is a i18n key.
class Widget::Controls::Help < Widget::Base
def render
id = "tip:#{@query}"
options = {:icon => {}, :tooltip => {}}
options.merge!(yield) if block_given?
sai = options[:show_at_id] ? ", show_at_id: '#{options[:show_at_id]}'" : ""
icon = tag :img, :src => '/images/icon_info_red.gif', :id => "target:#{@query}"
tip = content_tag_string :div, l(@query), tip_config(options[:tooltip]), false
script = content_tag :script,
"new Tooltip('target:#{@query}', 'tip:#{@query}', {className: 'tooltip'#{sai}});",
{:type => 'text/javascript'}, false
target = content_tag :a, icon + tip, icon_config(options[:icon])
target + script
end
def icon_config(options)
add_class = lambda do |cl|
if cl
"help #{cl}"
else
"help"
end
end
options.mega_merge! :href => '#', :class => add_class
end
def tip_config(options)
add_class = lambda do |cl|
if cl
"#{cl} tooltip"
else
"tooltip"
end
end
options.mega_merge! :id => "tip:#{@query}", :class => add_class
end
end
class Hash
def mega_merge!(hash)
hash.each do |key, value|
if value.kind_of?(Proc)
self[key] = value.call(self[key])
else
self[key] = value
end
end
self
end
end

@ -10,7 +10,7 @@ class Widget::Controls::SaveAs < Widget::Base
button = link_to content_tag(:span, content_tag(:em, link_name, :class => "button-icon icon-save-as")), "#", button = link_to content_tag(:span, content_tag(:em, link_name, :class => "button-icon icon-save-as")), "#",
:class => "button secondary", :class => "button secondary",
:id => 'query-icon-save-as', :title => link_name :id => 'query-icon-save-as', :title => link_name
button + render_popup maybe_with_help(button) + render_popup
end end
def render_popup_form def render_popup_form

@ -12,10 +12,18 @@ class Widget::Filters < Widget::Base
end end
end end
select = content_tag :div, :id => "add_filter_block" do select = content_tag :div, :id => "add_filter_block" do
select_tag 'add_filter_select', add_filter = select_tag 'add_filter_select',
options_for_select([["-- #{l(:label_filter_add)} --",'']] + selectables), options_for_select([["-- #{l(:label_filter_add)} --",'']] + selectables),
:class => "select-small", :class => "select-small",
:name => nil :name => nil
maybe_with_help add_filter, {
:icon => {
:class => 'filter-icon'
},
:tooltip => {
:class => 'filter-tip'
}
}
end end
content_tag(:div, table + select) content_tag(:div, table + select)
end end
@ -70,6 +78,20 @@ class Widget::Filters < Widget::Base
render_widget Filters::MultiValues, f, :to => html render_widget Filters::MultiValues, f, :to => html
end end
end end
render_filter_help f, :to => html
render_widget Filters::RemoveButton, f, :to => html render_widget Filters::RemoveButton, f, :to => html
end end
def render_filter_help(filter, options = {})
html = content_tag :td, :width => "25px" do
if filter.help_text
render_widget Widget::Controls::Help, filter.help_text
end
end
if canvas = options[:to]
canvas << "\n" << html
else
html
end
end
end end

@ -24,7 +24,7 @@ class Widget::GroupBys < Widget::Base
end end
end end
def render_group(type, initially_selected) def render_group(type, initially_selected, show_help = false)
initially_selected = initially_selected.map do |group_by| initially_selected = initially_selected.map do |group_by|
[group_by.class.underscore_name, l(group_by.class.label)] [group_by.class.underscore_name, l(group_by.class.label)]
end end
@ -46,13 +46,24 @@ class Widget::GroupBys < Widget::Base
end.join.html_safe end.join.html_safe
content content
end end
if show_help
maybe_with_help out.html_safe, {
:icon => {
:class => 'group-by-icon'
},
:tooltip => {
:class => 'group-by-tip'
}
}
else
out.html_safe out.html_safe
end end
end end
end
def render def render
content_tag :div, :id => 'group_by_area' do content_tag :div, :id => 'group_by_area' do
out = render_group 'columns', @query.group_bys(:column) out = render_group 'columns', @query.group_bys(:column), true
out += render_group 'rows', @query.group_bys(:row) out += render_group 'rows', @query.group_bys(:row)
out.html_safe out.html_safe
end end

@ -3,11 +3,13 @@ class Widget::Settings < Widget::Base
form_tag("#", {:id => 'query_form', :method => :post}) do form_tag("#", {:id => 'query_form', :method => :post}) do
content_tag :div, :id => "query_form_content" do content_tag :div, :id => "query_form_content" do
fieldsets = render_widget Widget::Settings::Fieldset, @query, { :type => "filter" } do fieldsets = render_widget Widget::Settings::Fieldset, @query,
{ :type => "filter", :help_text => self.filter_help } do
render_widget Widget::Filters, @query render_widget Widget::Filters, @query
end end
fieldsets += render_widget Widget::Settings::Fieldset, @query, { :type => "group_by" } do fieldsets += render_widget Widget::Settings::Fieldset, @query,
{ :type => "group_by", :help_text => self.group_by_help } do
render_widget Widget::GroupBys, @query render_widget Widget::GroupBys, @query
end end
@ -18,9 +20,24 @@ class Widget::Settings < Widget::Base
render_widget(Widget::Controls::Clear, @query, :to => widgets) render_widget(Widget::Controls::Clear, @query, :to => widgets)
render_widget(Widget::Controls::Delete, @query, :to => widgets) render_widget(Widget::Controls::Delete, @query, :to => widgets)
end end
fieldsets + controls fieldsets + controls
end end
end end
end end
def filter_help
if help_text.kind_of?(Array)
help_text[0]
else
nil
end
end
def group_by_help
if help_text.kind_of?(Array)
help_text[1]
else
nil
end
end
end end

@ -7,8 +7,14 @@ class Widget::Settings::Fieldset < Widget::Base
end end
def render def render
hash = self.hash
content_tag :fieldset, :id => @id, :class => "collapsible collapsed" do content_tag :fieldset, :id => @id, :class => "collapsible collapsed" do
html = content_tag :legend, l(@label), :onclick => "toggleFieldset(this);" #FIXME: onclick content = maybe_with_help l(@label),
:show_at_id => hash.to_s,
:icon => { :class => "#{@type}-legend-icon" },
:tooltip => { :class => "#{@type}-legend-tip" }
html = content_tag :legend, content,
{:onclick => "toggleFieldset(this);", :id => hash.to_s}, false #FIXME: onclick
html + yield html + yield
end end
end end

Loading…
Cancel
Save