Skip to content
Browse files

Added support for headings, linked reports and sub reports

  • Loading branch information...
1 parent 612c44a commit 72dd50f0f2e43ecf70021eeeffd527c24cdda5f8 Joshua Lippiner committed Jul 15, 2009
View
32 Rakefile
@@ -2,7 +2,7 @@ require "rake/testtask"
task :default => ["test:all"]
task :test => ["test:all"]
-namespace :test do
+namespace :test do
desc "Run Test Suite"
Rake::TestTask.new("all") do |test|
test.pattern = "test/dynamic_reports.rb"
@@ -13,32 +13,32 @@ end
desc "Build the dynamic_reports gem and then install it."
task :gem do
- puts `gem uninstall dynamic_reports ; rm -f dynamic_reports-0.0.0.gem; gem build gemspec.rb ; gem install ./dynamic_reports-0.0.0.gem --no-ri -l`
+ puts `gem uninstall dynamic_reports ; rm -f dynamic_reports-0.0.0.gem; gem build gemspec.rb ; gem install ./dynamic_reports-0.0.0.gem --no-ri -l`
end
-namespace :gem do
+namespace :gem do
desc "Build the dynamic_reports gem."
- task :build do
+ task :build do
puts `gem build gemspec.rb`
end
desc "Install the dynamic_reports gem."
- task :install do
+ task :install do
%x{gem install dynamic_reports*.gem --no-rdoc --no-ri -l}
end
end
begin
-require "rake/rdoctask"
-require "rdoc/generator"
-Rake::RDocTask.new do |rdoc|
- rdoc.rdoc_dir = "doc"
- rdoc.title = "Dynamic Reports"
- rdoc.options << "--line-numbers"
- rdoc.options << "--charset" << "utf-8"
- rdoc.rdoc_files.include("README.rdoc", "HISTORY")
- rdoc.rdoc_files.include("lib/*.rb")
- rdoc.rdoc_files.include("lib/dynamic_reports/*.rb")
-end
+ require "rake/rdoctask"
+ require "rdoc/generator"
+ Rake::RDocTask.new do |rdoc|
+ rdoc.rdoc_dir = "doc"
+ rdoc.title = "Dynamic Reports"
+ rdoc.options << "--line-numbers"
+ rdoc.options << "--charset" << "utf-8"
+ rdoc.rdoc_files.include("README.rdoc", "HISTORY")
+ rdoc.rdoc_files.include("lib/*.rb")
+ rdoc.rdoc_files.include("lib/dynamic_reports/*.rb")
+ end
rescue
puts "Skipping loading of rdoc tasks, missing rdoc gem."
View
BIN dynamic_reports-0.0.0.gem
Binary file not shown.
View
43 examples/rails/all_visitors_report.rb
@@ -0,0 +1,43 @@
+# Sample Report Definition
+#
+# Must be located at APP/REPORTS/ALL_VISITOR_REPORT.RB
+#
+class AllVisitorsReport < DynamicReports::Report
+ title "All Visitors"
+ columns :recorded_at, :visits, :pageviews
+
+ chart :visits do
+ title "visits"
+ type "line"
+ columns :visits
+ label_column :recorded_at
+ end
+
+ chart :visits_and_pageviews, {:chdlp=>"b"} do
+ title "Visits and Pageviews END"
+ type "column"
+ width "300"
+ height "600"
+ columns :visits, :pageviews
+ label_column :recorded_at
+ end
+
+ chart :visits_and_pageviews, {:chdlp=>"b"} do
+ title "Visits and Pageviews END"
+ type "bar"
+ width "600"
+ height "300"
+ columns :visits, :pageviews
+ label_column :recorded_at
+ end
+
+
+ chart :pie do
+ title "Visits"
+ type "pie"
+ label_column :recorded_at
+ columns :visits
+ width "500"
+ end
+
+end
View
18 examples/rails/sales_report.rb.rb
@@ -0,0 +1,18 @@
+# Sample Report Definition
+#
+# must be located at APP/REPORTS/SALES_REPORT.RB
+#
+class SalesReport < DynamicReports::Report
+ title "Sales By Territory"
+ columns :territory, :total_sales, :net_profit, :gross_profit
+ class_name "sales_div"
+
+ chart :pie do
+ title "Territory Breakdown"
+ type "pie"
+ label_column :territory
+ columns :net_profit
+ width "500"
+ end
+
+end
View
16 examples/rails/sample_controller.rb.rb
@@ -0,0 +1,16 @@
+require 'dynamic_reports'
+
+class SampleController < ApplicationController
+
+ def visitors_report
+ a = Analytics.all(:limit => 20)
+
+ render :inline => AllVisitorsReport.on(a).to_html
+ end
+
+ def sales_report
+ sales = Sales.find(:all, :conditions => "Territory <> 'Canada'")
+
+ render :inline => SalesReport.on(sales).to_html
+ end
+end
View
25 lib/dynamic_reports/reports.rb
@@ -8,7 +8,7 @@ module DynamicReports
class Report
@@default_engine = "erb"
- attr_accessor :name, :title, :sub_title, :columns, :charts, :records, :template, :class_name, :styles
+ attr_accessor :name, :title, :sub_title, :columns, :charts, :records, :template, :class_name, :styles, :links
# views accessor, array of view paths.
def views
@@ -160,6 +160,29 @@ def chart(name, *chart_options, &block)
chart_options = chart_options.shift || {}
charts(Chart.configure(name, chart_options, &block))
end
+
+ # Return an array of links defined for the report.
+ def links(object=nil)
+ options[:links] ||= []
+ options[:links] << object if object
+ options[:links]
+ end
+
+ # Define a link for the report
+ #
+ # Pass parameters within {}. Parameters are replaced with the row values
+ # from passed records. You do NOT need to include a parameter value as a
+ # report column for it to be used in a link. For example, you might
+ # want to generate a link with an ID field in it but not display that id
+ # in the actual report. Just include {id} to do this.
+ #
+ # Example:
+ #
+ # link :visits, '/reports/{visit}/details?date={recorded_at}'
+ #
+ def link(column, url, link_options=nil)
+ links({:column => column, :url => url, :link_options => link_options})
+ end
# Method for instanciating a report instance on a set of given records.
#
View
54 lib/dynamic_reports/templates.rb
@@ -32,7 +32,7 @@ def builder(options={}, locals={}, &block)
# TODO: Add Report Helpers for injection
def titleize(object)
- object.to_s.split('_').each{ |word| word.capitalize! }.join(' ')
+ object.to_s.split('_').each{ |word| word.capitalize! }.join(' ')
end
def commify(object)
@@ -43,9 +43,49 @@ def commify(object)
end
end
+ def linkcheck(record, column_object)
+ val = ''
+
+ if column_object.is_a?(Hash)
+ column = column_object[:column]
+ else
+ column = column_object
+ end
+
+ report.links.each do |link|
+ if link[:column] == column
+ url = link[:url]
+ url.scan(/\{(\w+)\}/).each do |parameter|
+ parameter = parameter.to_s
+ url = url.gsub("{#{parameter}}", CGI::escape(get_record_value(record, parameter.to_sym).to_s))
+ end
+
+ url_attribute_str = []
+ link[:link_options].keys.each do |key|
+ url_attribute_str << "#{key}='#{link[:link_options][key]}'"
+ end if link[:link_options]
+
+ val = "<a href='#{url}' #{url_attribute_str.join(' ')}>#{get_record_value(record,column)}</a>"
+ break
+ end if link[:column]
+ end if report.links
+
+ val.blank? ? get_record_value(record,column) : val
+ end
+
+ def get_record_value(record, column)
+ if record.is_a?(Hash)
+ record[column]
+ elsif record.respond_to?(column.to_sym)
+ record.send(column.to_sym)
+ else
+ column
+ end
+ end
+
def chart_url(chart,report)
columns = chart.columns ? chart.columns : report.columns
- chart_type = chart.type.nil? ? :line : chart.type.to_sym
+ chart_type = chart.type.nil? ? :line : chart.type.to_sym
case chart_type
when :line
Charts.line_chart(chart,columns,report)
@@ -62,7 +102,7 @@ def chart_url(chart,report)
end
private
-
+
def render(engine, template, options={}, locals={})
# merge app-level options
options = self.class.send(engine).merge(options) if self.class.respond_to?(engine)
@@ -74,7 +114,7 @@ def render(engine, template, options={}, locals={})
content_type = options.delete(:content_type)
locals = options.delete(:locals) || locals || {}
locals.merge!(:report => @report, :options => options || {})
-
+
# render template
data, options[:filename], options[:line] = lookup_template(engine, template, views, content_type)
output = __send__("render_#{engine}", template, data, options, locals)
@@ -101,7 +141,7 @@ def lookup_template(engine, template, views, content_type = nil, filename = nil,
lookup_template(engine, cached[:template], views, content_type, cached[:filename], cached[:line])
else
filename = "#{template}.#{content_type}.#{engine}"
- dir = views.to_a.detect do |view|
+ dir = views.to_a.detect do |view|
::File.exists?(::File.join(view, filename))
end
if dir
@@ -172,7 +212,7 @@ def require_warn(engine)
require engine.downcase
end
-
-
+
+
end
end
View
37 lib/dynamic_reports/views/default_report.html.haml
@@ -12,11 +12,11 @@
}
\.dynamic_report table tr th {
color: white;
- background: gray;
+ background: #666666;
padding:5px;
}
\.dynamic_report table tr td {
- border: 1px solid black;
+ border: 1px solid #333333;
padding:3px 15px;
}
\.dynamic_report .report_charts {
@@ -25,6 +25,21 @@
\.dynamic_report .report_chart {
margin:15px;
}
+ \.dynamic_report .subreport_row td {
+ padding: 10px 10px 10px 20px;
+ background-color: #FFFFCC;
+ font-size: 90%;
+ }
+ \.dynamic_report .subreport table tr td {
+ border: 1px dotted #CCCC99;
+ padding:3px 5px;
+ background-color: white;
+ }
+ \.dynamic_report .subreport table tr th {
+ color: black;
+ background: #CCCCCC;
+ padding:3px;
+ }
.dynamic_report{ :id => report.class_name }
- if report.title
@@ -40,18 +55,22 @@
%tr.report_header_row
- report.columns.each do |column|
%th
- = options[:titleize] ? titleize(column) : column
+ - if column.is_a?(Hash)
+ - if column.keys.include?(:heading)
+ = options[:titleize] ? titleize(column[:heading]) : column[:heading]
+ -else
+ = options[:titleize] ? titleize(column[:column]) : column[:column]
+ -else
+ = options[:titleize] ? titleize(column) : column
%tbody.report_body
- report.records.each do |record|
%tr.report_row
- report.columns.each do |column|
%td
- - if record.is_a?(Hash)
- = (options[:commas] == true) ? commify(record[column]) : record[column]
- - elsif record.respond_to?(column.to_sym)
- = (options[:commas] == true) ? commify(record.send(column.to_sym)) : record.send(column.to_sym)
- - else
- = column
+ = (options[:commas] == true) ? commify(linkcheck(record,column)) : linkcheck(record,column)
+ %tr.subreport_row{:style => "display:none"}
+ %td{:colspan => report.columns.size}
+ .subreport
- if report.charts && report.charts.class === Hash
- report.charts.each_pair do |name, chart|

0 comments on commit 72dd50f

Please sign in to comment.
Something went wrong with that request. Please try again.