simple_drilldown 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="