custom_report 0.0.1

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.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +107 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +42 -0
  7. data/Rakefile +29 -0
  8. data/app/controllers/custom_report/reports_controller.rb +211 -0
  9. data/app/models/custom_report/report.rb +77 -0
  10. data/app/models/custom_report/report_check_item.rb +11 -0
  11. data/app/views/custom_report/reports/_form.html.slim +37 -0
  12. data/app/views/custom_report/reports/edit.html.slim +3 -0
  13. data/app/views/custom_report/reports/index.html.slim +39 -0
  14. data/app/views/custom_report/reports/new.html.slim +3 -0
  15. data/app/views/custom_report/reports/show.html.slim +41 -0
  16. data/config/routes.rb +10 -0
  17. data/custom_report.gemspec +28 -0
  18. data/lib/custom_report/engine.rb +27 -0
  19. data/lib/custom_report/settings.rb +9 -0
  20. data/lib/custom_report/version.rb +3 -0
  21. data/lib/custom_report.rb +17 -0
  22. data/lib/generators/custom_report/custom_report_generator.rb +21 -0
  23. data/lib/generators/custom_report/templates/migration.rb +29 -0
  24. data/test/custom_report_test.rb +7 -0
  25. data/test/dummy/Rakefile +7 -0
  26. data/test/dummy/app/controllers/application_controller.rb +3 -0
  27. data/test/dummy/app/helpers/application_helper.rb +2 -0
  28. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  29. data/test/dummy/config/application.rb +45 -0
  30. data/test/dummy/config/boot.rb +10 -0
  31. data/test/dummy/config/database.yml +22 -0
  32. data/test/dummy/config/environment.rb +5 -0
  33. data/test/dummy/config/environments/development.rb +25 -0
  34. data/test/dummy/config/environments/production.rb +49 -0
  35. data/test/dummy/config/environments/test.rb +35 -0
  36. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  37. data/test/dummy/config/initializers/inflections.rb +10 -0
  38. data/test/dummy/config/initializers/mime_types.rb +5 -0
  39. data/test/dummy/config/initializers/secret_token.rb +7 -0
  40. data/test/dummy/config/initializers/session_store.rb +8 -0
  41. data/test/dummy/config/locales/en.yml +5 -0
  42. data/test/dummy/config/routes.rb +58 -0
  43. data/test/dummy/config.ru +4 -0
  44. data/test/dummy/db/migrate/20131114010848_create_custom_report_table.rb +29 -0
  45. data/test/dummy/db/schema.rb +16 -0
  46. data/test/dummy/public/404.html +26 -0
  47. data/test/dummy/public/422.html +26 -0
  48. data/test/dummy/public/500.html +26 -0
  49. data/test/dummy/public/favicon.ico +0 -0
  50. data/test/dummy/public/javascripts/application.js +2 -0
  51. data/test/dummy/public/javascripts/controls.js +965 -0
  52. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  53. data/test/dummy/public/javascripts/effects.js +1123 -0
  54. data/test/dummy/public/javascripts/prototype.js +6001 -0
  55. data/test/dummy/public/javascripts/rails.js +202 -0
  56. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  57. data/test/dummy/script/rails +6 -0
  58. data/test/integration/navigation_test.rb +7 -0
  59. data/test/support/integration_case.rb +5 -0
  60. data/test/test_helper.rb +22 -0
  61. metadata +131 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWJjMGQwNmExZjAwNGNmZTExNTNhYzdiZDU4ZTI3OWY1MjcyODFkNg==
5
+ data.tar.gz: !binary |-
6
+ MWFlMWRiMzM2N2Q3YzJkMTMwNTg3OGUyM2ExOTRkZWQ3NDk0MzcwMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NTZkYWFhYmI3MWE0YTA2ZjU4MjUwODRkZTU1OTU0YzA3YWJjM2YzNjYwMDQ2
10
+ ZDU4ZGMxODcxNTY0MTk3Yzg0NmYwNDYzMTcwYjhlMjJhM2RlY2M0Mzk2MmM2
11
+ ODIyZDg5NWQxMWUzMDUwNDljOTU1ZDM0MTBiMmFjNWQ4OWEzMzk=
12
+ data.tar.gz: !binary |-
13
+ MmUxMmZlN2M2MzE4OTlhYTljMTNmMjM4YTA2NjA2NTQ1MTgzODdjZDFkMzk3
14
+ Y2RlNWM0NTMxZjkxMzM5OWQwMDk4N2ZkMDYyYTgyZjY0OGUxMGMwNzhjMTRk
15
+ N2RjMzFhZDRiMGYxMDJhMDhiZDEyODAwMDFjOGZhZjBlY2YwNjA=
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", ">= 3.2.8"
4
+ gem "capybara", ">= 0.4.0"
5
+ gem "sqlite3"
6
+ gem "slim-rails"
7
+ gem "protected_attributes"
8
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
9
+ # gem 'ruby-debug'
10
+ # gem 'ruby-debug19'
data/Gemfile.lock ADDED
@@ -0,0 +1,107 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (4.0.1)
5
+ actionpack (= 4.0.1)
6
+ mail (~> 2.5.4)
7
+ actionpack (4.0.1)
8
+ activesupport (= 4.0.1)
9
+ builder (~> 3.1.0)
10
+ erubis (~> 2.7.0)
11
+ rack (~> 1.5.2)
12
+ rack-test (~> 0.6.2)
13
+ activemodel (4.0.1)
14
+ activesupport (= 4.0.1)
15
+ builder (~> 3.1.0)
16
+ activerecord (4.0.1)
17
+ activemodel (= 4.0.1)
18
+ activerecord-deprecated_finders (~> 1.0.2)
19
+ activesupport (= 4.0.1)
20
+ arel (~> 4.0.0)
21
+ activerecord-deprecated_finders (1.0.3)
22
+ activesupport (4.0.1)
23
+ i18n (~> 0.6, >= 0.6.4)
24
+ minitest (~> 4.2)
25
+ multi_json (~> 1.3)
26
+ thread_safe (~> 0.1)
27
+ tzinfo (~> 0.3.37)
28
+ arel (4.0.1)
29
+ atomic (1.1.14)
30
+ builder (3.1.4)
31
+ capybara (2.1.0)
32
+ mime-types (>= 1.16)
33
+ nokogiri (>= 1.3.3)
34
+ rack (>= 1.0.0)
35
+ rack-test (>= 0.5.4)
36
+ xpath (~> 2.0)
37
+ erubis (2.7.0)
38
+ hike (1.2.3)
39
+ i18n (0.6.5)
40
+ mail (2.5.4)
41
+ mime-types (~> 1.16)
42
+ treetop (~> 1.4.8)
43
+ mime-types (1.25)
44
+ mini_portile (0.5.2)
45
+ minitest (4.7.5)
46
+ multi_json (1.8.2)
47
+ nokogiri (1.6.0)
48
+ mini_portile (~> 0.5.0)
49
+ polyglot (0.3.3)
50
+ protected_attributes (1.0.3)
51
+ activemodel (>= 4.0.0, < 5.0)
52
+ rack (1.5.2)
53
+ rack-test (0.6.2)
54
+ rack (>= 1.0)
55
+ rails (4.0.1)
56
+ actionmailer (= 4.0.1)
57
+ actionpack (= 4.0.1)
58
+ activerecord (= 4.0.1)
59
+ activesupport (= 4.0.1)
60
+ bundler (>= 1.3.0, < 2.0)
61
+ railties (= 4.0.1)
62
+ sprockets-rails (~> 2.0.0)
63
+ railties (4.0.1)
64
+ actionpack (= 4.0.1)
65
+ activesupport (= 4.0.1)
66
+ rake (>= 0.8.7)
67
+ thor (>= 0.18.1, < 2.0)
68
+ rake (10.1.0)
69
+ slim (2.0.1)
70
+ temple (~> 0.6.6)
71
+ tilt (>= 1.3.3, < 2.1)
72
+ slim-rails (2.0.3)
73
+ actionpack (>= 3.0, < 4.1)
74
+ activesupport (>= 3.0, < 4.1)
75
+ railties (>= 3.0, < 4.1)
76
+ slim (~> 2.0)
77
+ sprockets (2.10.0)
78
+ hike (~> 1.2)
79
+ multi_json (~> 1.0)
80
+ rack (~> 1.0)
81
+ tilt (~> 1.1, != 1.3.0)
82
+ sprockets-rails (2.0.1)
83
+ actionpack (>= 3.0)
84
+ activesupport (>= 3.0)
85
+ sprockets (~> 2.8)
86
+ sqlite3 (1.3.8)
87
+ temple (0.6.7)
88
+ thor (0.18.1)
89
+ thread_safe (0.1.3)
90
+ atomic
91
+ tilt (1.4.1)
92
+ treetop (1.4.15)
93
+ polyglot
94
+ polyglot (>= 0.3.1)
95
+ tzinfo (0.3.38)
96
+ xpath (2.0.0)
97
+ nokogiri (~> 1.3)
98
+
99
+ PLATFORMS
100
+ ruby
101
+
102
+ DEPENDENCIES
103
+ capybara (>= 0.4.0)
104
+ protected_attributes
105
+ rails (>= 3.2.8)
106
+ slim-rails
107
+ sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # CustomReport
2
+
3
+ Create and view custom reports
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'custom_report'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install custom_report
18
+
19
+ ## Usage
20
+
21
+ In config/initializers/custom_report.rb
22
+
23
+ CustomReport.layout = "admin_bootstrap"
24
+ CustomReport.includes = AuthenticatedAdminSystem
25
+ CustomReport.admin_class = "Administrator"
26
+ CustomReport.before_filters = [:authenticate_or_request_admin]
27
+
28
+ In your routes
29
+
30
+ mount CustomReport::Engine => "/custom_report"
31
+
32
+ This creates the path
33
+
34
+ /custom_report/reports
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rake/rdoctask'
11
+
12
+ require 'rake/testtask'
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << 'lib'
16
+ t.libs << 'test'
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = false
19
+ end
20
+
21
+ task :default => :test
22
+
23
+ Rake::RDocTask.new(:rdoc) do |rdoc|
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = 'CustomReport'
26
+ rdoc.options << '--line-numbers' << '--inline-source'
27
+ rdoc.rdoc_files.include('README.rdoc')
28
+ rdoc.rdoc_files.include('lib/**/*.rb')
29
+ end
@@ -0,0 +1,211 @@
1
+ module CustomReport
2
+ class ReportsController < ::ApplicationController
3
+ layout CustomReport.layout
4
+
5
+ if CustomReport.includes
6
+ Array(CustomReport.includes).each do |inc|
7
+ include inc
8
+ end
9
+ end
10
+
11
+ if CustomReport.before_filters
12
+ Array(CustomReport.before_filters).each do |filter|
13
+ before_filter filter
14
+ end
15
+ end
16
+
17
+ def index
18
+ @custom_reports = custom_reports
19
+ end
20
+
21
+ def show
22
+ @report = custom_report
23
+ respond_to do |format|
24
+ format.html {
25
+ get_the_report
26
+ }
27
+ format.csv {
28
+ params[:dont_paginate] = 1
29
+ get_the_report
30
+ render_csv @results, :filename => "#{custom_report.name.parameterize}-#{Time.now.strftime("%Y%m%d%H%M%S")}", :columns => @columns
31
+ }
32
+ end
33
+ end
34
+
35
+ def get_the_report
36
+ begin
37
+ @filters = []
38
+
39
+ @filters.each do |filter|
40
+ if filter.first == "options"
41
+ filter.each do |key|
42
+ next if key == "options"
43
+ params[key.to_sym] = true
44
+ end
45
+ end
46
+ end
47
+ @filters.reject! {|f| f.first == "options" }
48
+
49
+ @filter_args = params[:filters] || {}
50
+ @results = @report.generate(params, @filter_args)
51
+ @iterator = @report.iterator
52
+ @columns = @report.columns_hash
53
+ @check_items = @report.report_check_items.group_by(&:item_id)
54
+
55
+ @report.update_column(:last_opened, Time.current)
56
+ rescue Exception => e
57
+ render :text => "<strong>Error:</strong> <p>#{e.class}: #{e.message}</p><p style='font-family: monospace;'>#{e.backtrace.join("<br>")}</p>"
58
+ end
59
+ end
60
+
61
+ def new
62
+ @report = CustomReport::Report.new
63
+ end
64
+
65
+ def create
66
+ @report = CustomReport::Report.new(
67
+ :name => params[:report][:name],
68
+ :category => params[:report][:category],
69
+ :description => params[:report][:description],
70
+ :scope => params[:report][:scope],
71
+ :columns_yaml => params[:report][:columns_yaml]
72
+ )
73
+ @report.save
74
+ redirect_to report_path(@report)
75
+ end
76
+
77
+ def edit
78
+ set_return_path
79
+ @report = CustomReport::Report.find(params[:id])
80
+ end
81
+
82
+ def update
83
+ set_return_path
84
+ if custom_report.update_attributes({"has_checklist" => "false"}.merge(params[:report]).merge(:administrator_type => CustomReport.admin_class))
85
+ redirect_to @return_path
86
+ else
87
+ render "edit"
88
+ end
89
+ end
90
+
91
+ def unarchive
92
+ custom_report.update_column(:deleted_at, nil)
93
+ redirect_to custom_reports_path(:show_archived => 1)
94
+ end
95
+
96
+ def format_column(entity, column, column_index)
97
+ format = column[:format] || "text"
98
+ raw = entity[column_index].to_s
99
+
100
+ case format
101
+ when "text"
102
+ raw
103
+ when "strong"
104
+ "<strong>#{raw}</strong>"
105
+ when "impersonate"
106
+ view_context.link_to "Impersonate", impersonate_path(:email => raw)
107
+ when "eval"
108
+ raw.html_safe
109
+ else
110
+ "unknown formatter: #{format}"
111
+ end
112
+ end
113
+ helper_method :format_column
114
+
115
+ def custom_reports
116
+ scope = CustomReport::Report.order("category,name")
117
+ scope = scope.where(:administrator_id => params[:show_for]) if params[:show_for].present?
118
+ scope = scope.where("custom_report_reports.deleted_at IS NULL") unless params[:show_archived].present?
119
+ scope.group_by(&:category)
120
+ end
121
+
122
+ def custom_report
123
+ if params[:id]
124
+ CustomReport::Report.includes(:report_check_items).find params[:id]
125
+ elsif params[:report]
126
+ CustomReport::Report.new(params[:report])
127
+ else
128
+ CustomReport::Report.new(:name => "Custom Report", :columns => [["Column 1", "some_method"], ["Column 2", "some_other_method"]])
129
+ end
130
+ end
131
+
132
+ def toggle_check_item
133
+ @item = CustomReport::ReportCheckItem.where(:report_id => params[:id], :item_id => params[:item_id]).first
134
+
135
+ unless @item
136
+ @item = CustomReport::ReportCheckItem.new
137
+ @item.report_id = params[:id]
138
+ @item.item_id = params[:item_id]
139
+ @item.save!
140
+ else
141
+ @item.destroy
142
+ end
143
+ render :nothing => true
144
+ end
145
+
146
+ def remove_all_check_items
147
+ CustomReport::ReportCheckItem.where(:report_id => params[:id]).delete_all
148
+
149
+ render :js => "$('.check_item').attr('checked',false);"
150
+ end
151
+
152
+ def destroy
153
+ custom_report.update_column(:deleted_at, Time.current)
154
+ redirect_to reports_path
155
+ end
156
+
157
+ private
158
+
159
+ def set_return_path
160
+ @return_path = params[:return_path] || reports_path
161
+ end
162
+
163
+ def my_object
164
+ "custom_report"
165
+ end
166
+
167
+ def render_csv(iterator, options = {})
168
+ filename = options[:filename] || "#{params[:action]}-#{Time.now.strftime("%Y%m%d%H%M%S")}"
169
+ filename << '.csv'
170
+
171
+ if request and request.env['HTTP_USER_AGENT'] =~ /msie/i
172
+ headers['Pragma'] = 'public'
173
+ headers["Content-type"] = "text/plain"
174
+ headers['Cache-Control'] = 'no-cache, must-revalidate, post-check=0, pre-check=0'
175
+ headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
176
+ headers['Expires'] = "0"
177
+ else
178
+ headers["Content-Type"] ||= 'text/csv'
179
+ headers["Content-Disposition"] = "attachment; filename=\"#{filename}\""
180
+ end
181
+
182
+ text = CSV.generate do |csv|
183
+ csv << @columns.map { |column| column[:name] }
184
+
185
+ iterator.each do |entity|
186
+ csv << @columns.each_with_index.map do |column, index|
187
+ format_column(entity, column, index)
188
+ end
189
+ end
190
+ end
191
+
192
+ render :layout => false, :inline => text
193
+ end
194
+
195
+ def method_missing(name, *args, &block)
196
+ main_app.send(name, *args, &block)
197
+ end
198
+ helper_method :method_missing
199
+
200
+ def administrator_class
201
+ if CustomReport.admin_class
202
+ CustomReport.admin_class.constantize
203
+ else
204
+ nil
205
+ end
206
+ end
207
+ helper_method :administrator_class
208
+ end
209
+
210
+
211
+ end
@@ -0,0 +1,77 @@
1
+ module CustomReport
2
+ class Report < ActiveRecord::Base
3
+ belongs_to :administrator, :polymorphic => true
4
+ has_many :report_check_items
5
+
6
+ validates_presence_of :name
7
+
8
+ validate :unharmful
9
+
10
+ serialize :columns
11
+
12
+ attr_accessor :iterator
13
+
14
+ def generate(options = {}, filter_args = {})
15
+ result = []
16
+ ActiveRecord::Base.transaction do
17
+ # Create the scope
18
+ begin
19
+ @iterator = eval(self.scope) unless self.scope.include?("destroy")
20
+
21
+ unless options[:dont_paginate]
22
+ @iterator = @iterator.paginate :page => options[:page], :per_page => (options[:per_page] || 20)
23
+ end
24
+
25
+ # Return an array of hashes
26
+ result = @iterator.map do |entity|
27
+ self.columns.map do |column|
28
+ evaluate(entity, column)
29
+ end
30
+ end
31
+
32
+ ensure
33
+ # Always roll back
34
+ raise ActiveRecord::Rollback
35
+ end
36
+ end
37
+ result
38
+ end
39
+
40
+ def evaluate(entity, column)
41
+ accessor = if column.is_a?(Hash) and column.size == 1
42
+ column.values.first
43
+ else
44
+ column[1]
45
+ end
46
+
47
+ unless accessor.include?("destroy")
48
+ entity.instance_eval(accessor)
49
+ end
50
+ end
51
+
52
+ def columns_yaml=(values)
53
+ self.columns = YAML::load(values)
54
+ end
55
+
56
+ def columns_yaml
57
+ self.columns.to_yaml
58
+ end
59
+
60
+ def columns_hash
61
+ columns.map do |c|
62
+ if c.is_a?(Array)
63
+ { :name => c[0], :format => c[2] }
64
+ else
65
+ { :name => c.keys.first, :format => nil }
66
+ end
67
+ end
68
+ end
69
+
70
+ def unharmful
71
+ if scope.include?(".destroy")
72
+ errors.add(:scope, 'Scope cannot destroy - unsafe!')
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ module CustomReport
2
+ class ReportCheckItem < ActiveRecord::Base
3
+ attr_accessible :custom_report_id, :item_id
4
+
5
+ belongs_to :report
6
+
7
+ validates_presence_of :report_id
8
+ validates_presence_of :item_id
9
+
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ css:
2
+ textarea.columns {
3
+ border: 1px solid #999999;
4
+ font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace;
5
+ }
6
+ textarea {
7
+ width: 600px;
8
+ }
9
+
10
+ = form_for @report, :role => "form" do |f|
11
+ = hidden_field_tag "return_path", @return_path
12
+ div.form-group
13
+ = f.label :name
14
+ = f.text_field :name, :class => "form-control"
15
+ - if administrator_class
16
+ div.form-group
17
+ = f.label :administrator_id, "Administrator"
18
+ = f.select :administrator_id, options_for_select([["Everybody", nil]] + administrator_class.all.map { |x| [x.name, x.id] }, f.object.new_record? ? nil : f.object.administrator_id), :class => "form-control"
19
+ div.form-group
20
+ = f.label :category
21
+ = f.text_field :category
22
+ div.form-group
23
+ = f.label :description
24
+ = f.text_area :description, :rows => 5
25
+ div.form-group
26
+ = f.label :scope
27
+ = f.text_area :scope, :size => 110
28
+ div.form-group
29
+ = f.label :columns_yaml, "Columns"
30
+ = f.text_area :columns_yaml, :class => "columns", :cols => 80
31
+ = f.submit "Save report", :class => "btn btn-default"
32
+ h3 Advanced
33
+ div.form-group
34
+ = f.label :has_checklist
35
+ = f.check_box(:has_checklist,{}, true, false)
36
+
37
+ = f.submit "Save report", :class => "btn btn-default"
@@ -0,0 +1,3 @@
1
+ h1 Edit Report
2
+
3
+ = render "form"
@@ -0,0 +1,39 @@
1
+ h1 All reports
2
+ span
3
+ = link_to "New report", new_report_path, :class => "btn btn-small"
4
+
5
+ table.table
6
+ tr
7
+ th Name
8
+ th For
9
+ th Updated at
10
+ th Last opened
11
+ th
12
+ th
13
+ th
14
+
15
+ - @custom_reports.each do |category, reports|
16
+ tr
17
+ td colspan="7" style="background-color: #eee; font-weight: bold; border-bottom: 1px solid #ccc;"
18
+ = category.presence || "No category"
19
+ - reports.each do |report|
20
+ tr
21
+ td
22
+ = link_to report.name, [report], :style => "color: blue;"
23
+ = " (deleted)" if report.deleted_at.present?
24
+ td
25
+ = report.administrator.try(:name) || report.administrator.try(:personal_name)
26
+ td
27
+ = l report.updated_at
28
+ td
29
+ = report.last_opened.present? ? l(report.last_opened) : ""
30
+ td
31
+ = link_to "CSV", report_path(report, :format => :csv), :class => "btn btn-small"
32
+ td
33
+ = link_to "Edit", edit_report_path(report), :class => "btn btn-small"
34
+ td
35
+ - if report.deleted_at.nil?
36
+ = link_to "Archive", report_path(report, :return_path => request.path), :method => :delete, :confirm => "Really?", :class => "btn btn-small btn-warning"
37
+
38
+
39
+ = link_to "Show archived", reports_path(:show_archived => true), :class => "btn btn-default"
@@ -0,0 +1,3 @@
1
+ h1 New Report
2
+
3
+ = render "form"
@@ -0,0 +1,41 @@
1
+ css:
2
+ form {
3
+ margin: 0;
4
+ }
5
+
6
+ h1
7
+ = @report.name
8
+ p
9
+ = link_to "Edit this report", edit_report_path(@report, :return_path => request.fullpath), :class => "btn btn-primary"
10
+ = " "
11
+ = link_to "List Reports", reports_path, :class => "btn btn-default"
12
+ p
13
+ = (@report.description || "").gsub("\n", "<br>").html_safe
14
+
15
+ = will_paginate @iterator if @iterator.respond_to?(:total_pages)
16
+
17
+ table.table.table-striped.table-condensed
18
+ thead
19
+ tr
20
+ - @columns.each do |column|
21
+ th = h column[:name]
22
+ - if @report.has_checklist
23
+ th
24
+ = link_to "Uncheck all", remove_all_check_items_report_path, :method => :post, :remote => true
25
+
26
+ tbody
27
+ - @results.each do |entity|
28
+ tr
29
+ - @columns.each_with_index do |column, index|
30
+ td
31
+ = format_column(entity, column, index).html_safe
32
+
33
+ - if @report.has_checklist
34
+ td
35
+ = form_tag toggle_check_item_report_path, :method => :post, :remote => true do
36
+ = check_box_tag :item_id, entity[0], @check_items.has_key?(entity[0]) && !@check_items[entity[0]].empty?, :onchange => "$(this).submit();", :class => "check_item"
37
+
38
+ = will_paginate @iterator if @iterator.respond_to?(:total_pages)
39
+
40
+ p
41
+ = link_to "[Download CSV]", request.path + ".csv" + "?#{request.query_string}"
data/config/routes.rb ADDED
@@ -0,0 +1,10 @@
1
+ CustomReport::Engine.routes.draw do
2
+ resources :reports do
3
+ member do
4
+ post :remove_all_check_items
5
+ post :toggle_check_item
6
+ end
7
+ end
8
+
9
+ root :to => "reports#index"
10
+ end