reports_kit 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2dcd95571d20aa7e439e9b97a97cefbd87ab3900
4
- data.tar.gz: 5ca4d871580f9d8dba7fa71a8219d6997a1b6472
3
+ metadata.gz: 13094de820c79cec7858078fa4c307a0137c001f
4
+ data.tar.gz: 971b1281d81369b1539aad7c4ac977a72c66558b
5
5
  SHA512:
6
- metadata.gz: 63afd0e91d6953bd43313af32908090c758a8adae00f56a2ce520af5cd934237f549cbf66e6fd32da95642f301b8888017ab3de4c6306a748a78d07189100445
7
- data.tar.gz: d46b89fd02d6183f09ab3de6cb1550718c5f04319cb3dfa673bfc27f9b0fba41290bcf82e5a98a3478954707e778ca40b14aa3fb873810de165f4b43c8754fb6
6
+ metadata.gz: 9c2d64e334083cb58173e9d3ae7daa4453a45c2f6715bf971ea01bc5b1f1b4a0d01bcddf4abc50c7acdaa2d2cedf31bc78ddbe16e1f8e97e363f0200fe53f8e4
7
+ data.tar.gz: f666b9e785d28c22754f8fd6e3fe178f04f3add4599b3b0673240e15d3ea7547a051e952ae683b3a334a6de6d43e24bcb062c86a95c61646e74f916aa9064691
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.2)
4
+ reports_kit (0.4.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.2)
4
+ reports_kit (0.4.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.2)
4
+ reports_kit (0.4.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.2)
4
+ reports_kit (0.4.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.3.2)
4
+ reports_kit (0.4.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -31,6 +31,7 @@ require 'reports_kit/reports/data/format_table'
31
31
  require 'reports_kit/reports/data/format_two_dimensions'
32
32
  require 'reports_kit/reports/data/generate'
33
33
  require 'reports_kit/reports/data/generate_for_properties'
34
+ require 'reports_kit/reports/data/normalize_properties'
34
35
  require 'reports_kit/reports/data/populate_one_dimension'
35
36
  require 'reports_kit/reports/data/populate_two_dimensions'
36
37
  require 'reports_kit/reports/data/utils'
@@ -44,12 +45,14 @@ require 'reports_kit/reports/filter_types/string'
44
45
 
45
46
  require 'reports_kit/reports/abstract_series'
46
47
  require 'reports_kit/reports/composite_series'
48
+ require 'reports_kit/reports/contextual_filter'
47
49
  require 'reports_kit/reports/dimension'
48
50
  require 'reports_kit/reports/dimension_with_series'
49
51
  require 'reports_kit/reports/filter'
50
52
  require 'reports_kit/reports/filter_with_series'
51
53
  require 'reports_kit/reports/generate_autocomplete_results'
52
54
  require 'reports_kit/reports/inferrable_configuration'
55
+ require 'reports_kit/reports/model_settings'
53
56
  require 'reports_kit/reports/properties'
54
57
  require 'reports_kit/reports/properties_to_filter'
55
58
  require 'reports_kit/reports/series'
@@ -6,5 +6,12 @@ module ReportsKit
6
6
  def context_record
7
7
  ReportsKit.configuration.context_record(self)
8
8
  end
9
+
10
+ private
11
+
12
+ def modify_context_params
13
+ modify_context_params_method = ReportsKit.configuration.modify_context_params_method
14
+ params[:context_params] = modify_context_params_method.call(params[:context_params], self) if modify_context_params_method
15
+ end
9
16
  end
10
17
  end
@@ -1,8 +1,8 @@
1
1
  module ReportsKit
2
2
  class Configuration
3
3
  attr_accessor :autocomplete_results_method, :cache_duration, :cache_store, :context_record_method, :custom_methods,
4
- :default_dimension_limit, :default_properties, :first_day_of_week, :properties_method, :report_filename_method,
5
- :use_concurrent_queries
4
+ :default_dimension_limit, :default_properties, :first_day_of_week, :modify_context_params_method, :properties_method,
5
+ :report_filename_method, :use_concurrent_queries
6
6
 
7
7
  DEFAULT_PROPERTIES_METHOD = lambda do |env|
8
8
  path = Rails.root.join('config', 'reports_kit', 'reports', "#{report_key}.yml")
@@ -18,6 +18,7 @@ module ReportsKit
18
18
  self.default_dimension_limit = 30
19
19
  self.default_properties = nil
20
20
  self.first_day_of_week = :sunday
21
+ self.modify_context_params_method = nil
21
22
  self.properties_method = DEFAULT_PROPERTIES_METHOD
22
23
  self.report_filename_method = nil
23
24
  self.use_concurrent_queries = false
@@ -1,5 +1,7 @@
1
1
  module ReportsKit
2
2
  class FiltersController < ReportsKit::BaseController
3
+ before_action :modify_context_params
4
+
3
5
  def autocomplete
4
6
  properties = Reports::Properties.generate(self)
5
7
  results = Reports::GenerateAutocompleteResults.new(params, properties, context_record: context_record).perform
@@ -1,9 +1,10 @@
1
1
  module ReportsKit
2
2
  class ModelConfiguration
3
- attr_accessor :aggregations, :dimensions, :filters
3
+ attr_accessor :aggregations, :contextual_filters, :dimensions, :filters
4
4
 
5
5
  def initialize
6
6
  self.aggregations = []
7
+ self.contextual_filters = []
7
8
  self.dimensions = []
8
9
  self.filters = []
9
10
  end
@@ -12,6 +13,10 @@ module ReportsKit
12
13
  aggregations << { key: key.to_s, expression: expression }.merge(properties).symbolize_keys
13
14
  end
14
15
 
16
+ def contextual_filter(key, method)
17
+ contextual_filters << { key: key, method: method }
18
+ end
19
+
15
20
  def dimension(key, properties)
16
21
  dimensions << { key: key.to_s }.merge(properties).symbolize_keys
17
22
  end
@@ -0,0 +1,19 @@
1
+ module ReportsKit
2
+ module Reports
3
+ class ContextualFilter
4
+ attr_accessor :key, :model_settings
5
+
6
+ delegate :settings_from_model, to: :model_settings
7
+
8
+ def initialize(key, series:)
9
+ self.key = key.to_sym
10
+ self.model_settings = ModelSettings.new(series, :contextual_filters, self.key)
11
+ end
12
+
13
+ def apply(relation, context_params)
14
+ raise ArgumentError.new("contextual_filter with key :#{key} not defined in #{model_class}") if settings_from_model.blank?
15
+ settings_from_model[:method].call(relation, context_params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,8 +4,6 @@ module ReportsKit
4
4
  class FormatTable
5
5
  attr_accessor :data, :format, :first_column_label, :report_options
6
6
 
7
- VALID_AGGREGATION_OPERATORS = [:sum]
8
-
9
7
  def initialize(data, format:, first_column_label:, report_options:)
10
8
  self.data = data
11
9
  self.format = format
@@ -6,10 +6,11 @@ module ReportsKit
6
6
 
7
7
  attr_accessor :properties, :context_record
8
8
 
9
- def initialize(properties, context_record: nil)
9
+ def initialize(properties, context_record: nil, context_params: nil)
10
10
  self.properties = properties.deep_symbolize_keys
11
11
  self.properties = ReportsKit.configuration.default_properties.deep_merge(self.properties) if ReportsKit.configuration.default_properties
12
- self.properties = Utils.normalize_properties(self.properties)
12
+ self.properties[:context_params] = context_params if context_params
13
+ self.properties = NormalizeProperties.new(self.properties).perform
13
14
  self.context_record = context_record
14
15
  end
15
16
 
@@ -0,0 +1,62 @@
1
+ module ReportsKit
2
+ module Reports
3
+ module Data
4
+ class NormalizeProperties
5
+ attr_accessor :raw_properties
6
+
7
+ def initialize(raw_properties)
8
+ self.raw_properties = raw_properties.dup
9
+ end
10
+
11
+ def perform
12
+ context_properties = raw_properties.slice(:context_params, :contextual_filters)
13
+ properties = recursively_normalize_properties(raw_properties)
14
+ populate_context_properties(properties, context_properties: context_properties)
15
+ end
16
+
17
+ private
18
+
19
+ def normalize_filters(series_properties, ui_filters)
20
+ series_properties[:filters] = series_properties[:filters].map do |filter_properties|
21
+ filter_properties = { key: filter_properties } if filter_properties.is_a?(String)
22
+ key = filter_properties[:key]
23
+ ui_key = filter_properties[:ui_key]
24
+ value = ui_filters[key.to_sym]
25
+ value ||= ui_filters[ui_key.to_sym] if ui_key
26
+ if value
27
+ filter_properties[:criteria] ||= {}
28
+ filter_properties[:criteria][:value] = value
29
+ end
30
+ filter_properties
31
+ end
32
+ series_properties
33
+ end
34
+
35
+ def recursively_normalize_properties(properties, ui_filters: nil)
36
+ can_have_nesting = properties[:composite_operator].present? || properties[:series].is_a?(Array)
37
+ ui_filters ||= properties[:ui_filters]
38
+ properties[:series] ||= properties.slice(*Series::VALID_KEYS).presence
39
+ properties[:series] = [properties[:series]] if properties[:series].is_a?(Hash) && properties[:series].present?
40
+ return properties if ui_filters.blank? || properties[:series].blank?
41
+ properties[:series] = properties[:series].map do |series_properties|
42
+ series_properties = recursively_normalize_properties(series_properties, ui_filters: ui_filters) if can_have_nesting
43
+ next(series_properties) if series_properties[:filters].blank?
44
+ normalize_filters(series_properties, ui_filters)
45
+ end
46
+ properties
47
+ end
48
+
49
+ def populate_context_properties(properties, context_properties: nil)
50
+ return properties if context_properties.blank? || properties.blank? || properties[:series].blank?
51
+ can_have_nesting = properties[:composite_operator].present? || properties[:series].is_a?(Array)
52
+ properties[:series] = properties[:series].map do |series_properties|
53
+ series_properties = series_properties.merge(context_properties)
54
+ series_properties = populate_context_properties(series_properties, context_properties: context_properties) if can_have_nesting
55
+ series_properties
56
+ end
57
+ properties
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -146,37 +146,6 @@ module ReportsKit
146
146
  formatted_value = value_format_method.call(raw_value) if value_format_method
147
147
  Value.new(raw_value, formatted_value)
148
148
  end
149
-
150
- def self.normalize_filters(series_properties, ui_filters)
151
- series_properties[:filters] = series_properties[:filters].map do |filter_properties|
152
- filter_properties = { key: filter_properties } if filter_properties.is_a?(String)
153
- key = filter_properties[:key]
154
- ui_key = filter_properties[:ui_key]
155
- value = ui_filters[key.to_sym]
156
- value ||= ui_filters[ui_key.to_sym] if ui_key
157
- if value
158
- filter_properties[:criteria] ||= {}
159
- filter_properties[:criteria][:value] = value
160
- end
161
- filter_properties
162
- end
163
- series_properties
164
- end
165
-
166
- def self.normalize_properties(properties, ui_filters: nil)
167
- can_have_nesting = properties[:composite_operator].present? || properties[:series].is_a?(Array)
168
- ui_filters ||= properties[:ui_filters]
169
- properties = properties.dup
170
- properties[:series] ||= properties.slice(*Series::VALID_KEYS).presence
171
- properties[:series] = [properties[:series]] if properties[:series].is_a?(Hash) && properties[:series].present?
172
- return properties if ui_filters.blank? || properties[:series].blank?
173
- properties[:series] = properties[:series].map do |series_properties|
174
- series_properties = normalize_properties(series_properties, ui_filters: ui_filters) if can_have_nesting
175
- next(series_properties) if series_properties[:filters].blank?
176
- normalize_filters(series_properties, ui_filters)
177
- end
178
- properties
179
- end
180
149
  end
181
150
  end
182
151
  end
@@ -9,13 +9,15 @@ module ReportsKit
9
9
  :text
10
10
  ]
11
11
 
12
- attr_accessor :inferrable, :inferrable_type
12
+ attr_accessor :inferrable, :inferrable_type, :model_settings
13
13
 
14
14
  delegate :key, :expression, :series, to: :inferrable
15
+ delegate :model_class, :settings_from_model, to: :model_settings
15
16
 
16
17
  def initialize(inferrable, inferrable_type)
17
18
  self.inferrable = inferrable
18
19
  self.inferrable_type = inferrable_type
20
+ self.model_settings = ModelSettings.new(series, inferrable_type, key)
19
21
  end
20
22
 
21
23
  def configuration_strategy
@@ -47,15 +49,6 @@ module ReportsKit
47
49
  column_type == :datetime
48
50
  end
49
51
 
50
- def settings_from_model
51
- return {} if model_configuration.blank?
52
- return {} if model_configuration.public_send(inferrable_type).blank?
53
- config_hash = model_configuration.public_send(inferrable_type).find do |hash|
54
- hash[:key] == key
55
- end
56
- config_hash || {}
57
- end
58
-
59
52
  def reflection
60
53
  model_class.reflect_on_association(expression.to_sym)
61
54
  end
@@ -118,16 +111,6 @@ module ReportsKit
118
111
  column_type = model_class.columns_hash[expression.to_s].try(:type)
119
112
  return column_type if SUPPORTED_COLUMN_TYPES.include?(column_type)
120
113
  end
121
-
122
- def model_configuration
123
- return unless model_class && model_class.respond_to?(:reports_kit_configuration)
124
- model_class.reports_kit_configuration
125
- end
126
-
127
- def model_class
128
- return unless series
129
- series.model_class
130
- end
131
114
  end
132
115
  end
133
116
  end
@@ -0,0 +1,35 @@
1
+ module ReportsKit
2
+ module Reports
3
+ class ModelSettings
4
+ attr_accessor :series, :model_configuration_type, :key
5
+
6
+ def initialize(series, model_configuration_type, key)
7
+ self.series = series
8
+ self.model_configuration_type = model_configuration_type
9
+ self.key = key
10
+ end
11
+
12
+ def settings_from_model
13
+ return {} if model_configuration.blank?
14
+ config_hashes = model_configuration.public_send(model_configuration_type)
15
+ return {} if config_hashes.blank?
16
+ config_hash = config_hashes.find do |hash|
17
+ hash[:key] == key
18
+ end
19
+ config_hash || {}
20
+ end
21
+
22
+ def model_class
23
+ return unless series
24
+ series.model_class
25
+ end
26
+
27
+ private
28
+
29
+ def model_configuration
30
+ return unless model_class && model_class.respond_to?(:reports_kit_configuration)
31
+ model_class.reports_kit_configuration
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,9 +1,9 @@
1
1
  module ReportsKit
2
2
  module Reports
3
3
  class Series < AbstractSeries
4
- VALID_KEYS = [:measure, :dimensions, :filters, :limit, :report_options]
4
+ VALID_KEYS = [:measure, :dimensions, :contextual_filters, :context_params, :filters, :limit, :context_params, :report_options]
5
5
 
6
- attr_accessor :properties, :dimensions, :filters, :context_record
6
+ attr_accessor :properties, :dimensions, :contextual_filters, :filters, :context_record
7
7
 
8
8
  def initialize(properties, context_record: nil)
9
9
  properties = { measure: properties } if properties.is_a?(String)
@@ -13,6 +13,7 @@ module ReportsKit
13
13
  properties[:measure] = { key: properties[:measure] } if properties[:measure].is_a?(String)
14
14
  raise ArgumentError.new("Measure properties must be a String or Hash, not a #{properties.class.name}: #{properties.inspect}") unless properties.is_a?(Hash)
15
15
 
16
+ contextual_filter_keys = properties[:contextual_filters] || []
16
17
  dimension_hashes = properties[:dimensions] || []
17
18
  dimension_hashes = dimension_hashes.values if dimension_hashes.is_a?(Hash) && dimension_hashes.key?(:'0')
18
19
  filter_hashes = properties[:filters] || []
@@ -22,6 +23,7 @@ module ReportsKit
22
23
  self.context_record = context_record
23
24
  self.dimensions = dimension_hashes.map { |dimension_hash| DimensionWithSeries.new(dimension: Dimension.new(dimension_hash), series: self) }
24
25
  self.filters = filter_hashes.map { |filter_hash| FilterWithSeries.new(filter: Filter.new(filter_hash), series: self) }
26
+ self.contextual_filters = contextual_filter_keys.map { |key| ContextualFilter.new(key, series: self) }
25
27
  end
26
28
 
27
29
  def key
@@ -91,6 +93,9 @@ module ReportsKit
91
93
  filters.each do |filter|
92
94
  relation = filter.apply(relation)
93
95
  end
96
+ contextual_filters.each do |filter|
97
+ relation = filter.apply(relation, properties[:context_params])
98
+ end
94
99
  relation
95
100
  end
96
101
 
@@ -3,6 +3,8 @@ require 'spreadsheet'
3
3
 
4
4
  module ReportsKit
5
5
  class ReportsController < ReportsKit::BaseController
6
+ before_action :modify_context_params
7
+
6
8
  VALID_PARAMS_PROPERTIES_KEYS = [:ui_filters]
7
9
 
8
10
  def index
@@ -35,7 +37,7 @@ module ReportsKit
35
37
  end
36
38
 
37
39
  def report_data
38
- Reports::Data::Generate.new(properties, context_record: context_record).perform
40
+ Reports::Data::Generate.new(properties, context_record: context_record, context_params: context_params).perform
39
41
  end
40
42
 
41
43
  def properties
@@ -1,3 +1,3 @@
1
1
  module ReportsKit
2
- VERSION = '0.3.3'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReportsKit::Reports::Data::Generate do
4
+ subject { described_class.new(properties).perform }
5
+
6
+ let(:repo) { create(:repo) }
7
+ let(:repo2) { create(:repo) }
8
+ let(:chart_data) do
9
+ chart_data = subject[:chart_data].except(:options)
10
+ chart_data[:datasets] = chart_data[:datasets].map do |dataset|
11
+ dataset.except(:backgroundColor, :borderColor)
12
+ end
13
+ chart_data
14
+ end
15
+
16
+ let!(:issues) do
17
+ [
18
+ create(:issue, repo: repo),
19
+ create(:issue, repo: repo),
20
+ create(:issue, repo: repo2)
21
+ ]
22
+ end
23
+
24
+ context 'with a contextual_filter' do
25
+ context 'with context_params' do
26
+ let(:properties) do
27
+ {
28
+ measure: 'issue',
29
+ contextual_filters: %w(for_repo),
30
+ dimensions: %w(repo),
31
+ context_params: { repo_id: repo.id }
32
+ }
33
+ end
34
+
35
+ it 'returns the chart_data' do
36
+ expect(chart_data).to eq({
37
+ labels: [repo.to_s],
38
+ datasets: [{ label: 'Issues', data: [2] }]
39
+ })
40
+ end
41
+ end
42
+
43
+ context 'without context_params' do
44
+ let(:properties) do
45
+ {
46
+ measure: 'issue',
47
+ contextual_filters: %w(for_repo),
48
+ dimensions: %w(repo)
49
+ }
50
+ end
51
+
52
+ it 'returns the chart_data' do
53
+ expect(chart_data).to eq({
54
+ labels: [repo.to_s, repo2.to_s],
55
+ datasets: [{ label: 'Issues', data: [2, 1] }]
56
+ })
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,196 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReportsKit::Reports::Data::NormalizeProperties do
4
+ describe '#perform' do
5
+ let(:normalized_properties) { described_class.new(properties).perform }
6
+ let(:series) { normalized_properties[:series] }
7
+ let(:context_params) { { foo: 'bar' } }
8
+ let(:name) { 'Foo' }
9
+
10
+ context 'without a series key' do
11
+ let(:properties) do
12
+ {
13
+ measure: 'issue',
14
+ dimensions: %w(opened_at)
15
+ }
16
+ end
17
+
18
+ it 'normalizes' do
19
+ expect(series).to eq([properties])
20
+ end
21
+ end
22
+
23
+ context 'with a series key' do
24
+ let(:properties) do
25
+ {
26
+ series: {
27
+ measure: 'issue',
28
+ dimensions: %w(opened_at)
29
+ }
30
+ }
31
+ end
32
+
33
+ it 'normalizes' do
34
+ expect(series).to eq([properties[:series]])
35
+ end
36
+ end
37
+
38
+ context 'with a series array and context_params' do
39
+ let(:properties) do
40
+ {
41
+ series: [{
42
+ measure: 'issue',
43
+ dimensions: %w(opened_at)
44
+ }],
45
+ context_params: context_params
46
+ }
47
+ end
48
+
49
+ it 'normalizes' do
50
+ expect(series).to eq([{
51
+ measure: 'issue',
52
+ dimensions: %w(opened_at),
53
+ context_params: context_params
54
+ }])
55
+ end
56
+ end
57
+
58
+ context 'with a composite series and context_params' do
59
+ let(:properties) do
60
+ {
61
+ name: name,
62
+ composite_operator: '%',
63
+ series: [
64
+ {
65
+ measure: 'issue',
66
+ dimensions: %w(created_at)
67
+ },
68
+ {
69
+ measure: 'tag',
70
+ dimensions: %w(created_at)
71
+ }
72
+ ],
73
+ context_params: context_params
74
+ }
75
+ end
76
+
77
+ it 'copies the context_params to the series' do
78
+ expect(normalized_properties).to eq({
79
+ name: name,
80
+ composite_operator: '%',
81
+ series: [
82
+ {
83
+ measure: 'issue',
84
+ dimensions: %w(created_at),
85
+ context_params: context_params
86
+ },
87
+ {
88
+ measure: 'tag',
89
+ dimensions: %w(created_at),
90
+ context_params: context_params
91
+ }
92
+ ],
93
+ context_params: context_params
94
+ })
95
+ end
96
+ end
97
+
98
+ context 'with a composite series and context_params' do
99
+ let(:properties) do
100
+ {
101
+ series: [
102
+ {
103
+ name: name,
104
+ composite_operator: '+',
105
+ series: [
106
+ {
107
+ measure: 'issue',
108
+ dimensions: %w(created_at)
109
+ }
110
+ ]
111
+ }
112
+ ],
113
+ context_params: context_params
114
+ }
115
+ end
116
+
117
+ it 'copies the context_params to the series' do
118
+ expect(normalized_properties).to eq({
119
+ series: [
120
+ {
121
+ name: name,
122
+ composite_operator: '+',
123
+ series: [
124
+ {
125
+ measure: 'issue',
126
+ dimensions: %w(created_at),
127
+ context_params: context_params
128
+ }
129
+ ],
130
+ context_params: context_params
131
+ }
132
+ ],
133
+ context_params: context_params
134
+ })
135
+ end
136
+ end
137
+
138
+ context 'with a composite series, a series, and context_params' do
139
+ let(:properties) do
140
+ {
141
+ series: [
142
+ {
143
+ measure: 'issue',
144
+ dimensions: %w(opened_at)
145
+ },
146
+ {
147
+ name: name,
148
+ composite_operator: '%',
149
+ series: [
150
+ {
151
+ measure: 'issue',
152
+ dimensions: %w(created_at)
153
+ },
154
+ {
155
+ measure: 'tag',
156
+ dimensions: %w(created_at)
157
+ }
158
+ ]
159
+ }
160
+ ],
161
+ context_params: context_params
162
+ }
163
+ end
164
+
165
+ it 'copies the context_params to the series' do
166
+ expect(normalized_properties).to eq({
167
+ series: [
168
+ {
169
+ measure: 'issue',
170
+ dimensions: %w(opened_at),
171
+ context_params: context_params
172
+ },
173
+ {
174
+ name: name,
175
+ composite_operator: '%',
176
+ series: [
177
+ {
178
+ measure: 'issue',
179
+ dimensions: %w(created_at),
180
+ context_params: context_params
181
+ },
182
+ {
183
+ measure: 'tag',
184
+ dimensions: %w(created_at),
185
+ context_params: context_params
186
+ }
187
+ ],
188
+ context_params: context_params
189
+ }
190
+ ],
191
+ context_params: context_params
192
+ })
193
+ end
194
+ end
195
+ end
196
+ end
@@ -8,6 +8,7 @@ class Issue < ActiveRecord::Base
8
8
 
9
9
  reports_kit do
10
10
  aggregation :average_duration, [:average, REPORTS_KIT_DATABASE_TYPE == :mysql ? 'DATEDIFF(closed_at, opened_at)' : '(closed_at::date - opened_at::date)']
11
+ contextual_filter :for_repo, ->(relation, context_params) { context_params ? relation.where(repo_id: context_params[:repo_id]) : relation }
11
12
  dimension :titleized_state, group: 'issues.state', key_to_label: -> (state) { state.try(:titleize) }
12
13
  end
13
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reports_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Benner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-14 00:00:00.000000000 Z
11
+ date: 2017-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -221,6 +221,7 @@ files:
221
221
  - lib/reports_kit/reports/adapters/mysql.rb
222
222
  - lib/reports_kit/reports/adapters/postgresql.rb
223
223
  - lib/reports_kit/reports/composite_series.rb
224
+ - lib/reports_kit/reports/contextual_filter.rb
224
225
  - lib/reports_kit/reports/data/add_table_aggregations.rb
225
226
  - lib/reports_kit/reports/data/aggregate_composite.rb
226
227
  - lib/reports_kit/reports/data/aggregate_one_dimension.rb
@@ -231,6 +232,7 @@ files:
231
232
  - lib/reports_kit/reports/data/format_two_dimensions.rb
232
233
  - lib/reports_kit/reports/data/generate.rb
233
234
  - lib/reports_kit/reports/data/generate_for_properties.rb
235
+ - lib/reports_kit/reports/data/normalize_properties.rb
234
236
  - lib/reports_kit/reports/data/populate_one_dimension.rb
235
237
  - lib/reports_kit/reports/data/populate_two_dimensions.rb
236
238
  - lib/reports_kit/reports/data/utils.rb
@@ -246,6 +248,7 @@ files:
246
248
  - lib/reports_kit/reports/filter_with_series.rb
247
249
  - lib/reports_kit/reports/generate_autocomplete_results.rb
248
250
  - lib/reports_kit/reports/inferrable_configuration.rb
251
+ - lib/reports_kit/reports/model_settings.rb
249
252
  - lib/reports_kit/reports/properties.rb
250
253
  - lib/reports_kit/reports/properties_to_filter.rb
251
254
  - lib/reports_kit/reports/series.rb
@@ -263,7 +266,9 @@ files:
263
266
  - spec/fixtures/generate_outputs.yml
264
267
  - spec/reports_kit/form_builder_spec.rb
265
268
  - spec/reports_kit/relative_time_spec.rb
269
+ - spec/reports_kit/reports/data/generate/contextual_filters_spec.rb
266
270
  - spec/reports_kit/reports/data/generate_spec.rb
271
+ - spec/reports_kit/reports/data/normalize_properties_spec.rb
267
272
  - spec/reports_kit/reports/dimension_with_series_spec.rb
268
273
  - spec/reports_kit/reports/filter_with_series_spec.rb
269
274
  - spec/spec_helper.rb