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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 50df5df0e40d9cd127c03bacec3905c401be05ab
4
- data.tar.gz: 071d750fe875bcdaa4308fde9e6bf280b18c5d3e
3
+ metadata.gz: e12a4b95211ec84a8662237e268dfacfcd23978a
4
+ data.tar.gz: c5ec6f7f3f4e8bd9613764e8cd74108971255c26
5
5
  SHA512:
6
- metadata.gz: a6fbfb97c8e5f30a23d1260c73046e5f1e19941b0cdaad796ae490c8ebcbf73eeacc3eb3cfc1cd974f80e58b7c31e56d7366e3311e6af9146da055a64c410f25
7
- data.tar.gz: 57c6cdba6764b876efbe81d85f98285c5945b85f0571d8fa715806f2210b94b317698b06a957171ef78ea15fc23d2c21e904eb6f2f250e9036270f5217d26fd7
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 with customizable, interactive filters.
5
+ ReportsKit lets you easily create beautiful, interactive charts and tables.
6
6
 
7
- For interactive examples, see [reportskit.co](https://www.reportskit.co/).
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
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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
- * [Installation](#installation)
35
- * [Quick Start](#quick-start)
36
- * [Examples](https://www.reportskit.co/)
37
- * [Documentation](docs)
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 rowAggregationsCount = self.rowAggregationsCount(reportOptions);
41
- var rowAggregationsStartIndex = rowAggregationsCount ? (tableData.length - rowAggregationsCount) : null;
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 < tableData.length; i++) {
44
- if (i == 0) {
50
+ for(var i = 0; i < rowsCount; i++) {
51
+ if (i === headRowStartIndex) {
45
52
  html += '<thead><tr>';
46
- } else if (i == 1) {
53
+ } else if (i === (headRowEndIndex + 1)) {
47
54
  html += '<tbody><tr>';
48
- } else if (rowAggregationsCount && i == rowAggregationsStartIndex) {
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 == 0) {
69
+ if (i === headRowEndIndex) {
63
70
  html += '</tr></thead>';
64
- } else if (i == tableData.length && rowAggregationsCount) {
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;
@@ -28,3 +28,6 @@
28
28
  content: "\25BC"
29
29
  .headerSortDown::after
30
30
  content: "\25B2"
31
+ .reports_kit_actions
32
+ margin-top: 12px
33
+ text-align: right
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.2.0)
4
+ reports_kit (0.3.1)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- reports_kit (0.2.0)
4
+ reports_kit (0.3.1)
5
5
  rails (>= 3)
6
6
  spreadsheet (>= 1.1)
7
7
 
@@ -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, :default_dimension_limit,
4
- :default_properties, :first_day_of_week, :properties_method, :report_filename_method, :use_concurrent_queries
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
@@ -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
- additional_params = { context_params: context_params, report_params: report_params }
11
- params.merge!(additional_params)
12
- properties = instance_eval(&ReportsKit.configuration.properties_method)
13
- properties = properties.deep_symbolize_keys
14
- builder = ReportsKit::ReportBuilder.new(properties, additional_params: additional_params)
15
- path = reports_kit.reports_kit_reports_path({ format: 'json' }.merge(additional_params))
16
- data = { properties: properties.slice(:format), path: path, report_class: js_report_class }
17
- content_tag :div, nil, class: 'reports_kit_report form-inline', data: data do
18
- elements = []
19
- if block_given?
20
- elements << form_tag(path, method: 'get', class: 'reports_kit_report_form') do
21
- capture(builder, &block)
22
- end
23
- end
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
- private
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 generate_action_elements(actions, additional_params)
42
- return if actions.blank?
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 export_csv_element(additional_params)
51
- data = {
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
- DEFAULT_DATE_RANGE_VALUE = ['-2M', 'now']
5
+ attr_accessor :report_params, :context_params, :additional_params, :actions, :js_report_class, :properties, :view_context, :block, :form_builder
6
6
 
7
- attr_accessor :properties, :additional_params
7
+ ACTION_KEYS_METHODS = {
8
+ 'export_csv' => :export_csv_button,
9
+ 'export_xls' => :export_xls_button
10
+ }
8
11
 
9
- def initialize(properties, additional_params: nil)
10
- self.properties = properties.deep_symbolize_keys
11
- self.additional_params = additional_params
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 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)
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 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)
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 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)
42
+ def export_csv_button(text='Download CSV', options = {}, &block)
43
+ export_button(text, 'csv', options, &block)
50
44
  end
51
45
 
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)
46
+ def export_xls_button(text='Download Excel', options = {}, &block)
47
+ export_button(text, 'xls', options, &block)
57
48
  end
58
49
 
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
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
- def filters
69
- ui_filters + series_filters
70
- end
63
+ private
71
64
 
72
- def series_filters
73
- serieses.map(&:filters).flatten
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 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)
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 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(' ')
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
@@ -1,3 +1,3 @@
1
1
  module ReportsKit
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
@@ -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
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe ReportsKit::ReportBuilder do
3
+ describe ReportsKit::FormBuilder do
4
4
  subject { described_class.new(properties) }
5
5
 
6
6
  context 'with a datetime dimension' do
@@ -876,7 +876,7 @@ describe ReportsKit::Reports::Data::Generate do
876
876
  end
877
877
  end
878
878
 
879
- describe 'composite aggregations' do
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 aggregation' do
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.0
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-08-19 00:00:00.000000000 Z
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