reports_kit 0.1.0 → 0.2.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 +4 -4
- data/README.md +6 -5
- data/app/assets/javascripts/reports_kit/lib/chart.js +33 -8
- data/app/assets/javascripts/reports_kit/lib/report.js +27 -26
- data/app/assets/javascripts/reports_kit/lib/table.js +58 -0
- data/app/assets/javascripts/reports_kit/vendor/jquery.tablesorter.min.js +4 -0
- data/app/assets/stylesheets/reports_kit/reports.css.sass +20 -0
- data/config/initializers/mime_types.rb +1 -0
- data/docs/dimensions.md +34 -26
- data/docs/display_options.md +15 -12
- data/docs/filters.md +2 -2
- data/docs/measures.md +4 -3
- data/gemfiles/mysql.gemfile.lock +14 -1
- data/gemfiles/postgresql.gemfile.lock +14 -1
- data/lib/reports_kit.rb +15 -0
- data/lib/reports_kit/cache.rb +37 -0
- data/lib/reports_kit/configuration.rb +13 -1
- data/lib/reports_kit/helper.rb +54 -3
- data/lib/reports_kit/model_configuration.rb +6 -1
- data/lib/reports_kit/order.rb +33 -0
- data/lib/reports_kit/relative_time.rb +42 -0
- data/lib/reports_kit/report_builder.rb +34 -15
- data/lib/reports_kit/reports/abstract_measure.rb +9 -0
- data/lib/reports_kit/reports/adapters/mysql.rb +8 -1
- data/lib/reports_kit/reports/adapters/postgresql.rb +8 -1
- data/lib/reports_kit/reports/composite_measure.rb +43 -0
- data/lib/reports_kit/reports/data/chart_options.rb +5 -0
- data/lib/reports_kit/reports/data/composite_aggregation.rb +96 -0
- data/lib/reports_kit/reports/data/entity.rb +7 -0
- data/lib/reports_kit/reports/data/format_one_dimension.rb +120 -0
- data/lib/reports_kit/reports/data/format_two_dimensions.rb +141 -0
- data/lib/reports_kit/reports/data/generate.rb +72 -25
- data/lib/reports_kit/reports/data/generate_for_properties.rb +75 -0
- data/lib/reports_kit/reports/data/one_dimension.rb +15 -49
- data/lib/reports_kit/reports/data/populate_one_dimension.rb +36 -0
- data/lib/reports_kit/reports/data/populate_two_dimensions.rb +104 -0
- data/lib/reports_kit/reports/data/two_dimensions.rb +15 -110
- data/lib/reports_kit/reports/data/utils.rb +77 -12
- data/lib/reports_kit/reports/data/value.rb +7 -0
- data/lib/reports_kit/reports/dimension.rb +4 -110
- data/lib/reports_kit/reports/dimension_with_measure.rb +137 -0
- data/lib/reports_kit/reports/filter.rb +5 -64
- data/lib/reports_kit/reports/filter_types/base.rb +1 -1
- data/lib/reports_kit/reports/filter_types/boolean.rb +9 -7
- data/lib/reports_kit/reports/filter_types/datetime.rb +7 -5
- data/lib/reports_kit/reports/filter_types/number.rb +2 -0
- data/lib/reports_kit/reports/filter_with_measure.rb +84 -0
- data/lib/reports_kit/reports/generate_autocomplete_results.rb +1 -1
- data/lib/reports_kit/reports/inferrable_configuration.rb +32 -13
- data/lib/reports_kit/reports/measure.rb +48 -12
- data/lib/reports_kit/reports_controller.rb +42 -3
- data/lib/reports_kit/version.rb +1 -1
- data/reports_kit.gemspec +2 -0
- data/spec/fixtures/generate_inputs.yml +146 -21
- data/spec/fixtures/generate_outputs.yml +768 -17
- data/spec/reports_kit/relative_time_spec.rb +29 -0
- data/spec/reports_kit/report_builder_spec.rb +28 -0
- data/spec/reports_kit/reports/data/generate_spec.rb +614 -27
- data/spec/reports_kit/reports/dimension_with_measure_spec.rb +69 -0
- data/spec/reports_kit/reports/{filter_spec.rb → filter_with_measure_spec.rb} +4 -3
- data/spec/spec_helper.rb +7 -2
- data/spec/support/config.rb +11 -0
- data/spec/support/helpers.rb +3 -3
- data/spec/support/models/issue.rb +7 -0
- metadata +53 -4
- data/spec/reports_kit/reports/dimension_spec.rb +0 -54
data/docs/filters.md
CHANGED
@@ -60,7 +60,7 @@ measure:
|
|
60
60
|
filters:
|
61
61
|
- key: is_on_time
|
62
62
|
criteria:
|
63
|
-
|
63
|
+
value: true
|
64
64
|
dimensions:
|
65
65
|
- carrier
|
66
66
|
```
|
@@ -139,7 +139,7 @@ measure:
|
|
139
139
|
filters:
|
140
140
|
- key: was_delayed
|
141
141
|
criteria:
|
142
|
-
|
142
|
+
value: true
|
143
143
|
dimensions:
|
144
144
|
- carrier
|
145
145
|
```
|
data/docs/measures.md
CHANGED
@@ -5,8 +5,9 @@ The measure is what is being counted (or aggregated in another way). You can use
|
|
5
5
|
For example, say we have a `Flight` model with a `flight_at` datetime column. We can chart the number of flights over time:
|
6
6
|
|
7
7
|
```yaml
|
8
|
-
measure:
|
9
|
-
|
10
|
-
|
8
|
+
measure:
|
9
|
+
key: flight
|
10
|
+
dimensions:
|
11
|
+
- flight_at
|
11
12
|
```
|
12
13
|
[<img src="images/flights_by_flight_at.png?raw=true" width="500" />](images/flights_by_flight_at.png?raw=true)
|
data/gemfiles/mysql.gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
reports_kit (0.0
|
4
|
+
reports_kit (0.2.0)
|
5
5
|
rails (>= 3)
|
6
|
+
spreadsheet (>= 1.1)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -50,9 +51,14 @@ GEM
|
|
50
51
|
thor (>= 0.14.0)
|
51
52
|
arel (8.0.0)
|
52
53
|
builder (3.2.3)
|
54
|
+
byebug (2.7.0)
|
55
|
+
columnize (~> 0.3)
|
56
|
+
debugger-linecache (~> 1.2)
|
53
57
|
coderay (1.1.1)
|
58
|
+
columnize (0.9.0)
|
54
59
|
concurrent-ruby (1.0.5)
|
55
60
|
database_cleaner (1.6.1)
|
61
|
+
debugger-linecache (1.2.0)
|
56
62
|
diff-lcs (1.3)
|
57
63
|
erubi (1.6.1)
|
58
64
|
factory_girl (4.8.0)
|
@@ -79,6 +85,9 @@ GEM
|
|
79
85
|
coderay (~> 1.1.0)
|
80
86
|
method_source (~> 0.8.1)
|
81
87
|
slop (~> 3.4)
|
88
|
+
pry-byebug (1.3.3)
|
89
|
+
byebug (~> 2.7)
|
90
|
+
pry (~> 0.10)
|
82
91
|
rack (2.0.3)
|
83
92
|
rack-test (0.6.3)
|
84
93
|
rack (>= 1.0)
|
@@ -119,7 +128,10 @@ GEM
|
|
119
128
|
diff-lcs (>= 1.2.0, < 2.0)
|
120
129
|
rspec-support (~> 3.6.0)
|
121
130
|
rspec-support (3.6.0)
|
131
|
+
ruby-ole (1.2.12.1)
|
122
132
|
slop (3.6.0)
|
133
|
+
spreadsheet (1.1.4)
|
134
|
+
ruby-ole (>= 1.0)
|
123
135
|
sprockets (3.7.1)
|
124
136
|
concurrent-ruby (~> 1.0)
|
125
137
|
rack (> 1, < 3)
|
@@ -146,6 +158,7 @@ DEPENDENCIES
|
|
146
158
|
mysql2
|
147
159
|
pg (>= 0.15)
|
148
160
|
pry (~> 0)
|
161
|
+
pry-byebug (~> 1)
|
149
162
|
reports_kit!
|
150
163
|
rspec (~> 3)
|
151
164
|
timecop (~> 0)
|
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
reports_kit (0.0
|
4
|
+
reports_kit (0.2.0)
|
5
5
|
rails (>= 3)
|
6
|
+
spreadsheet (>= 1.1)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -50,9 +51,14 @@ GEM
|
|
50
51
|
thor (>= 0.14.0)
|
51
52
|
arel (8.0.0)
|
52
53
|
builder (3.2.3)
|
54
|
+
byebug (2.7.0)
|
55
|
+
columnize (~> 0.3)
|
56
|
+
debugger-linecache (~> 1.2)
|
53
57
|
coderay (1.1.1)
|
58
|
+
columnize (0.9.0)
|
54
59
|
concurrent-ruby (1.0.5)
|
55
60
|
database_cleaner (1.6.1)
|
61
|
+
debugger-linecache (1.2.0)
|
56
62
|
diff-lcs (1.3)
|
57
63
|
erubi (1.6.1)
|
58
64
|
factory_girl (4.8.0)
|
@@ -78,6 +84,9 @@ GEM
|
|
78
84
|
coderay (~> 1.1.0)
|
79
85
|
method_source (~> 0.8.1)
|
80
86
|
slop (~> 3.4)
|
87
|
+
pry-byebug (1.3.3)
|
88
|
+
byebug (~> 2.7)
|
89
|
+
pry (~> 0.10)
|
81
90
|
rack (2.0.3)
|
82
91
|
rack-test (0.6.3)
|
83
92
|
rack (>= 1.0)
|
@@ -118,7 +127,10 @@ GEM
|
|
118
127
|
diff-lcs (>= 1.2.0, < 2.0)
|
119
128
|
rspec-support (~> 3.6.0)
|
120
129
|
rspec-support (3.6.0)
|
130
|
+
ruby-ole (1.2.12.1)
|
121
131
|
slop (3.6.0)
|
132
|
+
spreadsheet (1.1.4)
|
133
|
+
ruby-ole (>= 1.0)
|
122
134
|
sprockets (3.7.1)
|
123
135
|
concurrent-ruby (~> 1.0)
|
124
136
|
rack (> 1, < 3)
|
@@ -144,6 +156,7 @@ DEPENDENCIES
|
|
144
156
|
factory_girl (~> 4)
|
145
157
|
pg
|
146
158
|
pry (~> 0)
|
159
|
+
pry-byebug (~> 1)
|
147
160
|
reports_kit!
|
148
161
|
rspec (~> 3)
|
149
162
|
timecop (~> 0)
|
data/lib/reports_kit.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'rails/all'
|
2
2
|
|
3
3
|
require 'reports_kit/base_controller'
|
4
|
+
require 'reports_kit/cache'
|
4
5
|
require 'reports_kit/configuration'
|
5
6
|
require 'reports_kit/engine'
|
6
7
|
require 'reports_kit/helper'
|
7
8
|
require 'reports_kit/model'
|
8
9
|
require 'reports_kit/model_configuration'
|
10
|
+
require 'reports_kit/order'
|
11
|
+
require 'reports_kit/relative_time'
|
9
12
|
require 'reports_kit/report_builder'
|
10
13
|
require 'reports_kit/resources_controller'
|
11
14
|
require 'reports_kit/reports_controller'
|
@@ -15,10 +18,18 @@ require 'reports_kit/reports/adapters/mysql'
|
|
15
18
|
require 'reports_kit/reports/adapters/postgresql'
|
16
19
|
|
17
20
|
require 'reports_kit/reports/data/chart_options'
|
21
|
+
require 'reports_kit/reports/data/composite_aggregation'
|
22
|
+
require 'reports_kit/reports/data/entity'
|
23
|
+
require 'reports_kit/reports/data/format_one_dimension'
|
24
|
+
require 'reports_kit/reports/data/format_two_dimensions'
|
18
25
|
require 'reports_kit/reports/data/generate'
|
26
|
+
require 'reports_kit/reports/data/generate_for_properties'
|
19
27
|
require 'reports_kit/reports/data/one_dimension'
|
28
|
+
require 'reports_kit/reports/data/populate_one_dimension'
|
29
|
+
require 'reports_kit/reports/data/populate_two_dimensions'
|
20
30
|
require 'reports_kit/reports/data/two_dimensions'
|
21
31
|
require 'reports_kit/reports/data/utils'
|
32
|
+
require 'reports_kit/reports/data/value'
|
22
33
|
|
23
34
|
require 'reports_kit/reports/filter_types/base'
|
24
35
|
require 'reports_kit/reports/filter_types/boolean'
|
@@ -27,8 +38,12 @@ require 'reports_kit/reports/filter_types/number'
|
|
27
38
|
require 'reports_kit/reports/filter_types/records'
|
28
39
|
require 'reports_kit/reports/filter_types/string'
|
29
40
|
|
41
|
+
require 'reports_kit/reports/abstract_measure'
|
42
|
+
require 'reports_kit/reports/composite_measure'
|
30
43
|
require 'reports_kit/reports/dimension'
|
44
|
+
require 'reports_kit/reports/dimension_with_measure'
|
31
45
|
require 'reports_kit/reports/filter'
|
46
|
+
require 'reports_kit/reports/filter_with_measure'
|
32
47
|
require 'reports_kit/reports/generate_autocomplete_results'
|
33
48
|
require 'reports_kit/reports/inferrable_configuration'
|
34
49
|
require 'reports_kit/reports/measure'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ReportsKit
|
2
|
+
class Cache
|
3
|
+
CACHE_PREFIX = 'reports_kit:reports:'
|
4
|
+
|
5
|
+
def self.get(properties, context_record)
|
6
|
+
return unless store
|
7
|
+
key = self.key(properties, context_record)
|
8
|
+
json_string = store.get(key)
|
9
|
+
return if json_string.blank?
|
10
|
+
ActiveSupport::JSON.decode(json_string)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.set(properties, context_record, data)
|
14
|
+
return unless store
|
15
|
+
key = self.key(properties, context_record)
|
16
|
+
json_string = ActiveSupport::JSON.encode(data)
|
17
|
+
store.setex(key, duration, json_string)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def self.key(properties, context_record)
|
23
|
+
key = properties.to_json
|
24
|
+
key += "#{context_record.class}#{context_record.id}" if context_record
|
25
|
+
key = Digest::MD5.hexdigest(key)
|
26
|
+
"#{CACHE_PREFIX}#{key}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.duration
|
30
|
+
@duration ||= ReportsKit.configuration.cache_duration
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.store
|
34
|
+
@store ||= ReportsKit.configuration.cache_store
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,10 +1,22 @@
|
|
1
1
|
module ReportsKit
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :cache_duration, :cache_store,
|
4
|
+
:context_params_method, :context_record_method, :custom_methods, :first_day_of_week
|
4
5
|
|
5
6
|
def initialize
|
7
|
+
self.cache_duration = 5.minutes
|
8
|
+
self.cache_store = nil
|
9
|
+
self.context_params_method = nil
|
6
10
|
self.context_record_method = nil
|
11
|
+
self.custom_methods = {}
|
7
12
|
self.first_day_of_week = :sunday
|
8
13
|
end
|
14
|
+
|
15
|
+
def custom_method(method_name)
|
16
|
+
return if method_name.blank?
|
17
|
+
method = custom_methods[method_name.to_sym]
|
18
|
+
raise ArgumentError.new("A method named '#{method_name}' is not defined") unless method
|
19
|
+
method
|
20
|
+
end
|
9
21
|
end
|
10
22
|
end
|
data/lib/reports_kit/helper.rb
CHANGED
@@ -1,19 +1,70 @@
|
|
1
1
|
module ReportsKit
|
2
2
|
module Helper
|
3
|
+
ACTION_KEYS_METHODS = {
|
4
|
+
'export_csv' => :export_csv_element,
|
5
|
+
'export_xls' => :export_xls_element
|
6
|
+
}
|
7
|
+
|
3
8
|
def render_report(properties, &block)
|
4
9
|
raise ArgumentError.new('`properties` must be a Hash or String') if properties.blank?
|
5
10
|
if properties.is_a?(String)
|
6
11
|
path = Rails.root.join('config', 'reports_kit', 'reports', "#{properties}.yml")
|
7
12
|
properties = YAML.load_file(path)
|
8
13
|
end
|
9
|
-
builder = ReportsKit::ReportBuilder.new(properties)
|
10
|
-
|
14
|
+
builder = ReportsKit::ReportBuilder.new(properties, additional_params: additional_params)
|
15
|
+
path = reports_kit.reports_kit_reports_path({ format: 'json' }.merge(additional_params))
|
16
|
+
content_tag :div, nil, class: 'reports_kit_report form-inline', data: { properties: builder.properties, path: path } do
|
17
|
+
elements = []
|
11
18
|
if block_given?
|
12
|
-
form_tag
|
19
|
+
elements << form_tag(path, method: 'get', class: 'reports_kit_report_form') do
|
13
20
|
capture(builder, &block)
|
14
21
|
end
|
15
22
|
end
|
23
|
+
elements << content_tag(:div, nil, class: 'reports_kit_visualization')
|
24
|
+
action_elements = action_elements_for_properties(properties)
|
25
|
+
if action_elements
|
26
|
+
elements << content_tag(:div, nil, class: 'reports_kit_actions') do
|
27
|
+
action_elements.map { |element| concat(element) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
elements.join.html_safe
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def additional_params
|
37
|
+
@additional_params ||= begin
|
38
|
+
context_params_method = ReportsKit.configuration.context_params_method
|
39
|
+
return {} unless context_params_method
|
40
|
+
context_params = instance_eval(&context_params_method)
|
41
|
+
{ context_params: context_params }
|
16
42
|
end
|
17
43
|
end
|
44
|
+
|
45
|
+
def action_elements_for_properties(properties)
|
46
|
+
return if properties['actions'].blank?
|
47
|
+
properties['actions'].map do |action|
|
48
|
+
element_method = ACTION_KEYS_METHODS[action]
|
49
|
+
raise ArgumentError.new("Invalid action: #{action}") unless element_method
|
50
|
+
send(element_method)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def export_csv_element
|
55
|
+
data = {
|
56
|
+
role: 'reports_kit_export_button',
|
57
|
+
path: reports_kit.reports_kit_reports_path({ format: 'csv' }.merge(additional_params))
|
58
|
+
}
|
59
|
+
link_to('Download CSV', '#', class: 'btn btn-primary', data: data)
|
60
|
+
end
|
61
|
+
|
62
|
+
def export_xls_element
|
63
|
+
data = {
|
64
|
+
role: 'reports_kit_export_button',
|
65
|
+
path: reports_kit.reports_kit_reports_path({ format: 'xls' }.merge(additional_params))
|
66
|
+
}
|
67
|
+
link_to('Download Excel', '#', class: 'btn btn-primary', data: data)
|
68
|
+
end
|
18
69
|
end
|
19
70
|
end
|
@@ -1,13 +1,18 @@
|
|
1
1
|
module ReportsKit
|
2
2
|
class ModelConfiguration
|
3
|
-
attr_accessor :dimensions, :filters, :autocomplete_scopes
|
3
|
+
attr_accessor :aggregations, :dimensions, :filters, :autocomplete_scopes
|
4
4
|
|
5
5
|
def initialize
|
6
|
+
self.aggregations = []
|
6
7
|
self.dimensions = []
|
7
8
|
self.filters = []
|
8
9
|
self.autocomplete_scopes = []
|
9
10
|
end
|
10
11
|
|
12
|
+
def aggregation(key, expression, properties={})
|
13
|
+
aggregations << { key: key.to_s, expression: expression }.merge(properties).symbolize_keys
|
14
|
+
end
|
15
|
+
|
11
16
|
def dimension(key, properties)
|
12
17
|
dimensions << { key: key.to_s }.merge(properties).symbolize_keys
|
13
18
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ReportsKit
|
2
|
+
class Order
|
3
|
+
attr_accessor :relation, :field, :direction
|
4
|
+
|
5
|
+
VALID_RELATIONS = %w(count dimension1 dimension2)
|
6
|
+
VALID_FIELDS = [nil, 'label']
|
7
|
+
VALID_DIRECTIONS = %w(asc desc)
|
8
|
+
|
9
|
+
def initialize(relation, field, direction)
|
10
|
+
self.relation = relation
|
11
|
+
self.field = field
|
12
|
+
self.direction = direction
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse(string)
|
16
|
+
string ||= ''
|
17
|
+
field_expression, direction = string.to_s.split(/\s+/)
|
18
|
+
relation, field = (field_expression || '').split('.')
|
19
|
+
|
20
|
+
relation = relation.presence
|
21
|
+
field = field.presence
|
22
|
+
direction = direction.presence || 'asc'
|
23
|
+
|
24
|
+
relation = relation.to_i if relation =~ /^\d+$/
|
25
|
+
|
26
|
+
raise ArgumentError.new("Invalid relation: #{relation}") unless VALID_RELATIONS.include?(relation) || relation.is_a?(Fixnum)
|
27
|
+
raise ArgumentError.new("Invalid field: #{field}") unless VALID_FIELDS.include?(field)
|
28
|
+
raise ArgumentError.new("Invalid direction: #{direction}") unless VALID_DIRECTIONS.include?(direction)
|
29
|
+
|
30
|
+
new(relation, field, direction)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ReportsKit
|
2
|
+
class RelativeTime
|
3
|
+
LETTERS_DURATION_METHODS = {
|
4
|
+
'y' => :years,
|
5
|
+
'M' => :months,
|
6
|
+
'w' => :weeks,
|
7
|
+
'd' => :days,
|
8
|
+
'h' => :hours,
|
9
|
+
'm' => :minutes,
|
10
|
+
's' => :seconds
|
11
|
+
}
|
12
|
+
LETTERS = LETTERS_DURATION_METHODS.keys.join
|
13
|
+
|
14
|
+
def self.parse(string, prevent_exceptions: false)
|
15
|
+
return Time.zone.now if string == 'now'
|
16
|
+
original_string = string
|
17
|
+
string = string.to_s.strip
|
18
|
+
is_negative = string[0, 1] == '-'
|
19
|
+
string = string[1..-1] if is_negative
|
20
|
+
|
21
|
+
result_string = is_negative ? '-' : ''
|
22
|
+
result_durations = []
|
23
|
+
|
24
|
+
string.scan(/(\d+)([#{LETTERS}]?)/) do |number, letter|
|
25
|
+
result_string += "#{number}#{letter}"
|
26
|
+
duration_method = LETTERS_DURATION_METHODS[letter]
|
27
|
+
unless duration_method
|
28
|
+
return if prevent_exceptions
|
29
|
+
raise ArgumentError.new("Invalid duration letter: #{letter.inspect}")
|
30
|
+
end
|
31
|
+
result_durations << number.to_i.public_send(duration_method)
|
32
|
+
end
|
33
|
+
|
34
|
+
if result_string == '-' || result_string != original_string.to_s.strip
|
35
|
+
return if prevent_exceptions
|
36
|
+
raise ArgumentError.new("Invalid time duration: #{original_string.inspect}")
|
37
|
+
end
|
38
|
+
duration = result_durations.reduce(&:+)
|
39
|
+
is_negative ? duration.ago : duration.from_now
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -2,15 +2,18 @@ module ReportsKit
|
|
2
2
|
class ReportBuilder
|
3
3
|
include ActionView::Helpers
|
4
4
|
|
5
|
-
|
5
|
+
DEFAULT_DATE_RANGE_VALUE = ['-2M', 'now']
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
attr_accessor :properties, :additional_params
|
8
|
+
|
9
|
+
def initialize(properties, additional_params: nil)
|
10
|
+
self.properties = properties.deep_symbolize_keys
|
11
|
+
self.additional_params = additional_params
|
9
12
|
end
|
10
13
|
|
11
14
|
def check_box(filter_key, options={})
|
12
15
|
filter = validate_filter!(filter_key)
|
13
|
-
checked = filter.
|
16
|
+
checked = filter.normalized_properties[:criteria][:value] == 'true'
|
14
17
|
check_box_tag(filter_key, '1', checked, options)
|
15
18
|
end
|
16
19
|
|
@@ -18,13 +21,17 @@ module ReportsKit
|
|
18
21
|
filter = validate_filter!(filter_key)
|
19
22
|
defaults = { class: 'form-control input-sm date_range_picker' }
|
20
23
|
options = defaults.deep_merge(options)
|
21
|
-
|
24
|
+
value = filter.normalized_properties[:criteria][:value].presence
|
25
|
+
value ||= default_date_range_value
|
26
|
+
text_field_tag(filter_key, value, options)
|
22
27
|
end
|
23
28
|
|
24
29
|
def multi_autocomplete(filter_key, options={})
|
25
30
|
validate_filter!(filter_key)
|
31
|
+
filter = measure_filters.find { |f| f.key == filter_key.to_s }
|
26
32
|
reports_kit_path = Rails.application.routes.url_helpers.reports_kit_path
|
27
|
-
path = "#{reports_kit_path}reports_kit/resources/measures/#{measure.key}/filters/#{filter_key}/autocomplete"
|
33
|
+
path = "#{reports_kit_path}reports_kit/resources/measures/#{filter.measure.key}/filters/#{filter_key}/autocomplete?"
|
34
|
+
path += additional_params.to_query if additional_params.present?
|
28
35
|
scope = options.delete(:scope)
|
29
36
|
params = {}
|
30
37
|
params[:scope] = scope if scope.present?
|
@@ -46,7 +53,7 @@ module ReportsKit
|
|
46
53
|
filter = validate_filter!(filter_key)
|
47
54
|
defaults = { class: 'form-control input-sm' }
|
48
55
|
options = defaults.deep_merge(options)
|
49
|
-
text_field_tag(filter_key, filter.
|
56
|
+
text_field_tag(filter_key, filter.normalized_properties[:criteria][:value], options)
|
50
57
|
end
|
51
58
|
|
52
59
|
private
|
@@ -59,18 +66,30 @@ module ReportsKit
|
|
59
66
|
end
|
60
67
|
|
61
68
|
def filters
|
62
|
-
|
69
|
+
ui_filters + measure_filters
|
70
|
+
end
|
71
|
+
|
72
|
+
def measure_filters
|
73
|
+
measures.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
|
63
81
|
end
|
64
82
|
|
65
|
-
def
|
66
|
-
Reports::Measure.
|
83
|
+
def measures
|
84
|
+
Reports::Measure.new_from_properties!(properties, context_record: nil)
|
67
85
|
end
|
68
86
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
87
|
+
def default_date_range_value
|
88
|
+
@default_date_range_value ||= begin
|
89
|
+
start_date = Reports::Data::Utils.format_time_value(DEFAULT_DATE_RANGE_VALUE[0])
|
90
|
+
end_date = Reports::Data::Utils.format_time_value(DEFAULT_DATE_RANGE_VALUE[1])
|
91
|
+
[start_date, Reports::FilterTypes::Datetime::SEPARATOR, end_date].join(' ')
|
92
|
+
end
|
74
93
|
end
|
75
94
|
end
|
76
95
|
end
|