meta_reports 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/Guardfile +15 -0
  3. data/LICENSE +20 -0
  4. data/README.md +146 -0
  5. data/Rakefile +29 -0
  6. data/app/assets/images/meta_reports/print.png +0 -0
  7. data/app/assets/images/meta_reports/spreadsheet.png +0 -0
  8. data/app/assets/javascripts/meta_reports/reports.js +2 -0
  9. data/app/controllers/meta_reports/application_controller.rb +4 -0
  10. data/app/controllers/meta_reports/reports_controller.rb +91 -0
  11. data/app/helpers/meta_reports/reports_helper.rb +140 -0
  12. data/app/models/meta_reports/base.rb +90 -0
  13. data/app/models/meta_reports/data.rb +34 -0
  14. data/app/models/meta_reports/table.rb +80 -0
  15. data/config/routes.rb +9 -0
  16. data/db/migrate/20130801071213_create_meta_reports_reports.rb +17 -0
  17. data/lib/generators/meta_reports/install_generator.rb +40 -0
  18. data/lib/generators/meta_reports/templates/models/report.rb +30 -0
  19. data/lib/generators/meta_reports/templates/views/_form.html.erb +45 -0
  20. data/lib/generators/meta_reports/templates/views/edit.html.erb +6 -0
  21. data/lib/generators/meta_reports/templates/views/forms/_form_example.html.erb +1 -0
  22. data/lib/generators/meta_reports/templates/views/forms/form.html.erb +17 -0
  23. data/lib/generators/meta_reports/templates/views/index.html.erb +36 -0
  24. data/lib/generators/meta_reports/templates/views/new.html.erb +5 -0
  25. data/lib/generators/meta_reports/templates/views/templates/_default.html.erb +26 -0
  26. data/lib/generators/meta_reports/templates/views/templates/_default_footer.pdf.prawn +12 -0
  27. data/lib/generators/meta_reports/templates/views/templates/_default_header.pdf.prawn +14 -0
  28. data/lib/generators/meta_reports/templates/views/templates/_default_header.xlsx.axlsx +20 -0
  29. data/lib/generators/meta_reports/templates/views/templates/_default_table.html.erb +24 -0
  30. data/lib/generators/meta_reports/templates/views/templates/_default_table.pdf.prawn +29 -0
  31. data/lib/generators/meta_reports/templates/views/templates/default.html.erb +1 -0
  32. data/lib/generators/meta_reports/templates/views/templates/default.pdf.prawn +26 -0
  33. data/lib/generators/meta_reports/templates/views/templates/default.xlsx.axlsx +43 -0
  34. data/lib/meta_reports.rb +4 -0
  35. data/lib/meta_reports/engine.rb +15 -0
  36. data/lib/meta_reports/version.rb +3 -0
  37. data/lib/tasks/meta_reports_tasks.rake +4 -0
  38. data/spec/dummy/README.rdoc +261 -0
  39. data/spec/dummy/Rakefile +7 -0
  40. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  41. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  42. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  43. data/spec/dummy/app/controllers/home_controller.rb +4 -0
  44. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  45. data/spec/dummy/app/models/meta_reports/report.rb +30 -0
  46. data/spec/dummy/app/views/home/index.html.erb +4 -0
  47. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  48. data/spec/dummy/app/views/meta_reports/reports/_form.html.erb +45 -0
  49. data/spec/dummy/app/views/meta_reports/reports/edit.html.erb +6 -0
  50. data/spec/dummy/app/views/meta_reports/reports/forms/_form_moo.html.erb +1 -0
  51. data/spec/dummy/app/views/meta_reports/reports/forms/form.html.erb +17 -0
  52. data/spec/dummy/app/views/meta_reports/reports/index.html.erb +36 -0
  53. data/spec/dummy/app/views/meta_reports/reports/new.html.erb +5 -0
  54. data/spec/dummy/app/views/meta_reports/reports/templates/_default.html.erb +26 -0
  55. data/spec/dummy/app/views/meta_reports/reports/templates/_default_footer.pdf.prawn +12 -0
  56. data/spec/dummy/app/views/meta_reports/reports/templates/_default_header.pdf.prawn +14 -0
  57. data/spec/dummy/app/views/meta_reports/reports/templates/_default_header.xlsx.axlsx +20 -0
  58. data/spec/dummy/app/views/meta_reports/reports/templates/_default_table.html.erb +24 -0
  59. data/spec/dummy/app/views/meta_reports/reports/templates/_default_table.pdf.prawn +29 -0
  60. data/spec/dummy/app/views/meta_reports/reports/templates/default.html.erb +1 -0
  61. data/spec/dummy/app/views/meta_reports/reports/templates/default.pdf.prawn +26 -0
  62. data/spec/dummy/app/views/meta_reports/reports/templates/default.xlsx.axlsx +43 -0
  63. data/spec/dummy/config.ru +4 -0
  64. data/spec/dummy/config/application.rb +65 -0
  65. data/spec/dummy/config/boot.rb +10 -0
  66. data/spec/dummy/config/database.yml +25 -0
  67. data/spec/dummy/config/environment.rb +5 -0
  68. data/spec/dummy/config/environments/development.rb +37 -0
  69. data/spec/dummy/config/environments/production.rb +67 -0
  70. data/spec/dummy/config/environments/test.rb +37 -0
  71. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  72. data/spec/dummy/config/initializers/inflections.rb +15 -0
  73. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  74. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  75. data/spec/dummy/config/initializers/session_store.rb +8 -0
  76. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  77. data/spec/dummy/config/locales/en.yml +5 -0
  78. data/spec/dummy/config/routes.rb +4 -0
  79. data/spec/dummy/config/routes_empty.rb +3 -0
  80. data/spec/dummy/config/routes_original.rb +4 -0
  81. data/spec/dummy/db/development.sqlite3 +0 -0
  82. data/spec/dummy/db/schema.rb +31 -0
  83. data/spec/dummy/log/development.log +22317 -0
  84. data/spec/dummy/public/404.html +26 -0
  85. data/spec/dummy/public/422.html +26 -0
  86. data/spec/dummy/public/500.html +25 -0
  87. data/spec/dummy/public/favicon.ico +0 -0
  88. data/spec/dummy/script/rails +6 -0
  89. data/spec/dummy/tmp/cache/assets/C9B/140/sprockets%2F805babf865ce32228222420a522c7b36 +0 -0
  90. data/spec/dummy/tmp/cache/assets/CBD/2B0/sprockets%2F9e22e937dd267c81a146665f15471b8e +0 -0
  91. data/spec/dummy/tmp/cache/assets/CD0/810/sprockets%2Fe858c95fa595e319dac0065d49982967 +0 -0
  92. data/spec/dummy/tmp/cache/assets/CD0/AC0/sprockets%2F1d341d7a2fc1328567d4b23e0809b2e2 +0 -0
  93. data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  94. data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  95. data/spec/dummy/tmp/cache/assets/D3D/EB0/sprockets%2F2d47bd3108d9abbb12c0497e36d9674d +0 -0
  96. data/spec/dummy/tmp/cache/assets/D40/8F0/sprockets%2F290aea2004dfecfc76f42e48970f1484 +0 -0
  97. data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  98. data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  99. data/spec/dummy/tmp/cache/assets/D61/310/sprockets%2Fc168b1c9be3e38ac1c8403a3074b5b8c +0 -0
  100. data/spec/dummy/tmp/cache/assets/D74/AE0/sprockets%2F9ad0425db5cfa16a9426f7b1a7958d7d +0 -0
  101. data/spec/dummy/tmp/cache/assets/D98/270/sprockets%2F0b7ba158ff62bbbb378d6bea80680c63 +0 -0
  102. data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  103. data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  104. data/spec/dummy/tmp/cache/assets/E5A/EF0/sprockets%2Fb0d5af721ea37c98fd4bccd8e1e5c6ab +0 -0
  105. data/spec/dummy/tmp/pids/server.pid +1 -0
  106. data/spec/features/dummy_spec.rb +42 -0
  107. data/spec/generators/install_spec.rb +51 -0
  108. data/spec/models/data_spec.rb +45 -0
  109. data/spec/models/table_spec.rb +78 -0
  110. data/spec/spec_helper.rb +41 -0
  111. metadata +454 -0
@@ -0,0 +1,90 @@
1
+ class MetaReports::Base < ActiveRecord::Base
2
+ attr_accessible :description, :direct, :group, :name, :target, :title, :views, :formats_mask
3
+ validates_presence_of :name, :title, :group
4
+
5
+ self.table_name = "meta_reports_reports"
6
+
7
+ def self.test_report(params)
8
+ {title: 'Test Report', subtitle: 'this is a test report', tables: {'Table 1' => [['One','Two','Three'],[1,2,3]]}}
9
+ end
10
+
11
+ #
12
+ # Utility methods
13
+ #
14
+
15
+ FORMATS = %w[html pdf xlsx]
16
+
17
+ def self.color(klass, row = 0)
18
+ color = COLORS[klass.to_sym]
19
+ return nil unless color
20
+ if color.is_a? Array
21
+ # the trailing split first is to drop any !important directive
22
+ # color = color[row%color.length].to_s.split.first
23
+ # the trailing gsub is to drop any !important directive
24
+ color = color[row%color.length].to_s.gsub(/\s.*$/,'')
25
+ end
26
+ if color.gsub!(/^\$/, '') # we have a variable
27
+ color = COLORS[color.to_sym]
28
+ if color.is_a? Array
29
+ choice = color.gsub!(/Odd/,'') ? 1 : 0
30
+ color = color[choice]
31
+ end
32
+ end
33
+ color
34
+ end
35
+
36
+ def self.format_mask(format)
37
+ 1 << (FORMATS.index(format.to_s) || -1)
38
+ end
39
+
40
+ def self.formats_mask(*formats)
41
+ formats.inject(0) {|mask, format| mask | (1 << (FORMATS.index(format.to_s) || -1) )}
42
+ end
43
+
44
+ def displays_all_formats?(*formats)
45
+ has_all = true
46
+ ([*formats] & FORMATS).each do |format|
47
+ i = FORMATS.index(format.to_s)
48
+ has_any = false if formats_mask[i] != 1
49
+ end
50
+ has_all
51
+ end
52
+
53
+ def displays_any_format?(*formats)
54
+ has_any = false
55
+ ([*formats] & FORMATS).each do |format|
56
+ i = FORMATS.index(format.to_s)
57
+ has_any = true if formats_mask[i] == 1
58
+ end
59
+ has_any
60
+ end
61
+
62
+ def formats=(formats)
63
+ self.formats_mask = ([*formats] & FORMATS).inject(0) { |sum,r| sum += 1 << FORMATS.index(r) }
64
+ end
65
+
66
+ def formats
67
+ FORMATS.reject { |r| (formats_mask || 0)[FORMATS.index(r)].zero? }
68
+ end
69
+
70
+ def format?(format)
71
+ i = FORMATS.index(format.to_s)
72
+ i ? (formats_mask[i] == 1) : nil
73
+ end
74
+
75
+ def run(params)
76
+ report = ::MetaReports::Report.send(name, params)
77
+ report[:id] = "report_#{name}"
78
+ report[:report] = self
79
+ report
80
+ end
81
+
82
+ def view
83
+ connection.execute("UPDATE meta_reports_reports SET views = views + 1 WHERE id = #{id}")
84
+ end
85
+
86
+ COLORS = {
87
+ even: 'efefef',
88
+ odd: 'ffffff',
89
+ }
90
+ end
@@ -0,0 +1,34 @@
1
+ class MetaReports::Data
2
+ def initialize
3
+ @hash = {tables: {}}
4
+ yield self if block_given?
5
+ self
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ method_string = method.to_s
10
+ if method_string =~ /^(.+)=$/
11
+ @hash[$1.to_sym] = args.first
12
+ elsif @hash[method.to_sym]
13
+ @hash[method.to_sym]
14
+ else
15
+ @hash.send(method, *args)
16
+ end
17
+ end
18
+
19
+ def [](key)
20
+ @hash[key]
21
+ end
22
+
23
+ def []=(key, value)
24
+ @hash[key] = value
25
+ end
26
+
27
+ def tables
28
+ @hash[:tables]
29
+ end
30
+
31
+ def to_h
32
+ @hash
33
+ end
34
+ end
@@ -0,0 +1,80 @@
1
+ class MetaReports::Table
2
+ def initialize
3
+ @data = []
4
+ @options = {row_classes: {}}
5
+ yield self if block_given?
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ method_string = method.to_s
10
+ if method_string =~ /^(.+)=$/
11
+ @options[$1.to_sym] = args.first
12
+ elsif @options[method.to_sym]
13
+ @options[method.to_sym]
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ # options methods
20
+
21
+ def [](key)
22
+ @options[key]
23
+ end
24
+
25
+ def []=(key,val)
26
+ @options[key] = val
27
+ end
28
+
29
+ def options
30
+ @options
31
+ end
32
+
33
+ def row_classes
34
+ @options[:row_classes]
35
+ end
36
+
37
+ # data methods
38
+
39
+ def <<(val)
40
+ @data << val
41
+ end
42
+
43
+ def +(arr)
44
+ @data += arr
45
+ end
46
+
47
+ def first
48
+ @data.first
49
+ end
50
+
51
+ def last
52
+ @data.last
53
+ end
54
+
55
+ def length
56
+ @data.length
57
+ end
58
+
59
+ def pop
60
+ @data.pop
61
+ end
62
+
63
+ def push(val)
64
+ @data.push(val)
65
+ end
66
+
67
+ def shift
68
+ @data.shift
69
+ end
70
+
71
+ def to_a
72
+ @data
73
+ end
74
+
75
+ def unshift(val)
76
+ @data.unshift(val)
77
+ end
78
+
79
+ alias_method :data, :to_a
80
+ end
@@ -0,0 +1,9 @@
1
+ MetaReports::Engine.routes.draw do
2
+ root to: "reports#index"
3
+
4
+ get 'reports/file/:dir' => 'reports#file', as: 'file'
5
+ resources :reports
6
+ match ':id(.:format)' => 'reports#show', as: 'short_show'
7
+ get ':id/edit' => 'reports#edit', as: 'short_edit'
8
+ get ':id/form' => 'reports#form', as: 'short_form'
9
+ end
@@ -0,0 +1,17 @@
1
+ class CreateMetaReportsReports < ActiveRecord::Migration
2
+ def change
3
+ create_table :meta_reports_reports do |t|
4
+ t.string :name
5
+ t.text :description
6
+ t.string :title
7
+ t.string :group
8
+ t.boolean :direct
9
+ t.integer :views
10
+ t.string :target
11
+ t.integer :formats_mask
12
+
13
+ t.timestamps
14
+ end
15
+ add_index :meta_reports_reports, :name
16
+ end
17
+ end
@@ -0,0 +1,40 @@
1
+ require 'rails/generators'
2
+
3
+ module MetaReports
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ desc 'Copy meta_reports migration, models, controllers, and views.'
9
+
10
+ def create_migration_file
11
+ Dir.chdir(Rails.root) do
12
+ `rake meta_reports:install:migrations`
13
+ end
14
+ end
15
+
16
+ def install_model
17
+ copy_file "models/report.rb", "app/models/meta_reports/report.rb"
18
+ end
19
+
20
+ def install_views
21
+ directory "views", "app/views/meta_reports/reports"
22
+ end
23
+
24
+ def mount_engine
25
+ routes_file = "#{Rails.root}/config/routes.rb"
26
+ unless open(routes_file).grep(/MetaReports::Engine/)
27
+ insert_into_file(routes_file, :after => /routes.draw.do\n/) do
28
+ %Q{
29
+ # This line mounts MetaReports's routes at /reports by default.
30
+ # This means, any requests to the /reports URL of your application will go to MetaReports::ReportsController#index.
31
+ # If you would like to change where this extension is mounted, simply change '/reports' to something different.
32
+ mount MetaReports::Engine => '/reports'
33
+
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ class MetaReports::Report < MetaReports::Base
2
+
3
+ #
4
+ # Shared colors. The key is the class name, value is RGB in hex format
5
+ #
6
+
7
+ COLORS = {
8
+ even: 'efefef',
9
+ odd: 'ffffff',
10
+ }
11
+
12
+
13
+ #
14
+ # Reports
15
+ #
16
+
17
+ def self.example_report(params)
18
+ {title: 'Example Report', subtitle: 'this is a test report', tables: {'Table 1' => [['One','Two','Three'],[1,2,3]]}}
19
+ MetaReports::Data.new do |d|
20
+ d.title = 'Example Report'
21
+ d.subtitle = 'Of the Testing Kind'
22
+ d.description = 'This is a test report.'
23
+ d.tables["Table 1"] = MetaReports::Table.new do |t|
24
+ t << ['One', 'Two', 'Three']
25
+ t << [1, 2, 3]
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,45 @@
1
+ <%= form_for(@report) do |f| %>
2
+ <% if @report.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@report.errors.count, "error") %> prohibited this report from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @report.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= f.label :name %><br />
16
+ <%= f.text_field :name %>
17
+ </div>
18
+ <div class="field">
19
+ <%= f.label :description %><br />
20
+ <%= f.text_area :description %>
21
+ </div>
22
+ <div class="field">
23
+ <%= f.label :title %><br />
24
+ <%= f.text_field :title %>
25
+ </div>
26
+ <div class="field">
27
+ <%= f.label :group %><br />
28
+ <%= f.text_field :group %>
29
+ </div>
30
+ <div class="field">
31
+ <%= f.label :direct %><br />
32
+ <%= f.check_box :direct %>
33
+ </div>
34
+ <div class="field">
35
+ <%= f.label :views %><br />
36
+ <%= f.number_field :views, disabled: true %>
37
+ </div>
38
+ <div class="field">
39
+ <%= f.label :target %><br />
40
+ <%= f.text_field :target %>
41
+ </div>
42
+ <div class="actions">
43
+ <%= f.submit %>
44
+ </div>
45
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing report</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', meta_reports.short_form_path(@report) %> |
6
+ <%= link_to 'Back', reports_path %>
@@ -0,0 +1 @@
1
+ <%= select_tag :type, options_for_select(['One','Two']), include_blank: true %>
@@ -0,0 +1,17 @@
1
+ <h3><%= @report.title %></h3>
2
+ <%= form_tag(meta_reports.short_show_path(@report), id: 'meta_reports_report_form') do %>
3
+ <p>
4
+ <%= render "meta_reports/reports/forms/form_#{@report.name}" %>
5
+ </p>
6
+ <p class='form-actions'>
7
+ <% if @report.format? :html %>
8
+ <%= submit_tag 'Display', data: {action: "/reports/#{@report.name}"} %>
9
+ <% end -%>
10
+ <% if @report.format? :pdf %>
11
+ <%= image_submit_tag image_path('meta_reports/print.png'), name: 'format_print', align: 'absmiddle', data: {action: "/reports/#{@report.name}.pdf", target: '_blank'} %>
12
+ <% end -%>
13
+ <% if @report.format? :xlsx %>
14
+ <%= image_submit_tag image_path('meta_reports/spreadsheet.png'), name: 'format_xlsx', align: 'absmiddle', data: {action: "/reports/#{@report.name}.xlsx", target: '_blank'} %>
15
+ <% end -%>
16
+ </p>
17
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <h1>Listing reports</h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <th>Name</th>
6
+ <th>Description</th>
7
+ <th>Title</th>
8
+ <th>Group</th>
9
+ <th>Direct</th>
10
+ <th>Views</th>
11
+ <th>Target</th>
12
+ <th></th>
13
+ <th></th>
14
+ <th></th>
15
+ </tr>
16
+
17
+ <% @reports.each do |report| %>
18
+ <tr>
19
+ <td><%= report.name %></td>
20
+ <td><%= report.description %></td>
21
+ <td><%= report.title %></td>
22
+ <td><%= report.group %></td>
23
+ <td><%= report.direct %></td>
24
+ <td><%= report.views %></td>
25
+ <td><%= report.target %></td>
26
+ <td><%= report_link(report, 'Show') %></td>
27
+ <td><%= link_to 'Edit', edit_report_path(report) %></td>
28
+ <td><%= link_to 'Destroy', report, method: :delete, data: { confirm: 'Are you sure?' } %></td>
29
+ </tr>
30
+ <% end %>
31
+ </table>
32
+
33
+ <br />
34
+
35
+ <%= link_to 'New Report', new_report_path %>
36
+
@@ -0,0 +1,5 @@
1
+ <h1>New report</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', reports_path %>
@@ -0,0 +1,26 @@
1
+ <%
2
+ report = @report if defined?(report).nil?
3
+ %>
4
+ <%= content_tag(:div, :id => report[:id]) do %>
5
+ <%
6
+ title = report[:title]
7
+ title += '<br>'+content_tag(:span, report[:subtitle], :class => 'small') if report[:subtitle]
8
+ %>
9
+ <%= content_tag(:h3, title.html_safe) if title %>
10
+ <div>
11
+ <%= report_alt_links(report[:report], params) %>
12
+ <% if report[:description] %><br><p class='description'><%= report[:description] %></p><% end %>
13
+ </div>
14
+
15
+ <%= content_tag(:div, "No data found", :class => 'textcenter') if report[:tables].blank? %>
16
+
17
+ <%
18
+ table_names = report[:table_order] || report[:tables].keys.sort_by {|k| k.to_s}
19
+ table_names.each do |table_name| %>
20
+ <%= render partial: 'meta_reports/reports/templates/default_table', locals: {table_name: table_name, table: report[:tables][table_name]} %>
21
+ <% end %>
22
+ <% end %>
23
+
24
+ <% unless request.xhr? %>
25
+ <%= link_to 'Reports', '/meta_reports' %>
26
+ <% end -%>