simple_drilldown 0.6.7 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/views/drilldown/_excel_record_list.builder +4 -1
- data/app/views/drilldown/_excel_row.builder +6 -1
- data/app/views/drilldown/_excel_styles.builder +1 -2
- data/app/views/drilldown/_excel_summary_row.builder +5 -1
- data/app/views/drilldown/data_1.builder +6 -2
- data/app/views/drilldown/data_2.builder +21 -9
- data/app/views/drilldown/data_3.builder +34 -11
- data/app/views/drilldown/excel_export.builder +4 -2
- data/app/views/drilldown/{excel_export_transactions.builder → excel_export_records.builder} +8 -7
- data/app/views/drilldown/html_export.html.erb +3 -3
- data/app/views/drilldown/print.html.erb +7 -4
- data/config/routes.rb +1 -0
- data/lib/generators/drilldown_controller/drilldown_controller_generator.rb +1 -1
- data/lib/simple_drilldown/controller.rb +45 -39
- data/lib/simple_drilldown/helper.rb +48 -17
- data/lib/simple_drilldown/routing.rb +6 -5
- data/lib/simple_drilldown/search.rb +4 -12
- data/lib/simple_drilldown/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d998f2cd5f57af22c3c8831275dad5d173180d99000f2770e02db5accf6183ab
|
4
|
+
data.tar.gz: c1dab92e5b931b7c2396ad59ffabd97e1b61c8b28bd58a30e5409216488a5dd8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 734f1d871a340e5b6f7c44e28eadc13f91e60b7492bead90f4b6681e0ec1f76db237042856350795d43ac3d0ed2b099dfd74ada3f3c5ba801019a57cd5bde217
|
7
|
+
data.tar.gz: 71fe4b0435b2ca9230f4baaea43535522ef48389f37fe1c03b895769de8bf045ba95be62eb39421a9cc7db81039fa94dd7a882f0a21e5fdf33e9ddd251fabb4a
|
@@ -3,5 +3,8 @@
|
|
3
3
|
xml << render(partial: '/drilldown/excel_row_header')
|
4
4
|
|
5
5
|
result[:records].each do |t|
|
6
|
-
xml << render(
|
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 = (
|
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)
|
@@ -46,8 +46,7 @@ xml.Styles do
|
|
46
46
|
xml.Interior 'ss:Color' => '#dedede', 'ss:Pattern' => 'Solid'
|
47
47
|
xml.NumberFormat 'ss:Format' => "\#,\#\#0"
|
48
48
|
end
|
49
|
-
xml.Style 'ss:ID' => 'Outer'
|
50
|
-
end
|
49
|
+
xml.Style 'ss:ID' => 'Outer'
|
51
50
|
xml.Style 'ss:ID' => 'ShortDate' do
|
52
51
|
xml.NumberFormat 'ss:Format' => 'Short Date'
|
53
52
|
end
|
@@ -9,7 +9,11 @@ xml.Row do
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
if dimension > 0
|
12
|
-
xml.Cell('ss:StyleID' => 'Outer',
|
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' }
|
@@ -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
|
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]
|
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
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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:
|
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
|
-
|
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(
|
21
|
-
|
22
|
-
|
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,
|
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,
|
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,7 +10,7 @@ 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: '/
|
13
|
+
xml << render(partial: '/drilldown/excel_styles')
|
14
14
|
|
15
15
|
xml.Worksheet 'ss:Name' => 'Drilldown' do
|
16
16
|
xml.Table do
|
@@ -26,17 +26,17 @@ xml.Workbook(
|
|
26
26
|
end
|
27
27
|
|
28
28
|
xml.Row 'ss:StyleID' => 'Heading' do
|
29
|
-
@
|
29
|
+
@search.fields.each do |field|
|
30
30
|
if field == 'time'
|
31
31
|
xml.Cell do
|
32
|
-
xml.Data (
|
32
|
+
xml.Data (t :short_date).to_s, 'ss:Type' => 'String'
|
33
33
|
end
|
34
34
|
xml.Cell do
|
35
|
-
xml.Data (
|
35
|
+
xml.Data (t :time).to_s, 'ss:Type' => 'String'
|
36
36
|
end
|
37
37
|
else
|
38
38
|
xml.Cell do
|
39
|
-
xml.Data (
|
39
|
+
xml.Data (t field).to_s, 'ss:Type' => 'String'
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -44,7 +44,7 @@ xml.Workbook(
|
|
44
44
|
|
45
45
|
@records.each do |transaction|
|
46
46
|
xml.Row do
|
47
|
-
@
|
47
|
+
@search.fields.each do |field|
|
48
48
|
field_map = controller.c_fields[field.to_sym]
|
49
49
|
if field == 'time'
|
50
50
|
xml.Cell 'ss:StyleID' => 'DateOnlyFormat' do
|
@@ -54,7 +54,8 @@ xml.Workbook(
|
|
54
54
|
xml.Data transaction.completed_at.gmtime.xmlschema, 'ss:Type' => 'DateTime'
|
55
55
|
end
|
56
56
|
else
|
57
|
-
|
57
|
+
attr_method = field_map[:attr_method]
|
58
|
+
value = attr_method ? attr_method.call(transaction) : transaction.send(field)
|
58
59
|
xml.Cell field_map[:excel_style] ? { 'ss:StyleID' => field_map[:excel_style] } : {} do
|
59
60
|
xml.Data value, 'ss:Type' => field_map[:excel_type] || 'String'
|
60
61
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
-
|
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
|
-
<%=
|
6
|
-
<%= stylesheet_link_tag 'drilldown' %>
|
5
|
+
<%= stylesheet_link_tag 'application' %>
|
7
6
|
<body>
|
8
7
|
<style type="text/css">
|
9
|
-
|
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">
|
data/config/routes.rb
CHANGED
@@ -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}
|
9
|
+
route "draw_drilldown :#{singular_name}"
|
10
10
|
end
|
11
11
|
end
|
@@ -33,8 +33,12 @@ 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
|
39
|
+
return unless base.c_target_class.try :paranoid?
|
40
|
+
|
41
|
+
base.c_base_condition = "#{base.c_target_class.table_name}.deleted_at IS NULL"
|
38
42
|
end
|
39
43
|
|
40
44
|
def base_condition(base_condition)
|
@@ -101,7 +105,9 @@ module SimpleDrilldown
|
|
101
105
|
raise "Unexpected options: #{options.inspect}" if options.present?
|
102
106
|
|
103
107
|
queries.each do |query_opts|
|
104
|
-
|
108
|
+
unless (query_opts.keys - %i[select includes where]).empty?
|
109
|
+
raise "Unknown options: #{query_opts.keys.inspect}"
|
110
|
+
end
|
105
111
|
end
|
106
112
|
|
107
113
|
c_dimension_defs[name.to_s] = {
|
@@ -125,7 +131,8 @@ module SimpleDrilldown
|
|
125
131
|
pretty_name: I18n.t(name, default: :"activerecord.models.#{name}"),
|
126
132
|
queries: queries,
|
127
133
|
reverse: reverse,
|
128
|
-
select_expression:
|
134
|
+
select_expression:
|
135
|
+
queries.size == 1 ? queries[0][:select] : "COALESCE(#{queries.map { |q| q[:select] }.join(',')})",
|
129
136
|
row_class: row_class,
|
130
137
|
url_param_name: name.to_s
|
131
138
|
}
|
@@ -182,7 +189,7 @@ module SimpleDrilldown
|
|
182
189
|
dimension_def = c_dimension_defs[field]
|
183
190
|
raise "Unknown filter field: #{field.inspect}" if dimension_def.nil?
|
184
191
|
|
185
|
-
values =
|
192
|
+
values = Array(values)
|
186
193
|
if dimension_def[:interval]
|
187
194
|
values *= 2 if values.size == 1
|
188
195
|
raise "Need 2 values for interval filter: #{values.inspect}" if values.size != 2
|
@@ -237,9 +244,9 @@ module SimpleDrilldown
|
|
237
244
|
when Hash
|
238
245
|
sql = +''
|
239
246
|
include.each do |parent, child|
|
240
|
-
sql <<
|
247
|
+
sql << " #{make_join(joins, model, parent)}"
|
241
248
|
ass = model.to_s.camelize.constantize.reflect_on_association parent
|
242
|
-
sql <<
|
249
|
+
sql << " #{make_join(joins, parent, child, ass.class_name.constantize)}"
|
243
250
|
end
|
244
251
|
sql
|
245
252
|
when Symbol
|
@@ -373,8 +380,7 @@ module SimpleDrilldown
|
|
373
380
|
selected = @search.filter[dimension_name] || []
|
374
381
|
raise "Unknown dimension #{dimension_name.inspect}: #{c_dimension_defs.keys.inspect}" unless dimension
|
375
382
|
|
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 } || [])
|
383
|
+
choices = [[t(:all), nil]] + (legal_values_for_dimension(dimension) || [])
|
378
384
|
choices_html = choices.map do |c|
|
379
385
|
%(<option value="#{c[1]}"#{' SELECTED' if selected.include?(c[1])}>#{c[0]}</option>)
|
380
386
|
end.join("\n")
|
@@ -383,36 +389,37 @@ module SimpleDrilldown
|
|
383
389
|
|
384
390
|
def html_export
|
385
391
|
index(false)
|
386
|
-
render template: '/drilldown/html_export', layout: 'print'
|
392
|
+
render template: '/drilldown/html_export', layout: '../drilldown/print'
|
387
393
|
end
|
388
394
|
|
389
395
|
def excel_export
|
390
396
|
index(false)
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
397
|
+
set_excel_headers
|
398
|
+
if params.dig(:search, :list) == '1'
|
399
|
+
@records = get_records(@result)
|
400
|
+
render template: '/drilldown/excel_export_records', layout: false
|
401
|
+
else
|
402
|
+
render template: '/drilldown/excel_export', layout: false
|
403
|
+
end
|
395
404
|
end
|
396
405
|
|
397
406
|
def excel_export_records
|
407
|
+
params[:search] ||= {}
|
398
408
|
params[:search][:list] = '1'
|
399
|
-
|
400
|
-
@records = get_records(@result)
|
401
|
-
headers['Content-Type'] = 'application/vnd.ms-excel'
|
402
|
-
headers['Content-Disposition'] = 'attachment; filename="drilldown.xml"'
|
403
|
-
render template: '/drilldown/excel_export_records', layout: false
|
409
|
+
excel_export
|
404
410
|
end
|
405
411
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
headers['Content-
|
411
|
-
headers['
|
412
|
-
render template: '/drilldown/xml_export', layout: false
|
412
|
+
private
|
413
|
+
|
414
|
+
def set_excel_headers
|
415
|
+
headers['Content-Type'] = 'application/vnd.ms-excel'
|
416
|
+
headers['Content-Disposition'] = %{attachment; filename="#{c_target_class.table_name}.xml"}
|
417
|
+
headers['Cache-Control'] = ''
|
413
418
|
end
|
414
419
|
|
415
|
-
|
420
|
+
def legal_values_for_dimension(dimension)
|
421
|
+
dimension[:legal_values]&.call(@search)&.map { |o| o.is_a?(Array) ? o[0..1].map(&:to_s) : o.to_s }
|
422
|
+
end
|
416
423
|
|
417
424
|
def new_search_object
|
418
425
|
SimpleDrilldown::Search.new(params[:search]&.to_unsafe_h, c_default_fields, c_default_select_value)
|
@@ -495,7 +502,8 @@ module SimpleDrilldown
|
|
495
502
|
|
496
503
|
result_rows = []
|
497
504
|
loop do
|
498
|
-
sub_result = result_from_rows(rows, row_index, dimension + 1,
|
505
|
+
sub_result = result_from_rows(rows, row_index, dimension + 1,
|
506
|
+
values + [rows[row_index]["value#{dimension + 1}"]])
|
499
507
|
break if sub_result.nil?
|
500
508
|
|
501
509
|
result_rows << sub_result
|
@@ -517,23 +525,20 @@ module SimpleDrilldown
|
|
517
525
|
end
|
518
526
|
|
519
527
|
def populate_list(conditions, includes, result, values)
|
520
|
-
if result[:rows]
|
521
|
-
|
522
|
-
end
|
528
|
+
return result[:rows].each { |r| populate_list(conditions, includes, r, values + [r[:value]]) } if result[:rows]
|
529
|
+
|
523
530
|
list_includes = merge_includes(includes, c_list_includes)
|
524
531
|
@search.fields.each do |field|
|
525
532
|
field_def = c_fields[field.to_sym]
|
526
533
|
raise "Field definition missing for: #{field.inspect}" unless field_def
|
527
534
|
|
528
535
|
field_includes = field_def[:include]
|
529
|
-
if field_includes
|
530
|
-
list_includes = merge_includes(list_includes , field_includes)
|
531
|
-
end
|
536
|
+
list_includes = merge_includes(list_includes, field_includes) if field_includes
|
532
537
|
end
|
533
538
|
if @search.list_change_times
|
534
539
|
@history_fields.each do |f|
|
535
540
|
if @search.fields.include? f
|
536
|
-
list_includes = merge_includes(list_includes, assignment: { order: :"#{f}_changes" }
|
541
|
+
list_includes = merge_includes(list_includes, assignment: { order: :"#{f}_changes" })
|
537
542
|
end
|
538
543
|
end
|
539
544
|
end
|
@@ -546,12 +551,12 @@ module SimpleDrilldown
|
|
546
551
|
|
547
552
|
def merge_includes(*args)
|
548
553
|
hash = hash_includes(*args)
|
549
|
-
result = hash.dup.map
|
554
|
+
result = hash.dup.map do |k, v|
|
550
555
|
if v.blank?
|
551
556
|
hash.delete(k)
|
552
557
|
k
|
553
558
|
end
|
554
|
-
|
559
|
+
end.compact
|
555
560
|
result << hash unless hash.blank?
|
556
561
|
case result.size
|
557
562
|
when 0
|
@@ -567,14 +572,15 @@ module SimpleDrilldown
|
|
567
572
|
args.inject({}) do |h, inc|
|
568
573
|
case inc
|
569
574
|
when Array
|
570
|
-
inc.each
|
575
|
+
inc.each do |v|
|
571
576
|
h = hash_includes(h, v)
|
572
|
-
|
577
|
+
end
|
573
578
|
when Hash
|
574
|
-
inc.each
|
579
|
+
inc.each do |k, v|
|
575
580
|
h[k] = merge_includes(h[k], v)
|
576
|
-
|
581
|
+
end
|
577
582
|
when NilClass, FalseClass
|
583
|
+
# Leave as it is
|
578
584
|
when String, Symbol
|
579
585
|
h[inc] ||= []
|
580
586
|
else
|
@@ -3,6 +3,10 @@
|
|
3
3
|
module SimpleDrilldown
|
4
4
|
# View helper for SimpleDrilldown
|
5
5
|
module Helper
|
6
|
+
# FIXME(uwe): Should not be necessary: https://github.com/rails/rails/issues/41038
|
7
|
+
include Rails.application.routes.url_helpers
|
8
|
+
# EMXIF
|
9
|
+
|
6
10
|
def value_label(dimension_index, value)
|
7
11
|
dimension = @dimensions[dimension_index]
|
8
12
|
return nil if dimension.nil?
|
@@ -11,9 +15,8 @@ module SimpleDrilldown
|
|
11
15
|
end
|
12
16
|
|
13
17
|
def caption
|
14
|
-
result = @search.title ||
|
15
|
-
|
16
|
-
result.gsub('$date', [*@search.filter[:calendar_date]].uniq.join(' - '))
|
18
|
+
result = @search.title || caption_txt
|
19
|
+
result.gsub('$date', Array(@search.filter[:calendar_date]).uniq.join(' - '))
|
17
20
|
end
|
18
21
|
|
19
22
|
def subcaption
|
@@ -21,9 +24,15 @@ module SimpleDrilldown
|
|
21
24
|
end
|
22
25
|
|
23
26
|
def summary_row(result, parent_result = nil, dimension = 0, headers = [], new_row = true)
|
24
|
-
html = render(partial: '/drilldown/summary_row', locals: {
|
27
|
+
html = render(partial: '/drilldown/summary_row', locals: {
|
28
|
+
result: result, parent_result: parent_result, new_row: new_row, dimension: dimension,
|
29
|
+
headers: headers, with_results: !result[:rows]
|
30
|
+
})
|
25
31
|
if result[:rows]
|
26
|
-
sub_headers = headers + [{
|
32
|
+
sub_headers = headers + [{
|
33
|
+
value: result[:value],
|
34
|
+
display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0)
|
35
|
+
}]
|
27
36
|
significant_rows = result[:rows].reject { |r| r[:row_count].zero? }
|
28
37
|
significant_rows.each_with_index do |r, i|
|
29
38
|
html << summary_row(r, result, dimension + 1, sub_headers, i.positive?)
|
@@ -31,7 +40,12 @@ module SimpleDrilldown
|
|
31
40
|
elsif @search.list
|
32
41
|
html << render(partial: '/drilldown/record_list', locals: { result: result })
|
33
42
|
end
|
34
|
-
|
43
|
+
if dimension < @dimensions.size
|
44
|
+
html << render(partial: '/drilldown/summary_total_row',
|
45
|
+
locals: {
|
46
|
+
result: result, parent_result: parent_result, headers: headers.dup, dimension: dimension
|
47
|
+
})
|
48
|
+
end
|
35
49
|
|
36
50
|
html
|
37
51
|
end
|
@@ -41,25 +55,42 @@ module SimpleDrilldown
|
|
41
55
|
if result[:rows]
|
42
56
|
significant_rows = result[:rows].reject { |r| r[:row_count].zero? }
|
43
57
|
significant_rows.each_with_index do |r, i|
|
44
|
-
sub_headers =
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
sub_headers =
|
59
|
+
if i.zero?
|
60
|
+
if dimension.zero?
|
61
|
+
headers
|
62
|
+
else
|
63
|
+
headers + [{
|
64
|
+
value: result[:value],
|
65
|
+
display_row_count: result[:nodes] + result[:row_count] * (@search.list ? 1 : 0)
|
66
|
+
}]
|
67
|
+
end
|
68
|
+
else
|
69
|
+
[] # [{:value => result[:value], :row_count => result[:row_count]}]
|
70
|
+
end
|
53
71
|
xml << excel_summary_row(r, result, dimension + 1, sub_headers)
|
54
72
|
end
|
55
73
|
else
|
56
|
-
xml << render(partial: '/drilldown/excel_summary_row',
|
74
|
+
xml << render(partial: '/drilldown/excel_summary_row',
|
75
|
+
locals: { result: result, parent_result: parent_result, headers: headers.dup,
|
76
|
+
dimension: dimension })
|
57
77
|
|
58
78
|
xml << render(partial: '/drilldown/excel_record_list', locals: { result: result }) if @search.list
|
59
79
|
end
|
60
80
|
|
61
|
-
|
81
|
+
if dimension < @dimensions.size
|
82
|
+
xml << render(partial: '/drilldown/excel_summary_total_row', locals: {
|
83
|
+
result: result, headers: headers.dup, dimension: dimension
|
84
|
+
})
|
85
|
+
end
|
62
86
|
xml
|
63
87
|
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def caption_txt
|
92
|
+
"#{controller.c_target_class} #{t(@search.select_value.downcase)}" +
|
93
|
+
(@dimensions && @dimensions.any? ? " by #{@dimensions.map { |d| d[:pretty_name] }.join(' and ')}" : '')
|
94
|
+
end
|
64
95
|
end
|
65
96
|
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module SimpleDrilldown
|
4
4
|
# Routing helper methods
|
5
5
|
module Routing
|
6
|
-
def draw_drilldown(path, controller =
|
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[
|
10
|
-
|
11
|
-
end
|
10
|
+
scope path, controller: controller, as: path do
|
11
|
+
%i[excel_export excel_export_records html_export].each { |action| get action }
|
12
|
+
get 'choices/:dimension_name', action: :choices, as: :choices
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
@@ -19,17 +19,9 @@ module SimpleDrilldown
|
|
19
19
|
VOLUME_COMPENSATED = 'VOLUME_COMPENSATED'
|
20
20
|
end
|
21
21
|
|
22
|
-
attr_reader :dimensions
|
23
|
-
|
24
|
-
|
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] =
|
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')
|
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.
|
4
|
+
version: 0.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uwe Kubosch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chartkick
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '1.1'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
60
|
+
version: '1.1'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: sqlite3
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,7 +113,7 @@ files:
|
|
113
113
|
- app/views/drilldown/data_2.builder
|
114
114
|
- app/views/drilldown/data_3.builder
|
115
115
|
- app/views/drilldown/excel_export.builder
|
116
|
-
- app/views/drilldown/
|
116
|
+
- app/views/drilldown/excel_export_records.builder
|
117
117
|
- app/views/drilldown/html_export.html.erb
|
118
118
|
- app/views/drilldown/index.html.erb
|
119
119
|
- app/views/drilldown/print.html.erb
|
@@ -146,14 +146,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
146
|
requirements:
|
147
147
|
- - ">="
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version: '
|
149
|
+
version: '2.5'
|
150
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
151
|
requirements:
|
152
152
|
- - ">="
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '0'
|
155
155
|
requirements: []
|
156
|
-
rubygems_version: 3.
|
156
|
+
rubygems_version: 3.2.3
|
157
157
|
signing_key:
|
158
158
|
specification_version: 4
|
159
159
|
summary: Simple data warehouse and drilldown.
|