reports_kit 0.3.1 → 0.3.2

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/reports_kit/lib/report.js +0 -2
  3. data/config/routes.rb +3 -3
  4. data/gemfiles/mysql.gemfile.lock +3 -3
  5. data/gemfiles/postgresql.gemfile.lock +3 -3
  6. data/lib/reports_kit.rb +5 -2
  7. data/lib/reports_kit/base_controller.rb +3 -3
  8. data/lib/reports_kit/configuration.rb +5 -0
  9. data/lib/reports_kit/filters_controller.rb +9 -0
  10. data/lib/reports_kit/form_builder.rb +10 -39
  11. data/lib/reports_kit/helper.rb +3 -13
  12. data/lib/reports_kit/model_configuration.rb +1 -6
  13. data/lib/reports_kit/normalized_params.rb +16 -0
  14. data/lib/reports_kit/report_builder.rb +3 -2
  15. data/lib/reports_kit/reports/composite_series.rb +4 -3
  16. data/lib/reports_kit/reports/data/aggregate_composite.rb +1 -1
  17. data/lib/reports_kit/reports/data/generate_for_properties.rb +1 -1
  18. data/lib/reports_kit/reports/filter_with_series.rb +4 -0
  19. data/lib/reports_kit/reports/generate_autocomplete_results.rb +5 -20
  20. data/lib/reports_kit/reports/inferrable_configuration.rb +1 -1
  21. data/lib/reports_kit/reports/properties.rb +10 -0
  22. data/lib/reports_kit/reports/properties_to_filter.rb +40 -0
  23. data/lib/reports_kit/reports/series.rb +7 -2
  24. data/lib/reports_kit/reports_controller.rb +1 -15
  25. data/lib/reports_kit/version.rb +1 -1
  26. data/spec/factories/pro_repo_factory.rb +5 -0
  27. data/spec/reports_kit/reports/data/generate_spec.rb +27 -0
  28. data/spec/spec_helper.rb +4 -3
  29. data/spec/support/models/pro/repo.rb +5 -0
  30. data/spec/support/models/pro/special_issue.rb +4 -0
  31. metadata +9 -33
  32. data/docs/README.md +0 -8
  33. data/docs/dimensions.md +0 -110
  34. data/docs/display_options.md +0 -80
  35. data/docs/filters.md +0 -216
  36. data/docs/images/chart_options.png +0 -0
  37. data/docs/images/dashed_line.png +0 -0
  38. data/docs/images/demo_area.png +0 -0
  39. data/docs/images/demo_dashed_line.png +0 -0
  40. data/docs/images/demo_horizontal_stacked.png +0 -0
  41. data/docs/images/demo_legend.png +0 -0
  42. data/docs/images/demo_multiautocomplete.png +0 -0
  43. data/docs/images/demo_radar.png +0 -0
  44. data/docs/images/flights_by_carrier.png +0 -0
  45. data/docs/images/flights_by_carrier_and_flight_at.png +0 -0
  46. data/docs/images/flights_by_delay.png +0 -0
  47. data/docs/images/flights_by_flight_at.png +0 -0
  48. data/docs/images/flights_by_hours_delayed.png +0 -0
  49. data/docs/images/flights_with_check_box.png +0 -0
  50. data/docs/images/flights_with_configured_boolean.png +0 -0
  51. data/docs/images/flights_with_configured_datetime.png +0 -0
  52. data/docs/images/flights_with_configured_number.png +0 -0
  53. data/docs/images/flights_with_configured_string.png +0 -0
  54. data/docs/images/flights_with_date_range.png +0 -0
  55. data/docs/images/flights_with_filters.png +0 -0
  56. data/docs/images/flights_with_multi_autocomplete.png +0 -0
  57. data/docs/images/flights_with_string_filter.png +0 -0
  58. data/docs/images/horizontal_bar.png +0 -0
  59. data/docs/images/legend_right.png +0 -0
  60. data/docs/images/users_by_created_at_with_filter.png +0 -0
  61. data/docs/measures.md +0 -12
  62. data/lib/reports_kit/resources_controller.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e12a4b95211ec84a8662237e268dfacfcd23978a
4
- data.tar.gz: c5ec6f7f3f4e8bd9613764e8cd74108971255c26
3
+ metadata.gz: ae53802c82ae537f372cf8813f596ba837be224a
4
+ data.tar.gz: 8c46d69d66a2e1b3e1e47d88b7bc45f398e9a8e0
5
5
  SHA512:
6
- metadata.gz: 94b293476548bdd6ad1bed10018e4889f4d28a56b59490059274777fcd608790399a2f835b6f858d9f4075fd96c9accfe382d6fa4e9474079a827008fb157b0f
7
- data.tar.gz: fd582ab216f799db4dbf3c0c197b95f5ebe155b55fa9bcc17bfbb15adcdf79dc22f85d999109187d02d8678b045fcc57846d8aa0748d8c1830d8e7e030662e3c
6
+ metadata.gz: 26b7239f82a98fb70d5229963bccd6c77850c9600f76441f369cfe987a25d4bd54adec86dce6ceb5a1a58a01e600e38e1ce4d49fcf25721fd9fd179d2433cf1d
7
+ data.tar.gz: 1369039cdb9b87cbcbb0047ea6873b934d8071aa911e04bf54d76f8e5be47308f020c2d6cd0869c2cd60e47e2f33a6d582410b759687da3b7e92d625d7ff880f
@@ -73,8 +73,6 @@ ReportsKit.Report = (function() {
73
73
  format: 'MMM D, YYYY'
74
74
  },
75
75
  ranges: {
76
- 'Today': [moment(), moment()],
77
- 'Last 7 Days': [moment().subtract(7, 'days'), moment()],
78
76
  'Last 30 Days': [moment().subtract(30, 'days'), moment()],
79
77
  'Last 2 Months': [moment().subtract(2, 'months'), moment()],
80
78
  'Last 3 Months': [moment().subtract(3, 'months'), moment()],
@@ -1,9 +1,9 @@
1
1
  ReportsKit::Engine.routes.draw do
2
2
  namespace :reports_kit do
3
3
  resources :reports, only: [:index]
4
- resources :resources, only: [] do
5
- collection do
6
- get 'measures/:measure_key/filters/:filter_key/autocomplete' => :autocomplete
4
+ resources :filters, only: [], param: :key do
5
+ member do
6
+ get :autocomplete
7
7
  end
8
8
  end
9
9
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.1)
4
+ reports_kit (0.3.2)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -135,7 +135,7 @@ GEM
135
135
  sprockets (3.7.1)
136
136
  concurrent-ruby (~> 1.0)
137
137
  rack (> 1, < 3)
138
- sprockets-rails (3.2.0)
138
+ sprockets-rails (3.2.1)
139
139
  actionpack (>= 4.0)
140
140
  activesupport (>= 4.0)
141
141
  sprockets (>= 3.0.0)
@@ -164,4 +164,4 @@ DEPENDENCIES
164
164
  timecop (~> 0)
165
165
 
166
166
  BUNDLED WITH
167
- 1.14.6
167
+ 1.15.4
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.1)
4
+ reports_kit (0.3.2)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -134,7 +134,7 @@ GEM
134
134
  sprockets (3.7.1)
135
135
  concurrent-ruby (~> 1.0)
136
136
  rack (> 1, < 3)
137
- sprockets-rails (3.2.0)
137
+ sprockets-rails (3.2.1)
138
138
  actionpack (>= 4.0)
139
139
  activesupport (>= 4.0)
140
140
  sprockets (>= 3.0.0)
@@ -162,4 +162,4 @@ DEPENDENCIES
162
162
  timecop (~> 0)
163
163
 
164
164
  BUNDLED WITH
165
- 1.14.6
165
+ 1.15.4
@@ -1,18 +1,19 @@
1
1
  require 'rails/all'
2
2
 
3
+ require 'reports_kit/normalized_params'
3
4
  require 'reports_kit/base_controller'
4
5
  require 'reports_kit/cache'
5
6
  require 'reports_kit/configuration'
6
7
  require 'reports_kit/engine'
7
8
  require 'reports_kit/entity'
8
- require 'reports_kit/report_builder'
9
+ require 'reports_kit/filters_controller'
9
10
  require 'reports_kit/form_builder'
10
11
  require 'reports_kit/helper'
11
12
  require 'reports_kit/model'
12
13
  require 'reports_kit/model_configuration'
13
14
  require 'reports_kit/order'
14
15
  require 'reports_kit/relative_time'
15
- require 'reports_kit/resources_controller'
16
+ require 'reports_kit/report_builder'
16
17
  require 'reports_kit/reports_controller'
17
18
  require 'reports_kit/value'
18
19
  require 'reports_kit/version'
@@ -49,6 +50,8 @@ require 'reports_kit/reports/filter'
49
50
  require 'reports_kit/reports/filter_with_series'
50
51
  require 'reports_kit/reports/generate_autocomplete_results'
51
52
  require 'reports_kit/reports/inferrable_configuration'
53
+ require 'reports_kit/reports/properties'
54
+ require 'reports_kit/reports/properties_to_filter'
52
55
  require 'reports_kit/reports/series'
53
56
 
54
57
  module ReportsKit
@@ -1,10 +1,10 @@
1
1
  module ReportsKit
2
2
  class BaseController < ActionController::Base
3
+ include ReportsKit::NormalizedParams
4
+
3
5
  # This is intentionally public to allow external code to access it
4
6
  def context_record
5
- context_record_method = ReportsKit.configuration.context_record_method
6
- return unless context_record_method
7
- instance_eval(&context_record_method)
7
+ ReportsKit.configuration.context_record(self)
8
8
  end
9
9
  end
10
10
  end
@@ -35,5 +35,10 @@ module ReportsKit
35
35
  return custom_methods.call if custom_methods.is_a?(Proc)
36
36
  raise ArgumentError.new("Invalid type for custom_methods configuration: #{custom_methods.class}")
37
37
  end
38
+
39
+ def context_record(context)
40
+ return unless context_record_method
41
+ context.instance_eval(&context_record_method)
42
+ end
38
43
  end
39
44
  end
@@ -0,0 +1,9 @@
1
+ module ReportsKit
2
+ class FiltersController < ReportsKit::BaseController
3
+ def autocomplete
4
+ properties = Reports::Properties.generate(self)
5
+ results = Reports::GenerateAutocompleteResults.new(params, properties, context_record: context_record).perform
6
+ render json: { data: results }
7
+ end
8
+ end
9
+ end
@@ -4,21 +4,23 @@ module ReportsKit
4
4
 
5
5
  DEFAULT_DATE_RANGE_VALUE = ['-2M', 'now']
6
6
 
7
- attr_accessor :properties, :additional_params
7
+ attr_accessor :properties, :additional_params, :context_record, :properties_to_filter
8
8
 
9
- def initialize(properties, additional_params: nil)
9
+ def initialize(properties, additional_params: nil, context_record: nil)
10
10
  self.properties = properties.deep_symbolize_keys
11
11
  self.additional_params = additional_params
12
+ self.context_record = context_record
13
+ self.properties_to_filter = Reports::PropertiesToFilter.new(properties, context_record: context_record)
12
14
  end
13
15
 
14
16
  def check_box(filter_key, options = {})
15
- filter = validate_filter!(filter_key)
17
+ filter = properties_to_filter.perform(filter_key)
16
18
  checked = filter.normalized_properties[:criteria][:value] == 'true'
17
19
  check_box_tag(filter_key, '1', checked, options)
18
20
  end
19
21
 
20
22
  def date_range(filter_key, options = {})
21
- filter = validate_filter!(filter_key)
23
+ filter = properties_to_filter.perform(filter_key)
22
24
  defaults = { class: 'form-control input-sm date_range_picker' }
23
25
  options = defaults.deep_merge(options)
24
26
  value = filter.normalized_properties[:criteria][:value].presence
@@ -27,22 +29,17 @@ module ReportsKit
27
29
  end
28
30
 
29
31
  def multi_autocomplete(filter_key, options = {})
30
- validate_filter!(filter_key)
31
- filter = series_filters.find { |f| f.key == filter_key.to_s }
32
+ filter = properties_to_filter.perform(filter_key)
32
33
  reports_kit_path = Rails.application.routes.url_helpers.reports_kit_path
33
- path = "#{reports_kit_path}reports_kit/resources/measures/#{filter.series.key}/filters/#{filter_key}/autocomplete?"
34
+ path = "#{reports_kit_path}reports_kit/filters/#{filter_key}/autocomplete?"
34
35
  path += additional_params.to_query if additional_params.present?
35
- scope = options.delete(:scope)
36
- params = {}
37
- params[:scope] = scope if scope.present?
38
36
 
39
37
  defaults = {
40
38
  class: 'form-control input-sm select2',
41
39
  multiple: 'multiple',
42
40
  data: {
43
41
  placeholder: options[:placeholder],
44
- path: path,
45
- params: params
42
+ path: path
46
43
  }
47
44
  }
48
45
  options = defaults.deep_merge(options)
@@ -50,7 +47,7 @@ module ReportsKit
50
47
  end
51
48
 
52
49
  def string_filter(filter_key, options = {})
53
- filter = validate_filter!(filter_key)
50
+ filter = properties_to_filter.perform(filter_key)
54
51
  defaults = { class: 'form-control input-sm' }
55
52
  options = defaults.deep_merge(options)
56
53
  text_field_tag(filter_key, filter.normalized_properties[:criteria][:value], options)
@@ -58,32 +55,6 @@ module ReportsKit
58
55
 
59
56
  private
60
57
 
61
- def validate_filter!(filter_key)
62
- filter_key = filter_key.to_s
63
- filter = filters.find { |f| f.key == filter_key }
64
- raise ArgumentError.new("A filter with key '#{filter_key}' is not configured in this report") unless filter
65
- filter
66
- end
67
-
68
- def filters
69
- ui_filters + series_filters
70
- end
71
-
72
- def series_filters
73
- serieses.map(&:filters).flatten
74
- end
75
-
76
- def ui_filters
77
- return [] if properties[:ui_filters].blank?
78
- properties[:ui_filters].map do |ui_filter_properties|
79
- Reports::Filter.new(ui_filter_properties)
80
- end
81
- end
82
-
83
- def serieses
84
- Reports::Series.new_from_properties!(properties, context_record: nil)
85
- end
86
-
87
58
  def default_date_range_value
88
59
  @default_date_range_value ||= begin
89
60
  start_date = Reports::Data::Utils.format_time_value(DEFAULT_DATE_RANGE_VALUE[0])
@@ -1,9 +1,11 @@
1
1
  module ReportsKit
2
2
  module Helper
3
+ include ReportsKit::NormalizedParams
4
+
3
5
  def render_report(report_params, context_params: {}, actions: %w(export_csv export_xls), js_report_class: 'Report', &block)
4
6
  report_params = { key: report_params } if report_params.is_a?(String)
5
7
  params.merge!(context_params: context_params, report_params: report_params)
6
- properties = instance_eval(&ReportsKit.configuration.properties_method).deep_symbolize_keys
8
+ properties = Reports::Properties.generate(self)
7
9
  builder = ReportBuilder.new(
8
10
  report_params: report_params,
9
11
  context_params: context_params,
@@ -18,17 +20,5 @@ module ReportsKit
18
20
  builder.render
19
21
  end
20
22
  end
21
-
22
- def context_params
23
- params[:context_params]
24
- end
25
-
26
- def report_params
27
- params[:report_params]
28
- end
29
-
30
- def report_key
31
- report_params[:key]
32
- end
33
23
  end
34
24
  end
@@ -1,12 +1,11 @@
1
1
  module ReportsKit
2
2
  class ModelConfiguration
3
- attr_accessor :aggregations, :dimensions, :filters, :autocomplete_scopes
3
+ attr_accessor :aggregations, :dimensions, :filters
4
4
 
5
5
  def initialize
6
6
  self.aggregations = []
7
7
  self.dimensions = []
8
8
  self.filters = []
9
- self.autocomplete_scopes = []
10
9
  end
11
10
 
12
11
  def aggregation(key, expression, properties = {})
@@ -20,9 +19,5 @@ module ReportsKit
20
19
  def filter(key, type_key, properties)
21
20
  filters << { key: key.to_s, type_key: type_key }.merge(properties).symbolize_keys
22
21
  end
23
-
24
- def autocomplete_scope(*scopes)
25
- self.autocomplete_scopes += scopes.map(&:to_s)
26
- end
27
22
  end
28
23
  end
@@ -0,0 +1,16 @@
1
+ module ReportsKit
2
+ module NormalizedParams
3
+ def report_params
4
+ params[:report_params]
5
+ end
6
+
7
+ def context_params
8
+ params[:context_params]
9
+ end
10
+
11
+ def report_key
12
+ raise ArgumentError.new('Blank report_params') if report_params.blank?
13
+ report_params[:key]
14
+ end
15
+ end
16
+ end
@@ -17,8 +17,9 @@ module ReportsKit
17
17
  self.js_report_class = js_report_class
18
18
  self.view_context = view_context
19
19
  self.block = block
20
- self.properties = properties#view_context.instance_eval(&ReportsKit.configuration.properties_method).deep_symbolize_keys
21
- self.form_builder = ReportsKit::FormBuilder.new(properties, additional_params: additional_params)
20
+ self.properties = properties
21
+ context_record = ReportsKit.configuration.context_record(view_context)
22
+ self.form_builder = ReportsKit::FormBuilder.new(properties, additional_params: additional_params, context_record: context_record)
22
23
  end
23
24
 
24
25
  def render
@@ -1,10 +1,11 @@
1
1
  module ReportsKit
2
2
  module Reports
3
3
  class CompositeSeries < AbstractSeries
4
- attr_accessor :properties
4
+ attr_accessor :properties, :context_record
5
5
 
6
- def initialize(properties)
6
+ def initialize(properties, context_record:)
7
7
  self.properties = properties.dup
8
+ self.context_record = context_record
8
9
  end
9
10
 
10
11
  def label
@@ -24,7 +25,7 @@ module ReportsKit
24
25
  end
25
26
 
26
27
  def serieses
27
- @serieses ||= Reports::Series.new_from_properties!(properties, context_record: nil)
28
+ @serieses ||= Reports::Series.new_from_properties!(properties, context_record: context_record)
28
29
  end
29
30
 
30
31
  def filters
@@ -20,7 +20,7 @@ module ReportsKit
20
20
  }
21
21
 
22
22
  def initialize(properties, context_record:)
23
- self.composite_series = CompositeSeries.new(properties)
23
+ self.composite_series = CompositeSeries.new(properties, context_record: context_record)
24
24
  self.context_record = context_record
25
25
  end
26
26
 
@@ -15,7 +15,7 @@ module ReportsKit
15
15
  if composite_operator
16
16
  raise ArgumentError.new('Aggregations require at least one series') if all_serieses.length == 0
17
17
  dimension_keys_values = Data::AggregateComposite.new(properties, context_record: context_record).perform
18
- serieses_dimension_keys_values = { CompositeSeries.new(properties) => dimension_keys_values }
18
+ serieses_dimension_keys_values = { CompositeSeries.new(properties, context_record: context_record) => dimension_keys_values }
19
19
  elsif all_serieses.length == 1 && composite_serieses.length == 1
20
20
  dimension_keys_values = Data::AggregateComposite.new(composite_serieses.first.properties, context_record: context_record).perform
21
21
  serieses_dimension_keys_values = { all_serieses.first => dimension_keys_values }
@@ -54,6 +54,10 @@ module ReportsKit
54
54
  }
55
55
  end
56
56
 
57
+ def context_record_association
58
+ properties[:context_record_association] || instance_class.name.tableize
59
+ end
60
+
57
61
  def type_klass
58
62
  type_klass_for_configuration_strategy = CONFIGURATION_STRATEGIES_FILTER_TYPE_CLASSES[configuration_strategy]
59
63
  return type_klass_for_configuration_strategy if type_klass_for_configuration_strategy
@@ -1,12 +1,12 @@
1
1
  module ReportsKit
2
2
  module Reports
3
3
  class GenerateAutocompleteResults
4
- attr_accessor :params, :measure_key, :filter_key, :context_record
4
+ attr_accessor :params, :filter_key, :filter, :context_record
5
5
 
6
- def initialize(params, context_record: nil)
6
+ def initialize(params, properties, context_record: nil)
7
7
  self.params = params
8
- self.measure_key = params[:measure_key]
9
- self.filter_key = params[:filter_key]
8
+ self.filter_key = params[:key]
9
+ self.filter = Reports::PropertiesToFilter.new(properties, context_record: context_record).perform(filter_key)
10
10
  self.context_record = context_record
11
11
  end
12
12
 
@@ -14,7 +14,6 @@ module ReportsKit
14
14
  raise ArgumentError.new("Could not find a model for filter_key: '#{filter_key}'") unless model
15
15
  return autocomplete_results_method.call(params: params, context_record: context_record, relation: relation) if autocomplete_results_method
16
16
  results = relation
17
- results = results.public_send(scope) if scope
18
17
  results = results.limit(10_000)
19
18
  results = results.map { |result| { id: result.id, text: result.to_s } }
20
19
  results = results.sort_by { |result| result[:text].downcase }
@@ -30,7 +29,7 @@ module ReportsKit
30
29
 
31
30
  def relation
32
31
  if context_record
33
- context_record.public_send(model.name.tableize)
32
+ context_record.public_send(filter.context_record_association)
34
33
  else
35
34
  model
36
35
  end
@@ -46,23 +45,9 @@ module ReportsKit
46
45
 
47
46
  def model
48
47
  @model ||= begin
49
- series = Series.new(measure_key, context_record: context_record)
50
- filter = FilterWithSeries.new(filter: Filter.new(filter_key), series: series)
51
48
  filter.instance_class
52
49
  end
53
50
  end
54
-
55
- def scope
56
- @scope ||= begin
57
- scope = params[:scope]
58
- return unless scope.present?
59
- return unless model.try(:reports_kit_configuration) && model.reports_kit_configuration.autocomplete_scopes.present?
60
- unless model.reports_kit_configuration.autocomplete_scopes.include?(scope)
61
- raise ArgumentError.new("Unallowed scope '#{scope}' for model #{model.name}")
62
- end
63
- scope
64
- end
65
- end
66
51
  end
67
52
  end
68
53
  end
@@ -61,7 +61,7 @@ module ReportsKit
61
61
  end
62
62
 
63
63
  def instance_class
64
- return reflection.class_name.constantize if reflection
64
+ return reflection.klass if reflection
65
65
  nil
66
66
  end
67
67