active_scaffold_export 3.6.1 → 3.8.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: 248e0924b010eb5822ad05cdb735f486bd848295091e3962d27c5d3717611f97
4
- data.tar.gz: d19079c8bb42ee90124f5b97440b0c0564fc418b28f23d4d7de8dd47d466a2c2
3
+ metadata.gz: b710509185a1efb5c735e70ac427495e39798ba165dd9dd392f4dc6696511fdb
4
+ data.tar.gz: 25fe42fc33045159ab7cd6f47eef137e44ecf8703829fae6b263fcd2abebab8e
5
5
  SHA512:
6
- metadata.gz: 882365bcd892ca7bdbda4a0638b30baca1a7e7c08220dbf53ab1751976d0904149dd1da50431210e09b9eaf9ad8a62999abd03f28f95660121ec6d054da66767
7
- data.tar.gz: 2aeb345b8beff579c6ca03b5b2fc1a595c17ab471ac8de73ff4c492cd97c7782f41952369795ea0406af3d217b6776a9b0e6569b4868eae04b206a9219b9786f
6
+ metadata.gz: 446846da6e6032788f4f637d277e6a682afa71b1d1cbc3661ca5c55fbce5cd3dcdaf6161aace8f54b18cf8b8676547951a407aa146316836a062216b8517e361
7
+ data.tar.gz: 2bf4efd5ee989034947641d012e8ceedb97ff2c41cc466c925b9f23728635c4f9f9823002e961d412ce3577bad94e7d3eef319d9165c512fca92712d1592d83a
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Active Scaffold Export
2
- ### An [active scaffold](https://github.com/activescaffold/active_scaffold) addon to let it export data in CSV or XLSX format
2
+ An [active scaffold](https://github.com/activescaffold/active_scaffold) addon to let it export data in CSV or XLSX format
3
3
 
4
- ####How to?
4
+ ### How to?
5
5
  Easy. First get [active scaffold](https://github.com/activescaffold/active_scaffold) if you haven't yet.
6
6
  Then, add this to your Gemfile:
7
7
  ```
@@ -14,7 +14,7 @@ gem 'fastercsv'
14
14
  ```
15
15
  if you want xlsx format, add:
16
16
  ```
17
- gem 'axlsx_rails'
17
+ gem 'caxlsx_rails'
18
18
  ```
19
19
  if that gem is present, XLSX will be used by default.
20
20
  You can change this by adding to active scaffold config:
@@ -9,10 +9,10 @@
9
9
  }
10
10
 
11
11
  data = CSV.generate(**fcsv_options) do |csv|
12
- csv << fcsv_options[:headers] unless params[:skip_header] == 'true'
12
+ csv << fcsv_options[:headers] unless params[:skip_header]
13
13
  @records.each do |record|
14
14
  csv << @export_columns.collect { |column|
15
- get_export_column_value(record, column, :csv)
15
+ get_export_column_value(record, column, :csv).first
16
16
  }
17
17
  end
18
18
  end
@@ -23,19 +23,24 @@
23
23
  <%= content_tag(:label, text_field_tag('delimiter', export_config.default_delimiter, :size => 1, :maxlength => 1) + " #{as_(:delimiter)}".html_safe) %>
24
24
  </div>
25
25
  <div class="separator"></div>
26
+ <% if export_config.allow_full_download %>
26
27
  <div class="option checkbox-wrapper">
27
- <%= content_tag(:label, radio_button_tag('full_download', false, !export_config.default_full_download) + " #{as_(:this_page)}".html_safe) if export_config.allow_full_download %>
28
+ <%= content_tag(:label, radio_button_tag('full_download', false, !export_config.default_full_download) + " #{as_(:this_page)}".html_safe) %>
28
29
  </div>
29
30
  <div class="option checkbox-wrapper">
30
- <%= content_tag(:label, radio_button_tag('full_download', true, export_config.default_full_download) + " #{as_(:all_pages)}".html_safe) if export_config.allow_full_download %>
31
+ <%= content_tag(:label, radio_button_tag('full_download', true, export_config.default_full_download) + " #{as_(:all_pages)}".html_safe) %>
31
32
  </div>
32
33
  <div class="separator"></div>
34
+ <% end %>
35
+ <% if export_config.formats.many? %>
36
+ <% export_config.formats.each do |format| %>
33
37
  <div class="option checkbox-wrapper">
34
- <%= content_tag(:label, radio_button_tag('format', :xlsx, export_config.default_file_format.to_sym == :xlsx) + ' XLSX') %>
35
- </div>
36
- <div class="option checkbox-wrapper">
37
- <%= content_tag(:label, radio_button_tag('format', :csv, export_config.default_file_format.to_sym == :csv) + ' CSV') %>
38
+ <%= content_tag(:label, safe_join([radio_button_tag('format', format, export_config.default_file_format.to_sym == format), format.upcase], ' ')) %>
38
39
  </div>
40
+ <% end %>
41
+ <% else %>
42
+ <%= hidden_field_tag 'format', export_config.formats[0] %>
43
+ <% end %>
39
44
  &nbsp;
40
45
  </div>
41
46
  <div class="separator"></div>
@@ -49,17 +49,13 @@ module ActiveScaffold::Actions
49
49
  end
50
50
  response.headers['Content-Disposition'] = "attachment; filename=#{export_file_name}"
51
51
 
52
- unless defined? Mime::XLSX
53
- Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx
54
- end
55
-
56
52
  respond_to_action(:export)
57
53
  end
58
54
 
59
55
  protected
60
56
 
61
57
  def export_respond_to_csv
62
- response.headers['Content-type'] = 'text/csv'
58
+ response.headers['Content-type'] = Mime[:csv]
63
59
  # start streaming output
64
60
  self.response_body = Enumerator.new do |y|
65
61
  find_items_for_export do |records|
@@ -72,17 +68,30 @@ module ActiveScaffold::Actions
72
68
  end
73
69
 
74
70
  def export_respond_to_xlsx
75
- response.headers['Content-type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
71
+ response.headers['Content-type'] = Mime[:xlsx]
76
72
  pkg = Axlsx::Package.new
77
- header = pkg.workbook.styles.add_style sz: 11, b: true,:bg_color => "69B5EF", :fg_color => "FF", alignment: { horizontal: :center }
78
73
  pkg.workbook.add_worksheet(name: worksheet_name) do |sheet|
79
- sheet.add_row(@export_columns.collect { |column| view_context.format_export_column_header_name(column) }, style: header) unless params[:skip_header]
74
+ styles = @export_columns.collect { |column| view_context.export_column_header_style(column, :xlsx) }
75
+ widths = @export_columns.map.with_index { |column, i| styles.dig(i, :width) || column.export_options&.dig(:xlsx, :width) || :auto }
76
+ unless params[:skip_header]
77
+ styles.map! { |style| pkg.workbook.styles.add_style style if style }
78
+ sheet.add_row(@export_columns.collect { |column| view_context.format_export_column_header_name(column) }, style: styles, widths: widths)
79
+ end
80
80
  find_items_for_export do |records|
81
81
  records.each do |record|
82
- sheet.add_row @export_columns.collect { |column| view_context.get_export_column_value(record, column, :xlsx) }
82
+ row = []
83
+ styles = []
84
+ @export_columns.each do |column|
85
+ data, style = view_context.get_export_column_value(record, column, :xlsx)
86
+ style = pkg.workbook.styles.add_style style if style
87
+ row << data
88
+ styles << style
89
+ end
90
+ sheet.add_row row, style: styles, widths: widths
83
91
  end
84
92
  end
85
93
  end
94
+ customize_xlsx(pkg)
86
95
  stream = pkg.to_stream # when adding rows to sheet, they won't pass to this stream if declared before. axlsx issue?
87
96
  self.response_body = Enumerator.new do |y|
88
97
  y << stream.read
@@ -95,6 +104,9 @@ module ActiveScaffold::Actions
95
104
  truncate(Axlsx::WORKSHEET_MAX_NAME_LENGTH, options)
96
105
  end
97
106
 
107
+ def customize_xlsx(package)
108
+ end
109
+
98
110
  def export_columns
99
111
  return @export_columns if defined? @export_columns
100
112
  @export_columns = active_scaffold_config.export.columns.reject { |col| params[:export_columns][col.to_sym].nil? }
@@ -138,12 +150,8 @@ module ActiveScaffold::Actions
138
150
  def export_file_name
139
151
  filename = self.controller_name.clone
140
152
 
141
- if params[:format]
142
- if params[:format].to_sym == :xlsx
143
- filename << '.xlsx'
144
- elsif params[:format].to_sym == :csv
145
- filename << '.csv'
146
- end
153
+ if params[:format] && active_scaffold_config.export.formats.map(&:to_s).include?(params[:format])
154
+ filename << ".#{params[:format]}"
147
155
  else
148
156
  filename << ".#{active_scaffold_config.export.default_file_format}"
149
157
  end
@@ -3,7 +3,15 @@ module ActiveScaffold::Config
3
3
  self.crud_type = :read
4
4
 
5
5
  def initialize(core_config)
6
+ super
6
7
  @core = core_config
8
+ self.show_form = self.class.show_form
9
+ self.allow_full_download = self.class.allow_full_download
10
+ self.force_quotes = self.class.force_quotes
11
+ self.default_full_download = self.class.default_full_download
12
+ self.default_delimiter = self.class.default_delimiter
13
+ self.default_skip_header = self.class.default_skip_header
14
+ self.default_file_format = self.class.default_file_format
7
15
  @formats = [:csv, :xlsx]
8
16
  end
9
17
 
@@ -30,45 +38,63 @@ module ActiveScaffold::Config
30
38
  end
31
39
  end
32
40
 
33
- attr_writer :show_form, :allow_full_download, :force_quotes, :default_full_download, :default_delimiter, :default_skip_header, :default_deselected_columns, :default_file_format
34
- def show_form
35
- self.show_form = @core.export_show_form if @show_form.nil?
36
- @show_form
37
- end
38
- def allow_full_download
39
- self.allow_full_download = @core.export_allow_full_download if @allow_full_download.nil?
40
- @allow_full_download
41
- end
42
- def force_quotes
43
- self.force_quotes = @core.export_force_quotes if @force_quotes.nil?
44
- @force_quotes
45
- end
46
- def default_full_download
47
- self.default_full_download = @core.export_default_full_download if @default_full_download.nil?
48
- @default_full_download
49
- end
50
- def default_delimiter
51
- self.default_delimiter = @core.export_default_delimiter if @default_delimiter.nil?
52
- @default_delimiter
53
- end
54
- def default_skip_header
55
- self.default_skip_header = @core.export_default_skip_header if @default_skip_header.nil?
56
- @default_skip_header
57
- end
41
+ # whether open a form to allow selecting columns and format settings, or export directly with the defined settings in the controller
42
+ cattr_accessor :show_form, instance_accessor: false
43
+ @@show_form = true
44
+
45
+ # whether user can ask for full or page export, or default is forced
46
+ cattr_accessor :allow_full_download, instance_accessor: false
47
+ @@allow_full_download = true
48
+
49
+ # force_quotes option for CSV library
50
+ cattr_accessor :force_quotes, instance_accessor: false
51
+ @@force_quotes = false
52
+
53
+ # default setting for full export or page export, it can be changed in the form if show_form is enabled
54
+ cattr_accessor :default_full_download, instance_accessor: false
55
+ @@default_full_download = true
56
+
57
+ # default column separator for CSV, it can be changed in the form if show_form is enabled
58
+ cattr_accessor :default_delimiter, instance_accessor: false
59
+ @@default_delimiter = ','
60
+
61
+ # wheter export a header (false) or skip exporting a header (true), it can be changed in the form if show_form is enabled
62
+ cattr_accessor :default_skip_header, instance_accessor: false
63
+ @@default_skip_header = false
64
+
65
+ # default file format to export, it can be changed in the form if show_form is enabled
66
+ cattr_accessor :default_file_format, instance_accessor: false
67
+ @@default_file_format = Gem::Specification::find_all_by_name('caxlsx').any? ? 'xlsx' : 'csv'
68
+
69
+ # instance-level configuration
70
+ # ----------------------------
71
+
72
+ # whether open a form to allow selecting columns and format settings, or export directly with the defined settings in the controller
73
+ attr_accessor :show_form
74
+
75
+ # whether user can ask for full or page export, or default is forced
76
+ attr_accessor :allow_full_download
77
+
78
+ # force_quotes option for CSV library
79
+ attr_accessor :force_quotes
80
+
81
+ # default setting for full export or page export, it can be changed in the form if show_form is enabled
82
+ attr_accessor :default_full_download
83
+
84
+ # default column separator for CSV, it can be changed in the form if show_form is enabled
85
+ attr_accessor :default_delimiter
86
+
87
+ # wheter export a header (false) or skip exporting a header (true), it can be changed in the form if show_form is enabled
88
+ attr_accessor :default_skip_header
89
+
90
+ # default file format to export, it can be changed in the form if show_form is enabled
91
+ attr_accessor :default_file_format
92
+
93
+ attr_writer :default_deselected_columns
58
94
  def default_deselected_columns
59
95
  self.default_deselected_columns = [] if @default_deselected_columns.nil?
60
96
  @default_deselected_columns
61
97
  end
62
- def default_file_format
63
- if @core.export_xlsx_avaliable
64
- self.default_file_format = @default_file_format || 'xlsx'
65
- else
66
- self.default_file_format = @default_file_format || @core.export_default_file_format
67
- end
68
- end
69
- def xlsx_present?
70
- Gem::Specification::find_all_by_name('axlsx_rails').any?
71
- end
72
98
 
73
99
  columns_accessor :columns
74
100
 
@@ -11,19 +11,25 @@ module ActiveScaffold
11
11
  # format_plural_association_export_column(association_records)
12
12
  def get_export_column_value(record, column, format)
13
13
  if (method = export_column_override(column))
14
- send(method, record)
14
+ value, options = send(method, record, format)
15
+ [value, options || column.export_options&.dig(format)]
16
+ elsif column.list_ui && (method = override_export_ui(column.list_ui))
17
+ value, options = send(method, record, column, format, ui_options: column.list_ui_options || column.options)
18
+ [value, options || column.export_options&.dig(format)]
15
19
  else
16
20
  raw_value = record.send(column.name)
17
21
 
18
- if column.association.nil? or column_empty?(raw_value)
19
- format_export_column(raw_value, format)
20
- elsif column.association
21
- if column.association.collection?
22
- format_plural_association_export_column(raw_value)
23
- else
24
- format_singular_association_export_column(raw_value)
22
+ value =
23
+ if column.association.nil? or column_empty?(raw_value)
24
+ format_export_column(raw_value, format)
25
+ elsif column.association
26
+ if column.association.collection?
27
+ format_plural_association_export_column(raw_value, format)
28
+ else
29
+ format_singular_association_export_column(raw_value, format)
30
+ end
25
31
  end
26
- end
32
+ [value, column.export_options&.dig(format)]
27
33
  end
28
34
  end
29
35
 
@@ -31,6 +37,15 @@ module ActiveScaffold
31
37
  override_helper column, 'export_column'
32
38
  end
33
39
 
40
+ # the naming convention for overriding column types with helpers
41
+ def override_export_ui(list_ui)
42
+ ActiveScaffold::Registry.cache :export_ui_overrides, list_ui do
43
+ method = "active_scaffold_export_#{list_ui}"
44
+ method if respond_to? method
45
+ end
46
+ end
47
+ alias override_export_ui? override_export_ui
48
+
34
49
  def format_export_column(raw_value, format)
35
50
  method = "format_value_for_#{format}"
36
51
  respond_to?(method) ? send(method, raw_value) : raw_value
@@ -48,22 +63,29 @@ module ActiveScaffold
48
63
  end
49
64
  end
50
65
 
51
- def format_singular_association_export_column(association_record)
66
+ def format_singular_association_export_column(association_record, format)
52
67
  format_value(association_record.to_label)
53
68
  end
54
69
 
55
- def format_plural_association_export_column(association_records)
70
+ def format_plural_association_export_column(association_records, format)
56
71
  firsts = association_records.first(4).collect { |v| v.to_label }
57
72
  firsts[3] = ' ' if firsts.length == 4
58
73
  format_value(firsts.join(','))
59
74
  end
60
75
 
61
- ## This helper can be overridden to change the way that the headers
62
- # are formatted. For instance, you might want column.name.to_s.humanize
76
+ ## This helper can be overridden to change the name of the headers
77
+ # For instance, you might want column.name.to_s.humanize
63
78
  def format_export_column_header_name(column)
64
79
  column.label
65
80
  end
66
81
 
82
+ ## This helper can be overridden to change the style of the headers
83
+ def export_column_header_style(column, format)
84
+ if format == :xlsx
85
+ @default_style ||= {sz: 11, b: true, bg_color: "69B5EF", fg_color: "FF", alignment: {horizontal: :center}}
86
+ end
87
+ end
88
+
67
89
  end
68
90
  end
69
91
  end
@@ -0,0 +1,5 @@
1
+ module ActiveScaffoldExport
2
+ module Column
3
+ attr_accessor :export_options
4
+ end
5
+ end
@@ -4,11 +4,17 @@ module ActiveScaffoldExport
4
4
  ActiveSupport.on_load :active_scaffold_routing do
5
5
  self::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:show_export] = :get
6
6
  self::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:export] = :post
7
+ unless Mime[:xlsx]
8
+ Mime::Type.register 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', :xlsx
9
+ end
10
+ unless Mime[:csv]
11
+ Mime::Type.register 'text/csv', :csv
12
+ end
7
13
  end
8
14
  end
9
15
 
10
- initializer 'active_scaffold_sortable.extensions' do
11
- require "active_scaffold_export/config/core.rb"
16
+ initializer 'active_scaffold_export.extensions' do
17
+ ActiveScaffold::DataStructures::Column.send :include, ActiveScaffoldExport::Column
12
18
  end
13
19
  end
14
20
  end
@@ -1,8 +1,8 @@
1
1
  module ActiveScaffoldExport
2
2
  module Version
3
3
  MAJOR = 3
4
- MINOR = 6
5
- PATCH = 1
4
+ MINOR = 8
5
+ PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
@@ -8,6 +8,7 @@ module ActiveScaffoldExport
8
8
  def self.root
9
9
  File.dirname(__FILE__) + "/.."
10
10
  end
11
+ autoload 'Column', 'active_scaffold_export/column.rb'
11
12
  end
12
13
 
13
14
  module ActiveScaffold
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_scaffold_export
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.1
4
+ version: 3.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volker Hochstein
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-26 00:00:00.000000000 Z
13
+ date: 2024-07-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: active_scaffold
@@ -47,7 +47,7 @@ files:
47
47
  - lib/active_scaffold/config/export.rb
48
48
  - lib/active_scaffold/helpers/export_helpers.rb
49
49
  - lib/active_scaffold_export.rb
50
- - lib/active_scaffold_export/config/core.rb
50
+ - lib/active_scaffold_export/column.rb
51
51
  - lib/active_scaffold_export/engine.rb
52
52
  - lib/active_scaffold_export/version.rb
53
53
  homepage: http://github.com/active_scaffold/active_scaffold_export
@@ -1,17 +0,0 @@
1
- # Need to open the AS module carefully due to Rails 2.3 lazy loading
2
- ActiveScaffold::Config::Core.class_eval do
3
- # For some note obvious reasons, the class variables need to be defined
4
- # *before* the cattr !!
5
- self.send :class_variable_set, :@@export_show_form, true
6
- self.send :class_variable_set, :@@export_allow_full_download, true
7
- self.send :class_variable_set, :@@export_default_full_download, true
8
- self.send :class_variable_set, :@@export_force_quotes, false
9
- self.send :class_variable_set, :@@export_default_skip_header, false
10
- self.send :class_variable_set, :@@export_default_delimiter, ','
11
- self.send :class_variable_set, :@@export_default_file_format, Gem::Specification::find_all_by_name('axlsx_rails').any? ? 'xlsx' : 'csv'
12
-
13
- cattr_accessor :export_show_form, :export_allow_full_download,
14
- :export_force_quotes, :export_default_full_download,
15
- :export_default_delimiter, :export_default_skip_header,
16
- :export_default_file_format, :export_xlsx_avaliable
17
- end