reports_kit 0.3.0 → 0.3.1
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 +7 -104
- data/app/assets/javascripts/reports_kit/lib/table.js +17 -23
- data/app/assets/stylesheets/reports_kit/reports.css.sass +3 -0
- data/gemfiles/mysql.gemfile.lock +1 -1
- data/gemfiles/postgresql.gemfile.lock +1 -1
- data/lib/reports_kit.rb +2 -1
- data/lib/reports_kit/configuration.rb +4 -2
- data/lib/reports_kit/form_builder.rb +95 -0
- data/lib/reports_kit/helper.rb +20 -52
- data/lib/reports_kit/report_builder.rb +59 -67
- data/lib/reports_kit/reports/data/generate.rb +8 -1
- data/lib/reports_kit/reports/generate_autocomplete_results.rb +5 -0
- data/lib/reports_kit/reports_controller.rb +13 -4
- data/lib/reports_kit/version.rb +1 -1
- data/spec/fixtures/generate_inputs.yml +26 -0
- data/spec/fixtures/generate_outputs.yml +28 -0
- data/spec/reports_kit/{report_builder_spec.rb → form_builder_spec.rb} +1 -1
- data/spec/reports_kit/reports/data/generate_spec.rb +2 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e12a4b95211ec84a8662237e268dfacfcd23978a
|
4
|
+
data.tar.gz: c5ec6f7f3f4e8bd9613764e8cd74108971255c26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94b293476548bdd6ad1bed10018e4889f4d28a56b59490059274777fcd608790399a2f835b6f858d9f4075fd96c9accfe382d6fa4e9474079a827008fb157b0f
|
7
|
+
data.tar.gz: fd582ab216f799db4dbf3c0c197b95f5ebe155b55fa9bcc17bfbb15adcdf79dc22f85d999109187d02d8678b045fcc57846d8aa0748d8c1830d8e7e030662e3c
|
data/README.md
CHANGED
@@ -2,117 +2,20 @@ ReportsKit
|
|
2
2
|
=====
|
3
3
|
[](https://travis-ci.org/tombenner/reports_kit)
|
4
4
|
|
5
|
-
ReportsKit lets you easily create beautiful charts
|
5
|
+
ReportsKit lets you easily create beautiful, interactive charts and tables.
|
6
6
|
|
7
|
-
For
|
8
|
-
|
9
|
-
---
|
7
|
+
For examples and documentation, see [reportskit.co](https://www.reportskit.co/).
|
10
8
|
|
11
9
|
[<img src="docs/images/demo.gif?raw=true" width="700" />](docs/images/demo.gif?raw=true)
|
12
10
|
|
13
|
-
[<img src="docs/images/demo_area.png?raw=true" width="425" />](docs/images/demo_area.png?raw=true)
|
14
|
-
|
15
|
-
[<img src="docs/images/demo_dashed_line.png?raw=true" width="425" />](docs/images/demo_dashed_line.png?raw=true)
|
16
|
-
|
17
|
-
[<img src="docs/images/demo_horizontal_stacked.png?raw=true" width="425" />](docs/images/demo_horizontal_stacked.png?raw=true)
|
18
|
-
|
19
|
-
[<img src="docs/images/demo_legend.png?raw=true" width="425" />](docs/images/demo_legend.png?raw=true)
|
20
|
-
|
21
|
-
[<img src="docs/images/demo_multiautocomplete.png?raw=true" width="425" />](docs/images/demo_multiautocomplete.png?raw=true)
|
22
|
-
|
23
|
-
[<img src="docs/images/demo_radar.png?raw=true" width="230" />](docs/images/demo_radar.png?raw=true)
|
24
|
-
|
25
|
-
---
|
26
|
-
|
27
|
-
1. **Quick setup** - Install ReportsKit and create your first chart in less than one minute using just ~5 lines of code.
|
28
|
-
1. **Simple chart configuration** - Create charts using your existing Rails models. ReportsKit examines the column types and associations to understand how to render the chart.
|
29
|
-
1. **Powerful results** - To see what ReportsKit can create with minimal code, see [reportskit.co](https://www.reportskit.co/).
|
30
|
-
|
31
11
|
Resources
|
32
12
|
---------
|
33
13
|
|
34
|
-
* [
|
35
|
-
* [
|
36
|
-
* [Examples](https://www.reportskit.co/)
|
37
|
-
* [
|
38
|
-
|
39
|
-
Installation
|
40
|
-
------------
|
41
|
-
|
42
|
-
In `Gemfile`:
|
43
|
-
```ruby
|
44
|
-
gem 'reports_kit'
|
45
|
-
```
|
46
|
-
|
47
|
-
In `app/assets/stylesheets/application.css.scss`:
|
48
|
-
```scss
|
49
|
-
*= require reports_kit/application
|
50
|
-
```
|
51
|
-
|
52
|
-
In `app/assets/javascripts/application.js`:
|
53
|
-
```js
|
54
|
-
//= require reports_kit/application
|
55
|
-
```
|
56
|
-
|
57
|
-
In `config/routes.rb`:
|
58
|
-
```ruby
|
59
|
-
Rails.application.routes.draw do
|
60
|
-
mount ReportsKit::Engine, at: '/'
|
61
|
-
# ...
|
62
|
-
end
|
63
|
-
```
|
64
|
-
|
65
|
-
Quick Start
|
66
|
-
-----------
|
67
|
-
|
68
|
-
After installation, you can create your first chart with just a YAML file and a single line in any view.
|
69
|
-
|
70
|
-
Configure the chart in the YAML file:
|
71
|
-
|
72
|
-
`config/reports_kit/reports/my_users.yml`
|
73
|
-
```yaml
|
74
|
-
measure: user
|
75
|
-
dimensions:
|
76
|
-
- created_at
|
77
|
-
```
|
78
|
-
|
79
|
-
Then pass that filename to `render_report` in a view:
|
80
|
-
|
81
|
-
`app/views/users/index.html.haml`
|
82
|
-
```haml
|
83
|
-
= render_report 'my_users'
|
84
|
-
```
|
85
|
-
|
86
|
-
You're done! `render_report` will render the following chart:
|
87
|
-
|
88
|
-
[<img src="docs/images/users_by_created_at.png?raw=true" width="500" />](docs/images/users_by_created_at.png?raw=true)
|
89
|
-
|
90
|
-
### Form Controls
|
91
|
-
|
92
|
-
You can add a date range form control to the above chart with a single line, using one of ReportsKit's form helpers:
|
93
|
-
|
94
|
-
`app/views/users/index.html.haml`
|
95
|
-
```haml
|
96
|
-
= render_report 'my_users' do |f|
|
97
|
-
= f.date_range :created_at
|
98
|
-
```
|
99
|
-
|
100
|
-
[<img src="docs/images/users_by_created_at_with_filter.png?raw=true" width="500" />](docs/images/users_by_created_at_with_filter.png?raw=true)
|
101
|
-
|
102
|
-
Many other form controls are available; see [Filters](docs/filters.md) for more.
|
103
|
-
|
104
|
-
### How It Works
|
105
|
-
|
106
|
-
In the Quick Start chart, `measure: user` tells ReportsKit to count the number of `User` records, and `dimensions: ['created_at']` tells it to group by the week of the `created_at` column. Since `created_at` is a `datetime` column, ReportsKit knows that it should group the counts by week (the granularity is configurable), sort them chronologically, and add in zeros for any missing weeks.
|
107
|
-
|
108
|
-
ReportsKit infers sane defaults from your ActiveRecord model configurations. If there was a `belongs_to :company` association on `User` and you used `dimensions: ['company']`, then ReportsKit would count users grouped by the `company_id` column and show company names on the x-axis.
|
109
|
-
|
110
|
-
If you need more customization (e.g. custom filters, custom dimensions, custom aggregation functions, custom orders, aggregations of aggregations, etc), ReportsKit is very flexible and powerful and supports all of these with a simple syntax. It lets you use SQL, too.
|
111
|
-
|
112
|
-
To learn how to use more of ReportsKit's features, check out the following resources:
|
113
|
-
|
114
|
-
* [Examples](https://www.reportskit.co/)
|
115
|
-
* [Documentation](docs)
|
14
|
+
* [Documentation](https://www.reportskit.co/)
|
15
|
+
* [Getting Started](https://www.reportskit.co/categories/getting_started)
|
16
|
+
* [Data Examples](https://www.reportskit.co/categories/data)
|
17
|
+
* [Visualization Examples](https://www.reportskit.co/categories/visualization)
|
18
|
+
* [How It Works](https://www.reportskit.co/categories/getting_started/subcategories/how_it_works)
|
116
19
|
|
117
20
|
Testing
|
118
21
|
-------
|
@@ -37,15 +37,22 @@ ReportsKit.Table = (function(options) {
|
|
37
37
|
}
|
38
38
|
self.table.show().fadeTo(300, 1);
|
39
39
|
|
40
|
-
var
|
41
|
-
|
40
|
+
var rowsCount = tableData.length;
|
41
|
+
|
42
|
+
var hasHead = typeof reportOptions.head_rows_count !== 'undefined';
|
43
|
+
var hasFoot = typeof reportOptions.foot_rows_count !== 'undefined';
|
44
|
+
var headRowStartIndex = hasHead ? 0 : 0;
|
45
|
+
var headRowEndIndex = hasHead ? reportOptions.head_rows_count - 1 : 0;
|
46
|
+
var footRowStartIndex = hasFoot ? rowsCount - reportOptions.foot_rows_count : null;
|
47
|
+
var footRowEndIndex = hasFoot ? rowsCount - 1 : null;
|
48
|
+
|
42
49
|
var html = '';
|
43
|
-
for(var i = 0; i <
|
44
|
-
if (i
|
50
|
+
for(var i = 0; i < rowsCount; i++) {
|
51
|
+
if (i === headRowStartIndex) {
|
45
52
|
html += '<thead><tr>';
|
46
|
-
} else if (i
|
53
|
+
} else if (i === (headRowEndIndex + 1)) {
|
47
54
|
html += '<tbody><tr>';
|
48
|
-
} else if (
|
55
|
+
} else if (i === footRowStartIndex) {
|
49
56
|
html += '<tfoot><tr>';
|
50
57
|
} else {
|
51
58
|
html += '<tr>';
|
@@ -59,12 +66,12 @@ ReportsKit.Table = (function(options) {
|
|
59
66
|
}
|
60
67
|
}
|
61
68
|
|
62
|
-
if (i
|
69
|
+
if (i === headRowEndIndex) {
|
63
70
|
html += '</tr></thead>';
|
64
|
-
} else if (i
|
65
|
-
html += '</tfoot></tbody>';
|
66
|
-
} else if (i == tableData.length) {
|
71
|
+
} else if (i === (footRowStartIndex - 1)) {
|
67
72
|
html += '</tr></tbody>';
|
73
|
+
} else if (i === footRowEndIndex) {
|
74
|
+
html += '</tfoot></tbody>';
|
68
75
|
} else {
|
69
76
|
html += '</tr>';
|
70
77
|
}
|
@@ -74,19 +81,6 @@ ReportsKit.Table = (function(options) {
|
|
74
81
|
});
|
75
82
|
};
|
76
83
|
|
77
|
-
self.rowAggregationsCount = function(reportOptions) {
|
78
|
-
if (!reportOptions.aggregations) {
|
79
|
-
return 0;
|
80
|
-
};
|
81
|
-
var rowAggregationsCount = 0;
|
82
|
-
for(var i = 0; i < reportOptions.aggregations.length; i++) {
|
83
|
-
if (reportOptions.aggregations[i].from === 'columns') {
|
84
|
-
rowAggregationsCount += 1;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
return rowAggregationsCount;
|
88
|
-
};
|
89
|
-
|
90
84
|
self.initialize(options);
|
91
85
|
|
92
86
|
return self;
|
data/gemfiles/mysql.gemfile.lock
CHANGED
data/lib/reports_kit.rb
CHANGED
@@ -5,12 +5,13 @@ require 'reports_kit/cache'
|
|
5
5
|
require 'reports_kit/configuration'
|
6
6
|
require 'reports_kit/engine'
|
7
7
|
require 'reports_kit/entity'
|
8
|
+
require 'reports_kit/report_builder'
|
9
|
+
require 'reports_kit/form_builder'
|
8
10
|
require 'reports_kit/helper'
|
9
11
|
require 'reports_kit/model'
|
10
12
|
require 'reports_kit/model_configuration'
|
11
13
|
require 'reports_kit/order'
|
12
14
|
require 'reports_kit/relative_time'
|
13
|
-
require 'reports_kit/report_builder'
|
14
15
|
require 'reports_kit/resources_controller'
|
15
16
|
require 'reports_kit/reports_controller'
|
16
17
|
require 'reports_kit/value'
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module ReportsKit
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :cache_duration, :cache_store, :context_record_method, :custom_methods,
|
4
|
-
:default_properties, :first_day_of_week, :properties_method, :report_filename_method,
|
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
|
5
6
|
|
6
7
|
DEFAULT_PROPERTIES_METHOD = lambda do |env|
|
7
8
|
path = Rails.root.join('config', 'reports_kit', 'reports', "#{report_key}.yml")
|
@@ -9,6 +10,7 @@ module ReportsKit
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def initialize
|
13
|
+
self.autocomplete_results_method = nil
|
12
14
|
self.cache_duration = 5.minutes
|
13
15
|
self.cache_store = nil
|
14
16
|
self.context_record_method = nil
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ReportsKit
|
2
|
+
class FormBuilder
|
3
|
+
include ActionView::Helpers
|
4
|
+
|
5
|
+
DEFAULT_DATE_RANGE_VALUE = ['-2M', 'now']
|
6
|
+
|
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
|
12
|
+
end
|
13
|
+
|
14
|
+
def check_box(filter_key, options = {})
|
15
|
+
filter = validate_filter!(filter_key)
|
16
|
+
checked = filter.normalized_properties[:criteria][:value] == 'true'
|
17
|
+
check_box_tag(filter_key, '1', checked, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def date_range(filter_key, options = {})
|
21
|
+
filter = validate_filter!(filter_key)
|
22
|
+
defaults = { class: 'form-control input-sm date_range_picker' }
|
23
|
+
options = defaults.deep_merge(options)
|
24
|
+
value = filter.normalized_properties[:criteria][:value].presence
|
25
|
+
value ||= default_date_range_value
|
26
|
+
text_field_tag(filter_key, value, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def multi_autocomplete(filter_key, options = {})
|
30
|
+
validate_filter!(filter_key)
|
31
|
+
filter = series_filters.find { |f| f.key == filter_key.to_s }
|
32
|
+
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 += additional_params.to_query if additional_params.present?
|
35
|
+
scope = options.delete(:scope)
|
36
|
+
params = {}
|
37
|
+
params[:scope] = scope if scope.present?
|
38
|
+
|
39
|
+
defaults = {
|
40
|
+
class: 'form-control input-sm select2',
|
41
|
+
multiple: 'multiple',
|
42
|
+
data: {
|
43
|
+
placeholder: options[:placeholder],
|
44
|
+
path: path,
|
45
|
+
params: params
|
46
|
+
}
|
47
|
+
}
|
48
|
+
options = defaults.deep_merge(options)
|
49
|
+
select_tag(filter_key, nil, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def string_filter(filter_key, options = {})
|
53
|
+
filter = validate_filter!(filter_key)
|
54
|
+
defaults = { class: 'form-control input-sm' }
|
55
|
+
options = defaults.deep_merge(options)
|
56
|
+
text_field_tag(filter_key, filter.normalized_properties[:criteria][:value], options)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
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
|
+
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
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/reports_kit/helper.rb
CHANGED
@@ -1,66 +1,34 @@
|
|
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
|
-
|
8
3
|
def render_report(report_params, context_params: {}, actions: %w(export_csv export_xls), js_report_class: 'Report', &block)
|
9
4
|
report_params = { key: report_params } if report_params.is_a?(String)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
elements << content_tag(:div, nil, class: 'reports_kit_visualization')
|
25
|
-
action_elements = generate_action_elements(actions, additional_params)
|
26
|
-
if action_elements
|
27
|
-
elements << content_tag(:div, nil, class: 'reports_kit_actions') do
|
28
|
-
action_elements.map { |element| concat(element) }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
elements.join.html_safe
|
5
|
+
params.merge!(context_params: context_params, report_params: report_params)
|
6
|
+
properties = instance_eval(&ReportsKit.configuration.properties_method).deep_symbolize_keys
|
7
|
+
builder = ReportBuilder.new(
|
8
|
+
report_params: report_params,
|
9
|
+
context_params: context_params,
|
10
|
+
actions: actions,
|
11
|
+
js_report_class: js_report_class,
|
12
|
+
properties: properties,
|
13
|
+
view_context: self,
|
14
|
+
block: block
|
15
|
+
)
|
16
|
+
capture do
|
17
|
+
capture(builder, &block) if block
|
18
|
+
builder.render
|
32
19
|
end
|
33
20
|
end
|
34
21
|
|
35
|
-
|
36
|
-
|
37
|
-
def report_key
|
38
|
-
params[:report_params][:key]
|
22
|
+
def context_params
|
23
|
+
params[:context_params]
|
39
24
|
end
|
40
25
|
|
41
|
-
def
|
42
|
-
|
43
|
-
actions.map do |action|
|
44
|
-
element_method = ACTION_KEYS_METHODS[action]
|
45
|
-
raise ArgumentError.new("Invalid action: #{action}") unless element_method
|
46
|
-
send(element_method, additional_params)
|
47
|
-
end
|
26
|
+
def report_params
|
27
|
+
params[:report_params]
|
48
28
|
end
|
49
29
|
|
50
|
-
def
|
51
|
-
|
52
|
-
role: 'reports_kit_export_button',
|
53
|
-
path: reports_kit.reports_kit_reports_path({ format: 'csv' }.merge(additional_params))
|
54
|
-
}
|
55
|
-
link_to('Download CSV', '#', class: 'btn btn-primary', data: data)
|
56
|
-
end
|
57
|
-
|
58
|
-
def export_xls_element(additional_params)
|
59
|
-
data = {
|
60
|
-
role: 'reports_kit_export_button',
|
61
|
-
path: reports_kit.reports_kit_reports_path({ format: 'xls' }.merge(additional_params))
|
62
|
-
}
|
63
|
-
link_to('Download Excel', '#', class: 'btn btn-primary', data: data)
|
30
|
+
def report_key
|
31
|
+
report_params[:key]
|
64
32
|
end
|
65
33
|
end
|
66
34
|
end
|
@@ -2,93 +2,85 @@ module ReportsKit
|
|
2
2
|
class ReportBuilder
|
3
3
|
include ActionView::Helpers
|
4
4
|
|
5
|
-
|
5
|
+
attr_accessor :report_params, :context_params, :additional_params, :actions, :js_report_class, :properties, :view_context, :block, :form_builder
|
6
6
|
|
7
|
-
|
7
|
+
ACTION_KEYS_METHODS = {
|
8
|
+
'export_csv' => :export_csv_button,
|
9
|
+
'export_xls' => :export_xls_button
|
10
|
+
}
|
8
11
|
|
9
|
-
def initialize(
|
10
|
-
self.
|
11
|
-
self.
|
12
|
+
def initialize(report_params:, context_params: {}, actions: %w(export_csv export_xls), js_report_class: 'Report', properties:, view_context:, block: nil)
|
13
|
+
self.report_params = report_params.is_a?(String) ? { key: report_params } : report_params
|
14
|
+
self.context_params = context_params
|
15
|
+
self.additional_params = { context_params: context_params, report_params: self.report_params }
|
16
|
+
self.actions = actions
|
17
|
+
self.js_report_class = js_report_class
|
18
|
+
self.view_context = view_context
|
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)
|
12
22
|
end
|
13
23
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
24
|
+
def render
|
25
|
+
data = { properties: properties.slice(:format), path: reports_data_path, report_class: js_report_class }
|
26
|
+
view_context.content_tag :div, nil, class: 'reports_kit_report form-inline', data: data do
|
27
|
+
elements = []
|
28
|
+
elements << view_context.capture(self, &block) if block
|
29
|
+
elements << view_context.content_tag(:div, nil, class: 'reports_kit_visualization')
|
30
|
+
elements << action_elements_container
|
31
|
+
elements.compact.join.html_safe
|
32
|
+
end
|
18
33
|
end
|
19
34
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
value ||= default_date_range_value
|
26
|
-
text_field_tag(filter_key, value, options)
|
35
|
+
def form(&block)
|
36
|
+
raise ArgumentError.new('No block given for ReportBuilder#form') unless block
|
37
|
+
view_context.form_tag(reports_data_path, method: 'get', class: 'reports_kit_report_form') do
|
38
|
+
view_context.capture(form_builder, &block)
|
39
|
+
end
|
27
40
|
end
|
28
41
|
|
29
|
-
def
|
30
|
-
|
31
|
-
filter = series_filters.find { |f| f.key == filter_key.to_s }
|
32
|
-
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 += additional_params.to_query if additional_params.present?
|
35
|
-
scope = options.delete(:scope)
|
36
|
-
params = {}
|
37
|
-
params[:scope] = scope if scope.present?
|
38
|
-
|
39
|
-
defaults = {
|
40
|
-
class: 'form-control input-sm select2',
|
41
|
-
multiple: 'multiple',
|
42
|
-
data: {
|
43
|
-
placeholder: options[:placeholder],
|
44
|
-
path: path,
|
45
|
-
params: params
|
46
|
-
}
|
47
|
-
}
|
48
|
-
options = defaults.deep_merge(options)
|
49
|
-
select_tag(filter_key, nil, options)
|
42
|
+
def export_csv_button(text='Download CSV', options = {}, &block)
|
43
|
+
export_button(text, 'csv', options, &block)
|
50
44
|
end
|
51
45
|
|
52
|
-
def
|
53
|
-
|
54
|
-
defaults = { class: 'form-control input-sm' }
|
55
|
-
options = defaults.deep_merge(options)
|
56
|
-
text_field_tag(filter_key, filter.normalized_properties[:criteria][:value], options)
|
46
|
+
def export_xls_button(text='Download Excel', options = {}, &block)
|
47
|
+
export_button(text, 'xls', options, &block)
|
57
48
|
end
|
58
49
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
50
|
+
def export_button(text, format, options, &block)
|
51
|
+
data = {
|
52
|
+
role: 'reports_kit_export_button',
|
53
|
+
path: view_context.reports_kit.reports_kit_reports_path({ format: format }.merge(additional_params))
|
54
|
+
}
|
55
|
+
options = { class: 'btn btn-primary', data: data }.merge(options)
|
56
|
+
if block_given?
|
57
|
+
view_context.link_to('#', options, &block)
|
58
|
+
else
|
59
|
+
view_context.link_to(text, '#', options)
|
60
|
+
end
|
66
61
|
end
|
67
62
|
|
68
|
-
|
69
|
-
ui_filters + series_filters
|
70
|
-
end
|
63
|
+
private
|
71
64
|
|
72
|
-
def
|
73
|
-
|
65
|
+
def reports_data_path
|
66
|
+
@reports_data_path ||= view_context.reports_kit.reports_kit_reports_path({ format: 'json' }.merge(additional_params))
|
74
67
|
end
|
75
68
|
|
76
|
-
def
|
77
|
-
return
|
78
|
-
|
79
|
-
|
69
|
+
def action_elements_container
|
70
|
+
return if action_elements.blank?
|
71
|
+
view_context.content_tag(:div, nil, class: 'reports_kit_actions') do
|
72
|
+
action_elements.map { |element| view_context.concat(element) }
|
80
73
|
end
|
81
74
|
end
|
82
75
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
[start_date, Reports::FilterTypes::Datetime::SEPARATOR, end_date].join(' ')
|
76
|
+
def action_elements
|
77
|
+
@action_elements ||= begin
|
78
|
+
return if actions.blank?
|
79
|
+
actions.map do |action|
|
80
|
+
element_method = ACTION_KEYS_METHODS[action]
|
81
|
+
raise ArgumentError.new("Invalid action: #{action}") unless element_method
|
82
|
+
send(element_method)
|
83
|
+
end.compact
|
92
84
|
end
|
93
85
|
end
|
94
86
|
end
|
@@ -91,7 +91,14 @@ module ReportsKit
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def report_options
|
94
|
-
properties[:report_options]
|
94
|
+
report_options = properties[:report_options] || {}
|
95
|
+
head_rows_count = report_options[:head_rows_count]
|
96
|
+
foot_rows_count = report_options[:foot_rows_count]
|
97
|
+
foot_rows_count ||= report_options[:aggregations].count { |config| config[:from] == 'rows' } if report_options[:aggregations]
|
98
|
+
|
99
|
+
report_options[:head_rows_count] = head_rows_count if head_rows_count && head_rows_count > 0
|
100
|
+
report_options[:foot_rows_count] = foot_rows_count if foot_rows_count && foot_rows_count > 0
|
101
|
+
report_options.presence
|
95
102
|
end
|
96
103
|
|
97
104
|
def data_format_method
|
@@ -12,6 +12,7 @@ module ReportsKit
|
|
12
12
|
|
13
13
|
def perform
|
14
14
|
raise ArgumentError.new("Could not find a model for filter_key: '#{filter_key}'") unless model
|
15
|
+
return autocomplete_results_method.call(params: params, context_record: context_record, relation: relation) if autocomplete_results_method
|
15
16
|
results = relation
|
16
17
|
results = results.public_send(scope) if scope
|
17
18
|
results = results.limit(10_000)
|
@@ -23,6 +24,10 @@ module ReportsKit
|
|
23
24
|
|
24
25
|
private
|
25
26
|
|
27
|
+
def autocomplete_results_method
|
28
|
+
ReportsKit.configuration.autocomplete_results_method
|
29
|
+
end
|
30
|
+
|
26
31
|
def relation
|
27
32
|
if context_record
|
28
33
|
context_record.public_send(model.name.tableize)
|
@@ -26,6 +26,19 @@ module ReportsKit
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def report_params
|
30
|
+
params[:report_params]
|
31
|
+
end
|
32
|
+
|
33
|
+
def context_params
|
34
|
+
params[:context_params]
|
35
|
+
end
|
36
|
+
|
37
|
+
def report_key
|
38
|
+
raise ArgumentError.new('Blank report_params') if report_params.blank?
|
39
|
+
report_params[:key]
|
40
|
+
end
|
41
|
+
|
29
42
|
private
|
30
43
|
|
31
44
|
def report_filename
|
@@ -38,10 +51,6 @@ module ReportsKit
|
|
38
51
|
Reports::Data::Generate.new(properties, context_record: context_record).perform
|
39
52
|
end
|
40
53
|
|
41
|
-
def report_key
|
42
|
-
params[:report_params][:key]
|
43
|
-
end
|
44
|
-
|
45
54
|
def properties
|
46
55
|
@properties ||= begin
|
47
56
|
properties_method = ReportsKit.configuration.properties_method
|
data/lib/reports_kit/version.rb
CHANGED
@@ -130,6 +130,32 @@
|
|
130
130
|
- from: rows
|
131
131
|
operator: sum
|
132
132
|
label: Total
|
133
|
+
- series:
|
134
|
+
- measure:
|
135
|
+
key: issue
|
136
|
+
name: Repo Issues
|
137
|
+
dimensions:
|
138
|
+
- key: repo
|
139
|
+
label:
|
140
|
+
- measure: label
|
141
|
+
dimensions:
|
142
|
+
- repo
|
143
|
+
format: table
|
144
|
+
report_options:
|
145
|
+
head_rows_count: 2
|
146
|
+
- series:
|
147
|
+
- measure:
|
148
|
+
key: issue
|
149
|
+
name: Repo Issues
|
150
|
+
dimensions:
|
151
|
+
- key: repo
|
152
|
+
label:
|
153
|
+
- measure: label
|
154
|
+
dimensions:
|
155
|
+
- repo
|
156
|
+
format: table
|
157
|
+
report_options:
|
158
|
+
foot_rows_count: 3
|
133
159
|
- series:
|
134
160
|
measure: label
|
135
161
|
dimensions:
|
@@ -425,6 +425,7 @@
|
|
425
425
|
- :from: rows
|
426
426
|
:operator: sum
|
427
427
|
:label: Total
|
428
|
+
:foot_rows_count: 1
|
428
429
|
:table_data:
|
429
430
|
- -
|
430
431
|
- Repo Issues
|
@@ -447,6 +448,7 @@
|
|
447
448
|
- :from: rows
|
448
449
|
:operator: sum
|
449
450
|
:label: Total
|
451
|
+
:foot_rows_count: 1
|
450
452
|
:table_data:
|
451
453
|
- -
|
452
454
|
- Repo Issues
|
@@ -464,6 +466,32 @@
|
|
464
466
|
- 2
|
465
467
|
- 3
|
466
468
|
- 5
|
469
|
+
- :type: table
|
470
|
+
:report_options:
|
471
|
+
:head_rows_count: 2
|
472
|
+
:table_data:
|
473
|
+
- -
|
474
|
+
- Repo Issues
|
475
|
+
- Labels
|
476
|
+
- - foo/bar1
|
477
|
+
- 2
|
478
|
+
- 1
|
479
|
+
- - foo/bar2
|
480
|
+
- 0
|
481
|
+
- 2
|
482
|
+
- :type: table
|
483
|
+
:report_options:
|
484
|
+
:foot_rows_count: 3
|
485
|
+
:table_data:
|
486
|
+
- -
|
487
|
+
- Repo Issues
|
488
|
+
- Labels
|
489
|
+
- - foo/bar1
|
490
|
+
- 2
|
491
|
+
- 1
|
492
|
+
- - foo/bar2
|
493
|
+
- 0
|
494
|
+
- 2
|
467
495
|
- :chart_data:
|
468
496
|
:labels:
|
469
497
|
- foo/bar1
|
@@ -876,7 +876,7 @@ describe ReportsKit::Reports::Data::Generate do
|
|
876
876
|
end
|
877
877
|
end
|
878
878
|
|
879
|
-
describe 'composite
|
879
|
+
describe 'composite series' do
|
880
880
|
context 'with two series' do
|
881
881
|
let(:properties) do
|
882
882
|
{
|
@@ -1114,7 +1114,7 @@ describe ReportsKit::Reports::Data::Generate do
|
|
1114
1114
|
end
|
1115
1115
|
end
|
1116
1116
|
|
1117
|
-
context 'with a nested composite
|
1117
|
+
context 'with a nested composite series' do
|
1118
1118
|
let(:properties) do
|
1119
1119
|
{
|
1120
1120
|
series: [
|
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.
|
4
|
+
version: 0.3.1
|
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-
|
11
|
+
date: 2017-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -226,6 +226,7 @@ files:
|
|
226
226
|
- lib/reports_kit/configuration.rb
|
227
227
|
- lib/reports_kit/engine.rb
|
228
228
|
- lib/reports_kit/entity.rb
|
229
|
+
- lib/reports_kit/form_builder.rb
|
229
230
|
- lib/reports_kit/helper.rb
|
230
231
|
- lib/reports_kit/model.rb
|
231
232
|
- lib/reports_kit/model_configuration.rb
|
@@ -274,8 +275,8 @@ files:
|
|
274
275
|
- spec/factories/tag_factory.rb
|
275
276
|
- spec/fixtures/generate_inputs.yml
|
276
277
|
- spec/fixtures/generate_outputs.yml
|
278
|
+
- spec/reports_kit/form_builder_spec.rb
|
277
279
|
- spec/reports_kit/relative_time_spec.rb
|
278
|
-
- spec/reports_kit/report_builder_spec.rb
|
279
280
|
- spec/reports_kit/reports/data/generate_spec.rb
|
280
281
|
- spec/reports_kit/reports/dimension_with_series_spec.rb
|
281
282
|
- spec/reports_kit/reports/filter_with_series_spec.rb
|