reporta-modules 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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +203 -0
  4. data/Rakefile +20 -0
  5. data/lib/generators/reporta/views_generator.rb +24 -0
  6. data/lib/generators/templates/reports/_box.html.erb +48 -0
  7. data/lib/generators/templates/reports/_chartjs_bar.html.erb +31 -0
  8. data/lib/generators/templates/reports/_chartjs_line.html.erb +33 -0
  9. data/lib/generators/templates/reports/_chartjs_pie.html.erb +19 -0
  10. data/lib/generators/templates/reports/_filters.html.erb +100 -0
  11. data/lib/generators/templates/reports/_table.html.erb +49 -0
  12. data/lib/reporta-modules.rb +15 -0
  13. data/lib/reporta/box_helper.rb +17 -0
  14. data/lib/reporta/chartjs_helper.rb +74 -0
  15. data/lib/reporta/models/column.rb +68 -0
  16. data/lib/reporta/models/filter.rb +42 -0
  17. data/lib/reporta/models/form.rb +77 -0
  18. data/lib/reporta/models/reportable.rb +50 -0
  19. data/lib/reporta/railtie.rb +8 -0
  20. data/lib/reporta/version.rb +3 -0
  21. data/lib/reporta/view_helper.rb +38 -0
  22. data/lib/tasks/reporta_tasks.rake +4 -0
  23. data/spec/dummy/README.rdoc +28 -0
  24. data/spec/dummy/Rakefile +6 -0
  25. data/spec/dummy/app/assets/javascripts/application.js +18 -0
  26. data/spec/dummy/app/assets/javascripts/jquery.dataTables.js +12099 -0
  27. data/spec/dummy/app/assets/javascripts/jquery.flot.js +3061 -0
  28. data/spec/dummy/app/assets/javascripts/jquery.flot.time.js +431 -0
  29. data/spec/dummy/app/assets/javascripts/jquery.js +2 -0
  30. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  31. data/spec/dummy/app/assets/stylesheets/bootstrap.min.css +9 -0
  32. data/spec/dummy/app/assets/stylesheets/style.css +57 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  34. data/spec/dummy/app/controllers/reports_controller.rb +18 -0
  35. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  36. data/spec/dummy/app/models/account.rb +3 -0
  37. data/spec/dummy/app/models/account_chart.rb +41 -0
  38. data/spec/dummy/app/models/account_report.rb +39 -0
  39. data/spec/dummy/app/models/user.rb +8 -0
  40. data/spec/dummy/app/views/layouts/application.html.erb +28 -0
  41. data/spec/dummy/app/views/reports/chart.html.erb +6 -0
  42. data/spec/dummy/app/views/reports/dynamic_table.html.erb +33 -0
  43. data/spec/dummy/app/views/reports/dynamic_table_with_bootstrap.html.erb +37 -0
  44. data/spec/dummy/app/views/reports/overview.html.erb +4 -0
  45. data/spec/dummy/app/views/reports/table.html.erb +12 -0
  46. data/spec/dummy/bin/bundle +3 -0
  47. data/spec/dummy/bin/rails +4 -0
  48. data/spec/dummy/bin/rake +4 -0
  49. data/spec/dummy/config.ru +4 -0
  50. data/spec/dummy/config/application.rb +23 -0
  51. data/spec/dummy/config/boot.rb +5 -0
  52. data/spec/dummy/config/database.yml +25 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +29 -0
  55. data/spec/dummy/config/environments/production.rb +80 -0
  56. data/spec/dummy/config/environments/test.rb +36 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  59. data/spec/dummy/config/initializers/inflections.rb +16 -0
  60. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  61. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  62. data/spec/dummy/config/initializers/session_store.rb +3 -0
  63. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  64. data/spec/dummy/config/locales/en.yml +23 -0
  65. data/spec/dummy/config/routes.rb +7 -0
  66. data/spec/dummy/db/migrate/20130622041213_create_users.rb +14 -0
  67. data/spec/dummy/db/migrate/20130623054801_create_accounts.rb +9 -0
  68. data/spec/dummy/db/schema.rb +33 -0
  69. data/spec/dummy/db/seeds.rb +20 -0
  70. data/spec/dummy/db/test.sqlite3 +0 -0
  71. data/spec/dummy/log/test.log +1190 -0
  72. data/spec/dummy/public/404.html +58 -0
  73. data/spec/dummy/public/422.html +58 -0
  74. data/spec/dummy/public/500.html +57 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/models/column_spec.rb +76 -0
  77. data/spec/models/filter_spec.rb +63 -0
  78. data/spec/models/form_spec.rb +81 -0
  79. data/spec/models/report_spec.rb +51 -0
  80. data/spec/spec_helper.rb +43 -0
  81. metadata +247 -0
@@ -0,0 +1,49 @@
1
+ <!--
2
+ Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ -->
23
+
24
+ <table class="<%= class_name %>">
25
+ <thead>
26
+ <tr>
27
+ <% report.columns.each do |name, column| %>
28
+ <th class="<%= column.class_names %>">
29
+ <%= column.title %>
30
+ </th>
31
+ <% end %>
32
+ </tr>
33
+ </thead>
34
+ <tbody>
35
+ <% report.rows.each do |record| %>
36
+ <tr>
37
+ <% report.columns.each do |name, column| %>
38
+ <td class="<%= column.class_names %>">
39
+ <% if column.helper %>
40
+ <%= send(column.helper, record) %>
41
+ <% else %>
42
+ <%= report.value_for(record, name) %>
43
+ <% end %>
44
+ </td>
45
+ <% end %>
46
+ </tr>
47
+ <% end %>
48
+ </tbody>
49
+ </table>
@@ -0,0 +1,15 @@
1
+ require 'reporta/railtie' if defined?(Rails)
2
+ module Reporta
3
+ extend ActiveSupport::Concern
4
+ extend ActiveSupport::Autoload
5
+
6
+ # view model
7
+ autoload :Form, 'reporta/models/form'
8
+ autoload :Filter, 'reporta/models/filter'
9
+ autoload :Column, 'reporta/models/column'
10
+ autoload :Reportable, 'reporta/models/reportable'
11
+
12
+ autoload :ViewHelper, 'reporta/view_helper'
13
+ autoload :ChartjsHelper, 'reporta/chartjs_helper'
14
+ autoload :BoxHelper, 'reporta/box_helper'
15
+ end
@@ -0,0 +1,17 @@
1
+ module Reporta
2
+ module BoxHelper
3
+ include ActionView::Helpers::NumberHelper
4
+ def readable_number(num)
5
+ num = num || 0
6
+ opts = {units: { thousand: 'K', million: 'M', billion: 'B'}}
7
+ number_to_human(num, opts)
8
+ end
9
+
10
+ def box_for(report, locals={})
11
+ locals.reverse_merge!(report: report)
12
+ render partial: 'reporta/reports/box', locals: locals
13
+ end
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,74 @@
1
+ module Reporta
2
+ module ChartjsHelper
3
+ include ActionView::Helpers::NumberHelper
4
+
5
+ def line_chart_for(report, x, y, locals={})
6
+ locals.reverse_merge!(
7
+ report: report,
8
+ x: x,
9
+ y: y,
10
+ prefix: report.class.to_s.demodulize,
11
+ rows: report.rows,
12
+ color: '#46BFBD')
13
+ render partial: "reporta/reports/chartjs_line", locals: locals
14
+ end
15
+
16
+ def pie_chart_for(report, x, y, locals={})
17
+ locals.reverse_merge!(
18
+ report: report,
19
+ x: x,
20
+ y: y,
21
+ prefix: report.class.to_s.demodulize,
22
+ rows: report.rows,
23
+ color: '#46BFBD')
24
+ render partial: "reporta/reports/chartjs_pie", locals: locals
25
+ end
26
+
27
+ def bar_chart_for(report, x, y, locals={})
28
+ locals.reverse_merge!(
29
+ report: report,
30
+ x: x,
31
+ y: y,
32
+ prefix: report.class.to_s.demodulize,
33
+ rows: report.rows,
34
+ color: '#46BFBD')
35
+ render partial: "reporta/reports/chartjs_bar", locals: locals
36
+ end
37
+
38
+ def chart_pie_from_rows(rows, x, y)
39
+ return {datasets:'[]', colors: '{}'} if rows.blank?
40
+ chart = {colors: {}, datasets: ''}
41
+ data = []
42
+ rows.each do |row|
43
+ color = cycle(*colors)
44
+ value = row.send(y)
45
+ label = row.send(x) || "Unknown"
46
+ data << { label: "#{label.humanize}", value: value, color: color }
47
+ chart[:colors][row.send(x)] = color
48
+ end
49
+ chart[:datasets] = data.to_json
50
+ chart
51
+ end
52
+
53
+ def colors
54
+ ['#F38630', '#E0E4CC', '#69D2E7','#F7464A', '#E2EAE9', '#D4CCC5', '#949FB1', '#4D5360']
55
+ end
56
+
57
+ def labels_from_rows(rows, attr, length=11)
58
+ return [] if rows.empty?
59
+ rows.collect{|r|
60
+ row = r.send(attr)
61
+ row = row.blank? ? 'Unknown' : row
62
+ truncate(row.to_s, length: length)}
63
+ end
64
+
65
+ def decimals_from_rows(rows, x, y, precision=2)
66
+ return [] if rows.blank?
67
+ rows.collect{|r|
68
+ row = r.send(y)
69
+ row = row.blank? ? 0 : row
70
+ number_with_precision(row.to_f, precision: precision).to_f }
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,68 @@
1
+ # Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
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.
21
+
22
+ require 'ostruct'
23
+
24
+ module Reporta
25
+ module Column
26
+ extend ActiveSupport::Concern
27
+
28
+ included do
29
+ cattr_accessor :columns
30
+ self.columns = {}
31
+ end
32
+
33
+ module ClassMethods
34
+ def column(name, options={})
35
+ columns[name] = OpenStruct.new options.reverse_merge(
36
+ title: name.to_s.humanize
37
+ )
38
+ end
39
+ end
40
+
41
+ def value_for(record, column_name)
42
+ column = columns[column_name]
43
+
44
+ # Local method defined that matches the column name
45
+ if respond_to? column_name
46
+ self.send column_name, record
47
+
48
+ # Column has the data_chain option set
49
+ elsif column.data_chain
50
+ data_chain_result(record, column.data_chain)
51
+
52
+ # Call the column name method on the record
53
+ else
54
+ record.send column_name
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def data_chain_result(record, data_chain)
61
+ data_chain = data_chain.to_s.split '.'
62
+ data_chain.reduce(record) do |obj, method|
63
+ obj.send method
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
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.
21
+
22
+ require 'ostruct'
23
+
24
+ module Reporta
25
+ module Filter
26
+ extend ActiveSupport::Concern
27
+
28
+ included do
29
+ cattr_accessor :filters
30
+ self.filters = {}
31
+ end
32
+
33
+ module ClassMethods
34
+ def filter(name, options={})
35
+ filters[name] = OpenStruct.new options.reverse_merge(
36
+ include_blank: true,
37
+ 'boolean?' => (options[:as] == :boolean)
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ # Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
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.
21
+
22
+ module Reporta
23
+ class Form
24
+ include ActiveModel::Validations
25
+ include ActiveModel::Conversion
26
+
27
+ attr_accessor :filters, :filter_applied, :params
28
+
29
+ validate do
30
+ filters.each do |name, options|
31
+ if options.required && send(name).blank?
32
+ # TODO: Allow for internationization of form validation errors
33
+ errors.add(name, "required")
34
+ end
35
+ end
36
+ end
37
+
38
+ def initialize(filters, values={})
39
+ @filters = filters
40
+ @params = values
41
+ self.class.send :attr_accessor, *filters.keys
42
+ self.filter_applied = values.any?
43
+ set_values filters, values
44
+ end
45
+
46
+ def filter_applied?
47
+ self.filter_applied
48
+ end
49
+
50
+ # This method is required so a Form instance can be passed into a form_for
51
+ # helper method
52
+ def persisted?
53
+ false
54
+ end
55
+
56
+ private
57
+
58
+ def set_values(filters, values)
59
+ filters.each do |name, filter|
60
+ value = values[name].present? ? values[name] : filter.default
61
+ value = convert_boolean(values[name]) if filter.boolean?
62
+
63
+ self.send "#{name}=", value
64
+ end
65
+ end
66
+
67
+ def convert_boolean(value)
68
+ if value == "0"
69
+ false
70
+ elsif value == "1"
71
+ true
72
+ else
73
+ !!value
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
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.
21
+
22
+ module Reporta
23
+ module Reportable
24
+ extend ActiveSupport::Concern
25
+ include Filter
26
+ include Column
27
+
28
+ attr_accessor :form
29
+
30
+ def initialize(args={})
31
+ args ||= {}
32
+ @form = Reporta::Form.new filters, args
33
+ form.valid? if args.present?
34
+ end
35
+
36
+ def id
37
+ self.class.name.underscore
38
+ end
39
+
40
+ private
41
+
42
+ # Delegate any undefined message to the @form object.
43
+ # This allows you to call `report.start_date` to get the value of the
44
+ # `start_date` filter or assign a value using
45
+ # `report.start_date = '2013-01-01'`
46
+ def method_missing(*args, &block)
47
+ self.form.send(*args, &block)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ require 'reporta/view_helper'
2
+ module Reporta
3
+ class Railtie < Rails::Railtie
4
+ initializer "reporta.application_helper" do
5
+ ActionView::Base.send :include, ViewHelper
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Reporta
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2013-2014 University of Technology, Sydney (github.com/uts)
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.
21
+
22
+ module Reporta
23
+ module ViewHelper
24
+
25
+ def filters_for(report)
26
+ render partial: "reporta/reports/filters", locals: { report: report }
27
+ end
28
+
29
+ def table_for(report, locals={})
30
+ locals.reverse_merge!(report: report, class_name: '')
31
+ render partial: "reporta/reports/table", locals: locals
32
+ end
33
+
34
+ def chart_for(report, locals={})
35
+ render partial: "reporta/reports/chart", locals: { report: report }
36
+ end
37
+ end
38
+ end