reports_kit 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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