reports_kit 0.5.0 → 0.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f73a1370ec5380438c97d70101c44741b71e11d4
4
- data.tar.gz: 512485a9a8703592305f62bc0af6f21cc339d4f0
3
+ metadata.gz: dce804c6f31b50a81956706d29aa594ecc4f945c
4
+ data.tar.gz: 03fc82ecfa636b3e20ae44b21d679d30b1b25f0a
5
5
  SHA512:
6
- metadata.gz: 7f05e2853acc4f162d822351bdeb4e25243557334af27cde8b20edbccc825f95b1458e076a514490b054eb733807d32fa6d310f84e20412f9793d4d56fa47c46
7
- data.tar.gz: 58c18993f9d3e24025a4fafe901b2c0345b8fa0019aedc01258873d0a128cc22bf1c92fbd173a7703bf5000c3919d10720f1b4b766c6d0fe5e509b7e9ad31e9b
6
+ metadata.gz: 0a7c324823890a61f417e69b923c18c5ab946ae6ecc238f8ed1fc8e9dfbf28a46e517772b5f248a6e9c9d8e6522dbd5b5410aeffa091d3efe76bbdd3709f62c0
7
+ data.tar.gz: 3de91410a8d07370d2664bae9a4deb04cd57100074c66672db30ae591e4f21d824fec442819946dd8993ff5675a50508eb9cebaec40970c68a6624ddd7856bf1
@@ -15,6 +15,7 @@ before_install: gem update bundler
15
15
  before_script:
16
16
  - psql -c 'CREATE DATABASE reports_kit_test;' -U postgres
17
17
  - mysql -e 'CREATE DATABASE IF NOT EXISTS reports_kit_test;'
18
+ - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
18
19
  - bundle exec appraisal install
19
20
 
20
21
  script: bundle exec appraisal rspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.5.0)
4
+ reports_kit (0.7.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -63,6 +63,8 @@ GEM
63
63
  activesupport (>= 3.0.0)
64
64
  globalid (0.4.0)
65
65
  activesupport (>= 4.2.0)
66
+ groupdate (3.2.0)
67
+ activesupport (>= 3)
66
68
  i18n (0.8.6)
67
69
  loofah (2.1.1)
68
70
  crass (~> 1.0.2)
@@ -149,6 +151,7 @@ DEPENDENCIES
149
151
  appraisal
150
152
  database_cleaner (~> 1)
151
153
  factory_girl (~> 4)
154
+ groupdate (~> 3)
152
155
  mysql2
153
156
  pg (>= 0.15)
154
157
  pry (~> 0)
@@ -159,4 +162,4 @@ DEPENDENCIES
159
162
  timecop (~> 0)
160
163
 
161
164
  BUNDLED WITH
162
- 1.15.4
165
+ 1.16.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.5.0)
4
+ reports_kit (0.7.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -63,6 +63,8 @@ GEM
63
63
  activesupport (>= 3.0.0)
64
64
  globalid (0.4.0)
65
65
  activesupport (>= 4.2.0)
66
+ groupdate (3.2.0)
67
+ activesupport (>= 3)
66
68
  i18n (0.8.6)
67
69
  loofah (2.1.1)
68
70
  crass (~> 1.0.2)
@@ -148,6 +150,7 @@ DEPENDENCIES
148
150
  appraisal
149
151
  database_cleaner (~> 1)
150
152
  factory_girl (~> 4)
153
+ groupdate (~> 3)
151
154
  pg
152
155
  pry (~> 0)
153
156
  pry-byebug (~> 1)
@@ -157,4 +160,4 @@ DEPENDENCIES
157
160
  timecop (~> 0)
158
161
 
159
162
  BUNDLED WITH
160
- 1.15.4
163
+ 1.16.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.4.1)
4
+ reports_kit (0.7.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -66,6 +66,8 @@ GEM
66
66
  activesupport (>= 3.0.0)
67
67
  globalid (0.4.0)
68
68
  activesupport (>= 4.2.0)
69
+ groupdate (3.2.0)
70
+ activesupport (>= 3)
69
71
  i18n (0.8.6)
70
72
  loofah (2.1.1)
71
73
  crass (~> 1.0.2)
@@ -154,6 +156,7 @@ DEPENDENCIES
154
156
  appraisal
155
157
  database_cleaner (~> 1)
156
158
  factory_girl (~> 4)
159
+ groupdate (~> 3)
157
160
  pg
158
161
  pry (~> 0)
159
162
  pry-byebug (~> 1)
@@ -163,4 +166,4 @@ DEPENDENCIES
163
166
  timecop (~> 0)
164
167
 
165
168
  BUNDLED WITH
166
- 1.15.4
169
+ 1.16.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.5.0)
4
+ reports_kit (0.7.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -66,6 +66,8 @@ GEM
66
66
  activesupport (>= 3.0.0)
67
67
  globalid (0.4.0)
68
68
  activesupport (>= 4.2.0)
69
+ groupdate (3.2.0)
70
+ activesupport (>= 3)
69
71
  i18n (0.8.6)
70
72
  loofah (2.1.1)
71
73
  crass (~> 1.0.2)
@@ -155,6 +157,7 @@ DEPENDENCIES
155
157
  appraisal
156
158
  database_cleaner (~> 1)
157
159
  factory_girl (~> 4)
160
+ groupdate (~> 3)
158
161
  mysql2
159
162
  pg (>= 0.15)
160
163
  pry (~> 0)
@@ -165,4 +168,4 @@ DEPENDENCIES
165
168
  timecop (~> 0)
166
169
 
167
170
  BUNDLED WITH
168
- 1.15.4
171
+ 1.16.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.5.0)
4
+ reports_kit (0.7.0)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -66,6 +66,8 @@ GEM
66
66
  activesupport (>= 3.0.0)
67
67
  globalid (0.4.0)
68
68
  activesupport (>= 4.2.0)
69
+ groupdate (3.2.0)
70
+ activesupport (>= 3)
69
71
  i18n (0.8.6)
70
72
  loofah (2.1.1)
71
73
  crass (~> 1.0.2)
@@ -154,6 +156,7 @@ DEPENDENCIES
154
156
  appraisal
155
157
  database_cleaner (~> 1)
156
158
  factory_girl (~> 4)
159
+ groupdate (~> 3)
157
160
  pg
158
161
  pry (~> 0)
159
162
  pry-byebug (~> 1)
@@ -163,4 +166,4 @@ DEPENDENCIES
163
166
  timecop (~> 0)
164
167
 
165
168
  BUNDLED WITH
166
- 1.15.4
169
+ 1.16.1
@@ -15,6 +15,7 @@ require 'reports_kit/order'
15
15
  require 'reports_kit/relative_time'
16
16
  require 'reports_kit/report_builder'
17
17
  require 'reports_kit/reports_controller'
18
+ require 'reports_kit/utils'
18
19
  require 'reports_kit/value'
19
20
  require 'reports_kit/version'
20
21
 
@@ -25,6 +26,7 @@ require 'reports_kit/reports/data/add_table_aggregations'
25
26
  require 'reports_kit/reports/data/aggregate_composite'
26
27
  require 'reports_kit/reports/data/aggregate_one_dimension'
27
28
  require 'reports_kit/reports/data/aggregate_two_dimensions'
29
+ require 'reports_kit/reports/data/chart_data_for_data_method'
28
30
  require 'reports_kit/reports/data/chart_options'
29
31
  require 'reports_kit/reports/data/format_one_dimension'
30
32
  require 'reports_kit/reports/data/format_table'
@@ -51,6 +53,7 @@ require 'reports_kit/reports/dimension_with_series'
51
53
  require 'reports_kit/reports/filter'
52
54
  require 'reports_kit/reports/filter_with_series'
53
55
  require 'reports_kit/reports/generate_autocomplete_results'
56
+ require 'reports_kit/reports/generate_autocomplete_method_results'
54
57
  require 'reports_kit/reports/inferrable_configuration'
55
58
  require 'reports_kit/reports/model_settings'
56
59
  require 'reports_kit/reports/properties'
@@ -65,4 +68,12 @@ module ReportsKit
65
68
  def self.configuration
66
69
  @configuration ||= Configuration.new
67
70
  end
71
+
72
+ def self.parse_date_range(string)
73
+ ReportsKit::Reports::Data::Utils.parse_date_range(string)
74
+ end
75
+
76
+ def self.format_date_range(string)
77
+ ReportsKit::Reports::Data::Utils.format_date_range(string)
78
+ end
68
79
  end
@@ -13,7 +13,6 @@ module ReportsKit
13
13
  self.autocomplete_results_method = nil
14
14
  self.cache_duration = 5.minutes
15
15
  self.cache_store = nil
16
- self.context_record_method = nil
17
16
  self.custom_methods = {}
18
17
  self.default_dimension_limit = 30
19
18
  self.default_properties = nil
@@ -15,7 +15,7 @@ module ReportsKit
15
15
 
16
16
  def check_box(filter_key, options = {})
17
17
  filter = properties_to_filter.perform(filter_key)
18
- checked = filter.normalized_properties[:criteria][:value] == 'true'
18
+ checked = options.key?(:value) ? options[:value] : filter.normalized_properties[:criteria].try(:[], :value) == 'true'
19
19
  check_box_tag(filter_key, '1', checked, options)
20
20
  end
21
21
 
@@ -23,7 +23,7 @@ module ReportsKit
23
23
  filter = properties_to_filter.perform(filter_key)
24
24
  defaults = { class: 'form-control input-sm date_range_picker' }
25
25
  options = defaults.deep_merge(options)
26
- value = filter.normalized_properties[:criteria][:value].presence
26
+ value = options[:value].presence || filter.normalized_properties[:criteria].try(:[], :value).presence
27
27
  value ||= default_date_range_value
28
28
  text_field_tag(filter_key, value, options)
29
29
  end
@@ -50,7 +50,7 @@ module ReportsKit
50
50
  filter = properties_to_filter.perform(filter_key)
51
51
  defaults = { class: 'form-control input-sm' }
52
52
  options = defaults.deep_merge(options)
53
- text_field_tag(filter_key, filter.normalized_properties[:criteria][:value], options)
53
+ text_field_tag(filter_key, filter.normalized_properties[:criteria].try(:[], :value), options)
54
54
  end
55
55
 
56
56
  private
@@ -16,6 +16,10 @@ module ReportsKit
16
16
  raise ArgumentError.new("Unsupported first_day_of_week: #{ReportsKit.configuration.first_day_of_week}")
17
17
  end
18
18
  end
19
+
20
+ def self.truncate_to_month(column)
21
+ "DATE_SUB(DATE(#{column}), INTERVAL DAY(#{column}) - 1 DAY)"
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -16,6 +16,10 @@ module ReportsKit
16
16
  raise ArgumentError.new("Unsupported first_day_of_week: #{ReportsKit.configuration.first_day_of_week}")
17
17
  end
18
18
  end
19
+
20
+ def self.truncate_to_month(column)
21
+ "DATE_TRUNC('month', #{column}::date)"
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -0,0 +1,62 @@
1
+ module ReportsKit
2
+ class ChartDataForDataMethod
3
+ attr_accessor :properties
4
+
5
+ def initialize(properties)
6
+ self.properties = properties
7
+ end
8
+
9
+ def perform
10
+ klass, method_name = ReportsKit::Utils.string_to_class_method(properties[:data_method], 'data_method')
11
+ raw_data = klass.public_send(method_name, properties)
12
+ {
13
+ raw_data: raw_data,
14
+ formatted_data: format_returned_data(raw_data)
15
+ }
16
+ end
17
+
18
+ private
19
+
20
+ def format_returned_data(returned_data)
21
+ return [] if returned_data.blank?
22
+ returned_data = returned_data.to_a
23
+
24
+ first_key = returned_data.first.first
25
+ if first_key.is_a?(Array) && first_key.length == 2
26
+ format_two_dimensional_returned_data(returned_data)
27
+ else
28
+ {
29
+ labels: returned_data.map(&:first),
30
+ datasets: [
31
+ {
32
+ data: returned_data.map(&:last)
33
+ }
34
+ ]
35
+ }
36
+ end
37
+ end
38
+
39
+ def format_two_dimensional_returned_data(returned_data)
40
+ primary_keys_secondary_keys_values = {}
41
+ secondary_keys_primary_keys_values = {}
42
+ secondary_keys = []
43
+ returned_data.each do |(primary_key, secondary_key), value|
44
+ secondary_keys_primary_keys_values[secondary_key] ||= {}
45
+ secondary_keys_primary_keys_values[secondary_key][primary_key] = value
46
+ primary_keys_secondary_keys_values[primary_key] ||= {}
47
+ primary_keys_secondary_keys_values[primary_key][secondary_key] = value
48
+ end
49
+ primary_keys = primary_keys_secondary_keys_values.keys
50
+ datasets = secondary_keys_primary_keys_values.map do |secondary_key, primary_keys_values|
51
+ {
52
+ label: secondary_key,
53
+ data: primary_keys.map { |primary_key| primary_keys_values[primary_key] || 0 }
54
+ }
55
+ end
56
+ {
57
+ labels: primary_keys,
58
+ datasets: datasets
59
+ }
60
+ end
61
+ end
62
+ end
@@ -18,6 +18,23 @@ module ReportsKit
18
18
  data = ReportsKit::Cache.get(properties, context_record)
19
19
  return data.deep_symbolize_keys if data
20
20
 
21
+ data_method_data = ChartDataForDataMethod.new(properties).perform if has_data_method?
22
+ chart_data = data_method_data ? data_method_data[:formatted_data] : properties_to_chart_data
23
+ data = { chart_data: chart_data }
24
+ data = ChartOptions.new(data, options: properties[:chart], inferred_options: inferred_options).perform
25
+ data[:report_options] = report_options if report_options
26
+ data = format_table_data(data, data_method_data) if table_or_csv?
27
+ ReportsKit::Cache.set(properties, context_record, data)
28
+ data
29
+ end
30
+
31
+ private
32
+
33
+ def has_data_method?
34
+ properties[:data_method].present?
35
+ end
36
+
37
+ def properties_to_chart_data
21
38
  if two_dimensions?
22
39
  raw_data = Data::FormatTwoDimensions.new(serieses.first, serieses_results.first.last, order: order, limit: limit).perform
23
40
  else
@@ -27,18 +44,9 @@ module ReportsKit
27
44
  raw_data = Data::AddTableAggregations.new(raw_data, report_options: report_options).perform if table_or_csv?
28
45
  raw_data = data_format_method.call(data: raw_data, properties: properties, context_record: context_record) if data_format_method
29
46
  raw_data = csv_data_format_method.call(data: raw_data, properties: properties, context_record: context_record) if csv_data_format_method && format == 'csv'
30
- chart_data = format_chart_data(raw_data)
31
-
32
- data = { chart_data: chart_data }
33
- data = ChartOptions.new(data, options: properties[:chart], inferred_options: inferred_options).perform
34
- data[:report_options] = report_options if report_options
35
- data = format_table_data(data) if table_or_csv?
36
- ReportsKit::Cache.set(properties, context_record, data)
37
- data
47
+ format_chart_data(raw_data)
38
48
  end
39
49
 
40
- private
41
-
42
50
  def format_chart_data(raw_data)
43
51
  chart_data = {}
44
52
  chart_data[:labels] = raw_data[:entities].map(&:label)
@@ -51,14 +59,18 @@ module ReportsKit
51
59
  chart_data
52
60
  end
53
61
 
54
- def format_table_data(data)
62
+ def format_table_data(data, data_method_data)
63
+ data[:type] = format
64
+ if has_data_method?
65
+ data[:table_data] = data_method_data[:raw_data]
66
+ return data
67
+ end
55
68
  data[:table_data] = Data::FormatTable.new(
56
69
  data.delete(:chart_data),
57
70
  format: format,
58
- first_column_label: primary_dimension.label,
71
+ first_column_label: primary_dimension.try(:label),
59
72
  report_options: report_options
60
73
  ).perform
61
- data[:type] = format
62
74
  data
63
75
  end
64
76
 
@@ -132,6 +144,7 @@ module ReportsKit
132
144
  end
133
145
 
134
146
  def inferred_options
147
+ return {} if has_data_method?
135
148
  {
136
149
  x_axis_label: primary_dimension.label,
137
150
  y_axis_label: serieses.length == 1 ? serieses.first.label : nil
@@ -14,6 +14,11 @@ module ReportsKit
14
14
  time.strftime('%b %-d, \'%y')
15
15
  end
16
16
 
17
+ def self.format_date_range(string)
18
+ start_at, end_at = parse_date_range(string, type: Array)
19
+ [format_display_time(start_at), FilterTypes::Datetime::SEPARATOR, format_display_time(end_at)].join(' ')
20
+ end
21
+
17
22
  def self.format_time_value(value)
18
23
  time = RelativeTime.parse(value, prevent_exceptions: true)
19
24
  return value unless time
@@ -36,6 +41,18 @@ module ReportsKit
36
41
  RelativeTime.parse(string)
37
42
  end
38
43
 
44
+ def self.parse_date_range(string, type: nil)
45
+ return if string.blank?
46
+ start_string, end_string = string.split(FilterTypes::Datetime::SEPARATOR)
47
+ start_at = parse_date_string(start_string)
48
+ end_at = parse_date_string(end_string)
49
+ if type == Array
50
+ [start_at, end_at]
51
+ else
52
+ (start_at..end_at)
53
+ end
54
+ end
55
+
39
56
  def self.populate_sparse_hash(hash, dimension:)
40
57
  keys = hash.keys
41
58
  is_nested = dimension.series.has_two_dimensions?
@@ -69,15 +86,23 @@ module ReportsKit
69
86
  first_key = first_key.to_date
70
87
  granularity = dimension.granularity
71
88
 
72
- first_key = first_key.beginning_of_week(ReportsKit.configuration.first_day_of_week) if granularity == 'week'
73
89
  keys = keys.sort
74
90
  last_key = (dimension.last_key || keys.last).to_date
75
- last_key = last_key.beginning_of_week(ReportsKit.configuration.first_day_of_week) if granularity == 'week'
76
- last_key ||= Date.today.beginning_of_week(ReportsKit.configuration.first_day_of_week) if granularity == 'week'
91
+ if granularity == 'week'
92
+ first_key = first_key.beginning_of_week(ReportsKit.configuration.first_day_of_week)
93
+ last_key = last_key.beginning_of_week(ReportsKit.configuration.first_day_of_week)
94
+ elsif granularity == 'month'
95
+ first_key = first_key.beginning_of_month
96
+ last_key = last_key.beginning_of_month
97
+ end
77
98
 
78
99
  date = first_key
79
100
  populated_keys = []
80
- interval = granularity == 'week' ? 1.week : 1.day
101
+ interval = case granularity
102
+ when 'day' then 1.day
103
+ when 'month' then 1.month
104
+ else 1.week
105
+ end
81
106
  loop do
82
107
  populated_keys << date
83
108
  break if date >= last_key
@@ -111,9 +136,10 @@ module ReportsKit
111
136
 
112
137
  def self.dimension_to_dimension_ids_dimension_instances(dimension, dimension_ids)
113
138
  return nil unless dimension.instance_class
114
- dimension_instances = dimension.instance_class.where(id: dimension_ids.uniq)
139
+ primary_key = dimension.instance_class.primary_key
140
+ dimension_instances = dimension.instance_class.where(primary_key => dimension_ids.uniq)
115
141
  dimension_ids_dimension_instances = dimension_instances.map do |dimension_instance|
116
- [dimension_instance.id, dimension_instance]
142
+ [dimension_instance.send(primary_key), dimension_instance]
117
143
  end
118
144
  Hash[dimension_ids_dimension_instances]
119
145
  end
@@ -2,7 +2,7 @@ module ReportsKit
2
2
  module Reports
3
3
  class DimensionWithSeries
4
4
  DEFAULT_GRANULARITY = 'week'
5
- VALID_GRANULARITIES = %w(day week).freeze
5
+ VALID_GRANULARITIES = %w(day week month).freeze
6
6
  ADAPTER_NAMES_CLASSES = {
7
7
  'mysql2' => Adapters::Mysql,
8
8
  'postgresql' => Adapters::Postgresql
@@ -52,7 +52,11 @@ module ReportsKit
52
52
  elsif configured_by_association?
53
53
  inferred_settings_from_association[:column]
54
54
  elsif configured_by_column? && configured_by_time?
55
- granularity == 'day' ? day_expression : week_expression
55
+ case granularity
56
+ when 'day' then day_expression
57
+ when 'month' then month_expression
58
+ else week_expression
59
+ end
56
60
  elsif configured_by_column?
57
61
  column_expression
58
62
  else
@@ -131,6 +135,10 @@ module ReportsKit
131
135
  def week_expression
132
136
  adapter.truncate_to_week(column_expression)
133
137
  end
138
+
139
+ def month_expression
140
+ adapter.truncate_to_month(column_expression)
141
+ end
134
142
  end
135
143
  end
136
144
  end
@@ -17,13 +17,7 @@ module ReportsKit
17
17
  end
18
18
 
19
19
  def start_at_end_at
20
- @start_at_end_at ||= begin
21
- return unless valid?
22
- start_string, end_string = value.split(SEPARATOR)
23
- start_at = ReportsKit::Reports::Data::Utils.parse_date_string(start_string)
24
- end_at = ReportsKit::Reports::Data::Utils.parse_date_string(end_string)
25
- adjust_range_to_dimension(start_at, end_at)
26
- end
20
+ @start_at_end_at ||= valid? ? adjust_range_to_dimension(*Reports::Data::Utils.parse_date_range(value, type: Array)) : nil
27
21
  end
28
22
 
29
23
  def start_at
@@ -41,6 +35,10 @@ module ReportsKit
41
35
  start_at.beginning_of_week(ReportsKit.configuration.first_day_of_week),
42
36
  end_at.end_of_week(ReportsKit.configuration.first_day_of_week)
43
37
  ] if primary_dimension.granularity == 'week'
38
+ return [
39
+ start_at.beginning_of_month,
40
+ end_at.end_of_month
41
+ ] if primary_dimension.granularity == 'month'
44
42
  [start_at, end_at]
45
43
  end
46
44
 
@@ -0,0 +1,29 @@
1
+ module ReportsKit
2
+ module Reports
3
+ class GenerateAutocompleteMethodResults
4
+ attr_accessor :filter_key, :params, :properties
5
+
6
+ def initialize(filter_key, properties, params)
7
+ self.filter_key = filter_key
8
+ self.params = params
9
+ self.properties = properties
10
+ end
11
+
12
+ def perform
13
+ return unless properties[:ui_filters]
14
+ klass, method_name = ReportsKit::Utils.string_to_class_method(autocomplete_method, 'autocomplete_method')
15
+ klass.public_send(method_name, params, properties)
16
+ end
17
+
18
+ private
19
+
20
+ def filter_hash
21
+ properties[:ui_filters].find { |filter_params| filter_params.is_a?(Hash) && filter_params[:key] == filter_key }
22
+ end
23
+
24
+ def autocomplete_method
25
+ filter_hash[:autocomplete_method]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,10 +1,11 @@
1
1
  module ReportsKit
2
2
  module Reports
3
3
  class GenerateAutocompleteResults
4
- attr_accessor :params, :filter_key, :filter, :context_params, :context_record
4
+ attr_accessor :params, :properties, :filter_key, :filter, :context_params, :context_record
5
5
 
6
6
  def initialize(params, properties, context_record: nil)
7
7
  self.params = params
8
+ self.properties = properties
8
9
  self.context_params = params[:context_params]
9
10
  self.filter_key = params[:key]
10
11
  self.filter = Reports::PropertiesToFilter.new(properties, context_record: context_record).perform(filter_key)
@@ -12,6 +13,8 @@ module ReportsKit
12
13
  end
13
14
 
14
15
  def perform
16
+ autocomplete_method_results = Reports::GenerateAutocompleteMethodResults.new(filter_key, properties, params).perform
17
+ return autocomplete_method_results if autocomplete_method_results
15
18
  raise ArgumentError.new("Could not find a model for filter_key: '#{filter_key}'") unless model
16
19
  return autocomplete_results_method.call(params: params, context_record: context_record, relation: relation) if autocomplete_results_method
17
20
  results = filter.apply_contextual_filters(relation, context_params)
@@ -0,0 +1,11 @@
1
+ module ReportsKit
2
+ class Utils
3
+ def self.string_to_class_method(string, string_identifer)
4
+ class_name, method_name = string.split('.')
5
+ raise ArgumentError.new("The #{string_identifer} value should be a class method with a format of MyClass.my_method") unless class_name && method_name
6
+ klass = class_name.constantize
7
+ raise ArgumentError.new("The #{string_identifer} class (#{class_name}) does not respond to a method named \"#{method_name}\"") unless klass.respond_to?(method_name)
8
+ [klass, method_name]
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module ReportsKit
2
- VERSION = '0.5.0'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.add_development_dependency 'rspec', '~> 3'
21
21
  s.add_development_dependency 'database_cleaner', '~> 1'
22
22
  s.add_development_dependency 'factory_girl', '~> 4'
23
+ s.add_development_dependency 'groupdate', '~> 3'
23
24
  s.add_development_dependency 'pg', '>= 0.15'
24
25
  s.add_development_dependency 'pry', '~> 0'
25
26
  s.add_development_dependency 'pry-byebug', '~> 1'
@@ -242,3 +242,13 @@
242
242
  - key: opened_at
243
243
  - key: repo
244
244
  order: count desc
245
+ - data_method: ExampleDataMethods.issues_by_opened_at
246
+ - data_method: ExampleDataMethods.issues_by_opened_at_and_repo
247
+ - data_method: ExampleDataMethods.issues_by_opened_at_with_filters
248
+ - data_method: ExampleDataMethods.issues_by_opened_at_with_filters
249
+ ui_filters:
250
+ state: open
251
+ - data_method: ExampleDataMethods.issues_by_opened_at_with_filters
252
+ ui_filters:
253
+ state: open
254
+ format: table
@@ -1064,3 +1064,153 @@
1064
1064
  :xPadding: 8
1065
1065
  :yPadding: 7
1066
1066
  :type: bar
1067
+ - :chart_data:
1068
+ :labels:
1069
+ - Dec 13, '09
1070
+ - Dec 20, '09
1071
+ - Dec 27, '09
1072
+ :datasets:
1073
+ - :data:
1074
+ - 1
1075
+ - 0
1076
+ - 1
1077
+ :backgroundColor: "#1f77b4"
1078
+ :borderColor: "#1f77b4"
1079
+ :options:
1080
+ :scales:
1081
+ :xAxes:
1082
+ - :gridLines:
1083
+ :display: false
1084
+ :barPercentage: 0.9
1085
+ :categoryPercentage: 0.9
1086
+ :yAxes:
1087
+ - :ticks:
1088
+ :beginAtZero: true
1089
+ :legend:
1090
+ :labels:
1091
+ :usePointStyle: true
1092
+ :maintainAspectRatio: false
1093
+ :tooltips:
1094
+ :xPadding: 8
1095
+ :yPadding: 7
1096
+ :type: bar
1097
+ - :chart_data:
1098
+ :labels:
1099
+ - Dec 13, '09
1100
+ - Dec 20, '09
1101
+ - Dec 27, '09
1102
+ :datasets:
1103
+ - :label: foo/bar1
1104
+ :data:
1105
+ - 1
1106
+ - 0
1107
+ - 1
1108
+ :backgroundColor: "#1f77b4"
1109
+ :borderColor: "#1f77b4"
1110
+ :options:
1111
+ :scales:
1112
+ :xAxes:
1113
+ - :gridLines:
1114
+ :display: false
1115
+ :barPercentage: 0.9
1116
+ :categoryPercentage: 0.9
1117
+ :yAxes:
1118
+ - :ticks:
1119
+ :beginAtZero: true
1120
+ :legend:
1121
+ :labels:
1122
+ :usePointStyle: true
1123
+ :maintainAspectRatio: false
1124
+ :tooltips:
1125
+ :xPadding: 8
1126
+ :yPadding: 7
1127
+ :type: bar
1128
+ - :chart_data:
1129
+ :labels:
1130
+ - Dec 13, '09
1131
+ - Dec 20, '09
1132
+ - Dec 27, '09
1133
+ :datasets:
1134
+ - :data:
1135
+ - 1
1136
+ - 0
1137
+ - 1
1138
+ :backgroundColor: "#1f77b4"
1139
+ :borderColor: "#1f77b4"
1140
+ :options:
1141
+ :scales:
1142
+ :xAxes:
1143
+ - :gridLines:
1144
+ :display: false
1145
+ :barPercentage: 0.9
1146
+ :categoryPercentage: 0.9
1147
+ :yAxes:
1148
+ - :ticks:
1149
+ :beginAtZero: true
1150
+ :legend:
1151
+ :labels:
1152
+ :usePointStyle: true
1153
+ :maintainAspectRatio: false
1154
+ :tooltips:
1155
+ :xPadding: 8
1156
+ :yPadding: 7
1157
+ :type: bar
1158
+ - :chart_data:
1159
+ :labels:
1160
+ - Dec 13, '09
1161
+ :datasets:
1162
+ - :data:
1163
+ - 1
1164
+ :backgroundColor: "#1f77b4"
1165
+ :borderColor: "#1f77b4"
1166
+ :options:
1167
+ :scales:
1168
+ :xAxes:
1169
+ - :gridLines:
1170
+ :display: false
1171
+ :barPercentage: 0.9
1172
+ :categoryPercentage: 0.9
1173
+ :yAxes:
1174
+ - :ticks:
1175
+ :beginAtZero: true
1176
+ :legend:
1177
+ :labels:
1178
+ :usePointStyle: true
1179
+ :maintainAspectRatio: false
1180
+ :tooltips:
1181
+ :xPadding: 8
1182
+ :yPadding: 7
1183
+ :type: bar
1184
+ - :chart_data:
1185
+ :labels:
1186
+ - Date
1187
+ - Dec 13, '09
1188
+ :datasets:
1189
+ - :data:
1190
+ - Issue count
1191
+ - 1
1192
+ :backgroundColor: "#1f77b4"
1193
+ :borderColor: "#1f77b4"
1194
+ :options:
1195
+ :scales:
1196
+ :xAxes:
1197
+ - :gridLines:
1198
+ :display: false
1199
+ :barPercentage: 0.9
1200
+ :categoryPercentage: 0.9
1201
+ :yAxes:
1202
+ - :ticks:
1203
+ :beginAtZero: true
1204
+ :legend:
1205
+ :labels:
1206
+ :usePointStyle: true
1207
+ :maintainAspectRatio: false
1208
+ :tooltips:
1209
+ :xPadding: 8
1210
+ :yPadding: 7
1211
+ :type: table
1212
+ :table_data:
1213
+ - - Date
1214
+ - Issue count
1215
+ - - Dec 13, '09
1216
+ - 1
@@ -274,6 +274,36 @@ describe ReportsKit::Reports::Data::Generate do
274
274
  })
275
275
  end
276
276
  end
277
+
278
+ context 'with month granularity' do
279
+ let(:properties) do
280
+ {
281
+ measure: 'issue',
282
+ dimensions: [{ key: 'opened_at', granularity: 'month' }]
283
+ }
284
+ end
285
+ let!(:issues) do
286
+ [
287
+ create(:issue, repo: repo, opened_at: now - 2.days),
288
+ create(:issue, repo: repo, opened_at: now)
289
+ ]
290
+ end
291
+
292
+ it 'returns the data' do
293
+ expect(chart_data).to eq({
294
+ labels: [
295
+ ReportsKit::Reports::Data::Utils.format_display_time(issues.first.opened_at.beginning_of_month),
296
+ ReportsKit::Reports::Data::Utils.format_display_time(issues.last.opened_at.beginning_of_month)
297
+ ],
298
+ datasets: [
299
+ {
300
+ label: 'Issues',
301
+ data: [1, 1]
302
+ }
303
+ ]
304
+ })
305
+ end
306
+ end
277
307
  end
278
308
 
279
309
  context 'with an association dimension' do
@@ -23,7 +23,7 @@ describe ReportsKit::Reports::GenerateAutocompleteResults do
23
23
  end
24
24
 
25
25
  it 'returns the results' do
26
- expect(subject).to eq([
26
+ expect(subject).to match_array([
27
27
  { id: repo.id, text: repo.to_s },
28
28
  { id: repo2.id, text: repo2.to_s }
29
29
  ])
@@ -42,7 +42,7 @@ describe ReportsKit::Reports::GenerateAutocompleteResults do
42
42
  end
43
43
 
44
44
  it 'returns the results' do
45
- expect(subject).to eq([
45
+ expect(subject).to match_array([
46
46
  { id: repo.id, text: repo.to_s }
47
47
  ])
48
48
  end
@@ -59,7 +59,7 @@ describe ReportsKit::Reports::GenerateAutocompleteResults do
59
59
  end
60
60
 
61
61
  it 'returns the results' do
62
- expect(subject).to eq([
62
+ expect(subject).to match_array([
63
63
  { id: repo.id, text: repo.to_s },
64
64
  { id: repo2.id, text: repo2.to_s }
65
65
  ])
@@ -1,6 +1,7 @@
1
1
  require 'reports_kit'
2
2
 
3
3
  require 'database_cleaner'
4
+ require 'groupdate'
4
5
  require 'pry'
5
6
  require 'pry-byebug'
6
7
  require 'timecop'
@@ -35,6 +36,7 @@ Dir.glob("#{directory}/support/models/**/*.rb") { |file| require file }
35
36
  Dir.glob("#{directory}/factories/*.rb") { |file| require file }
36
37
 
37
38
  require 'support/config'
39
+ require 'support/example_data_methods'
38
40
  require 'support/schema'
39
41
 
40
42
  RSpec.configure do |config|
@@ -0,0 +1,25 @@
1
+ class ExampleDataMethods
2
+ def self.issues_by_opened_at(properties)
3
+ Issue.group_by_week(:opened_at).count.map { |date, count| [format_date(date), count] }
4
+ end
5
+
6
+ def self.issues_by_opened_at_and_repo(properties)
7
+ Issue.group_by_week(:opened_at).joins(:repo).group('repos.full_name').count.map do |(date, name), count|
8
+ [[format_date(date), name], count]
9
+ end
10
+ end
11
+
12
+ def self.issues_by_opened_at_with_filters(properties)
13
+ format = properties[:format]
14
+ ui_filters = properties[:ui_filters]
15
+ issues = Issue.group_by_week(:opened_at)
16
+ issues = issues.where(state: ui_filters[:state]) if ui_filters.try(:[], :state).present?
17
+ dates_issue_counts = issues.count.map { |date, count| [format_date(date), count] }
18
+ return dates_issue_counts unless format == 'table'
19
+ [['Date', 'Issue count']] + dates_issue_counts
20
+ end
21
+
22
+ def self.format_date(date)
23
+ date.strftime('%b %-d, \'%y')
24
+ end
25
+ 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.5.0
4
+ version: 0.7.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-18 00:00:00.000000000 Z
11
+ date: 2018-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: groupdate
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: pg
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -226,6 +240,7 @@ files:
226
240
  - lib/reports_kit/reports/data/aggregate_composite.rb
227
241
  - lib/reports_kit/reports/data/aggregate_one_dimension.rb
228
242
  - lib/reports_kit/reports/data/aggregate_two_dimensions.rb
243
+ - lib/reports_kit/reports/data/chart_data_for_data_method.rb
229
244
  - lib/reports_kit/reports/data/chart_options.rb
230
245
  - lib/reports_kit/reports/data/format_one_dimension.rb
231
246
  - lib/reports_kit/reports/data/format_table.rb
@@ -246,6 +261,7 @@ files:
246
261
  - lib/reports_kit/reports/filter_types/records.rb
247
262
  - lib/reports_kit/reports/filter_types/string.rb
248
263
  - lib/reports_kit/reports/filter_with_series.rb
264
+ - lib/reports_kit/reports/generate_autocomplete_method_results.rb
249
265
  - lib/reports_kit/reports/generate_autocomplete_results.rb
250
266
  - lib/reports_kit/reports/inferrable_configuration.rb
251
267
  - lib/reports_kit/reports/model_settings.rb
@@ -253,6 +269,7 @@ files:
253
269
  - lib/reports_kit/reports/properties_to_filter.rb
254
270
  - lib/reports_kit/reports/series.rb
255
271
  - lib/reports_kit/reports_controller.rb
272
+ - lib/reports_kit/utils.rb
256
273
  - lib/reports_kit/value.rb
257
274
  - lib/reports_kit/version.rb
258
275
  - reports_kit.gemspec
@@ -274,6 +291,7 @@ files:
274
291
  - spec/reports_kit/reports/generate_autocomplete_results_spec.rb
275
292
  - spec/spec_helper.rb
276
293
  - spec/support/config.rb
294
+ - spec/support/example_data_methods.rb
277
295
  - spec/support/factory_girl.rb
278
296
  - spec/support/helpers.rb
279
297
  - spec/support/models/issue.rb