clark_kent 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/clark_kent/application.js +18291 -0
- data/app/assets/stylesheets/clark_kent/application.css +21 -0
- data/app/controllers/clark_kent/report_columns_controller.rb +6 -3
- data/app/controllers/clark_kent/report_emails_controller.rb +7 -3
- data/app/controllers/clark_kent/report_filters_controller.rb +12 -4
- data/app/controllers/clark_kent/reports_controller.rb +21 -8
- data/app/controllers/clark_kent/user_report_emails_controller.rb +7 -3
- data/app/models/clark_kent/cloneable.rb +18 -0
- data/app/models/clark_kent/date_filter_option.rb +7 -0
- data/app/models/clark_kent/number_filter_option.rb +7 -0
- data/app/models/clark_kent/object_filter_option.rb +7 -0
- data/app/models/clark_kent/report.rb +49 -6
- data/app/models/clark_kent/report_column.rb +31 -4
- data/app/models/clark_kent/report_config.rb +24 -0
- data/app/models/clark_kent/report_date_filter.rb +0 -2
- data/app/models/clark_kent/report_email.rb +1 -2
- data/app/models/clark_kent/report_filter.rb +1 -2
- data/app/models/clark_kent/report_filter_error.rb +4 -0
- data/app/models/clark_kent/report_filter_option.rb +5 -9
- data/app/models/clark_kent/report_number_filter.rb +0 -3
- data/app/models/clark_kent/reportable.rb +28 -3
- data/app/models/clark_kent/resource_option.rb +10 -0
- data/app/models/clark_kent/sharing_scope_kind.rb +38 -4
- data/app/models/clark_kent/string_filter_option.rb +7 -0
- data/app/models/clark_kent/user_report_email.rb +2 -4
- data/app/views/clark_kent/report_columns/_form.html.erb +1 -1
- data/app/views/clark_kent/reports/_edit.html.erb +8 -4
- data/app/views/clark_kent/reports/show.html.erb +5 -0
- data/db/migrate/20131226170042_create_clark_kent_report_filter.rb +17 -0
- data/db/migrate/20131226170112_create_clark_kent_report_column.rb +12 -0
- data/db/migrate/20140114010048_create_clark_kent_report_emails.rb +9 -0
- data/db/migrate/20140129051754_create_clark_kent_user_report_email.rb +7 -0
- data/db/migrate/20150304233739_create_clark_kent_reports.rb +2 -0
- data/lib/clark_kent/version.rb +1 -1
- data/lib/clark_kent.rb +4 -2
- data/test/_print_report.html.erb_spec.rb +32 -0
- data/test/controllers/clark_kent/reports_controller_test.rb +35 -12
- data/test/dummy/app/controllers/application_controller.rb +12 -0
- data/test/dummy/app/models/department.rb +4 -0
- data/test/dummy/app/models/order.rb +6 -0
- data/test/dummy/app/models/reporting/order.rb +54 -0
- data/test/dummy/app/models/user.rb +9 -0
- data/test/dummy/app/views/layouts/application.html.erb +5 -2
- data/test/dummy/config/initializers/zz_clark_kent.rb +11 -0
- data/test/dummy/config/routes.rb +1 -1
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20150309232850_create_orders.rb +10 -0
- data/test/dummy/db/migrate/20150309232855_create_users.rb +9 -0
- data/test/dummy/db/migrate/20150310143940_create_departments.rb +8 -0
- data/test/dummy/db/migrate/20150313144011_create_clark_kent_report_filter.clark_kent.rb +18 -0
- data/test/dummy/db/migrate/20150313144012_create_clark_kent_report_column.clark_kent.rb +13 -0
- data/test/dummy/db/migrate/20150313144013_create_clark_kent_report_emails.clark_kent.rb +10 -0
- data/test/dummy/db/migrate/20150313144014_create_clark_kent_user_report_email.clark_kent.rb +8 -0
- data/test/dummy/db/migrate/20150313144015_create_clark_kent_reports.clark_kent.rb +15 -0
- data/test/dummy/db/schema.rb +61 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +18038 -0
- data/test/dummy/log/test.log +14137 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0a5b3da98f8307d16bc302a1f7206591 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0a9995208f1340e4b34008cbd5b73c64 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0ec37c0a58c1be93659732a3efc73581 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0fd54fd98cd2fa0085b77e6743046927 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8aa37926d964a9eb59cf9b940e4fe2f4 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ebe8eac74b8e6016fd44b19e6e708e61 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0a5b3da98f8307d16bc302a1f7206591 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0a9995208f1340e4b34008cbd5b73c64 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0ec37c0a58c1be93659732a3efc73581 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0fd54fd98cd2fa0085b77e6743046927 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/60fb63be4cad769d9adc90c4c5501c67 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8aa37926d964a9eb59cf9b940e4fe2f4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/92058832b745b88c29a75bf2aad7245d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ebe8eac74b8e6016fd44b19e6e708e61 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/pids/server.pid +1 -0
- data/test/helpers/clark_kent/reports_helper_spec.rb +26 -0
- data/test/integration/navigation_test.rb +0 -2
- data/test/models/clark_kent/report_test.rb +6 -6
- data/test/support/db_utils.rb +29 -0
- data/test/test_helper.rb +7 -6
- metadata +148 -3
- data/app/assets/javascripts/clark_kent/reports.js +0 -10
@@ -0,0 +1,18 @@
|
|
1
|
+
module ClarkKent
|
2
|
+
module Cloneable
|
3
|
+
def cloneable_attributes
|
4
|
+
these_attrs = self.attributes.dup
|
5
|
+
these_attrs.delete('id')
|
6
|
+
these_attrs.delete('created_at')
|
7
|
+
these_attrs.delete('updated_at')
|
8
|
+
these_attrs
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_timestamps
|
12
|
+
updated_at = nil
|
13
|
+
created_at = nil
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -2,12 +2,10 @@ module ClarkKent
|
|
2
2
|
# load the builders
|
3
3
|
Dir.glob(Rails.root.join('app/models/reporting/*.rb')) { |file| load file }
|
4
4
|
class Report < ActiveRecord::Base
|
5
|
-
|
6
|
-
include Cloneable
|
5
|
+
include ClarkKent::Cloneable
|
7
6
|
|
8
7
|
SortDirections = {'A->Z' => 'asc', 'Z->A' => 'desc'}
|
9
8
|
|
10
|
-
attr_accessible :resource_type, :name, :sharing_scope_id, :sharing_scope_type
|
11
9
|
attr_accessor :summary_row_storage
|
12
10
|
|
13
11
|
belongs_to :sharing_scope, polymorphic: true
|
@@ -80,6 +78,27 @@ module ClarkKent
|
|
80
78
|
@resource_class ||= self.resource_type.constantize
|
81
79
|
end
|
82
80
|
|
81
|
+
## This ephemeral class allows us to create a row object that has the same attributes as the AR response
|
82
|
+
## to the query, including all the custom columns defined in the resource class report config.
|
83
|
+
## currently only used for the summary row, since we can't get that in the same AR query and have to
|
84
|
+
## add it to the collection after the query returns.
|
85
|
+
def row_class
|
86
|
+
report_columns = self.report_columns
|
87
|
+
@row_class ||= Class.new do
|
88
|
+
report_columns.each do |report_column|
|
89
|
+
attr_accessor report_column.column_name.to_sym
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize params = {}
|
93
|
+
params.each { |key, value| send "#{key}=", value }
|
94
|
+
end
|
95
|
+
|
96
|
+
def [](key)
|
97
|
+
self.send key
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
83
102
|
def sort_column
|
84
103
|
@sort_column ||= self.report_columns.where("clark_kent_report_columns.report_sort is not NULL and clark_kent_report_columns.report_sort != ''").first
|
85
104
|
end
|
@@ -88,7 +107,7 @@ module ClarkKent
|
|
88
107
|
if self.sort_column
|
89
108
|
sort_column_name = self.sort_column.column_name
|
90
109
|
sort_direction = Report::SortDirections[sort_column.report_sort]
|
91
|
-
|
110
|
+
ReportSort.new(order_column: sort_column_name, order_direction: sort_direction)
|
92
111
|
end
|
93
112
|
end
|
94
113
|
|
@@ -127,6 +146,9 @@ module ClarkKent
|
|
127
146
|
}.flatten.compact
|
128
147
|
end
|
129
148
|
|
149
|
+
## These are the built-in filter params that define this report. They are merged at a later
|
150
|
+
## step with the runtime params entered by the user for a specific report run.
|
151
|
+
## nb. the sorter column here may be overridden by a runtime sort if requested by the user.
|
130
152
|
def report_filter_params
|
131
153
|
Hash[*self.report_filters.map{|filter| filter.filter_match_params}.flatten].
|
132
154
|
merge(order: self.sorter)
|
@@ -169,6 +191,8 @@ module ClarkKent
|
|
169
191
|
self.resource_class::REPORT_FILTER_OPTIONS.select{|filter| 'date_filter' == filter.kind}.map{|filter| filter.param}
|
170
192
|
end
|
171
193
|
|
194
|
+
## These are the filters available for defining a report for this resource. They do not include date
|
195
|
+
## filters as those only make sense at runtime, or in an auto-generated, timed emailed report.
|
172
196
|
def available_filters
|
173
197
|
self.available_email_filters.reject{|name| self.date_filter_names.include? name}
|
174
198
|
end
|
@@ -177,6 +201,8 @@ module ClarkKent
|
|
177
201
|
self.available_filters.map{|id| [self.filter_options_for(id).label,id]}
|
178
202
|
end
|
179
203
|
|
204
|
+
## This is the full set of filter options for defining a report, including the date filters for
|
205
|
+
## an automatic, timed, emailed report.
|
180
206
|
def available_email_filters
|
181
207
|
self.resource_class::REPORT_DEFINITION_OPTIONS.reject{|name| (self.report_filters.pluck(:filter_name)).include? name}
|
182
208
|
end
|
@@ -185,10 +211,14 @@ module ClarkKent
|
|
185
211
|
self.resource_class::REPORT_FILTER_OPTIONS.detect{|filter| filter.param == filter_name}.collection
|
186
212
|
end
|
187
213
|
|
214
|
+
## These are the filters available at runtime, ie. not including the ones set to define this report.
|
215
|
+
## If updating the report, this is the set available to add as new report definition filters.
|
188
216
|
def custom_filters
|
189
217
|
self.resource_class::REPORT_FILTER_OPTIONS.select{|filter| self.report_filters.pluck(:filter_name).exclude? filter.param}
|
190
218
|
end
|
191
219
|
|
220
|
+
## This is the set of columns not chosed to use in the report. These are the ones available to add
|
221
|
+
## when updating a report.
|
192
222
|
def available_columns
|
193
223
|
self.resource_class::REPORT_COLUMN_OPTIONS.keys.reject{|column| self.report_columns.pluck(:column_name).include? column.to_s}
|
194
224
|
end
|
@@ -202,7 +232,11 @@ module ClarkKent
|
|
202
232
|
end
|
203
233
|
|
204
234
|
def resource_type_pretty
|
205
|
-
self.resource_class.prettify_name
|
235
|
+
if self.resource_class.respond_to? :prettify_name
|
236
|
+
self.resource_class.prettify_name.pluralize
|
237
|
+
else
|
238
|
+
self.resource_class.name.humanize
|
239
|
+
end
|
206
240
|
end
|
207
241
|
|
208
242
|
def get_filter_class(params)
|
@@ -220,7 +254,7 @@ module ClarkKent
|
|
220
254
|
row_array = self.report_columns.map do |report_column|
|
221
255
|
[report_column.column_name,report_column.calculate_summary(rows.map{|row| row.send(report_column.column_name)})]
|
222
256
|
end
|
223
|
-
|
257
|
+
row_class.new(row_array.to_h)
|
224
258
|
end
|
225
259
|
|
226
260
|
def summary_row?
|
@@ -269,4 +303,13 @@ module ClarkKent
|
|
269
303
|
end
|
270
304
|
|
271
305
|
end
|
306
|
+
|
307
|
+
class ReportSort
|
308
|
+
attr_accessor :order_column, :order_direction
|
309
|
+
|
310
|
+
def initialize params = {}
|
311
|
+
params.each { |key, value| send "#{key}=", value }
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
272
315
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module ClarkKent
|
2
2
|
class ReportColumn < ActiveRecord::Base
|
3
|
-
include Cloneable
|
3
|
+
include ClarkKent::Cloneable
|
4
4
|
|
5
5
|
SummaryMethods = ['total','average']
|
6
|
-
|
6
|
+
|
7
7
|
belongs_to :report
|
8
8
|
|
9
9
|
scope :sorted, -> { order("clark_kent_report_columns.column_order") }
|
@@ -14,11 +14,38 @@ module ClarkKent
|
|
14
14
|
|
15
15
|
def calculate_summary(values)
|
16
16
|
return nil unless self.summary_method.present?
|
17
|
-
values.
|
17
|
+
calculator.new(values).calculate
|
18
18
|
end
|
19
19
|
|
20
20
|
def summarizable?
|
21
|
-
report.column_options_for(self.column_name).
|
21
|
+
report.column_options_for(self.column_name).summarizable
|
22
|
+
end
|
23
|
+
|
24
|
+
def calculator
|
25
|
+
('ClarkKent::' + summary_method.camelcase + 'Calculator').constantize
|
22
26
|
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class AbstractCalculator
|
31
|
+
def initialize values
|
32
|
+
@values = values
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class TotalCalculator < AbstractCalculator
|
37
|
+
def calculate
|
38
|
+
@values.sum
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class AverageCalculator < AbstractCalculator
|
43
|
+
def calculate
|
44
|
+
if @values.length < 1
|
45
|
+
return nil
|
46
|
+
else
|
47
|
+
return (@values.sum.to_f / @values.length)
|
48
|
+
end
|
49
|
+
end
|
23
50
|
end
|
24
51
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ClarkKent
|
2
|
+
module ReportConfig
|
3
|
+
module ClassMethods
|
4
|
+
def filter_config(params)
|
5
|
+
filter_option_class = ('ClarkKent::' + ((params[:kind] + '_option').camelcase)).constantize
|
6
|
+
filter_option_class.new(params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def column_config(params)
|
10
|
+
ClarkKent::ReportColumnConfig.new(params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
extend ClassMethods
|
14
|
+
def self.included( other )
|
15
|
+
other.extend( ClassMethods )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
class ReportColumnConfig
|
19
|
+
attr_accessor :custom_select, :order_sql, :summarizable
|
20
|
+
def initialize params = {}
|
21
|
+
params.each { |key, value| send "#{key}=", value }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ClarkKent
|
2
2
|
class ReportEmail < ActiveRecord::Base
|
3
|
-
include Cloneable
|
3
|
+
include ClarkKent::Cloneable
|
4
4
|
|
5
5
|
SEND_TIMES = {
|
6
6
|
'Mondays' => 'Monday',
|
@@ -19,7 +19,6 @@ module ClarkKent
|
|
19
19
|
has_many :user_report_emails, dependent: :destroy
|
20
20
|
has_many :users, through: :user_report_emails
|
21
21
|
|
22
|
-
attr_accessible :report_id, :when_to_send, :name
|
23
22
|
|
24
23
|
def self.send_emails_for_today
|
25
24
|
today = Date.ih_today
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module ClarkKent
|
2
2
|
class ReportFilter < ActiveRecord::Base
|
3
|
-
include Cloneable
|
3
|
+
include ClarkKent::Cloneable
|
4
4
|
|
5
5
|
attr_accessor :filter_value_1, :filter_value_2
|
6
|
-
attr_accessible :filter_value_1, :filter_value_2, :report_id, :filter_name, :filter_value, :filterable_id, :filterable_type, :type
|
7
6
|
belongs_to :filterable, polymorphic: true
|
8
7
|
|
9
8
|
def filter_match_params
|
@@ -1,15 +1,11 @@
|
|
1
1
|
module ClarkKent
|
2
2
|
class ReportFilterOption
|
3
|
-
include Cloneable
|
4
3
|
|
5
|
-
attr_accessor :param, :label, :collection, :kind, :select
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.kind = params[:kind] if params[:kind].present?
|
11
|
-
self.select = params[:select] if params[:select].present?
|
12
|
-
end
|
4
|
+
attr_accessor :param, :label, :collection, :kind, :select, :in_required_date_group
|
5
|
+
|
6
|
+
def initialize params = {}
|
7
|
+
params.each { |key, value| send "#{key}=", value }
|
8
|
+
end
|
13
9
|
|
14
10
|
def label
|
15
11
|
@label || @param
|
@@ -15,7 +15,22 @@ module ClarkKent
|
|
15
15
|
query
|
16
16
|
end
|
17
17
|
|
18
|
+
def required_date_params
|
19
|
+
self::REPORT_FILTER_OPTIONS.select{|rfo| rfo.in_required_date_group}.map{|rfo| rfo.filter_params}.flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate_params(params,report)
|
23
|
+
if required_date_params.any?
|
24
|
+
missing_params = required_date_params - params.select{|k,v| v.present? }.keys
|
25
|
+
# a bit clunky, it only requires any 2 date filters. It would be better to require at least one pair of before/after filters
|
26
|
+
if missing_params.length > (required_date_params.length - 2)
|
27
|
+
raise ClarkKent::ReportFilterError.new("At least one date range is required.")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
18
32
|
def report(params,report,count = false)
|
33
|
+
validate_params(params, report)
|
19
34
|
@selects = []
|
20
35
|
@includes = []
|
21
36
|
@joins = []
|
@@ -48,9 +63,9 @@ module ClarkKent
|
|
48
63
|
end
|
49
64
|
query = self.all
|
50
65
|
if @report_email and @report_email.is_a? ClarkKent::ReportEmail
|
51
|
-
params = @report_email.report_filter_params.symbolize_keys!.merge(params)
|
66
|
+
params = @report_email.report_filter_params.symbolize_keys!.merge(params.symbolize_keys)
|
52
67
|
else
|
53
|
-
params = report.report_filter_params.symbolize_keys!.merge(params)
|
68
|
+
params = report.report_filter_params.symbolize_keys!.merge(params.symbolize_keys)
|
54
69
|
end
|
55
70
|
params.each do |param_type,param_value|
|
56
71
|
if param_value.present?
|
@@ -121,8 +136,18 @@ module ClarkKent
|
|
121
136
|
where("#{self.table_name}.#{field_name.to_s.sub(/_from/,'')} >= :date_limit", date_limit: match_value)
|
122
137
|
end
|
123
138
|
|
139
|
+
def above_number_arel(query, field_name, match_value)
|
140
|
+
query.
|
141
|
+
where("#{self.table_name}.#{field_name.to_s.sub(/_above/,'')} >= :lower_limit", lower_limit: match_value)
|
142
|
+
end
|
143
|
+
|
144
|
+
def below_number_arel(query, field_name, match_value)
|
145
|
+
query.
|
146
|
+
where("#{self.table_name}.#{field_name.to_s.sub(/_below/,'')} <= :upper_limit", upper_limit: match_value)
|
147
|
+
end
|
148
|
+
|
124
149
|
def order_arel(query, field_name, match_value)
|
125
|
-
if match_value.is_a?
|
150
|
+
if match_value.is_a? ClarkKent::ReportSort
|
126
151
|
order_column = match_value.order_column
|
127
152
|
order_direction = match_value.order_direction
|
128
153
|
else
|
@@ -17,19 +17,45 @@ module ClarkKent
|
|
17
17
|
self.all.detect{|ssk| klass_name == ssk.class_name}
|
18
18
|
end
|
19
19
|
|
20
|
+
def self.has_some(thing)
|
21
|
+
if thing.present?
|
22
|
+
if thing.respond_to? :any?
|
23
|
+
thing.any?
|
24
|
+
else
|
25
|
+
true
|
26
|
+
end
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
20
32
|
def self.custom
|
21
33
|
all.select{|ssk| ['everyone',ClarkKent.user_class_name.underscore].exclude? ssk.type}
|
22
34
|
end
|
23
35
|
|
36
|
+
def self.custom_for_user(user)
|
37
|
+
custom.select{|ssk| has_some(ssk.associated_containers_for(user)) }
|
38
|
+
end
|
39
|
+
|
24
40
|
def self.select_options
|
25
41
|
return @sharing_scope_options if @sharing_scope_options
|
26
42
|
@sharing_scope_options = {}
|
27
|
-
self.all.each do |
|
28
|
-
@sharing_scope_options[
|
43
|
+
self.all.each do |sharing_scope_kind|
|
44
|
+
@sharing_scope_options[sharing_scope_kind.human_name] = sharing_scope_kind.class_name
|
29
45
|
end
|
30
46
|
@sharing_scope_options
|
31
47
|
end
|
32
48
|
|
49
|
+
def self.select_options_for_user(user)
|
50
|
+
sharing_scope_options = {}
|
51
|
+
self.all.each do |sharing_scope_kind|
|
52
|
+
if custom.exclude?(sharing_scope_kind) || has_some(sharing_scope_kind.associated_containers_for(user))
|
53
|
+
sharing_scope_options[sharing_scope_kind.human_name] = sharing_scope_kind.class_name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
sharing_scope_options
|
57
|
+
end
|
58
|
+
|
33
59
|
def initialize(class_name,user_association = nil)
|
34
60
|
if 'Everyone' == class_name
|
35
61
|
@class_name = ''
|
@@ -63,8 +89,16 @@ module ClarkKent
|
|
63
89
|
when ClarkKent.user_class_name.underscore
|
64
90
|
[ClarkKent::SharingScope.new(user,self)]
|
65
91
|
else
|
66
|
-
associated_containers_for(user).map
|
67
|
-
|
92
|
+
if associated_containers_for(user).respond_to? :map
|
93
|
+
associated_containers_for(user).map do |associated_container|
|
94
|
+
ClarkKent::SharingScope.new(associated_container,self)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
if associated_containers_for(user).present?
|
98
|
+
[ClarkKent::SharingScope.new(associated_containers_for(user),self)]
|
99
|
+
else
|
100
|
+
[]
|
101
|
+
end
|
68
102
|
end
|
69
103
|
end
|
70
104
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
module ClarkKent
|
2
2
|
class UserReportEmail < ActiveRecord::Base
|
3
|
-
belongs_to :user
|
3
|
+
belongs_to :user, class_name: ClarkKent.user_class_name
|
4
4
|
belongs_to :report_email
|
5
5
|
|
6
|
-
attr_accessible :email, :report_email_id
|
7
|
-
|
8
6
|
validates_with UserEmailValidator
|
9
7
|
|
10
8
|
def email=(address)
|
11
|
-
self.user =
|
9
|
+
self.user = ClarkKent.user_class.where("lower(#{ClarkKent.user_class_name.underscore.pluralize}.email) = lower(:email)",email: address).first
|
12
10
|
self.errors.add(:email, "Couldn't find a user with that email addres") unless self.user.present?
|
13
11
|
end
|
14
12
|
|
@@ -27,7 +27,7 @@
|
|
27
27
|
</div>
|
28
28
|
<div class="ih-span one-fifth">
|
29
29
|
<% if !report_column.new_record? and report_column.summarizable? %>
|
30
|
-
<%= f.input :summary_method, collection: ReportColumn::SummaryMethods %>
|
30
|
+
<%= f.input :summary_method, collection: ClarkKent::ReportColumn::SummaryMethods %>
|
31
31
|
<% else %>
|
32
32
|
|
33
33
|
<% end %>
|
@@ -16,15 +16,19 @@
|
|
16
16
|
<div class="ih-span one-quarter">
|
17
17
|
<div class="ih-row">sharing</div>
|
18
18
|
<div class="ih-row">
|
19
|
-
<%= f.input :sharing_scope_type, collection: ClarkKent::SharingScopeKind.
|
19
|
+
<%= f.input :sharing_scope_type, collection: ClarkKent::SharingScopeKind.select_options_for_user(current_user),
|
20
20
|
input_html: {data: {revealer: true, sub_type: "FormFieldRevealer", revealer_children_id: "sharing_options"}},
|
21
21
|
label: false, include_blank: false %>
|
22
22
|
</div>
|
23
23
|
<div class="ih-row" data-revealer-target="sharing_options">
|
24
24
|
<%= f.input :sharing_scope_id, as: :hidden, input_html: {value: current_user.id}, wrapper_html: {'data-revealer_id' => "sharing_options", 'data-revealer-trigger' => ClarkKent.user_class_name, id: "sharing_options_#{ClarkKent.user_class_name}"} %>
|
25
|
-
<% ClarkKent::SharingScopeKind.
|
26
|
-
|
27
|
-
|
25
|
+
<% ClarkKent::SharingScopeKind.custom_for_user(current_user).each do |sharing_scope_kind| %>
|
26
|
+
<% if sharing_scope_kind.associated_containers_for(current_user).respond_to? :each %>
|
27
|
+
<%= f.input :sharing_scope_id, collection: sharing_scope_kind.associated_containers_for(current_user), label: false, include_blank: false,
|
28
|
+
wrapper_html: {'data-revealer_id' => "sharing_options", 'data-revealer-trigger' => sharing_scope_kind.class_name, id: "sharing_options_#{sharing_scope_kind.class_name}"} %>
|
29
|
+
<% else %>
|
30
|
+
<%= f.input :sharing_scope_id, as: :hidden, input_html: {value: sharing_scope_kind.associated_containers_for(current_user).id}, wrapper_html: {'data-revealer_id' => "sharing_options", 'data-revealer-trigger' => sharing_scope_kind.associated_containers_for(current_user).class.name, id: "sharing_options_#{sharing_scope_kind.associated_containers_for(current_user).class.name}"} %>
|
31
|
+
<% end %>
|
28
32
|
<% end %>
|
29
33
|
<%= f.input :sharing_scope_id, as: :hidden, input_html: {value: ''},
|
30
34
|
wrapper_html: {'data-revealer_id' => "sharing_options", 'data-revealer-trigger' => "", id: "sharing_options_"} %>
|
@@ -1,6 +1,11 @@
|
|
1
1
|
<h1><%= @report.name %></h1>
|
2
2
|
<%= link_to "← back to report index".html_safe, reports_url, id: 'report_index' %>
|
3
3
|
|
4
|
+
<% if @errors %>
|
5
|
+
<div class="error">
|
6
|
+
<%= @errors %>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
4
9
|
<div class="ih-row margin-top">
|
5
10
|
<form action="<%= report_url(@report) %>" method="get">
|
6
11
|
<% @report.custom_filters.each do |filter| %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateClarkKentReportFilter < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :clark_kent_report_filters do |t|
|
4
|
+
t.integer :filterable_id
|
5
|
+
t.string :filterable_type, :string, default: 'ClarkKent::Report'
|
6
|
+
t.string :filter_name
|
7
|
+
t.string :filter_value
|
8
|
+
t.string :type
|
9
|
+
t.string :duration
|
10
|
+
t.string :kind_of_day
|
11
|
+
t.string :offset
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
add_index :clark_kent_report_filters, :filterable_id
|
15
|
+
add_index :clark_kent_report_filters, :filterable_type
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateClarkKentReportColumn < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :clark_kent_report_columns do |t|
|
4
|
+
t.integer :report_id
|
5
|
+
t.string :column_name
|
6
|
+
t.integer :column_order
|
7
|
+
t.string :report_sort
|
8
|
+
t.string :summary_method
|
9
|
+
end
|
10
|
+
add_index :clark_kent_report_columns, :report_id
|
11
|
+
end
|
12
|
+
end
|
data/lib/clark_kent/version.rb
CHANGED
data/lib/clark_kent.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
require "clark_kent/engine"
|
2
|
+
require 'simple_form'
|
3
|
+
require 'thin_man'
|
2
4
|
|
3
5
|
module ClarkKent
|
4
6
|
mattr_accessor :resource_options, :user_class_name, :other_sharing_scopes, :base_controller,
|
5
7
|
:custom_report_links
|
6
8
|
|
7
9
|
def self.config(options)
|
8
|
-
@@resource_options = options[:resource_options]
|
10
|
+
@@resource_options = options[:resource_options].map{|option_hash| ClarkKent::ResourceOption.new option_hash}
|
9
11
|
@@user_class_name = options[:user_class_name]
|
10
12
|
@@other_sharing_scopes = options[:other_sharing_scopes]
|
11
13
|
base_controller_name = options[:base_controller_name]
|
12
14
|
@@base_controller = base_controller_name.constantize
|
13
|
-
@@custom_report_links = options[:custom_report_links]
|
15
|
+
@@custom_report_links = options[:custom_report_links] || []
|
14
16
|
end
|
15
17
|
|
16
18
|
def self.user_class
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "manage/reports/_print_report.html.erb" do
|
4
|
+
it "displays the print button with the modal" do
|
5
|
+
rows = nil
|
6
|
+
|
7
|
+
assign(:rows, rows)
|
8
|
+
render partial: "manage/reports/print_report", locals: { rows: rows }
|
9
|
+
|
10
|
+
expect(rendered).to eq("")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "displays the print button with the modal" do
|
14
|
+
rows = mock()
|
15
|
+
rows.stubs(:count).returns(50)
|
16
|
+
rows.stubs(:total_count).returns(51)
|
17
|
+
assign(:rows, rows)
|
18
|
+
render partial: "manage/reports/print_report", locals: { rows: rows }
|
19
|
+
|
20
|
+
expect(rendered).to have_selector("div#print_report_modal")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "displays just the print button" do
|
24
|
+
rows = mock()
|
25
|
+
rows.stubs(:count).returns(50)
|
26
|
+
rows.stubs(:total_count).returns(49)
|
27
|
+
assign(:rows, rows)
|
28
|
+
render partial: "manage/reports/print_report", locals: { rows: rows }
|
29
|
+
|
30
|
+
expect(rendered).not_to have_selector("div#print_report_modal")
|
31
|
+
end
|
32
|
+
end
|