reports_kit 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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rubocop.yml +83 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +468 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/reports_kit/application.js +14 -0
- data/app/assets/javascripts/reports_kit/lib/_init.js +8 -0
- data/app/assets/javascripts/reports_kit/lib/chart.js +39 -0
- data/app/assets/javascripts/reports_kit/lib/report.js +119 -0
- data/app/assets/javascripts/reports_kit/vendor/chart.js +12269 -0
- data/app/assets/javascripts/reports_kit/vendor/daterangepicker.js +1627 -0
- data/app/assets/javascripts/reports_kit/vendor/moment.js +4040 -0
- data/app/assets/javascripts/reports_kit/vendor/select2.full.js +6436 -0
- data/app/assets/stylesheets/reports_kit/application.css.scss +3 -0
- data/app/assets/stylesheets/reports_kit/reports.css.sass +7 -0
- data/app/assets/stylesheets/reports_kit/select2_overrides.css.sass +7 -0
- data/app/assets/stylesheets/reports_kit/vendor/daterangepicker.css +269 -0
- data/app/assets/stylesheets/reports_kit/vendor/select2-bootstrap.css +721 -0
- data/app/assets/stylesheets/reports_kit/vendor/select2.css +484 -0
- data/config/routes.rb +10 -0
- data/docs/images/chart_options.png +0 -0
- data/docs/images/dashed_line.png +0 -0
- data/docs/images/flights_by_carrier.png +0 -0
- data/docs/images/flights_by_carrier_and_flight_at.png +0 -0
- data/docs/images/flights_by_delay.png +0 -0
- data/docs/images/flights_by_flight_at.png +0 -0
- data/docs/images/flights_by_hours_delayed.png +0 -0
- data/docs/images/flights_with_check_box.png +0 -0
- data/docs/images/flights_with_configured_boolean.png +0 -0
- data/docs/images/flights_with_configured_datetime.png +0 -0
- data/docs/images/flights_with_configured_number.png +0 -0
- data/docs/images/flights_with_configured_string.png +0 -0
- data/docs/images/flights_with_date_range.png +0 -0
- data/docs/images/flights_with_filters.png +0 -0
- data/docs/images/flights_with_multi_autocomplete.png +0 -0
- data/docs/images/flights_with_string_filter.png +0 -0
- data/docs/images/horizontal_bar.png +0 -0
- data/docs/images/legend_right.png +0 -0
- data/docs/images/users_by_created_at.png +0 -0
- data/gists/doc.txt +58 -0
- data/lib/reports_kit.rb +17 -0
- data/lib/reports_kit/base_controller.rb +11 -0
- data/lib/reports_kit/configuration.rb +10 -0
- data/lib/reports_kit/engine.rb +21 -0
- data/lib/reports_kit/helper.rb +19 -0
- data/lib/reports_kit/model.rb +16 -0
- data/lib/reports_kit/model_configuration.rb +23 -0
- data/lib/reports_kit/rails.rb +5 -0
- data/lib/reports_kit/report_builder.rb +76 -0
- data/lib/reports_kit/reports/data/chart_options.rb +132 -0
- data/lib/reports_kit/reports/data/generate.rb +65 -0
- data/lib/reports_kit/reports/data/one_dimension.rb +71 -0
- data/lib/reports_kit/reports/data/two_dimensions.rb +129 -0
- data/lib/reports_kit/reports/data/utils.rb +79 -0
- data/lib/reports_kit/reports/dimension.rb +78 -0
- data/lib/reports_kit/reports/filter.rb +84 -0
- data/lib/reports_kit/reports/filter_types/base.rb +47 -0
- data/lib/reports_kit/reports/filter_types/boolean.rb +30 -0
- data/lib/reports_kit/reports/filter_types/datetime.rb +27 -0
- data/lib/reports_kit/reports/filter_types/number.rb +28 -0
- data/lib/reports_kit/reports/filter_types/records.rb +26 -0
- data/lib/reports_kit/reports/filter_types/string.rb +38 -0
- data/lib/reports_kit/reports/generate_autocomplete_results.rb +55 -0
- data/lib/reports_kit/reports/inferrable_configuration.rb +113 -0
- data/lib/reports_kit/reports/measure.rb +58 -0
- data/lib/reports_kit/reports_controller.rb +15 -0
- data/lib/reports_kit/resources_controller.rb +8 -0
- data/lib/reports_kit/version.rb +3 -0
- data/reports_kit.gemspec +23 -0
- data/spec/factories/issue_factory.rb +4 -0
- data/spec/factories/issues_label_factory.rb +4 -0
- data/spec/factories/label_factory.rb +4 -0
- data/spec/factories/repo_factory.rb +5 -0
- data/spec/factories/tag_factory.rb +4 -0
- data/spec/fixtures/generate_inputs.yml +35 -0
- data/spec/fixtures/generate_outputs.yml +208 -0
- data/spec/reports_kit/reports/data/generate_spec.rb +275 -0
- data/spec/reports_kit/reports/dimension_spec.rb +38 -0
- data/spec/reports_kit/reports/filter_spec.rb +38 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/support/factory_girl.rb +5 -0
- data/spec/support/helpers.rb +13 -0
- data/spec/support/models/issue.rb +6 -0
- data/spec/support/models/issues_label.rb +4 -0
- data/spec/support/models/label.rb +5 -0
- data/spec/support/models/repo.rb +7 -0
- data/spec/support/models/tag.rb +4 -0
- data/spec/support/schema.rb +38 -0
- metadata +232 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class Base
|
|
5
|
+
attr_accessor :settings, :properties
|
|
6
|
+
|
|
7
|
+
def initialize(settings, properties)
|
|
8
|
+
self.settings = settings || {}
|
|
9
|
+
self.properties = properties
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def apply_filter(records)
|
|
13
|
+
return records unless valid?
|
|
14
|
+
records = records.joins(joins) if joins.present?
|
|
15
|
+
return records if value.blank? && !is_a?(FilterTypes::Boolean)
|
|
16
|
+
apply_conditions(records)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def default_criteria
|
|
20
|
+
self.class::DEFAULT_CRITERIA
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def apply_conditions(_records)
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def criteria
|
|
30
|
+
properties[:criteria]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def value
|
|
34
|
+
criteria[:value]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def joins
|
|
38
|
+
settings[:joins]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def column
|
|
42
|
+
settings[:column] || properties[:key]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class Boolean < Base
|
|
5
|
+
DEFAULT_CRITERIA = {
|
|
6
|
+
operator: nil
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
def apply_conditions(records)
|
|
10
|
+
case criteria[:operator]
|
|
11
|
+
when true, 'true'
|
|
12
|
+
records.where("(#{column}) = true")
|
|
13
|
+
when false, 'false'
|
|
14
|
+
records.where("(#{column}) != true")
|
|
15
|
+
else
|
|
16
|
+
raise ArgumentError.new("Unsupported operator: '#{criteria[:operator]}'")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def valid?
|
|
21
|
+
criteria[:operator].present?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def column
|
|
25
|
+
settings[:conditions] || properties[:key]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class Datetime < Base
|
|
5
|
+
DEFAULT_CRITERIA = {
|
|
6
|
+
operator: 'between'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
def apply_conditions(records)
|
|
10
|
+
case criteria[:operator]
|
|
11
|
+
when 'between'
|
|
12
|
+
start_string, end_string = value.split(' - ')
|
|
13
|
+
start_at = Date.parse(start_string)
|
|
14
|
+
end_at = Date.parse(end_string)
|
|
15
|
+
records.where("#{column} IS NOT NULL").where("#{column} BETWEEN ? AND ?", start_at, end_at)
|
|
16
|
+
else
|
|
17
|
+
raise ArgumentError.new("Unsupported operator: '#{criteria[:operator]}'")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def valid?
|
|
22
|
+
value.present?
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class Number < Base
|
|
5
|
+
def apply_conditions(records)
|
|
6
|
+
case criteria[:operator]
|
|
7
|
+
when '>'
|
|
8
|
+
records.where("#{column} > #{value.to_i}")
|
|
9
|
+
when '>='
|
|
10
|
+
records.where("#{column} >= #{value.to_i}")
|
|
11
|
+
when '<'
|
|
12
|
+
records.where("#{column} < #{value.to_i}")
|
|
13
|
+
when '<='
|
|
14
|
+
records.where("#{column} <= #{value.to_i}")
|
|
15
|
+
when '='
|
|
16
|
+
records.where("#{column} = #{value.to_i}")
|
|
17
|
+
else
|
|
18
|
+
raise ArgumentError.new("Unsupported operator: '#{criteria[:operator]}'")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def valid?
|
|
23
|
+
value.present?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class Records < Base
|
|
5
|
+
DEFAULT_CRITERIA = {
|
|
6
|
+
operator: 'include'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
def apply_conditions(records)
|
|
10
|
+
case criteria[:operator]
|
|
11
|
+
when 'include'
|
|
12
|
+
records.where(column => value)
|
|
13
|
+
when 'does_not_include'
|
|
14
|
+
records.where.not(column => value)
|
|
15
|
+
else
|
|
16
|
+
raise ArgumentError.new("Unsupported operator: '#{criteria[:operator]}'")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def valid?
|
|
21
|
+
value.present?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
module FilterTypes
|
|
4
|
+
class String < Base
|
|
5
|
+
DEFAULT_CRITERIA = {
|
|
6
|
+
operator: 'contains'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
def apply_conditions(records)
|
|
10
|
+
case criteria[:operator]
|
|
11
|
+
when 'equals'
|
|
12
|
+
records.where("#{column} = ?", value)
|
|
13
|
+
when 'contains'
|
|
14
|
+
records.where("#{column} ILIKE ?", "%#{value}%")
|
|
15
|
+
when 'starts_with'
|
|
16
|
+
records.where("#{column} ILIKE ?", "#{value}%")
|
|
17
|
+
when 'ends_with'
|
|
18
|
+
records.where("#{column} ILIKE ?", "%#{value}")
|
|
19
|
+
when 'does_not_equal'
|
|
20
|
+
records.where("#{column} != ?", value)
|
|
21
|
+
when 'does_not_contain'
|
|
22
|
+
records.where("#{column} NOT ILIKE ?", "%#{value}%")
|
|
23
|
+
when 'does_not_start_with'
|
|
24
|
+
records.where("#{column} NOT ILIKE ?", "#{value}%")
|
|
25
|
+
when 'does_not_end_with'
|
|
26
|
+
records.where("#{column} NOT ILIKE ?", "%#{value}")
|
|
27
|
+
else
|
|
28
|
+
raise ArgumentError.new("Unsupported operator: '#{criteria[:operator]}'")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def valid?
|
|
33
|
+
value.present?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
class GenerateAutocompleteResults
|
|
4
|
+
attr_accessor :params, :measure_key, :filter_key, :context_record
|
|
5
|
+
|
|
6
|
+
def initialize(params, context_record: nil)
|
|
7
|
+
self.params = params
|
|
8
|
+
self.measure_key = params[:measure_key]
|
|
9
|
+
self.filter_key = params[:filter_key]
|
|
10
|
+
self.context_record = context_record
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform
|
|
14
|
+
raise ArgumentError.new("Could not find a model for filter_key: '#{filter_key}'") unless model
|
|
15
|
+
results = model
|
|
16
|
+
results = results.public_send(scope) if scope
|
|
17
|
+
results = results.limit(10_000)
|
|
18
|
+
results = results.map { |result| { id: result.id, text: result.to_s } }
|
|
19
|
+
results = results.sort_by { |result| result[:text].downcase }
|
|
20
|
+
results = filter_results(results)
|
|
21
|
+
results
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def filter_results(results)
|
|
27
|
+
query = params[:q].try(:downcase)
|
|
28
|
+
if query.present?
|
|
29
|
+
results = results.to_a.select { |r| r[:text].downcase.include?(query) }
|
|
30
|
+
end
|
|
31
|
+
results
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def model
|
|
35
|
+
@model ||= begin
|
|
36
|
+
measure = Measure.new(measure_key, context_record: context_record)
|
|
37
|
+
filter = Filter.new(filter_key, measure: measure)
|
|
38
|
+
filter.instance_class
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def scope
|
|
43
|
+
@scope ||= begin
|
|
44
|
+
scope = params[:scope]
|
|
45
|
+
return unless scope.present?
|
|
46
|
+
return unless model.try(:reports_kit_configuration) && model.reports_kit_configuration.autocomplete_scopes.present?
|
|
47
|
+
unless model.reports_kit_configuration.autocomplete_scopes.include?(scope)
|
|
48
|
+
raise ArgumentError.new("Unallowed scope '#{scope}' for model #{model.name}")
|
|
49
|
+
end
|
|
50
|
+
scope
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
class InferrableConfiguration
|
|
4
|
+
SUPPORTED_COLUMN_TYPES = [
|
|
5
|
+
:boolean,
|
|
6
|
+
:datetime,
|
|
7
|
+
:integer,
|
|
8
|
+
:string
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
attr_accessor :inferrable, :inferrable_type
|
|
12
|
+
|
|
13
|
+
delegate :key, :measure, to: :inferrable
|
|
14
|
+
|
|
15
|
+
def initialize(inferrable, inferrable_type)
|
|
16
|
+
self.inferrable = inferrable
|
|
17
|
+
self.inferrable_type = inferrable_type
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def configuration_strategy
|
|
21
|
+
if settings_from_model.present?
|
|
22
|
+
:model
|
|
23
|
+
elsif reflection
|
|
24
|
+
:association
|
|
25
|
+
elsif column_type
|
|
26
|
+
:column
|
|
27
|
+
else
|
|
28
|
+
inferrable_type_string = inferrable_type.to_s.singularize
|
|
29
|
+
raise ArgumentError.new("No configuration found on the #{model_class} model for #{inferrable_type_string} with key: '#{key}'")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def configured_by_association?
|
|
34
|
+
configuration_strategy == :association
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def configured_by_column?
|
|
38
|
+
configuration_strategy == :column
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def configured_by_model?
|
|
42
|
+
configuration_strategy == :model
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def configured_by_time?
|
|
46
|
+
column_type == :datetime
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def settings_from_model
|
|
50
|
+
return {} if model_configuration.blank?
|
|
51
|
+
return {} if model_configuration.public_send(inferrable_type).blank?
|
|
52
|
+
config_hash = model_configuration.public_send(inferrable_type).find do |hash|
|
|
53
|
+
hash[:key] == key
|
|
54
|
+
end
|
|
55
|
+
config_hash || {}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def reflection
|
|
59
|
+
model_class.reflect_on_association(key.to_sym)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def instance_class
|
|
63
|
+
return reflection.class_name.constantize if reflection
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def column
|
|
68
|
+
return unless inferred_settings
|
|
69
|
+
inferred_settings[:column]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def inferred_settings
|
|
73
|
+
return { column: "#{model_class.table_name}.#{key}" } if configured_by_column?
|
|
74
|
+
if configured_by_association?
|
|
75
|
+
return { column: "#{model_class.table_name}.#{reflection.foreign_key}" } if reflection.macro == :belongs_to
|
|
76
|
+
return inferred_settings_from_has_many if inferred_settings_from_has_many
|
|
77
|
+
end
|
|
78
|
+
{}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def inferred_settings_from_has_many
|
|
82
|
+
return unless reflection.macro == :has_many
|
|
83
|
+
through_reflection = reflection.through_reflection
|
|
84
|
+
if through_reflection
|
|
85
|
+
{
|
|
86
|
+
joins: through_reflection.name,
|
|
87
|
+
column: "#{through_reflection.table_name}.#{reflection.source_reflection.foreign_key}"
|
|
88
|
+
}
|
|
89
|
+
else
|
|
90
|
+
{
|
|
91
|
+
joins: reflection.name,
|
|
92
|
+
column: "#{reflection.klass.table_name}.#{reflection.klass.primary_key}"
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def column_type
|
|
98
|
+
column_type = model_class.columns_hash[key.to_s].try(:type)
|
|
99
|
+
return column_type if SUPPORTED_COLUMN_TYPES.include?(column_type)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def model_configuration
|
|
103
|
+
return unless model_class && model_class.respond_to?(:reports_kit_configuration)
|
|
104
|
+
model_class.reports_kit_configuration
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def model_class
|
|
108
|
+
return unless measure
|
|
109
|
+
measure.model_class
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
module Reports
|
|
3
|
+
class Measure
|
|
4
|
+
attr_accessor :properties, :filters, :context_record
|
|
5
|
+
|
|
6
|
+
def initialize(properties, context_record: nil)
|
|
7
|
+
properties = { key: properties } if properties.is_a?(String)
|
|
8
|
+
raise ArgumentError.new("Measure properties must be a String or Hash, not a #{properties.class.name}: #{properties.inspect}") unless properties.is_a?(Hash)
|
|
9
|
+
properties = properties.deep_symbolize_keys
|
|
10
|
+
filter_hashes = properties.delete(:filters) || []
|
|
11
|
+
filter_hashes = filter_hashes.values if filter_hashes.is_a?(Hash) && filter_hashes.key?(:'0')
|
|
12
|
+
|
|
13
|
+
self.properties = properties
|
|
14
|
+
self.filters = filter_hashes.map { |filter_hash| Filter.new(filter_hash, measure: self) }
|
|
15
|
+
self.context_record = context_record
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def key
|
|
19
|
+
properties[:key]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def label
|
|
23
|
+
key.pluralize.titleize
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def aggregate_function
|
|
27
|
+
:count
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def conditions
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def base_relation
|
|
35
|
+
return context_record.public_send(key.pluralize) if context_record
|
|
36
|
+
model_class
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def model_class
|
|
40
|
+
key.camelize.constantize
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def filtered_relation
|
|
44
|
+
relation = base_relation
|
|
45
|
+
filters.each do |filter|
|
|
46
|
+
relation = filter.apply(relation)
|
|
47
|
+
end
|
|
48
|
+
relation
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def properties_with_filters
|
|
52
|
+
all_properties = properties
|
|
53
|
+
all_properties[:filters] = filters.map(&:properties)
|
|
54
|
+
all_properties
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ReportsKit
|
|
2
|
+
class ReportsController < ReportsKit::BaseController
|
|
3
|
+
def index
|
|
4
|
+
# RubyProf.start
|
|
5
|
+
properties = ActiveSupport::JSON.decode(params[:properties])
|
|
6
|
+
report_data = Reports::Data::Generate.new(properties, context_record: context_record).perform
|
|
7
|
+
# result = RubyProf.stop
|
|
8
|
+
# printer = RubyProf::CallStackPrinter.new(result)
|
|
9
|
+
# File.open(Rails.root.join('tmp', 'out.html'), 'w') do |file|
|
|
10
|
+
# printer.print(file, :min_percent => 2)
|
|
11
|
+
# end
|
|
12
|
+
render json: { data: report_data }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|