effective_reports 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +110 -0
  4. data/Rakefile +18 -0
  5. data/app/assets/config/effective_reports_manifest.js +3 -0
  6. data/app/assets/javascripts/effective_reports/base.js +15 -0
  7. data/app/assets/javascripts/effective_reports.js +1 -0
  8. data/app/assets/stylesheets/effective_reports/base.scss +0 -0
  9. data/app/assets/stylesheets/effective_reports.scss +1 -0
  10. data/app/controllers/admin/reports_controller.rb +16 -0
  11. data/app/datatables/admin/effective_reports_datatable.rb +31 -0
  12. data/app/datatables/effective_report_datatable.rb +21 -0
  13. data/app/helpers/effective_reports_helper.rb +60 -0
  14. data/app/mailers/effective/reports_mailer.rb +38 -0
  15. data/app/models/concerns/acts_as_reportable.rb +72 -0
  16. data/app/models/effective/report.rb +94 -0
  17. data/app/models/effective/report_column.rb +89 -0
  18. data/app/models/effective/report_scope.rb +48 -0
  19. data/app/views/admin/reports/_form.html.haml +8 -0
  20. data/app/views/admin/reports/_form_report.html.haml +194 -0
  21. data/app/views/admin/reports/_layout.html.haml +2 -0
  22. data/app/views/admin/reports/_report.html.haml +17 -0
  23. data/config/effective_reports.rb +37 -0
  24. data/config/routes.rb +16 -0
  25. data/db/migrate/01_create_effective_reports.rb.erb +54 -0
  26. data/db/seeds.rb +1 -0
  27. data/lib/effective_reports/engine.rb +18 -0
  28. data/lib/effective_reports/version.rb +3 -0
  29. data/lib/effective_reports.rb +27 -0
  30. data/lib/generators/effective_reports/install_generator.rb +32 -0
  31. data/lib/generators/templates/effective_reports_mailer_preview.rb +4 -0
  32. data/lib/tasks/effective_reports_tasks.rake +8 -0
  33. metadata +270 -0
@@ -0,0 +1,194 @@
1
+ = effective_form_with(model: [:admin, report], engine: true) do |f|
2
+ = f.text_field :title
3
+ = f.text_area :description
4
+
5
+ - if f.object.new_record?
6
+ = f.select :reportable_class_name, EffectiveReports.reportable_classes.map(&:name), label: 'Resource',
7
+ 'data-load-ajax-url': effective_reports.new_admin_report_path,
8
+ 'data-load-ajax-div': '#effective-reports-ajax'
9
+ - else
10
+ = f.static_field :reportable_class_name, label: 'Resource'
11
+
12
+ #effective-reports-ajax
13
+ -# Attributes
14
+ - attributes = f.object.reportable_attributes
15
+ - attributes_collection = reportable_attributes_collection(attributes)
16
+
17
+ - value_booleans = attributes.select { |_, type| type == :boolean }.keys
18
+ - value_dates = attributes.select { |_, type| type == :date }.keys
19
+ - value_decimals = attributes.select { |_, type| type == :decimal }.keys
20
+ - value_integers = attributes.select { |_, type| type == :integer }.keys
21
+ - value_prices = attributes.select { |_, type| type == :price }.keys
22
+ - value_strings = attributes.select { |_, type| type == :string }.keys
23
+
24
+ - value_belong_tos = attributes.select { |_, type| type == :belongs_to }.keys
25
+ - value_belong_to_polymorphics = attributes.select { |_, type| type == :belongs_to_polymorphic }.keys
26
+ - value_has_manys = attributes.select { |_, type| type == :has_many }.keys
27
+ - value_has_ones = attributes.select { |_, type| type == :has_one }.keys
28
+
29
+ -# Scopes
30
+ - scopes = f.object.reportable_scopes
31
+ - scopes_collection = reportable_scopes_collection(scopes)
32
+
33
+ - if attributes.present?
34
+ %h2 Report Columns
35
+
36
+ = f.has_many :report_columns do |frc|
37
+ .card.mb-2
38
+ .card-body.pb-2
39
+ .row
40
+ .col-md-4
41
+ = frc.select :name, attributes_collection, grouped: true, required: false, label: false
42
+ .col
43
+ = frc.show_if_any(:name, value_booleans) do
44
+
45
+ .row
46
+ .col.mt-2
47
+ = frc.check_box :filter, label: 'Filter by this column'
48
+ = frc.hidden_field :as, value: :boolean
49
+
50
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
51
+ = frc.select :operation, reportable_operations_collection(:boolean), label: false
52
+
53
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
54
+ = frc.radios :value_boolean, reportable_boolean_collection, label: false, buttons: true
55
+
56
+ = frc.show_if_any(:name, value_dates) do
57
+ .row
58
+ .col.mt-2
59
+ = frc.check_box :filter, label: 'Filter by this column'
60
+ = frc.hidden_field :as, value: :date
61
+
62
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
63
+ = frc.select :operation, reportable_operations_collection(:date), label: false
64
+
65
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
66
+ = frc.date_field :value_date, label: false
67
+
68
+ = frc.show_if_any(:name, value_decimals) do
69
+ .row
70
+ .col.mt-2
71
+ = frc.check_box :filter, label: 'Filter by this column'
72
+ = frc.hidden_field :as, value: :decimal
73
+
74
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
75
+ = frc.select :operation, reportable_operations_collection(:decimal), label: false
76
+
77
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
78
+ = frc.float_field :value_decimal, label: false
79
+
80
+ = frc.show_if_any(:name, value_integers) do
81
+ .row
82
+ .col.mt-2
83
+ = frc.check_box :filter, label: 'Filter by this column'
84
+ = frc.hidden_field :as, value: :integer
85
+
86
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
87
+ = frc.select :operation, reportable_operations_collection(:integer), label: false
88
+
89
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
90
+ = frc.integer_field :value_integer, label: false
91
+
92
+ = frc.show_if_any(:name, value_prices) do
93
+ .row
94
+ .col.mt-2
95
+ = frc.check_box :filter, label: 'Filter by this column'
96
+ = frc.hidden_field :as, value: :price
97
+
98
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
99
+ = frc.select :operation, reportable_operations_collection(:price), label: false
100
+
101
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
102
+ = frc.price_field :value_price, label: false
103
+
104
+ = frc.show_if_any(:name, value_strings) do
105
+ .row
106
+ .col.mt-2
107
+ = frc.check_box :filter, label: 'Filter by this column'
108
+ = frc.hidden_field :as, value: :string
109
+
110
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
111
+ = frc.select :operation, reportable_operations_collection(:string), label: false
112
+
113
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
114
+ = frc.text_field :value_string, label: false
115
+
116
+ = frc.show_if_any(:name, value_belong_tos) do
117
+ .row
118
+ .col.mt-2
119
+ = frc.check_box :filter, label: 'Filter by this column'
120
+ = frc.hidden_field :as, value: :belongs_to
121
+
122
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
123
+ = frc.select :operation, reportable_operations_collection(:belongs_to), label: false
124
+
125
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
126
+ = frc.text_field :value_associated, label: false
127
+
128
+ = frc.show_if_any(:name, value_belong_to_polymorphics) do
129
+ .row
130
+ .col.mt-2
131
+ = frc.check_box :filter, label: 'Filter by this column'
132
+ = frc.hidden_field :as, value: :belongs_to_polymorphic
133
+
134
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
135
+ = frc.select :operation, reportable_operations_collection(:belongs_to_polymorphic), label: false
136
+
137
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
138
+ = frc.text_field :value_associated, label: false
139
+
140
+
141
+ = frc.show_if_any(:name, value_has_manys) do
142
+ .row
143
+ .col.mt-2
144
+ = frc.check_box :filter, label: 'Filter by this column'
145
+ = frc.hidden_field :as, value: :has_many
146
+
147
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
148
+ = frc.select :operation, reportable_operations_collection(:has_many), label: false
149
+
150
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
151
+ = frc.text_field :value_associated, label: false
152
+
153
+ = frc.show_if_any(:name, value_has_ones) do
154
+ .row
155
+ .col.mt-2
156
+ = frc.check_box :filter, label: 'Filter by this column'
157
+ = frc.hidden_field :as, value: :has_one
158
+
159
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
160
+ = frc.select :operation, reportable_operations_collection(:has_one), label: false
161
+
162
+ .col.effective-report-filter{style: ('display: none;' unless frc.object.filter?)}
163
+ = frc.text_field :value_associated, label: false
164
+
165
+ - if scopes.present?
166
+ %h2 Report Scopes
167
+
168
+ = f.has_many :report_scopes do |frs|
169
+ .card.mb-2
170
+ .card-body.pb-2
171
+ .row
172
+ .col
173
+ = frs.select :name, scopes_collection, grouped: true, required: false, label: false
174
+ .col
175
+ - scopes.select { |scope, type| type.present? }.each do |scope, type|
176
+ = frs.show_if(:name, scope) do
177
+ = frs.hidden_field :advanced, value: true
178
+
179
+ - if type == :boolean
180
+ = frs.radios :value_boolean, reportable_boolean_collection, label: 'Value', buttons: true, required: true, label: false
181
+ - elsif type == :date
182
+ = frs.date_field :value_date, label: 'Value', required: true, label: false
183
+ - elsif type == :decimal
184
+ = frs.date_field :value_decimal, label: 'Value', required: true, label: false
185
+ - elsif type == :integer
186
+ = frs.integer_field :value_integer, label: 'Value', required: true, label: false
187
+ - elsif type == :price
188
+ = frs.price_field :value_price, label: 'Value', required: true, label: false
189
+ - elsif type == :string
190
+ = frs.text_field :value_string, label: 'Value', required: true, label: false
191
+ - else
192
+ - raise("Unexpected scope datatype: #{type || 'nil'}")
193
+
194
+ = effective_submit(f)
@@ -0,0 +1,2 @@
1
+ .effective-reports
2
+ = yield
@@ -0,0 +1,17 @@
1
+ - if report.description.present?
2
+ %p= report.description.to_s
3
+
4
+ - if report.filtered_report_columns.present? || report.report_scopes.present?
5
+ %p The results of this report have been filtered by the following:
6
+
7
+ - if report.filtered_report_columns.present?
8
+ %p= badges(report.filtered_report_columns.map(&:to_s))
9
+
10
+ - if report.report_scopes.present?
11
+ %p= badges(report.report_scopes.map(&:to_s))
12
+
13
+ = collapse('Show SQL') do
14
+ %p= report.collection.to_sql
15
+
16
+ - datatable = EffectiveReportDatatable.new(report: report)
17
+ = render_datatable(datatable)
@@ -0,0 +1,37 @@
1
+ EffectiveReports.setup do |config|
2
+ config.reports_table_name = :reports
3
+ config.report_columns_table_name = :report_columns
4
+ config.report_scopes_table_name = :report_scopes
5
+
6
+ # Layout Settings
7
+ # Configure the Layout per controller, or all at once
8
+ # config.layout = { application: 'application', admin: 'admin' }
9
+
10
+ # Reports Settings
11
+ # Configure the class responsible for the reports.
12
+ # This should extend from Effective::Reports
13
+ # config.reports_class_name = 'Effective::Reports'
14
+
15
+ # Reportable Class Names
16
+ # The following classes will be available to build reports from
17
+ # They must define acts_as_reportable to be included
18
+ config.reportable_class_names = ['User', 'Effective::Order']
19
+
20
+ # Mailer Settings
21
+ # Please see config/initializers/effective_reports.rb for default effective_* gem mailer settings
22
+ #
23
+ # Configure the class responsible to send e-mails.
24
+ # config.mailer = 'Effective::ReportsMailer'
25
+ #
26
+ # Override effective_resource mailer defaults
27
+ #
28
+ # config.parent_mailer = nil # The parent class responsible for sending emails
29
+ # config.deliver_method = nil # The deliver method, deliver_later or deliver_now
30
+ # config.mailer_layout = nil # Default mailer layout
31
+ # config.mailer_sender = nil # Default From value
32
+ # config.mailer_admin = nil # Default To value for Admin correspondence
33
+ # config.mailer_subject = nil # Proc.new method used to customize Subject
34
+
35
+ # Will work with effective_email_templates gem
36
+ config.use_effective_email_templates = true
37
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ mount EffectiveReports::Engine => '/', as: 'effective_reports'
5
+ end
6
+
7
+ EffectiveReports::Engine.routes.draw do
8
+ # Public routes
9
+ scope module: 'effective' do
10
+ end
11
+
12
+ namespace :admin do
13
+ resources :reports
14
+ end
15
+
16
+ end
@@ -0,0 +1,54 @@
1
+ class CreateEffectiveReports < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table <%= @reports_table_name %> do |t|
4
+ t.integer :created_by_id
5
+ t.string :created_by_type
6
+
7
+ t.string :title
8
+ t.text :description
9
+
10
+ t.string :reportable_class_name
11
+
12
+ t.timestamps
13
+ end
14
+
15
+ create_table <%= @report_columns_table_name %> do |t|
16
+ t.integer :report_id
17
+
18
+ t.string :name
19
+ t.integer :position
20
+
21
+ t.string :as
22
+
23
+ t.boolean :filter
24
+ t.string :operation
25
+
26
+ t.text :value_associated
27
+ t.boolean :value_boolean
28
+ t.date :value_date
29
+ t.decimal :value_decimal
30
+ t.integer :value_integer
31
+ t.integer :value_price
32
+ t.string :value_string
33
+
34
+ t.timestamps
35
+ end
36
+
37
+ create_table <%= @report_scopes_table_name %> do |t|
38
+ t.integer :report_id
39
+
40
+ t.string :name
41
+ t.boolean :advanced
42
+
43
+ t.boolean :value_boolean
44
+ t.date :value_date
45
+ t.decimal :value_decimal
46
+ t.integer :value_integer
47
+ t.integer :value_price
48
+ t.string :value_string
49
+
50
+ t.timestamps
51
+ end
52
+
53
+ end
54
+ end
data/db/seeds.rb ADDED
@@ -0,0 +1 @@
1
+ puts "Running effective_reports seeds"
@@ -0,0 +1,18 @@
1
+ module EffectiveReports
2
+ class Engine < ::Rails::Engine
3
+ engine_name 'effective_reports'
4
+
5
+ # Set up our default configuration options.
6
+ initializer 'effective_reports.defaults', before: :load_config_initializers do |app|
7
+ eval File.read("#{config.root}/config/effective_reports.rb")
8
+ end
9
+
10
+ # Include acts_as_reportable concern and allow any ActiveRecord object to call it
11
+ initializer 'effective_reports.active_record' do |app|
12
+ app.config.to_prepare do
13
+ ActiveRecord::Base.extend(ActsAsReportable::Base)
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module EffectiveReports
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,27 @@
1
+ require 'effective_resources'
2
+ require 'effective_datatables'
3
+ require 'effective_reports/engine'
4
+ require 'effective_reports/version'
5
+
6
+ module EffectiveReports
7
+
8
+ def self.config_keys
9
+ [
10
+ # Database Tables
11
+ :reports_table_name, :report_columns_table_name, :report_scopes_table_name,
12
+
13
+ :reportable_class_names,
14
+
15
+ # Effective Gem
16
+ :layout,
17
+ :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
18
+ ]
19
+ end
20
+
21
+ include EffectiveGem
22
+
23
+ def self.reportable_classes
24
+ Array(reportable_class_names).map(&:safe_constantize).select { |klass| klass.try(:acts_as_reportable?) }
25
+ end
26
+
27
+ end
@@ -0,0 +1,32 @@
1
+ module EffectiveReports
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ desc 'Creates an EffectiveReports initializer in your application.'
7
+
8
+ source_root File.expand_path('../../templates', __FILE__)
9
+
10
+ def self.next_migration_number(dirname)
11
+ if not ActiveRecord::Base.timestamped_migrations
12
+ Time.new.utc.strftime("%Y%m%d%H%M%S")
13
+ else
14
+ '%.3d' % (current_migration_number(dirname) + 1)
15
+ end
16
+ end
17
+
18
+ def copy_initializer
19
+ template ('../' * 3) + 'config/effective_reports.rb', 'config/initializers/effective_reports.rb'
20
+ end
21
+
22
+ def create_migration_file
23
+ @reports_table_name = ':' + EffectiveReports.reports_table_name.to_s
24
+ @report_columns_table_name = ':' + EffectiveReports.report_columns_table_name.to_s
25
+ @report_scopes_table_name = ':' + EffectiveReports.report_scopes_table_name.to_s
26
+
27
+ migration_template ('../' * 3) + 'db/migrate/01_create_effective_reports.rb.erb', 'db/migrate/create_effective_reports.rb'
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,4 @@
1
+ # Visit http://localhost:3000/rails/mailers
2
+
3
+ class EffectiveReportsMailerPreview < ActionMailer::Preview
4
+ end
@@ -0,0 +1,8 @@
1
+ namespace :effective_reports do
2
+
3
+ # bundle exec rake effective_reports:seed
4
+ task seed: :environment do
5
+ load "#{__dir__}/../../db/seeds.rb"
6
+ end
7
+
8
+ end