simple_drilldown 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{LICENSE.txt → MIT-LICENSE} +1 -3
- data/README.md +15 -16
- data/Rakefile +32 -0
- data/app/assets/config/simple_drilldown_manifest.js +1 -0
- data/app/assets/stylesheets/simple_drilldown/application.css +121 -0
- data/app/controllers/simple_drilldown/application_controller.rb +7 -0
- data/app/helpers/simple_drilldown/application_helper.rb +6 -0
- data/app/jobs/simple_drilldown/application_job.rb +6 -0
- data/app/mailers/simple_drilldown/application_mailer.rb +8 -0
- data/app/models/simple_drilldown/application_record.rb +7 -0
- data/app/views/drilldown/_chart.html.erb +57 -0
- data/app/views/drilldown/_excel_record_list.builder +7 -0
- data/app/views/drilldown/_excel_row.builder +24 -0
- data/app/views/drilldown/_excel_row_header.builder +10 -0
- data/app/views/drilldown/_excel_styles.builder +69 -0
- data/app/views/drilldown/_excel_summary_row.builder +16 -0
- data/app/views/drilldown/_excel_summary_total_row.builder +14 -0
- data/app/views/drilldown/_field.html.erb +39 -0
- data/app/views/drilldown/_fields.html.erb +12 -0
- data/app/views/drilldown/_filter.html.erb +20 -0
- data/app/views/drilldown/_record_list.html.erb +12 -0
- data/app/views/drilldown/_row.html.erb +13 -0
- data/app/views/drilldown/_row_header.html.erb +8 -0
- data/app/views/drilldown/_summary_row.html.erb +18 -0
- data/app/views/drilldown/_summary_table.html.erb +12 -0
- data/app/views/drilldown/_summary_total_row.html.erb +4 -0
- data/app/views/drilldown/_tab_buttons.html.erb +5 -0
- data/app/views/drilldown/data_0.builder +10 -0
- data/app/views/drilldown/data_1.builder +11 -0
- data/app/views/drilldown/data_2.builder +37 -0
- data/app/views/drilldown/data_3.builder +37 -0
- data/app/views/drilldown/excel_export.builder +42 -0
- data/app/views/drilldown/excel_export_transactions.builder +90 -0
- data/app/views/drilldown/html_export.html.erb +6 -0
- data/app/views/drilldown/index.html.erb +107 -0
- data/app/views/drilldown/print.html.erb +18 -0
- data/app/views/layouts/simple_drilldown/application.html.erb +15 -0
- data/config/locales/en.yml +23 -0
- data/config/locales/nb.yml +20 -0
- data/config/routes.rb +4 -0
- data/lib/generators/drilldown_controller/USAGE +8 -0
- data/lib/generators/drilldown_controller/drilldown_controller_generator.rb +8 -0
- data/lib/generators/drilldown_controller/templates/drilldown_controller.rb.erb +41 -0
- data/lib/simple_drilldown.rb +3 -3
- data/lib/simple_drilldown/drilldown_controller.rb +389 -274
- data/lib/simple_drilldown/drilldown_helper.rb +68 -0
- data/lib/simple_drilldown/engine.rb +11 -0
- data/lib/simple_drilldown/search.rb +12 -1
- data/lib/simple_drilldown/version.rb +1 -1
- data/lib/tasks/simple_drilldown_tasks.rake +5 -0
- metadata +85 -34
- data/.document +0 -5
- data/.gitignore +0 -22
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -89
- data/README.rdoc +0 -19
- data/lib/sample_drilldown_controller.rb +0 -95
- data/lib/simple_drilldown/simple_drilldown_helper.rb +0 -66
- data/simple_drilldown.gemspec +0 -24
- data/test/helper.rb +0 -18
- data/test/test_simple_drilldown.rb +0 -7
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.Row do
|
4
|
+
1.upto(dimension - headers.size - 1) { |_n| xml.Cell('ss:StyleID' => 'Outer') }
|
5
|
+
|
6
|
+
headers.each_with_index do |h, i|
|
7
|
+
xml.Cell('ss:StyleID' => 'Outer', 'ss:Index' => (dimension - headers.size + i).to_s) do
|
8
|
+
xml.Data value_label(@dimensions.size - headers.size + i - 1, h[:value]), 'ss:Type' => 'String'
|
9
|
+
end
|
10
|
+
end
|
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' }
|
13
|
+
end
|
14
|
+
|
15
|
+
xml.Cell('ss:StyleID' => 'Outer') { xml.Data result[:count].inspect, 'ss:Type' => 'Number' }
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.Row do
|
4
|
+
1.upto(dimension) { |_n| xml.Cell('ss:StyleID' => 'Outer') }
|
5
|
+
|
6
|
+
(@dimensions.size - dimension).times do |i|
|
7
|
+
xml.Cell 'ss:Index' => (dimension + i + 1).to_s, 'ss:StyleID' => 'Sum' do
|
8
|
+
xml.Data '', 'ss:Type' => 'String'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
xml.Cell 'ss:Index' => (@dimensions.size + 1).to_s, 'ss:StyleID' => 'Sum' do
|
12
|
+
xml.Data result[:count], 'ss:Type' => 'Number'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<% dimension = @dimension_defs[dimension_name] %>
|
2
|
+
<% if dimension_name == 'calendar_date' %>
|
3
|
+
<% dates = [*@search.filter[dimension_name]] %>
|
4
|
+
<tr>
|
5
|
+
<td align="right" valign="top">
|
6
|
+
<%= form.label "filter[calendar_date]", t(:from_date) %>
|
7
|
+
</td>
|
8
|
+
<td>
|
9
|
+
<input type="text" data-behaviour="datepicker" id="search_filter[from_<%=dimension_name%>]"
|
10
|
+
name="search[filter][<%=dimension_name%>][]" class="form-control" value="<%=dates[0]%>"
|
11
|
+
placeholder="yyyy-mm-dd"/>
|
12
|
+
</td>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<td align="right" valign="top">
|
16
|
+
<%= form.label "filter[calendar_date]", t(:to_date) %>
|
17
|
+
</td>
|
18
|
+
<td>
|
19
|
+
<input type="text" data-behaviour="datepicker" id="search_filter[to_<%=dimension_name%>]"
|
20
|
+
name="search[filter][<%=dimension_name%>][]" class="form-control" value="<%=dates[1] || dates[0]%>"
|
21
|
+
placeholder="yyyy-mm-dd"/>
|
22
|
+
</td>
|
23
|
+
</tr>
|
24
|
+
<% else %>
|
25
|
+
<div class="form-group">
|
26
|
+
<%= form.label "filter[#{dimension_name}]", t(dimension_name) %>
|
27
|
+
<%= select :search, :filter,
|
28
|
+
choices,
|
29
|
+
{:selected => @search.filter[dimension_name]},
|
30
|
+
{
|
31
|
+
id: "search_filter[#{dimension_name}]",
|
32
|
+
name: "search[filter][#{dimension_name}][]",
|
33
|
+
size: 5,
|
34
|
+
multiple: true,
|
35
|
+
class: 'form-control',
|
36
|
+
}
|
37
|
+
%>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<style>
|
2
|
+
.field_label {
|
3
|
+
width: 67%;
|
4
|
+
text-align: right;
|
5
|
+
}
|
6
|
+
</style>
|
7
|
+
|
8
|
+
<% @transaction_fields.each do | field | %>
|
9
|
+
<%=form.label "fields[#{field}]", t(field), :class => "field_label" %>
|
10
|
+
<%=form.check_box :fields, :id => "search_fields[#{field}]", :name => "search[fields][#{field}]", :checked => @search.fields.include?(field) %>
|
11
|
+
<br/>
|
12
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class="form-group">
|
2
|
+
<%= form.label :title, t(:title) %>
|
3
|
+
<%= form.text_field :title, class: 'form-control' %>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<% choices = Concurrent::Hash.new %>
|
7
|
+
<% threads = @dimension_defs.keys.map do |dimension_name| %>
|
8
|
+
<% dimension = @dimension_defs[dimension_name] %>
|
9
|
+
<% t = Thread.start do |thread| %>
|
10
|
+
<% ActiveRecord::Base.connection_pool.with_connection do %>
|
11
|
+
<% choices[dimension_name] = [[t(:all), nil]] + (dimension[:legal_values] && dimension[:legal_values].call(@search).map { |o| o.is_a?(Array) ? [o[0].to_s, o[1].to_s] : o.to_s } || []) %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
<% next [t, dimension_name] %>
|
15
|
+
<% end %>
|
16
|
+
<% threads.each do |t, dimension_name| %>
|
17
|
+
<% t.join %>
|
18
|
+
<%= render partial: 'drilldown/field', locals: {choices: choices[dimension_name] || [],
|
19
|
+
form: form, dimension_name: dimension_name} %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% unless result[:transactions].empty? %>
|
2
|
+
<tr>
|
3
|
+
<td colspan="<%=@summary_fields.size + 1%>">
|
4
|
+
<table class="table table-condensed table-bordered" style="padding-bottom: 10px;">
|
5
|
+
<%=render :partial => '/drilldown/row_header' %>
|
6
|
+
<% result[:transactions].each do |t| %>
|
7
|
+
<%=render :partial => '/drilldown/row', :locals => {:transaction => t, :previous_transaction => nil, :errors => [], :error_row => false, :meter1_errors => false} %>
|
8
|
+
<% end %>
|
9
|
+
</table>
|
10
|
+
</td>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<tr valign="top">
|
2
|
+
<% @search.fields.each do |field| %>
|
3
|
+
<td>
|
4
|
+
<% if field == 'time' %>
|
5
|
+
<%= (transaction.respond_to?(:completed_at) ? transaction.completed_at : transaction.created_at).localtime.strftime('%Y-%m-%d %H:%M') %>
|
6
|
+
<% else %>
|
7
|
+
<% field_def = @transaction_fields_map[field.to_sym] %>
|
8
|
+
<%= field_def[:attr_method] ? field_def[:attr_method].call(transaction) : transaction.send(field) %>
|
9
|
+
<% end %>
|
10
|
+
</td>
|
11
|
+
<% end %>
|
12
|
+
<td><%= detour_to t(:show), transaction %></td>
|
13
|
+
</tr>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% if new_row -%>
|
2
|
+
<tr class="<%= cycle("odd", "even", :name => "dim#{dimension}") %>">
|
3
|
+
<% ((dimension + 1)..(@dimensions.size)).each { |i| cycle("odd", "even", :name => "dim#{i}") if current_cycle("dim#{i}") != current_cycle("dim#{dimension}") } -%>
|
4
|
+
<% end -%>
|
5
|
+
<% if dimension > 0 %>
|
6
|
+
<td valign="top" rowspan="<%= result[:nodes] %>">
|
7
|
+
<%= link_to value_label(dimension - 1, result[:value]), @search.drill_down(@dimensions, *[headers[1..-1], result].flatten.map { |h| h[:value] }).url_options %>
|
8
|
+
</td>
|
9
|
+
<% end %>
|
10
|
+
<% if with_results %>
|
11
|
+
<td align="right">
|
12
|
+
<%= result[:count] %>
|
13
|
+
<% if parent_result && @search.percent %>
|
14
|
+
(<%= 100 * result[:count] / parent_result[:count] %>%)
|
15
|
+
<% end %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<table class="table table-condensed table-bordered">
|
2
|
+
<tr>
|
3
|
+
<% @dimensions.each do |d| %>
|
4
|
+
<th><%=h d[:pretty_name]%></th>
|
5
|
+
<% end %>
|
6
|
+
<th><%= t @target_class.table_name.capitalize %></th>
|
7
|
+
<%= @summary_fields.map{|l| "<th>#{t(l)}</th>"}.join("\n").html_safe %>
|
8
|
+
</tr>
|
9
|
+
|
10
|
+
<%=summary_row(@result) %>
|
11
|
+
|
12
|
+
</table>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.chart(xAxisName: 'Elections',
|
4
|
+
showValues: '1', caption: caption, subcaption: subcaption,
|
5
|
+
yAxisName: "Election #{t(@search.select_value.downcase)}", numberSuffix: '') do
|
6
|
+
xml.set(
|
7
|
+
name: @result[:value0],
|
8
|
+
value: @result[:count]
|
9
|
+
)
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.chart(xAxisName: (@dimensions[0][:pretty_name] || 'Elections').gsub("'", ''),
|
4
|
+
showValues: '1', caption: caption, subcaption: subcaption,
|
5
|
+
yAxisName: "Election #{t(@search.select_value.downcase)}", numberSuffix: '') do
|
6
|
+
@result[:rows].each do |res|
|
7
|
+
xml.set(name: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(res[:value]) : res[:value],
|
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)) : '')
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
9
|
+
unless @result[:rows].empty?
|
10
|
+
xml.categories do
|
11
|
+
@result[:rows].each do |result|
|
12
|
+
xml.category label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(result[:value]) : result[:value]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@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
|
18
|
+
@result[:rows].each do |res|
|
19
|
+
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)))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
xml.styles do
|
28
|
+
xml.definition do
|
29
|
+
xml.style name: 'captionFont', type: 'font', size: '15'
|
30
|
+
end
|
31
|
+
|
32
|
+
xml.application do
|
33
|
+
xml.apply toObject: 'caption', styles: 'captionfont'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
9
|
+
unless @result[:rows].empty?
|
10
|
+
xml.categories do
|
11
|
+
@result[:rows].each do |result|
|
12
|
+
xml.category label: @dimensions[0][:label_method] ? @dimensions[0][:label_method].call(result[:value]) : result[:value]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@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
|
18
|
+
@result[:rows].each do |res|
|
19
|
+
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)))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
xml.styles do
|
28
|
+
xml.definition do
|
29
|
+
xml.style name: 'captionFont', type: 'font', size: '15'
|
30
|
+
end
|
31
|
+
|
32
|
+
xml.application do
|
33
|
+
xml.apply toObject: 'caption', styles: 'captionfont'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.instruct! :xml, version: '1.0', encoding: 'UTF-8'
|
4
|
+
xml.instruct! 'mso-application', progid: 'Excel.Sheet'
|
5
|
+
|
6
|
+
xml.Workbook(
|
7
|
+
'xmlns' => 'urn:schemas-microsoft-com:office:spreadsheet',
|
8
|
+
'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
|
9
|
+
'xmlns:x' => 'urn:schemas-microsoft-com:office:excel',
|
10
|
+
'xmlns:ss' => 'urn:schemas-microsoft-com:office:spreadsheet',
|
11
|
+
'xmlns:html' => 'http://www.w3.org/TR/REC-html40'
|
12
|
+
) do
|
13
|
+
xml << render('/drilldown/excel_styles')
|
14
|
+
|
15
|
+
xml.Worksheet 'ss:Name' => 'Transaction Summary' do
|
16
|
+
xml.Table do
|
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
|
19
|
+
xml.Data caption, 'ss:Type' => 'String'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
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.Data subcaption, 'ss:Type' => 'String'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
xml.Row do
|
29
|
+
@dimensions.each do |d|
|
30
|
+
xml.Cell 'ss:StyleID' => 'Heading' do
|
31
|
+
xml.Data (h d[:pretty_name]).to_s, 'ss:Type' => 'String'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
xml.Cell 'ss:StyleID' => 'Heading' do
|
35
|
+
xml.Data (t :count).to_s, 'ss:Type' => 'String'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
xml << excel_summary_row(@result)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.instruct! :xml, version: '1.0', encoding: 'UTF-8'
|
4
|
+
xml.instruct! 'mso-application', progid: 'Excel.Sheet'
|
5
|
+
|
6
|
+
xml.Workbook(
|
7
|
+
'xmlns' => 'urn:schemas-microsoft-com:office:spreadsheet',
|
8
|
+
'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
|
9
|
+
'xmlns:x' => 'urn:schemas-microsoft-com:office:excel',
|
10
|
+
'xmlns:ss' => 'urn:schemas-microsoft-com:office:spreadsheet',
|
11
|
+
'xmlns:html' => 'http://www.w3.org/TR/REC-html40'
|
12
|
+
) do
|
13
|
+
xml << render(partial: '/layouts/excel_styles')
|
14
|
+
|
15
|
+
xml.Worksheet 'ss:Name' => 'Transactions' do
|
16
|
+
xml.Table do
|
17
|
+
xml.Row 'ss:Height' => '18.75' do
|
18
|
+
xml.Cell 'ss:MergeAcross' => '35', 'ss:StyleID' => 'MainTitle' do
|
19
|
+
xml.Data caption, 'ss:Type' => 'String'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
xml.Row 'ss:Height' => '15.75' do
|
23
|
+
xml.Cell 'ss:MergeAcross' => '35', 'ss:StyleID' => 'SubTitle' do
|
24
|
+
xml.Data subcaption, 'ss:Type' => 'String'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
xml.Row 'ss:StyleID' => 'Heading' do
|
29
|
+
@transaction_fields.each do |field|
|
30
|
+
if field == 'time'
|
31
|
+
xml.Cell do
|
32
|
+
xml.Data (l :short_date).to_s, 'ss:Type' => 'String'
|
33
|
+
end
|
34
|
+
xml.Cell do
|
35
|
+
xml.Data (l :time).to_s, 'ss:Type' => 'String'
|
36
|
+
end
|
37
|
+
else
|
38
|
+
xml.Cell do
|
39
|
+
xml.Data (l field).to_s, 'ss:Type' => 'String'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@transactions.each do |transaction|
|
46
|
+
xml.Row do
|
47
|
+
@transaction_fields.each do |field|
|
48
|
+
field_map = @transaction_fields_map[field.to_sym]
|
49
|
+
if field == 'time'
|
50
|
+
xml.Cell 'ss:StyleID' => 'DateOnlyFormat' do
|
51
|
+
xml.Data transaction.completed_at.gmtime.xmlschema, 'ss:Type' => 'DateTime'
|
52
|
+
end
|
53
|
+
xml.Cell 'ss:StyleID' => 'TimeOnlyFormat' do
|
54
|
+
xml.Data transaction.completed_at.gmtime.xmlschema, 'ss:Type' => 'DateTime'
|
55
|
+
end
|
56
|
+
else
|
57
|
+
value = field_map[:attr_method] ? field_map[:attr_method].call(transaction) : transaction.send(field)
|
58
|
+
xml.Cell field_map[:excel_style] ? { 'ss:StyleID' => field_map[:excel_style] } : {} do
|
59
|
+
xml.Data value, 'ss:Type' => field_map[:excel_type] || 'String'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
xml.Row do
|
66
|
+
xml.Cell do
|
67
|
+
xml.Data '', 'ss:Type' => 'String'
|
68
|
+
end
|
69
|
+
xml.Cell do
|
70
|
+
xml.Data '', 'ss:Type' => 'String'
|
71
|
+
end
|
72
|
+
xml.Cell do
|
73
|
+
xml.Data '', 'ss:Type' => 'String'
|
74
|
+
end
|
75
|
+
xml.Cell do
|
76
|
+
xml.Data '', 'ss:Type' => 'String'
|
77
|
+
end
|
78
|
+
xml.Cell do
|
79
|
+
xml.Data '', 'ss:Type' => 'String'
|
80
|
+
end
|
81
|
+
xml.Cell do
|
82
|
+
xml.Data '', 'ss:Type' => 'String'
|
83
|
+
end
|
84
|
+
xml.Cell do
|
85
|
+
xml.Data '', 'ss:Type' => 'String'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
<% @page_title = "#{caption} #{subcaption}" %>
|
2
|
+
<%= javascript_include_tag 'chartkick' %>
|
3
|
+
<%= stylesheet_link_tag 'simple_drilldown/application' %>
|
4
|
+
<style type="text/css">
|
5
|
+
table#drill_down_layout > tbody > tr > td {
|
6
|
+
border: none;
|
7
|
+
font-size: 13px
|
8
|
+
}
|
9
|
+
|
10
|
+
table#drill_down_layout td {
|
11
|
+
padding: 2px;
|
12
|
+
line-height: 18px
|
13
|
+
}
|
14
|
+
</style>
|
15
|
+
|
16
|
+
<%= form_for @search, :html => {:id => 'edit_search_SEARCH', :method => :get, :class => :search, :style => 'background: inherit', :onsubmit => 'return this.submit()'}, :url => {} do |form| %>
|
17
|
+
<div class="row">
|
18
|
+
<div class="col-md-3" valign="top">
|
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>
|
23
|
+
</li>
|
24
|
+
</ul>
|
25
|
+
|
26
|
+
<!-- Tab panes -->
|
27
|
+
<div class="tab-content">
|
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} %>
|
31
|
+
</div>
|
32
|
+
<div class="tab-pane" id="fields">
|
33
|
+
<%= render :partial => '/drilldown/tab_buttons', :locals => {:form => form} %>
|
34
|
+
<%= render :partial => '/drilldown/fields', :locals => {:form => form} %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
</div>
|
39
|
+
<div class="col-md-9">
|
40
|
+
<div class="row" valign="top">
|
41
|
+
<div class="col-md-12">
|
42
|
+
<%= render :partial => '/drilldown/chart', :locals => {:form => form} %>
|
43
|
+
<br/>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div class="row">
|
48
|
+
<div class="col-md-12" valign="top">
|
49
|
+
<div style="float: right; clear: both;">
|
50
|
+
<%= link_to 'Excel', @search.url_options.merge(action: :excel_export) %> |
|
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'] %>
|
52
|
+
</div>
|
53
|
+
<br/>
|
54
|
+
|
55
|
+
<%= render :partial => '/drilldown/summary_table' %>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<% end %> <!-- END FORM -->
|
62
|
+
|
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 == "") {
|
70
|
+
continue;
|
71
|
+
}
|
72
|
+
if (el.type == "select-multiple") {
|
73
|
+
if (el.selectedIndex > 0) {
|
74
|
+
for (var j = 0; j < el.options.length; j++) {
|
75
|
+
// Ignore "All" and unselected options
|
76
|
+
if (el.options[j].selected) {
|
77
|
+
params.push("" + el.name + "=" + encodeURIComponent(el.options[j].value));
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
continue;
|
82
|
+
}
|
83
|
+
if (el.type == "select-one" && el.selectedIndex == 0) {
|
84
|
+
continue;
|
85
|
+
}
|
86
|
+
if (el.type == "checkbox" && el.checked != true) {
|
87
|
+
continue;
|
88
|
+
}
|
89
|
+
if (el.type == "radio" && el.checked != true) {
|
90
|
+
continue;
|
91
|
+
}
|
92
|
+
if (el.type == "hidden" && (el.value == "0" || el.value == "")) {
|
93
|
+
continue;
|
94
|
+
}
|
95
|
+
if (el.type == "submit") {
|
96
|
+
continue;
|
97
|
+
}
|
98
|
+
params.push("" + el.name + "=" + encodeURIComponent(el.value));
|
99
|
+
}
|
100
|
+
location = form.action + "?" + params.join('&');
|
101
|
+
return false;
|
102
|
+
};
|
103
|
+
|
104
|
+
$(document).ready(function () {
|
105
|
+
$('[data-behaviour~=datepicker]').datepicker({format: "yyyy-mm-dd"});
|
106
|
+
})
|
107
|
+
<% end %>
|