active_list 7.2.0 → 7.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_list/exporters/abstract_exporter.rb +34 -1
- data/lib/active_list/exporters/csv_exporter.rb +6 -2
- data/lib/active_list/exporters/excel_csv_exporter.rb +2 -2
- data/lib/active_list/exporters/open_document_spreadsheet_exporter.rb +34 -52
- data/lib/active_list/generator.rb +3 -2
- data/lib/active_list/generator/finder.rb +58 -0
- data/lib/active_list/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 493c967944f09543ead6e2782c62bbf1379d7db9ce73aaf99a31a30ae7f7ef26
|
4
|
+
data.tar.gz: 5b06ebaf0f046687c035febfd6399d86c700ab15540aa8629faf30793889dc29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abac2cf9a73fbb3ebcc26466e481178f4fb3645b30dbfb00dd01a807e84f6132d59b0bb3d4cd016ad9998cbc0c709c75012132f69fd9b4c434f4cb13adb7da9e
|
7
|
+
data.tar.gz: 8cf5cb483304b2da19a74b86ee1289a9d14612c640c6394f1bebed329498ddb4d2f7b9714d614db2df2813e45de7e5cebafd251cf38b988bcb0ff94ed709978f
|
@@ -12,12 +12,39 @@ module ActiveList
|
|
12
12
|
'txt'
|
13
13
|
end
|
14
14
|
|
15
|
+
def file_name_code
|
16
|
+
"file_name = #{table.model.name}.model_name.human\n".c
|
17
|
+
end
|
18
|
+
|
15
19
|
def mime_type
|
16
20
|
Mime::TEXT
|
17
21
|
end
|
18
22
|
|
23
|
+
def generate_file_code(format)
|
24
|
+
code = file_name_code
|
25
|
+
if generator.export_class
|
26
|
+
code << generator.exportable_query_code
|
27
|
+
code << "#{generator.export_class}.perform_later(user: current_user,\n"
|
28
|
+
code << " query: query,\n"
|
29
|
+
code << " content: #{columns_to_hash},\n"
|
30
|
+
code << " file_name: file_name,\n"
|
31
|
+
code << " format: '#{format}',\n"
|
32
|
+
code << " file_extension: '#{file_extension}')\n"
|
33
|
+
code << "notify_success(:document_in_preparation)\n"
|
34
|
+
code << "redirect_to(:back)\n"
|
35
|
+
else
|
36
|
+
code << generate_data_code
|
37
|
+
code << send_data_code
|
38
|
+
end
|
39
|
+
code.c
|
40
|
+
end
|
41
|
+
|
19
42
|
def send_data_code
|
20
|
-
raise NotImplementedError
|
43
|
+
raise NotImplementedError.new("#{self.class.name}#send_data_code must be implemented in sub-classes.")
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_data_code
|
47
|
+
raise NotImplementedError.new("#{self.class.name}#generate_data_code must be implemented in sub-classes.")
|
21
48
|
end
|
22
49
|
|
23
50
|
def columns_headers(options = {})
|
@@ -46,6 +73,12 @@ module ActiveList
|
|
46
73
|
end
|
47
74
|
array
|
48
75
|
end
|
76
|
+
|
77
|
+
def columns_to_hash
|
78
|
+
table.exportable_columns.map do |column|
|
79
|
+
[column.header_code, column.exporting_datum_code('record').to_s]
|
80
|
+
end.to_h
|
81
|
+
end
|
49
82
|
end
|
50
83
|
end
|
51
84
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module ActiveList
|
2
2
|
module Exporters
|
3
3
|
class CsvExporter < AbstractExporter
|
4
|
+
|
4
5
|
def file_extension
|
5
6
|
'csv'
|
6
7
|
end
|
@@ -9,7 +10,7 @@ module ActiveList
|
|
9
10
|
Mime[:csv]
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
+
def generate_data_code
|
13
14
|
record = 'r'
|
14
15
|
code = generator.select_data_code(paginate: false)
|
15
16
|
code << "data = ::CSV.generate do |csv|\n"
|
@@ -18,9 +19,12 @@ module ActiveList
|
|
18
19
|
code << " csv << [#{columns_to_array(:body, record: record).join(', ')}]\n"
|
19
20
|
code << " end\n"
|
20
21
|
code << "end\n"
|
21
|
-
code << "send_data(data, type: #{mime_type.to_s.inspect}, disposition: 'inline', filename: #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i, '_') + '.#{file_extension}')\n"
|
22
22
|
code.c
|
23
23
|
end
|
24
|
+
|
25
|
+
def send_data_code
|
26
|
+
"send_data(data, type: #{mime_type.to_s.inspect}, disposition: 'inline', filename: file_name.parameterize + '.#{file_extension}')\n".c
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
@@ -4,6 +4,7 @@ Mime::Type.register('text/csv', :xcsv) unless defined? Mime::XCSV
|
|
4
4
|
module ActiveList
|
5
5
|
module Exporters
|
6
6
|
class ExcelCsvExporter < CsvExporter
|
7
|
+
|
7
8
|
def file_extension
|
8
9
|
'csv'
|
9
10
|
end
|
@@ -12,7 +13,7 @@ module ActiveList
|
|
12
13
|
Mime[:xcsv]
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
+
def generate_data_code
|
16
17
|
record = 'r'
|
17
18
|
code = generator.select_data_code(paginate: false)
|
18
19
|
encoding = 'CP1252'
|
@@ -22,7 +23,6 @@ module ActiveList
|
|
22
23
|
code << " csv << [#{columns_to_array(:body, record: record, encoding: encoding).join(', ')}]\n"
|
23
24
|
code << " end\n"
|
24
25
|
code << "end\n"
|
25
|
-
code << "send_data(data, type: #{mime_type.to_s.inspect}, disposition: 'inline', filename: #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i,'_')+'.#{file_extension}')\n"
|
26
26
|
code.c
|
27
27
|
end
|
28
28
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'rodf'
|
4
4
|
|
5
5
|
# Register ODS format unless is already set
|
6
6
|
Mime::Type.register('application/vnd.oasis.opendocument.spreadsheet', :ods) unless defined? Mime::ODS
|
@@ -8,11 +8,6 @@ Mime::Type.register('application/vnd.oasis.opendocument.spreadsheet', :ods) unle
|
|
8
8
|
module ActiveList
|
9
9
|
module Exporters
|
10
10
|
class OpenDocumentSpreadsheetExporter < AbstractExporter
|
11
|
-
DATE_ELEMENTS = {
|
12
|
-
'm' => '<number:month number:style="long"/>',
|
13
|
-
'd' => '<number:day number:style="long"/>',
|
14
|
-
'Y' => '<number:year/>'
|
15
|
-
}.freeze
|
16
11
|
|
17
12
|
def file_extension
|
18
13
|
'ods'
|
@@ -22,55 +17,42 @@ module ActiveList
|
|
22
17
|
Mime[:ods]
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
xml_escape = "to_s.gsub('&', '&').gsub('\\'', ''').gsub('<', '<').gsub('>', '>')"
|
27
|
-
xml_escape << ".force_encoding('US-ASCII')" if xml_escape.respond_to?(:force_encoding)
|
20
|
+
def generate_data_code
|
28
21
|
record = 'r'
|
29
|
-
code = generator.select_data_code(paginate: false)
|
30
|
-
code << "name = #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i, '_')\n"
|
31
|
-
code << "file = ActiveList.temporary_directory.join(name + rand(999_999_999).to_s(36) + '.#{file_extension}')\n"
|
32
|
-
code << "FileUtils.mkdir_p(file.dirname)\n"
|
33
|
-
code << "Zip::OutputStream.open(file) do |zile|\n"
|
34
|
-
# MimeType in first place
|
35
|
-
code << " zile.put_next_entry('mimetype', nil, nil, Zip::Entry::STORED)\n"
|
36
|
-
code << " zile << '#{mime_type}'\n"
|
37
|
-
|
38
|
-
# Manifest
|
39
|
-
code << " zile.put_next_entry('META-INF/manifest.xml')\n"
|
40
|
-
code << " zile << ('<?xml version=\"1.0\" encoding=\"UTF-8\"?><manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\"><manifest:file-entry manifest:media-type=\"#{mime_type}\" manifest:full-path=\"/\"/><manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"content.xml\"/></manifest:manifest>')\n"
|
41
|
-
code << " zile.put_next_entry('content.xml')\n"
|
42
22
|
|
43
|
-
code
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
23
|
+
code = generator.select_data_code(paginate: false)
|
24
|
+
code << <<~RUBY
|
25
|
+
records = #{generator.records_variable_name}
|
26
|
+
data = RODF::Spreadsheet.new
|
27
|
+
|
28
|
+
data.instance_eval do
|
29
|
+
office_style :head, family: :cell do
|
30
|
+
property :text, 'font-weight': :bold
|
31
|
+
property :paragraph, 'text-align': :center
|
32
|
+
end
|
33
|
+
|
34
|
+
table #{table.model.name}.model_name.human do
|
35
|
+
row do
|
36
|
+
#{columns_to_array(:header)}.each do |header|
|
37
|
+
cell header, style: :head
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
for #{record} in records
|
42
|
+
row do
|
43
|
+
#{columns_to_array(:body, record: record)}.each do |value|
|
44
|
+
cell value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
code.c
|
52
|
+
end
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
code << " zile << ('<table:table-column table:number-columns-repeated=\"#{table.exportable_columns.size}\"/>')\n"
|
54
|
-
code << " zile << ('<table:table-header-rows><table:table-row>" + columns_headers.collect { |h| "<table:table-cell table:style-name=\"header\" office:value-type=\"string\"><text:p>'+(#{h}).#{xml_escape}+'</text:p></table:table-cell>" }.join + "</table:table-row></table:table-header-rows>')\n"
|
55
|
-
code << " for #{record} in #{generator.records_variable_name}\n"
|
56
|
-
code << " zile << ('<table:table-row>" + table.exportable_columns.collect do |column|
|
57
|
-
'<table:table-cell' + (if column.numeric? || column.datatype == :decimal
|
58
|
-
" office:value-type=\"float\" office:value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
|
59
|
-
elsif column.datatype == :boolean
|
60
|
-
" office:value-type=\"boolean\" office:boolean-value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
|
61
|
-
elsif column.datatype == :date
|
62
|
-
" office:value-type=\"date\" table:style-name=\"ce1\" office:date-value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
|
63
|
-
else
|
64
|
-
' office:value-type="string"'
|
65
|
-
end) + "><text:p>'+(" + column.exporting_datum_code(record, true) + ").#{xml_escape}+'</text:p></table:table-cell>"
|
66
|
-
end.join + "</table:table-row>')\n"
|
67
|
-
code << " end\n"
|
68
|
-
code << " zile << ('</table:table></office:spreadsheet></office:body></office:document-content>')\n"
|
69
|
-
code << "end\n"
|
70
|
-
code << "send_file(file, stream: false, type: #{mime_type.to_s.inspect}, disposition: 'inline', filename: name+'.#{file_extension}')\n"
|
71
|
-
# code << "File.delete(file)\n" # Removes tmp files before they explode the disk
|
72
|
-
# raise code
|
73
|
-
code
|
54
|
+
def send_data_code
|
55
|
+
"send_data(data.bytes, type: #{mime_type.to_s.inspect}, disposition: 'inline', filename: file_name.parameterize + '.#{file_extension}')\n".c
|
74
56
|
end
|
75
57
|
end
|
76
58
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ActiveList
|
2
2
|
class Generator
|
3
|
-
attr_accessor :table, :controller, :controller_method_name, :view_method_name, :records_variable_name
|
3
|
+
attr_accessor :table, :controller, :controller_method_name, :view_method_name, :records_variable_name, :export_class
|
4
4
|
|
5
5
|
def initialize(*args, &_block)
|
6
6
|
options = args.extract_options!
|
@@ -12,6 +12,7 @@ module ActiveList
|
|
12
12
|
@view_method_name = "_#{@controller.controller_name}_list_#{name}_tag"
|
13
13
|
@records_variable_name = "@#{name}"
|
14
14
|
@table = ActiveList::Definition::Table.new(name, model, options)
|
15
|
+
@export_class = options[:export_class]
|
15
16
|
if block_given?
|
16
17
|
yield @table
|
17
18
|
else
|
@@ -47,7 +48,7 @@ module ActiveList
|
|
47
48
|
code << " end\n"
|
48
49
|
for format, exporter in ActiveList::Exporters.hash
|
49
50
|
code << " format.#{format} do\n"
|
50
|
-
code << exporter.new(self).
|
51
|
+
code << exporter.new(self).generate_file_code(format).dig(3)
|
51
52
|
code << " end\n"
|
52
53
|
end
|
53
54
|
code << " end\n"
|
@@ -64,6 +64,64 @@ module ActiveList
|
|
64
64
|
code
|
65
65
|
end
|
66
66
|
|
67
|
+
def exportable_query_code(options = {})
|
68
|
+
unless @table.options.keys.include?(:order)
|
69
|
+
columns = @table.table_columns
|
70
|
+
@table.options[:order] = (columns.any? ? columns.first.name.to_sym : { id: :desc })
|
71
|
+
end
|
72
|
+
|
73
|
+
class_name = "options[\"constant_name\"]&.constantize || #{@table.model.name}"
|
74
|
+
class_name = "(controller_name != '#{class_name.tableize}' && !options[\"constant_name\"] ? controller_name.to_s.classify.constantize : #{class_name})" if collection?
|
75
|
+
|
76
|
+
code = ''
|
77
|
+
|
78
|
+
code << "query = #{class_name}.to_s\n"
|
79
|
+
code << "query << #{scope_code.inspect}\n" if scope_code
|
80
|
+
|
81
|
+
if select_code
|
82
|
+
code << "select = #{select_code}\n"
|
83
|
+
code << "query << \".select(\"\n"
|
84
|
+
code << "query << select.inspect\n"
|
85
|
+
code << "query << \")\"\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
if from_code
|
89
|
+
code << "from = #{from_code}\n"
|
90
|
+
code << "query << \".from(\"\n"
|
91
|
+
code << "query << from.inspect\n"
|
92
|
+
code << "query << \")\"\n"
|
93
|
+
end
|
94
|
+
|
95
|
+
unless @table.options[:conditions].blank?
|
96
|
+
code << "condition = #{conditions_code}\n"
|
97
|
+
code << "query << \".where(\"\n"
|
98
|
+
code << "query << condition.inspect\n"
|
99
|
+
code << "query << \")\"\n"
|
100
|
+
end
|
101
|
+
|
102
|
+
code << "query << \".joins(#{@table.options[:joins].inspect})\"\n" unless @table.options[:joins].blank?
|
103
|
+
|
104
|
+
unless includes_reflections.empty?
|
105
|
+
expr = includes_reflections.inspect[1..-2]
|
106
|
+
code << "query << \".includes(#{expr})\"\n"
|
107
|
+
code << "query << \".references(#{expr})\"\n"
|
108
|
+
end
|
109
|
+
|
110
|
+
unless @table.options[:group].blank?
|
111
|
+
code << "group = #{@table.options[:group].inspect}\n"
|
112
|
+
code << "query << \".group(\"\n"
|
113
|
+
code << "query << group.inspect\n"
|
114
|
+
code << "query << \")\"\n"
|
115
|
+
end
|
116
|
+
|
117
|
+
code << "order = #{var_name(:order)}\n"
|
118
|
+
code << "query << \".reorder(\"\n"
|
119
|
+
code << "query << order.inspect\n"
|
120
|
+
code << "query << \")\"\n"
|
121
|
+
|
122
|
+
code.c
|
123
|
+
end
|
124
|
+
|
67
125
|
protected
|
68
126
|
|
69
127
|
# Compute includes Hash
|
data/lib/active_list/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brice Texier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -86,6 +86,20 @@ dependencies:
|
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rodf
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
104
|
name: sqlite3
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|