simple_drilldown 0.6.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c25058c9633cfe67926c2cbf3dca1105481fde8297077ba68414063ab239e05e
4
- data.tar.gz: 5ff52f26970deef096886d62451ca80f545d3fbf88601ed20cc2ed3334c01397
3
+ metadata.gz: 8b9e45eda9e3936d570de7055da2f5ec4eea29f3bfc6a8acc7a7134d364e2343
4
+ data.tar.gz: e4738f7b4a2bb699724c34b3fcf764de181c56bdfb015f9274a048e8b630a363
5
5
  SHA512:
6
- metadata.gz: 478e1fa749626a6599055b82022553c5778f8ef4085fa513f28261c9340cb3a112235ff6968115f95de00d4c4af4ec6d9e9b721596edd03693249c5e299e0938
7
- data.tar.gz: 2c4b94ae99c33ced23f149fbb0d0f5356867773a13e979619fe0c030ae83fbfac18444579b2b6b78427c48bca1e66a650455640a9d1fe9d95eb2c9629116a2ad
6
+ metadata.gz: b3eb61535dcd5068e5353f5076c29fb1632aaa252f4bbb61d1644295c423db4f063f12a0417f3495f3b6dde3c01501351b1052af3dca04b1d43b59320e74e33c
7
+ data.tar.gz: 9f424d5a153153886d7f2732d1dbeeb7f141095f9fc991e4b32f1a09b4e4dee32de54564b67101f74a9d31127627e37a80ebd514e24a5b0e2f60a22c236cb6d1
@@ -2,6 +2,9 @@
2
2
 
3
3
  xml << render(partial: '/drilldown/excel_row_header')
4
4
 
5
- result[:transactions].each do |t|
6
- xml << render(partial: '/drilldown/excel_row', locals: { transaction: t, previous_transaction: nil, errors: [], error_row: false, meter1_errors: false })
5
+ result[:records].each do |t|
6
+ xml << render(
7
+ partial: '/drilldown/excel_row',
8
+ locals: { transaction: t, previous_transaction: nil, errors: [], error_row: false, meter1_errors: false }
9
+ )
7
10
  end
@@ -6,7 +6,12 @@ xml.Row do
6
6
 
7
7
  @search.fields.each_with_index do |field, i|
8
8
  if field == 'time'
9
- value = (transaction.respond_to?(:completed_at) ? transaction.completed_at : transaction.created_at).localtime.strftime('%Y-%m-%d %H:%M')
9
+ value = ((
10
+ if transaction.respond_to?(:completed_at)
11
+ transaction.completed_at
12
+ else
13
+ transaction.created_at
14
+ end)).localtime.strftime('%Y-%m-%d %H:%M')
10
15
  else
11
16
  value = if @transaction_fields_map[field.to_sym][:attr_method]
12
17
  @transaction_fields_map[field.to_sym][:attr_method].call(transaction)
@@ -9,7 +9,11 @@ xml.Row do
9
9
  end
10
10
  end
11
11
  if dimension > 0
12
- xml.Cell('ss:StyleID' => 'Outer', 'ss:Index' => dimension.to_s) { xml.Data value_label(dimension - 1, result[:value]), 'ss:Type' => 'String' }
12
+ xml.Cell('ss:StyleID' => 'Outer',
13
+ 'ss:Index' => dimension.to_s) do
14
+ xml.Data value_label(dimension - 1, result[:value]),
15
+ 'ss:Type' => 'String'
16
+ end
13
17
  end
14
18
 
15
19
  xml.Cell('ss:StyleID' => 'Outer') { xml.Data result[:count].inspect, 'ss:Type' => 'Number' }
@@ -0,0 +1,2 @@
1
+ <%= link_to 'Excel', @search.url_options.merge(action: :excel_export) %>&nbsp;|
2
+ <%= link_to 'HTML', @search.url_options.merge(action: :html_export), data_popup: ['Elections', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes, width=1024px'] %>
@@ -1,9 +1,9 @@
1
- <% unless result[:transactions].empty? %>
1
+ <% unless result[:records].empty? %>
2
2
  <tr>
3
3
  <td colspan="<%= controller.c_summary_fields.size + 1 %>">
4
4
  <table class="table table-condensed table-bordered" style="padding-bottom: 10px;">
5
5
  <%= render :partial => '/drilldown/row_header' %>
6
- <% result[:transactions].each do |t| %>
6
+ <% result[:records].each do |t| %>
7
7
  <%= render :partial => '/drilldown/row', :locals => { :transaction => t, :previous_transaction => nil, :errors => [], :error_row => false, :meter1_errors => false } %>
8
8
  <% end %>
9
9
  </table>
@@ -4,8 +4,12 @@ xml.chart(xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", '')
4
4
  showValues: '1', caption: caption, subcaption: subcaption,
5
5
  yAxisName: "Election #{t(@search.select_value.downcase)}", numberSuffix: '') do
6
6
  @result[:rows].each do |res|
7
- xml.set(name: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(res[:value]) : res[:value],
7
+ xml.set name: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(res[:value]) : res[:value],
8
8
  value: res[@search.select_value.downcase.to_sym],
9
- link: @dimensions[0][:url_param_name] ? CGI.escape(url_for(@search.drill_down(@dimensions, res[:value]).url_options)) : '')
9
+ link: if @dimensions[0][:url_param_name]
10
+ CGI.escape(url_for(@search.drill_down(@dimensions, res[:value]).url_options))
11
+ else
12
+ ''
13
+ end
10
14
  end
11
15
  end
@@ -1,23 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- xml.chart xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", ''), palette: '2',
4
- caption: caption, subcaption: subcaption,
5
- showNames: '1', showValues: @result[:rows].size > 15 || @result[:rows][0] && @result[:rows][0][:rows].size > 4 ? 0 : 1, decimals: '0',
6
- numberPrefix: '', clustered: '0', exeTime: '1.5', showPlotBorder: '0', zGapPlot: '30',
7
- zDepth: '90', divLineEffect: 'emboss', startAngX: '10', endAngX: '18', startAngY: '-10',
8
- numberSuffix: '', zAxisName: 'Z Axis', yAxisName: "Transaction #{t(@search.select_value.downcase)}", endAngY: '-40' do
3
+ xml.chart(
4
+ xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", ''), palette: '2',
5
+ caption: caption, subcaption: subcaption,
6
+ showNames: '1',
7
+ showValues: @result[:rows].size > 15 || @result[:rows][0] && @result[:rows][0][:rows].size > 4 ? 0 : 1,
8
+ decimals: '0',
9
+ numberPrefix: '', clustered: '0', exeTime: '1.5', showPlotBorder: '0', zGapPlot: '30',
10
+ zDepth: '90', divLineEffect: 'emboss', startAngX: '10', endAngX: '18', startAngY: '-10',
11
+ numberSuffix: '', zAxisName: 'Z Axis',
12
+ yAxisName: "Transaction #{t(@search.select_value.downcase)}", endAngY: '-40'
13
+ ) do
9
14
  unless @result[:rows].empty?
10
15
  xml.categories do
11
16
  @result[:rows].each do |result|
12
- xml.category label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(result[:value]) : result[:value]
17
+ label_method = @dimensions[0][:label_method]
18
+ xml.category label: label_method ? label_method.call(result[:value]) : result[:value]
13
19
  end
14
20
  end
15
21
 
16
22
  @result[:rows][0][:rows].reverse.each_with_index do |result, i|
17
- xml.dataset seriesName: @dimensions[1][:label_method] ? @dimensions[1][:label_method].call(result[:value]) : result[:value] do
23
+ name = if @dimensions[1][:label_method]
24
+ @dimensions[1][:label_method].call(result[:value])
25
+ else
26
+ result[:value]
27
+ end
28
+ xml.dataset seriesName: name do
18
29
  @result[:rows].each do |res|
19
30
  value = res[:rows].reverse[i][:value]
20
- xml.set(label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(res[:value]) : "#{res[:value]}, #{value}",
31
+ label_method = @dimensions[0][:label_method]
32
+ xml.set(label: (label_method ? label_method.call(res[:value]) : "#{res[:value]}, #{value}"),
21
33
  value: res[:rows].reverse[i][@search.select_value.downcase.to_sym],
22
34
  link: CGI.escape(url_for(@search.drill_down(@dimensions, res[:value], value).url_options)))
23
35
  end
@@ -1,25 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- xml.chart xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", ''), palette: '2',
4
- caption: caption, subcaption: subcaption,
5
- showNames: '1', showValues: @result[:rows].size > 15 || @result[:rows][0] && @result[:rows][0][:rows].size > 4 ? 0 : 1, decimals: '0',
6
- numberPrefix: '', clustered: '0', exeTime: '1.5', showPlotBorder: '0', zGapPlot: '30',
7
- zDepth: '90', divLineEffect: 'emboss', startAngX: '10', endAngX: '18', startAngY: '-10',
8
- numberSuffix: '', zAxisName: 'Z Axis', yAxisName: "Transaction #{t(@search.select_value.downcase)}", endAngY: '-40' do
3
+ xml.chart(
4
+ xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", ''), palette: '2',
5
+ caption: caption, subcaption: subcaption,
6
+ showNames: '1',
7
+ showValues:
8
+ @result[:rows].size > 15 || @result[:rows][0] && @result[:rows][0][:rows].size > 4 ? 0 : 1,
9
+ decimals: '0',
10
+ numberPrefix: '', clustered: '0', exeTime: '1.5', showPlotBorder: '0', zGapPlot: '30',
11
+ zDepth: '90', divLineEffect: 'emboss', startAngX: '10', endAngX: '18', startAngY: '-10',
12
+ numberSuffix: '', zAxisName: 'Z Axis',
13
+ yAxisName: "Transaction #{t(@search.select_value.downcase)}", endAngY: '-40'
14
+ ) do
9
15
  unless @result[:rows].empty?
10
16
  xml.categories do
11
17
  @result[:rows].each do |result|
12
- xml.category label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(result[:value]) : result[:value]
18
+ xml.category label: if @dimensions[0][:label_method]
19
+ @dimensions[0][:label_method].call(result[:value])
20
+ else
21
+ result[:value]
22
+ end
13
23
  end
14
24
  end
15
25
 
16
26
  @result[:rows][0][:rows].reverse.each_with_index do |result, i|
17
- xml.dataset seriesName: @dimensions[1][:label_method] ? @dimensions[1][:label_method].call(result[:value]) : result[:value] do
27
+ series_name =
28
+ if @dimensions[1][:label_method]
29
+ @dimensions[1][:label_method].call(result[:value])
30
+ else
31
+ result[:value]
32
+ end
33
+ xml.dataset seriesName: series_name do
18
34
  @result[:rows].each do |res|
19
35
  value = res[:rows].reverse[i][:value]
20
- xml.set(label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(res[:value]) : "#{res[:value]}, #{value}",
21
- value: res[:rows].reverse[i][@search.select_value.downcase.to_sym],
22
- link: CGI.escape(url_for(@search.drill_down(@dimensions, res[:value], value).url_options)))
36
+ xml.set(
37
+ label:
38
+ if @dimensions[0][:label_method]
39
+ @dimensions[0][:label_method].call(res[:value])
40
+ else
41
+ "#{res[:value]}, #{value}"
42
+ end,
43
+ value: res[:rows].reverse[i][@search.select_value.downcase.to_sym],
44
+ link: CGI.escape(url_for(@search.drill_down(@dimensions, res[:value], value).url_options))
45
+ )
23
46
  end
24
47
  end
25
48
  end
@@ -15,12 +15,14 @@ xml.Workbook(
15
15
  xml.Worksheet 'ss:Name' => 'Transaction Summary' do
16
16
  xml.Table do
17
17
  xml.Row 'ss:Height' => '18.75' do
18
- xml.Cell 'ss:MergeAcross' => @search.list ? @search.fields.size - 1 : @dimensions.size + 2, 'ss:StyleID' => 'MainTitle' do
18
+ xml.Cell 'ss:MergeAcross' => @search.list ? @search.fields.size - 1 : @dimensions.size + 2,
19
+ 'ss:StyleID' => 'MainTitle' do
19
20
  xml.Data caption, 'ss:Type' => 'String'
20
21
  end
21
22
  end
22
23
  xml.Row 'ss:Height' => '15.75' do
23
- xml.Cell 'ss:MergeAcross' => @search.list ? @search.fields.size - 1 : @dimensions.size + 2, 'ss:StyleID' => 'SubTitle' do
24
+ xml.Cell 'ss:MergeAcross' => @search.list ? @search.fields.size - 1 : @dimensions.size + 2,
25
+ 'ss:StyleID' => 'SubTitle' do
24
26
  xml.Data subcaption, 'ss:Type' => 'String'
25
27
  end
26
28
  end
@@ -10,9 +10,9 @@ xml.Workbook(
10
10
  'xmlns:ss' => 'urn:schemas-microsoft-com:office:spreadsheet',
11
11
  'xmlns:html' => 'http://www.w3.org/TR/REC-html40'
12
12
  ) do
13
- xml << render(partial: '/layouts/excel_styles')
13
+ xml << render(partial: '/drilldown/excel_styles')
14
14
 
15
- xml.Worksheet 'ss:Name' => 'Transactions' do
15
+ xml.Worksheet 'ss:Name' => 'Drilldown' do
16
16
  xml.Table do
17
17
  xml.Row 'ss:Height' => '18.75' do
18
18
  xml.Cell 'ss:MergeAcross' => '35', 'ss:StyleID' => 'MainTitle' do
@@ -29,20 +29,20 @@ xml.Workbook(
29
29
  @transaction_fields.each do |field|
30
30
  if field == 'time'
31
31
  xml.Cell do
32
- xml.Data (l :short_date).to_s, 'ss:Type' => 'String'
32
+ xml.Data (t :short_date).to_s, 'ss:Type' => 'String'
33
33
  end
34
34
  xml.Cell do
35
- xml.Data (l :time).to_s, 'ss:Type' => 'String'
35
+ xml.Data (t :time).to_s, 'ss:Type' => 'String'
36
36
  end
37
37
  else
38
38
  xml.Cell do
39
- xml.Data (l field).to_s, 'ss:Type' => 'String'
39
+ xml.Data (t field).to_s, 'ss:Type' => 'String'
40
40
  end
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
- @transactions.each do |transaction|
45
+ @records.each do |transaction|
46
46
  xml.Row do
47
47
  @transaction_fields.each do |field|
48
48
  field_map = controller.c_fields[field.to_sym]
@@ -13,25 +13,25 @@
13
13
  }
14
14
  </style>
15
15
 
16
- <%= form_for @search, :html => {:id => 'edit_search_SEARCH', :method => :get, :class => :search, :style => 'background: inherit', :onsubmit => 'return this.submit()'}, :url => {} do |form| %>
16
+ <%= form_for @search, html: { id: 'edit_search_SEARCH', method: :get, class: :search, style: 'background: inherit', onsubmit: 'return this.submit()' }, url: {} do |form| %>
17
17
  <div class="row">
18
18
  <div class="col-md-3" valign="top">
19
19
  <ul class="nav nav-tabs">
20
- <li class="active">
21
- <a href="#filter" data-toggle="tab"><em><%= t :filter %></em></a></li>
22
- <li><a href="#fields" data-toggle="tab"><em><%= t :fields %></em></a>
20
+ <li class="nav-item">
21
+ <a id="filter-tab" class="nav-link active" data-target="#filter" data-toggle="tab"><%= t :filter %></a></li>
22
+ <li><a id="fields-tab" class="nav-link" data-target="#fields" data-toggle="tab"><%= t :fields %></a>
23
23
  </li>
24
24
  </ul>
25
25
 
26
26
  <!-- Tab panes -->
27
27
  <div class="tab-content">
28
28
  <div class="tab-pane active" id="filter">
29
- <%= render :partial => '/drilldown/tab_buttons', :locals => {:form => form} %>
30
- <%= render :partial => '/drilldown/filter', :locals => {:form => form} %>
29
+ <%= render '/drilldown/tab_buttons', form: form %>
30
+ <%= render '/drilldown/filter', form: form %>
31
31
  </div>
32
32
  <div class="tab-pane" id="fields">
33
- <%= render :partial => '/drilldown/tab_buttons', :locals => {:form => form} %>
34
- <%= render :partial => '/drilldown/fields', :locals => {:form => form} %>
33
+ <%= render '/drilldown/tab_buttons', form: form %>
34
+ <%= render '/drilldown/fields', form: form %>
35
35
  </div>
36
36
  </div>
37
37
 
@@ -39,20 +39,16 @@
39
39
  <div class="col-md-9">
40
40
  <div class="row" valign="top">
41
41
  <div class="col-md-12">
42
- <%= render :partial => '/drilldown/chart', :locals => {:form => form} %>
43
- <br/>
42
+ <%= render '/drilldown/chart', form: form %>
44
43
  </div>
45
44
  </div>
46
45
 
47
46
  <div class="row">
48
47
  <div class="col-md-12" valign="top">
49
48
  <div style="float: right; clear: both;">
50
- <%= link_to 'Excel', @search.url_options.merge(action: :excel_export) %>&nbsp;|
51
- <%= link_to 'HTML', @search.url_options.merge(action: :html_export), :data_popup => ['Elections', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes, width=1024px'] %>
49
+ <%= render '/drilldown/export_links' %>
52
50
  </div>
53
- <br/>
54
-
55
- <%= render :partial => '/drilldown/summary_table' %>
51
+ <%= render '/drilldown/summary_table' %>
56
52
  </div>
57
53
  </div>
58
54
  </div>
@@ -60,16 +56,16 @@
60
56
 
61
57
  <% end %> <!-- END FORM -->
62
58
 
63
- <%=javascript_tag do %>
64
- form = document.getElementById("edit_search_SEARCH");
65
- form.submit = function() {
66
- elements = form.elements;
67
- params = new Array();
68
- for (var el, i = 0; (el = elements[i] ); i++) {
69
- if (el.type == "text" && el.value == "") {
59
+ <%= javascript_tag do %>
60
+ form = document.getElementById("edit_search_SEARCH");
61
+ form.submit = function() {
62
+ let elements = form.elements;
63
+ let params = [];
64
+ for (let el, i = 0; (el = elements[i] ); i++) {
65
+ if (el.name === '' || (el.type === "text" && el.value === "")) {
70
66
  continue;
71
67
  }
72
- if (el.type == "select-multiple") {
68
+ if (el.type === "select-multiple") {
73
69
  if (el.selectedIndex > 0) {
74
70
  for (var j = 0; j < el.options.length; j++) {
75
71
  // Ignore "All" and unselected options
@@ -80,28 +76,24 @@ form.submit = function() {
80
76
  }
81
77
  continue;
82
78
  }
83
- if (el.type == "select-one" && el.selectedIndex == 0) {
79
+ if (el.type === "select-one" && el.selectedIndex === 0) {
84
80
  continue;
85
81
  }
86
- if (el.type == "checkbox" && el.checked != true) {
82
+ if (el.type === "checkbox" && el.checked !== true) {
87
83
  continue;
88
84
  }
89
- if (el.type == "radio" && el.checked != true) {
85
+ if (el.type === "radio" && (el.checked !== true || el.value === 'NONE')) {
90
86
  continue;
91
87
  }
92
- if (el.type == "hidden" && (el.value == "0" || el.value == "")) {
88
+ if (el.type === "hidden" && (el.value === "0" || el.value === "")) {
93
89
  continue;
94
90
  }
95
- if (el.type == "submit") {
91
+ if (el.type === "submit") {
96
92
  continue;
97
93
  }
98
94
  params.push("" + el.name + "=" + encodeURIComponent(el.value));
99
95
  }
100
96
  location = form.action + "?" + params.join('&');
101
97
  return false;
102
- };
103
-
104
- $(document).ready(function () {
105
- $('[data-behaviour~=datepicker]').datepicker({format: "yyyy-mm-dd"});
106
- })
98
+ };
107
99
  <% end %>
@@ -1,12 +1,15 @@
1
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
 
4
4
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
- <%= render 'layouts/headers' %>
6
- <%= stylesheet_link_tag 'drilldown' %>
5
+ <%= stylesheet_link_tag 'application' %>
7
6
  <body>
8
7
  <style type="text/css">
9
- @media print {#print_link {display: none}}
8
+ @media print {
9
+ #print_link {
10
+ display: none
11
+ }
12
+ }
10
13
  </style>
11
14
  <div class="container">
12
15
  <div id="print_link" class="pull-right">
@@ -6,6 +6,6 @@ class DrilldownControllerGenerator < Rails::Generators::NamedBase
6
6
  def copy_drilldown_controller_file
7
7
  template 'drilldown_controller.rb.erb', "app/controllers/#{file_name}_drilldown_controller.rb"
8
8
  template 'drilldown_controller_test.rb.erb', "test/controllers/#{file_name}_drilldown_controller_test.rb"
9
- route "draw_drilldown :#{singular_name}_drilldown"
9
+ route "draw_drilldown :#{singular_name}"
10
10
  end
11
11
  end
@@ -33,6 +33,7 @@ module SimpleDrilldown
33
33
  begin
34
34
  base.c_target_class = base.name.chomp('Controller').constantize
35
35
  rescue NameError
36
+ # No default target class found
36
37
  end
37
38
  end
38
39
  end
@@ -101,7 +102,9 @@ module SimpleDrilldown
101
102
  raise "Unexpected options: #{options.inspect}" if options.present?
102
103
 
103
104
  queries.each do |query_opts|
104
- raise "Unknown options: #{query_opts.keys.inspect}" unless (query_opts.keys - %i[select includes where]).empty?
105
+ unless (query_opts.keys - %i[select includes where]).empty?
106
+ raise "Unknown options: #{query_opts.keys.inspect}"
107
+ end
105
108
  end
106
109
 
107
110
  c_dimension_defs[name.to_s] = {
@@ -125,7 +128,8 @@ module SimpleDrilldown
125
128
  pretty_name: I18n.t(name, default: :"activerecord.models.#{name}"),
126
129
  queries: queries,
127
130
  reverse: reverse,
128
- select_expression: queries.size > 1 ? "COALESCE(#{queries.map { |q| q[:select] }.join(',')})" : queries[0][:select],
131
+ select_expression:
132
+ queries.size == 1 ? queries[0][:select] : "COALESCE(#{queries.map { |q| q[:select] }.join(',')})",
129
133
  row_class: row_class,
130
134
  url_param_name: name.to_s
131
135
  }
@@ -182,7 +186,7 @@ module SimpleDrilldown
182
186
  dimension_def = c_dimension_defs[field]
183
187
  raise "Unknown filter field: #{field.inspect}" if dimension_def.nil?
184
188
 
185
- values = [*values]
189
+ values = Array(values)
186
190
  if dimension_def[:interval]
187
191
  values *= 2 if values.size == 1
188
192
  raise "Need 2 values for interval filter: #{values.inspect}" if values.size != 2
@@ -237,9 +241,9 @@ module SimpleDrilldown
237
241
  when Hash
238
242
  sql = +''
239
243
  include.each do |parent, child|
240
- sql << ' ' + make_join(joins, model, parent)
244
+ sql << " #{make_join(joins, model, parent)}"
241
245
  ass = model.to_s.camelize.constantize.reflect_on_association parent
242
- sql << ' ' + make_join(joins, parent, child, ass.class_name.constantize)
246
+ sql << " #{make_join(joins, parent, child, ass.class_name.constantize)}"
243
247
  end
244
248
  sql
245
249
  when Symbol
@@ -373,8 +377,7 @@ module SimpleDrilldown
373
377
  selected = @search.filter[dimension_name] || []
374
378
  raise "Unknown dimension #{dimension_name.inspect}: #{c_dimension_defs.keys.inspect}" unless dimension
375
379
 
376
- choices = [[t(:all), nil]] +
377
- (dimension[:legal_values]&.call(@search)&.map { |o| o.is_a?(Array) ? o[0..1].map(&:to_s) : o.to_s } || [])
380
+ choices = [[t(:all), nil]] + (legal_values_for_dimension(dimension) || [])
378
381
  choices_html = choices.map do |c|
379
382
  %(<option value="#{c[1]}"#{' SELECTED' if selected.include?(c[1])}>#{c[0]}</option>)
380
383
  end.join("\n")
@@ -383,36 +386,37 @@ module SimpleDrilldown
383
386
 
384
387
  def html_export
385
388
  index(false)
386
- render template: '/drilldown/html_export', layout: 'print'
389
+ render template: '/drilldown/html_export', layout: '../drilldown/print'
387
390
  end
388
391
 
389
392
  def excel_export
390
393
  index(false)
391
- headers['Content-Type'] = 'application/vnd.ms-excel'
392
- headers['Content-Disposition'] = 'attachment; filename="transactions.xml"'
393
- headers['Cache-Control'] = ''
394
- render template: '/drilldown/excel_export', layout: false
394
+ set_excel_headers
395
+ if params.dig(:search, :list) == '1'
396
+ @records = get_records(@result)
397
+ render template: '/drilldown/excel_export_records', layout: false
398
+ else
399
+ render template: '/drilldown/excel_export', layout: false
400
+ end
395
401
  end
396
402
 
397
- def excel_export_transactions
403
+ def excel_export_records
404
+ params[:search] ||= {}
398
405
  params[:search][:list] = '1'
399
- index(false)
400
- @transactions = get_transactions(@result)
401
- headers['Content-Type'] = 'application/vnd.ms-excel'
402
- headers['Content-Disposition'] = 'attachment; filename="transactions.xml"'
403
- render template: '/drilldown/excel_export_transactions', layout: false
406
+ excel_export
404
407
  end
405
408
 
406
- def xml_export
407
- params[:search][:list] = '1'
408
- index(false)
409
- @transactions = get_transactions(@result)
410
- headers['Content-Type'] = 'text/xml'
411
- headers['Content-Disposition'] = 'attachment; filename="transactions.xml"'
412
- render template: '/drilldown/xml_export', layout: false
409
+ private
410
+
411
+ def set_excel_headers
412
+ headers['Content-Type'] = 'application/vnd.ms-excel'
413
+ headers['Content-Disposition'] = %{attachment; filename="#{c_target_class.table_name}.xml"}
414
+ headers['Cache-Control'] = ''
413
415
  end
414
416
 
415
- private
417
+ def legal_values_for_dimension(dimension)
418
+ dimension[:legal_values]&.call(@search)&.map { |o| o.is_a?(Array) ? o[0..1].map(&:to_s) : o.to_s }
419
+ end
416
420
 
417
421
  def new_search_object
418
422
  SimpleDrilldown::Search.new(params[:search]&.to_unsafe_h, c_default_fields, c_default_select_value)
@@ -495,7 +499,8 @@ module SimpleDrilldown
495
499
 
496
500
  result_rows = []
497
501
  loop do
498
- sub_result = result_from_rows(rows, row_index, dimension + 1, values + [rows[row_index]["value#{dimension + 1}"]])
502
+ sub_result = result_from_rows(rows, row_index, dimension + 1,
503
+ values + [rows[row_index]["value#{dimension + 1}"]])
499
504
  break if sub_result.nil?
500
505
 
501
506
  result_rows << sub_result
@@ -517,23 +522,20 @@ module SimpleDrilldown
517
522
  end
518
523
 
519
524
  def populate_list(conditions, includes, result, values)
520
- if result[:rows]
521
- return result[:rows].each { |r| populate_list(conditions, includes, r, values + [r[:value]]) }
522
- end
525
+ return result[:rows].each { |r| populate_list(conditions, includes, r, values + [r[:value]]) } if result[:rows]
526
+
523
527
  list_includes = merge_includes(includes, c_list_includes)
524
528
  @search.fields.each do |field|
525
529
  field_def = c_fields[field.to_sym]
526
530
  raise "Field definition missing for: #{field.inspect}" unless field_def
527
531
 
528
532
  field_includes = field_def[:include]
529
- if field_includes
530
- list_includes = merge_includes(list_includes , field_includes)
531
- end
533
+ list_includes = merge_includes(list_includes, field_includes) if field_includes
532
534
  end
533
535
  if @search.list_change_times
534
536
  @history_fields.each do |f|
535
537
  if @search.fields.include? f
536
- list_includes = merge_includes(list_includes, assignment: { order: :"#{f}_changes" } )
538
+ list_includes = merge_includes(list_includes, assignment: { order: :"#{f}_changes" })
537
539
  end
538
540
  end
539
541
  end
@@ -541,17 +543,17 @@ module SimpleDrilldown
541
543
  list_conditions = list_conditions(conditions, values)
542
544
  base_query = c_target_class.unscoped.where(c_base_condition).joins(joins).order(c_list_order)
543
545
  base_query = base_query.where(list_conditions) if list_conditions
544
- result[:transactions] = base_query.to_a
546
+ result[:records] = base_query.to_a
545
547
  end
546
548
 
547
549
  def merge_includes(*args)
548
550
  hash = hash_includes(*args)
549
- result = hash.dup.map { |k, v|
551
+ result = hash.dup.map do |k, v|
550
552
  if v.blank?
551
553
  hash.delete(k)
552
554
  k
553
555
  end
554
- }.compact
556
+ end.compact
555
557
  result << hash unless hash.blank?
556
558
  case result.size
557
559
  when 0
@@ -567,14 +569,15 @@ module SimpleDrilldown
567
569
  args.inject({}) do |h, inc|
568
570
  case inc
569
571
  when Array
570
- inc.each { |v|
572
+ inc.each do |v|
571
573
  h = hash_includes(h, v)
572
- }
574
+ end
573
575
  when Hash
574
- inc.each { |k, v|
576
+ inc.each do |k, v|
575
577
  h[k] = merge_includes(h[k], v)
576
- }
578
+ end
577
579
  when NilClass, FalseClass
580
+ # Leave as it is
578
581
  when String, Symbol
579
582
  h[inc] ||= []
580
583
  else
@@ -594,10 +597,10 @@ module SimpleDrilldown
594
597
  [list_conditions_string, *(conditions[1..-1] + values)]
595
598
  end
596
599
 
597
- def get_transactions(tree)
598
- return tree[:transactions] if tree[:transactions]
600
+ def get_records(tree)
601
+ return tree[:records] if tree[:records]
599
602
 
600
- tree[:rows].map { |r| get_transactions(r) }.flatten
603
+ tree[:rows].map { |r| get_records(r) }.flatten
601
604
  end
602
605
 
603
606
  class ScopeHolder
@@ -11,9 +11,8 @@ module SimpleDrilldown
11
11
  end
12
12
 
13
13
  def caption
14
- result = @search.title || "#{controller.c_target_class} #{t(@search.select_value.downcase)}" +
15
- (@dimensions && @dimensions.any? ? ' by ' + @dimensions.map { |d| d[:pretty_name] }.join(' and ') : '')
16
- result.gsub('$date', [*@search.filter[:calendar_date]].uniq.join(' - '))
14
+ result = @search.title || caption_txt
15
+ result.gsub('$date', Array(@search.filter[:calendar_date]).uniq.join(' - '))
17
16
  end
18
17
 
19
18
  def subcaption
@@ -21,9 +20,15 @@ module SimpleDrilldown
21
20
  end
22
21
 
23
22
  def summary_row(result, parent_result = nil, dimension = 0, headers = [], new_row = true)
24
- html = render(partial: '/drilldown/summary_row', locals: { result: result, parent_result: parent_result, new_row: new_row, dimension: dimension, headers: headers, with_results: !result[:rows] })
23
+ html = render(partial: '/drilldown/summary_row', locals: {
24
+ result: result, parent_result: parent_result, new_row: new_row, dimension: dimension,
25
+ headers: headers, with_results: !result[:rows]
26
+ })
25
27
  if result[:rows]
26
- sub_headers = headers + [{ value: result[:value], display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0) }]
28
+ sub_headers = headers + [{
29
+ value: result[:value],
30
+ display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0)
31
+ }]
27
32
  significant_rows = result[:rows].reject { |r| r[:row_count].zero? }
28
33
  significant_rows.each_with_index do |r, i|
29
34
  html << summary_row(r, result, dimension + 1, sub_headers, i.positive?)
@@ -31,7 +36,12 @@ module SimpleDrilldown
31
36
  elsif @search.list
32
37
  html << render(partial: '/drilldown/record_list', locals: { result: result })
33
38
  end
34
- html << render(partial: '/drilldown/summary_total_row', locals: { result: result, parent_result: parent_result, headers: headers.dup, dimension: dimension }) if dimension < @dimensions.size
39
+ if dimension < @dimensions.size
40
+ html << render(partial: '/drilldown/summary_total_row',
41
+ locals: {
42
+ result: result, parent_result: parent_result, headers: headers.dup, dimension: dimension
43
+ })
44
+ end
35
45
 
36
46
  html
37
47
  end
@@ -41,25 +51,42 @@ module SimpleDrilldown
41
51
  if result[:rows]
42
52
  significant_rows = result[:rows].reject { |r| r[:row_count].zero? }
43
53
  significant_rows.each_with_index do |r, i|
44
- sub_headers = if i.zero?
45
- if dimension.zero?
46
- headers
47
- else
48
- headers + [{ value: result[:value], display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0) }]
49
- end
50
- else
51
- [] # [{:value => result[:value], :row_count => result[:row_count]}]
52
- end
54
+ sub_headers =
55
+ if i.zero?
56
+ if dimension.zero?
57
+ headers
58
+ else
59
+ headers + [{
60
+ value: result[:value],
61
+ display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0)
62
+ }]
63
+ end
64
+ else
65
+ [] # [{:value => result[:value], :row_count => result[:row_count]}]
66
+ end
53
67
  xml << excel_summary_row(r, result, dimension + 1, sub_headers)
54
68
  end
55
69
  else
56
- xml << render(partial: '/drilldown/excel_summary_row', locals: { result: result, parent_result: parent_result, headers: headers.dup, dimension: dimension })
70
+ xml << render(partial: '/drilldown/excel_summary_row',
71
+ locals: { result: result, parent_result: parent_result, headers: headers.dup,
72
+ dimension: dimension })
57
73
 
58
74
  xml << render(partial: '/drilldown/excel_record_list', locals: { result: result }) if @search.list
59
75
  end
60
76
 
61
- xml << render(partial: '/drilldown/excel_summary_total_row', locals: { result: result, headers: headers.dup, dimension: dimension }) if dimension < @dimensions.size
77
+ if dimension < @dimensions.size
78
+ xml << render(partial: '/drilldown/excel_summary_total_row', locals: {
79
+ result: result, headers: headers.dup, dimension: dimension
80
+ })
81
+ end
62
82
  xml
63
83
  end
84
+
85
+ private
86
+
87
+ def caption_txt
88
+ "#{controller.c_target_class} #{t(@search.select_value.downcase)}" +
89
+ (@dimensions && @dimensions.any? ? " by #{@dimensions.map { |d| d[:pretty_name] }.join(' and ')}" : '')
90
+ end
64
91
  end
65
92
  end
@@ -3,11 +3,13 @@
3
3
  module SimpleDrilldown
4
4
  # Routing helper methods
5
5
  module Routing
6
- def draw_drilldown(path, controller = path)
6
+ def draw_drilldown(path, controller = nil)
7
+ path = "#{path}_drilldown" unless /_drilldown$/.match?(path)
8
+ controller ||= path
7
9
  get "#{path}(.:format)" => "#{controller}#index", as: path
8
- scope path do
9
- %i[choices excel_export html_export index].each do |action|
10
- get "#{action}(/:id)(.:format)", controller: controller, action: action
10
+ scope path, as: path do
11
+ %i[choices excel_export excel_export_records html_export index].each do |action|
12
+ get "#{action}(/:id)(.:format)", controller: controller, action: action, as: action
11
13
  end
12
14
  end
13
15
  end
@@ -19,17 +19,9 @@ module SimpleDrilldown
19
19
  VOLUME_COMPENSATED = 'VOLUME_COMPENSATED'
20
20
  end
21
21
 
22
- attr_reader :dimensions
23
- attr_reader :display_type
24
- attr_reader :fields
25
- attr_reader :filter
26
- attr_accessor :list
27
- attr_accessor :percent
28
- attr_reader :list_change_times
29
- attr_reader :order_by_value
30
- attr_reader :select_value
31
- attr_reader :title
32
- attr_reader :default_fields
22
+ attr_reader :dimensions, :display_type, :fields, :filter, :list_change_times, :order_by_value,
23
+ :select_value, :title, :default_fields
24
+ attr_accessor :list, :percent
33
25
 
34
26
  def self.validators_on(_attribute)
35
27
  []
@@ -60,7 +52,7 @@ module SimpleDrilldown
60
52
  @dimensions = attributes && attributes[:dimensions] || []
61
53
  @dimensions.delete_if(&:empty?)
62
54
  @filter = attributes && attributes[:filter] ? attributes[:filter] : {}
63
- @filter.keys.dup.each { |k| @filter[k] = [*@filter[k]] }
55
+ @filter.keys.dup.each { |k| @filter[k] = Array(@filter[k]) }
64
56
  @filter.each do |_k, v|
65
57
  v.delete('')
66
58
  v.delete('Select Some Options')
@@ -108,6 +100,10 @@ module SimpleDrilldown
108
100
  'SEARCH'
109
101
  end
110
102
 
103
+ def list?
104
+ list
105
+ end
106
+
111
107
  def drill_down(dimensions, *values)
112
108
  raise 'Too many values' if values.size > self.dimensions.size
113
109
 
@@ -1,3 +1,3 @@
1
1
  module SimpleDrilldown
2
- VERSION = '0.6.4'
2
+ VERSION = '0.7.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_drilldown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uwe Kubosch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-13 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chartkick
@@ -97,6 +97,7 @@ files:
97
97
  - app/views/drilldown/_excel_styles.builder
98
98
  - app/views/drilldown/_excel_summary_row.builder
99
99
  - app/views/drilldown/_excel_summary_total_row.builder
100
+ - app/views/drilldown/_export_links.html.erb
100
101
  - app/views/drilldown/_field.html.erb
101
102
  - app/views/drilldown/_fields.html.erb
102
103
  - app/views/drilldown/_filter.html.erb
@@ -112,7 +113,7 @@ files:
112
113
  - app/views/drilldown/data_2.builder
113
114
  - app/views/drilldown/data_3.builder
114
115
  - app/views/drilldown/excel_export.builder
115
- - app/views/drilldown/excel_export_transactions.builder
116
+ - app/views/drilldown/excel_export_records.builder
116
117
  - app/views/drilldown/html_export.html.erb
117
118
  - app/views/drilldown/index.html.erb
118
119
  - app/views/drilldown/print.html.erb
@@ -145,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
146
  requirements:
146
147
  - - ">="
147
148
  - !ruby/object:Gem::Version
148
- version: '0'
149
+ version: '2.5'
149
150
  required_rubygems_version: !ruby/object:Gem::Requirement
150
151
  requirements:
151
152
  - - ">="