reports_kit 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/tombenner/reports_kit.svg?branch=master)](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
|