query_report 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/query_report/chart/custom_chart.rb +23 -3
- data/lib/query_report/chart/pie_chart.rb +19 -3
- data/lib/query_report/chart/themes.rb +116 -0
- data/lib/query_report/helper.rb +2 -2
- data/lib/query_report/report.rb +13 -11
- data/lib/query_report/report_pdf.rb +107 -0
- data/lib/query_report/row.rb +11 -0
- data/lib/query_report/version.rb +1 -1
- data/query_report.gemspec +2 -0
- metadata +37 -2
@@ -1,7 +1,10 @@
|
|
1
|
+
require 'query_report/row'
|
2
|
+
require 'query_report/chart/themes'
|
3
|
+
|
1
4
|
module QueryReport
|
2
5
|
module Chart
|
3
6
|
class CustomChart
|
4
|
-
attr_reader :title, :type, :options, :data_table, :row
|
7
|
+
attr_reader :title, :type, :options, :data_table, :row, :rows
|
5
8
|
|
6
9
|
def initialize(type, title, query, options={})
|
7
10
|
@type = type
|
@@ -9,6 +12,7 @@ module QueryReport
|
|
9
12
|
@query = query
|
10
13
|
@options = options
|
11
14
|
@row = []
|
15
|
+
@rows = []
|
12
16
|
@data_table = GoogleVisualr::DataTable.new
|
13
17
|
end
|
14
18
|
|
@@ -21,15 +25,31 @@ module QueryReport
|
|
21
25
|
val = block.call(@query)
|
22
26
|
@data_table.new_column(val.kind_of?(String) ? 'string' : 'number', column_title)
|
23
27
|
@row << val
|
28
|
+
@rows << Row.new(column_title, val)
|
24
29
|
end
|
25
30
|
|
26
31
|
def prepare
|
27
|
-
data_table.add_row(@row)
|
32
|
+
@data_table.add_row(@row)
|
28
33
|
opts = {:width => 500, :height => 240, :title => @title}.merge(options)
|
29
34
|
chart_type = "#{type}_chart".classify
|
30
35
|
chart_type = "GoogleVisualr::Interactive::#{chart_type}".constantize
|
31
|
-
chart_type.new(data_table, opts)
|
36
|
+
chart_type.new(@data_table, opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepare_gruff
|
40
|
+
@gruff = Gruff::Bar.new(options[:width] || 600)
|
41
|
+
@gruff.title = title
|
42
|
+
@gruff.theme = Gruff::Themes::GOOGLE_CHART
|
43
|
+
@rows.each do |row|
|
44
|
+
@gruff.data(row.name.humanize, row.value)
|
45
|
+
end
|
32
46
|
end
|
47
|
+
|
48
|
+
def to_blob
|
49
|
+
prepare_gruff
|
50
|
+
@gruff.to_blob
|
51
|
+
end
|
52
|
+
|
33
53
|
end
|
34
54
|
end
|
35
55
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'query_report/chart/themes'
|
2
|
+
|
1
3
|
module QueryReport
|
2
4
|
module Chart
|
3
5
|
class PieChart
|
@@ -8,9 +10,6 @@ module QueryReport
|
|
8
10
|
@options = options
|
9
11
|
@rows = []
|
10
12
|
@query = query
|
11
|
-
@data_table = GoogleVisualr::DataTable.new
|
12
|
-
@data_table.new_column('string', 'Item')
|
13
|
-
@data_table.new_column('number', 'Value')
|
14
13
|
end
|
15
14
|
|
16
15
|
def add(column_title, &block)
|
@@ -19,10 +18,27 @@ module QueryReport
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def prepare
|
21
|
+
@data_table = GoogleVisualr::DataTable.new
|
22
|
+
@data_table.new_column('string', 'Item')
|
23
|
+
@data_table.new_column('number', 'Value')
|
22
24
|
@data_table.add_rows(@rows)
|
23
25
|
opts = {:width => 500, :height => 240, :title => @title, :is3D => true}.merge(options)
|
24
26
|
GoogleVisualr::Interactive::PieChart.new(@data_table, opts)
|
25
27
|
end
|
28
|
+
|
29
|
+
def prepare_gruff
|
30
|
+
@gruff = Gruff::Pie.new(options[:width] || 600)
|
31
|
+
@gruff.title = title
|
32
|
+
@gruff.theme = Gruff::Themes::GOOGLE_CHART
|
33
|
+
@rows.each do |row|
|
34
|
+
@gruff.data(row[0], row[1])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_blob
|
39
|
+
prepare_gruff
|
40
|
+
@gruff.to_blob
|
41
|
+
end
|
26
42
|
end
|
27
43
|
end
|
28
44
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Gruff
|
2
|
+
module Themes
|
3
|
+
# A color scheme similar to the popular presentation software.
|
4
|
+
KEYNOTE = {
|
5
|
+
:colors => [
|
6
|
+
'#FDD84E', # yellow
|
7
|
+
'#6886B4', # blue
|
8
|
+
'#72AE6E', # green
|
9
|
+
'#D1695E', # red
|
10
|
+
'#8A6EAF', # purple
|
11
|
+
'#EFAA43', # orange
|
12
|
+
'white'
|
13
|
+
],
|
14
|
+
:marker_color => 'white',
|
15
|
+
:font_color => 'white',
|
16
|
+
:background_colors => ['black', '#4a465a']
|
17
|
+
}
|
18
|
+
|
19
|
+
# A color scheme plucked from the colors on the popular usability blog.
|
20
|
+
THIRTYSEVEN_SIGNALS = {
|
21
|
+
:colors => [
|
22
|
+
'#FFF804', # yellow
|
23
|
+
'#336699', # blue
|
24
|
+
'#339933', # green
|
25
|
+
'#ff0000', # red
|
26
|
+
'#cc99cc', # purple
|
27
|
+
'#cf5910', # orange
|
28
|
+
'black'
|
29
|
+
],
|
30
|
+
:marker_color => 'black',
|
31
|
+
:font_color => 'black',
|
32
|
+
:background_colors => ['#d1edf5', 'white']
|
33
|
+
}
|
34
|
+
|
35
|
+
# A color scheme from the colors used on the 2005 Rails keynote
|
36
|
+
# presentation at RubyConf.
|
37
|
+
RAILS_KEYNOTE = {
|
38
|
+
:colors => [
|
39
|
+
'#00ff00', # green
|
40
|
+
'#333333', # grey
|
41
|
+
'#ff5d00', # orange
|
42
|
+
'#f61100', # red
|
43
|
+
'white',
|
44
|
+
'#999999', # light grey
|
45
|
+
'black'
|
46
|
+
],
|
47
|
+
:marker_color => 'white',
|
48
|
+
:font_color => 'white',
|
49
|
+
:background_colors => ['#0083a3', '#0083a3']
|
50
|
+
}
|
51
|
+
|
52
|
+
# A color scheme similar to that used on the popular podcast site.
|
53
|
+
ODEO = {
|
54
|
+
:colors => [
|
55
|
+
'#202020', # grey
|
56
|
+
'white',
|
57
|
+
'#3a5b87', # dark blue
|
58
|
+
'#a21764', # dark pink
|
59
|
+
'#8ab438', # green
|
60
|
+
'#999999', # light grey
|
61
|
+
'black'
|
62
|
+
],
|
63
|
+
:marker_color => 'white',
|
64
|
+
:font_color => 'white',
|
65
|
+
:background_colors => ['#ff47a4', '#ff1f81']
|
66
|
+
}
|
67
|
+
|
68
|
+
# A pastel theme
|
69
|
+
PASTEL = {
|
70
|
+
:colors => [
|
71
|
+
'#a9dada', # blue
|
72
|
+
'#aedaa9', # green
|
73
|
+
'#daaea9', # peach
|
74
|
+
'#dadaa9', # yellow
|
75
|
+
'#a9a9da', # dk purple
|
76
|
+
'#daaeda', # purple
|
77
|
+
'#dadada' # grey
|
78
|
+
],
|
79
|
+
:marker_color => '#aea9a9', # Grey
|
80
|
+
:font_color => 'black',
|
81
|
+
:background_colors => 'white'
|
82
|
+
}
|
83
|
+
|
84
|
+
# A greyscale theme
|
85
|
+
GREYSCALE = {
|
86
|
+
:colors => [
|
87
|
+
'#282828', #
|
88
|
+
'#383838', #
|
89
|
+
'#686868', #
|
90
|
+
'#989898', #
|
91
|
+
'#c8c8c8', #
|
92
|
+
'#e8e8e8', #
|
93
|
+
],
|
94
|
+
:marker_color => '#aea9a9', # Grey
|
95
|
+
:font_color => 'black',
|
96
|
+
:background_colors => 'white'
|
97
|
+
}
|
98
|
+
|
99
|
+
# A pastel theme
|
100
|
+
GOOGLE_CHART = {
|
101
|
+
:colors => [
|
102
|
+
'#3366CC', # blue
|
103
|
+
'#DC3912', # red
|
104
|
+
'#FF9900', # yellow
|
105
|
+
'#109618', # green
|
106
|
+
'#990099', # dk purple
|
107
|
+
'#0099C6', # sky
|
108
|
+
'#DD4477' # grey
|
109
|
+
],
|
110
|
+
:marker_color => '#aea9a9', # Grey
|
111
|
+
:font_color => 'black',
|
112
|
+
:background_colors => 'white'
|
113
|
+
}
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
data/lib/query_report/helper.rb
CHANGED
@@ -4,7 +4,7 @@ module QueryReport
|
|
4
4
|
module Helper
|
5
5
|
def reporter(query, &block)
|
6
6
|
@report ||= QueryReport::Report.new(params)
|
7
|
-
@report.
|
7
|
+
@report.query = query
|
8
8
|
@report.instance_eval &block
|
9
9
|
render_report
|
10
10
|
end
|
@@ -14,7 +14,7 @@ module QueryReport
|
|
14
14
|
format.html { render 'query_report/list' }
|
15
15
|
format.json { render json: @report.records }
|
16
16
|
format.csv { send_data generate_csv_for_report(@report.all_records), :disposition => "attachment;" }
|
17
|
-
format.pdf { render_pdf(ReportPdf.new
|
17
|
+
format.pdf { render_pdf(ReportPdf.new(@report).standard) }
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/lib/query_report/report.rb
CHANGED
@@ -5,8 +5,7 @@ require 'query_report/chart/chart_with_total'
|
|
5
5
|
|
6
6
|
module QueryReport
|
7
7
|
class Report
|
8
|
-
attr_accessor :params, :
|
9
|
-
:filters, :search, :scopes, :current_scope
|
8
|
+
attr_accessor :params, :chart, :charts, :filters, :search, :scopes, :current_scope
|
10
9
|
|
11
10
|
def initialize(params, options={}, &block)
|
12
11
|
@params = params
|
@@ -24,13 +23,6 @@ module QueryReport
|
|
24
23
|
@columns << Column.new(name, options, block)
|
25
24
|
end
|
26
25
|
|
27
|
-
def set_query(query)
|
28
|
-
@query_cache = query
|
29
|
-
#apply ransack
|
30
|
-
@search = query.search(@params[:q])
|
31
|
-
@query_cache = @search.result
|
32
|
-
end
|
33
|
-
|
34
26
|
def columns
|
35
27
|
@columns
|
36
28
|
end
|
@@ -39,6 +31,10 @@ module QueryReport
|
|
39
31
|
@column_names ||= (@columns||[]).collect(&:humanize)
|
40
32
|
end
|
41
33
|
|
34
|
+
def query=(query)
|
35
|
+
@query_cache = query
|
36
|
+
end
|
37
|
+
|
42
38
|
def query
|
43
39
|
apply_filters_and_pagination
|
44
40
|
@query_cache
|
@@ -99,15 +95,19 @@ module QueryReport
|
|
99
95
|
private
|
100
96
|
def apply_filters_and_pagination
|
101
97
|
return if @applied_filters_and_pagination
|
98
|
+
#apply ransack
|
99
|
+
@search = @query_cache.search(@params[:q])
|
100
|
+
@query_cache = @search.result
|
101
|
+
|
102
|
+
#apply scope
|
102
103
|
if @current_scope and !['all', 'delete_all', 'destroy_all'].include?(@current_scope)
|
103
104
|
@query_cache = @query_cache.send(@current_scope)
|
104
105
|
end
|
105
106
|
|
107
|
+
#apply filters
|
106
108
|
@filters.each do |filter|
|
107
109
|
if filter.custom
|
108
110
|
param = @params[:custom_search]
|
109
|
-
#Rails.logger.debug "@params[:custom_search] :: #{@params[:custom_search].inspect}"
|
110
|
-
#Rails.logger.debug "param :: #{param.inspect}"
|
111
111
|
first_val = param[filter.keys.first] rescue nil
|
112
112
|
last_val = param[filter.keys.last] rescue nil
|
113
113
|
case filter.keys.size
|
@@ -120,6 +120,8 @@ module QueryReport
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
123
|
+
|
124
|
+
#apply pagination
|
123
125
|
@query_without_pagination_cache = @query_cache
|
124
126
|
@query_cache = @query_without_pagination_cache.page(@params[:page])
|
125
127
|
@applied_filters_and_pagination = true
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "prawn"
|
2
|
+
require "open-uri"
|
3
|
+
|
4
|
+
class ReportPdf
|
5
|
+
attr_accessor :pdf, :default_options
|
6
|
+
|
7
|
+
def initialize(report)
|
8
|
+
@report = report
|
9
|
+
self.default_options = {alternate_row_bg_color: ["DDDDDD", "FFFFFF"],
|
10
|
+
header_bg_color: 'AAAAAA',
|
11
|
+
color: '000000',
|
12
|
+
light_color: '555555'}
|
13
|
+
self.pdf = Prawn::Document.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_header(options={})
|
17
|
+
#pdf.font("Times-Roman", size: 10) do
|
18
|
+
# pdf.text_box current_institute.address.to_s,
|
19
|
+
# :at => [400, pdf.cursor+20],
|
20
|
+
# :inline_format => true,
|
21
|
+
# :height => 100,
|
22
|
+
# :width => 100
|
23
|
+
#end
|
24
|
+
end
|
25
|
+
|
26
|
+
def pdf_content(&code)
|
27
|
+
render_header
|
28
|
+
code.call(pdf)
|
29
|
+
pdf
|
30
|
+
end
|
31
|
+
|
32
|
+
def standard
|
33
|
+
pdf_content do
|
34
|
+
@report.charts.each do |chart|
|
35
|
+
if chart.respond_to?(:to_blob)
|
36
|
+
blob = chart.to_blob
|
37
|
+
data = StringIO.new(blob)
|
38
|
+
pdf.image(data)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
render_table_with(@report.all_records, {font_size: 8, header_font_size: 10})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def table_header_for(table_items, options={})
|
48
|
+
table_items.first.keys
|
49
|
+
end
|
50
|
+
|
51
|
+
def humanized_table_header_for(table_items, options={})
|
52
|
+
table_items.first.keys.collect(&:humanize) rescue table_header_for(table_items, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def table_content_for(table_items, options)
|
56
|
+
table_items.map do |item|
|
57
|
+
item_values = []
|
58
|
+
|
59
|
+
options[:table_header].each do |header|
|
60
|
+
item_values << cell_for(item, header)
|
61
|
+
end
|
62
|
+
item_values
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def cell_for(item, prop)
|
67
|
+
val = item.respond_to?(prop) ? item.send(prop) : item[prop]
|
68
|
+
if val.kind_of? Array
|
69
|
+
val.collect { |v| [v] }
|
70
|
+
return pdf.make_table(val)
|
71
|
+
end
|
72
|
+
val
|
73
|
+
end
|
74
|
+
|
75
|
+
def render_table_with(table_items, options={})
|
76
|
+
if table_items.present?
|
77
|
+
options[:table_header] ||= table_header_for(table_items, options)
|
78
|
+
items = [humanized_table_header_for(table_items)]
|
79
|
+
items += table_content_for(table_items, options)
|
80
|
+
items += table_footer_for(table_items, options)
|
81
|
+
options[:bold_footer] = options[:titles_of_column_to_sum].present?
|
82
|
+
render_table(items, options)
|
83
|
+
end
|
84
|
+
pdf
|
85
|
+
end
|
86
|
+
|
87
|
+
def render_table(items, options={})
|
88
|
+
options = default_options.merge options
|
89
|
+
header_bg_color = options[:header_bg_color]
|
90
|
+
pdf.move_down 10
|
91
|
+
pdf.table(items, :row_colors => options[:alternate_row_bg_color], :header => true, :cell_style => {:inline_format => true, :size => options[:font_size] || 10}) do
|
92
|
+
row(0).style(:font_style => :bold, :background_color => header_bg_color, :size => options[:header_font_size] || 14)
|
93
|
+
row(items.size-1).style(:font_style => :bold) if options[:bold_footer]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def table_footer_for(table_items, options)
|
98
|
+
return [] if options[:titles_of_column_to_sum].blank?
|
99
|
+
total_hash = {} #for calculating total for a column
|
100
|
+
options[:titles_of_column_to_sum].each do |col|
|
101
|
+
total_hash[col] = table_items.sum { |i| (i.respond_to?(col) ? i.send(col) : i[col]) || 0 }
|
102
|
+
end
|
103
|
+
|
104
|
+
render_footer_with_col_span(total_hash, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
data/lib/query_report/version.rb
CHANGED
data/query_report.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: query_report
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ransack
|
@@ -43,6 +43,38 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '2.1'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rmagick
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: gruff
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
46
78
|
description: This is a gem to help you to structure common reports of you application
|
47
79
|
just by writing in the controller
|
48
80
|
email:
|
@@ -64,10 +96,13 @@ files:
|
|
64
96
|
- lib/query_report/chart/chart_with_total.rb
|
65
97
|
- lib/query_report/chart/custom_chart.rb
|
66
98
|
- lib/query_report/chart/pie_chart.rb
|
99
|
+
- lib/query_report/chart/themes.rb
|
67
100
|
- lib/query_report/column.rb
|
68
101
|
- lib/query_report/filter.rb
|
69
102
|
- lib/query_report/helper.rb
|
70
103
|
- lib/query_report/report.rb
|
104
|
+
- lib/query_report/report_pdf.rb
|
105
|
+
- lib/query_report/row.rb
|
71
106
|
- lib/query_report/version.rb
|
72
107
|
- query_report.gemspec
|
73
108
|
homepage: https://github.com/ashrafuzzaman/query_report
|