active_list 6.9.3 → 7.2.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
- SHA1:
3
- metadata.gz: 1d974ce0487a1daa388beac4ddbb5ff08a6c6c2c
4
- data.tar.gz: f9b308f405d8a88365bd1ecb457f189c1f79e12b
2
+ SHA256:
3
+ metadata.gz: 884ba63410b0ba502c551bdbf9035360ad2ddefefc959de5d0b3809274e57b60
4
+ data.tar.gz: 38f2ddcea9c3beb17cc6c4527152f1dba440869e4830d73d8f2c46db0b7c5f7e
5
5
  SHA512:
6
- metadata.gz: f2ef81730abf3d78093f164e899c2f0b7fc632058e634da3b4736c34ff4fe47d9e3e0688841d0a120b2aa80498e192d43018675fcc3cfc258573172743be71ae
7
- data.tar.gz: 973afbb44c55421b312fd2f8e6c78be04e7db128a581cb10173a4de0ae57c3b70c8020e70f0f5541765aaf36fdb5aa29f6f6b89c53d31af4dd40ebb3c573fb37
6
+ metadata.gz: dfa9c5a61880233f0b49f883cfe340a6b63d197a2369fd6a26a079ff87f059fea98ed8ee9f4bc853a97dd6b20112de497923ab62995f642907eb3dfabfcaa877
7
+ data.tar.gz: e3bf5e8a58a7ecdc81924f71476a433c03fb52b313ff304ebc8755ab13a39b7d2ea60194c669368d1139fbe37321fadbb38c854932fc46fce04d025c1e55e9e1
@@ -23,7 +23,7 @@ ActiveList = {}
23
23
  content = $(data)
24
24
  list_data = content.find(".list-data")
25
25
  list_control = content.find(".list-control")
26
- for type in ["actions", "pagination", "settings"]
26
+ for type in ["actions", "pagination", "footer-pagination","settings"]
27
27
  $("*[data-list-ref='#{list_id}'].list-#{type}").replaceWith list_control.find(".list-#{type}")
28
28
  list.find(".list-data").html(list_data)
29
29
  selection = list.prop('selection')
@@ -158,6 +158,11 @@ ActiveList = {}
158
158
 
159
159
  # Select row
160
160
  $(document).on "click", "*[data-list-source] td>input[data-list-selector]", (event) ->
161
+ mainCheckbox = $("input[data-list-selector]").first()
162
+ someChecked = $("*[data-list-source] td>input[data-list-selector]:checked").length > 0
163
+ someUnchecked = $("*[data-list-source] td>input[data-list-selector]:not(:checked)").length > 0
164
+ mainCheckbox.prop("indeterminate", someChecked && someUnchecked);
165
+ mainCheckbox.prop("checked", someChecked || !someUnchecked);
161
166
  AL.select $(this)
162
167
  true
163
168
 
@@ -78,7 +78,7 @@
78
78
  @include background(transparentize(mix($theme-color, #FFF, 40%), 0.7));
79
79
  }
80
80
 
81
- .list-pagination {
81
+ .list-pagination, .list-footer-pagination {
82
82
  & { text-align: left; }
83
83
  html[dir="rtl"] & { text-align: right; }
84
84
  & > * {
@@ -4,6 +4,7 @@ require 'action_dispatch'
4
4
  require 'rails'
5
5
  require 'code_string'
6
6
  require 'i18n-complements'
7
+ require 'tmpdir'
7
8
 
8
9
  module ActiveList
9
10
  # Build and returns a short UID
@@ -1,13 +1,14 @@
1
1
  module ActiveList
2
2
  module Definition
3
3
  class AbstractColumn
4
- attr_reader :table, :name, :id, :options
4
+ attr_reader :table, :name, :id, :options, :condition
5
5
 
6
6
  def initialize(table, name, options = {})
7
7
  @table = table
8
8
  @name = name.to_sym
9
9
  @options = options
10
10
  @hidden = !!@options.delete(:hidden)
11
+ @condition = @options.delete(:condition)
11
12
  @id = 'c' + @table.new_column_id # ActiveList.new_uid
12
13
  end
13
14
 
@@ -94,8 +94,8 @@ module ActiveList
94
94
  url[:redirect] ||= 'params[:redirect]'.c
95
95
  url.delete_if { |_k, v| v.nil? }
96
96
  cases << "#{record}.#{@name} == #{expected.inspect}\nlink_to(content_tag(:i) + h(#{url[:action].inspect}.t(scope: 'rest.actions'))"\
97
- ', {' + url.collect { |k, v| "#{k}: " + urlify(v, record) }.join(', ') + format + '}' \
98
- ", {class: '#{@name}'" + link_options + '}'\
97
+ ', {' + url.collect { |k, v| "#{k}: " + urlify(k, v, record) }.join(', ') + format + '}' \
98
+ ", {class: '#{@options[:icon_name] || @name}'" + link_options + '}'\
99
99
  ")\n"
100
100
  end
101
101
 
@@ -108,8 +108,8 @@ module ActiveList
108
108
  url[:id] = 'RECORD.id'.c if url[:id] == ID_PLACEHOLDER
109
109
  url[:redirect] ||= 'params[:redirect]'.c
110
110
  url.delete_if { |_k, v| v.nil? }
111
- url = '{' + url.collect { |k, v| "#{k}: " + urlify(v, record) }.join(', ') + format + '}'
112
- code = "{class: '#{@name}'" + link_options + '}'
111
+ url = '{' + url.collect { |k, v| "#{k}: " + urlify(k, v, record) }.join(', ') + format + '}'
112
+ code = "{class: '#{@options[:icon_name] || @name}'" + link_options + '}'
113
113
  code = "link_to(content_tag(:i) + h(' ' + :#{action}.t(scope: 'rest.actions')), " + url + ', ' + code + ')'
114
114
  end
115
115
  if @options[:if]
@@ -11,13 +11,7 @@ module ActiveList
11
11
  else
12
12
  @label_method.to_s.gsub('human_', '').to_sym
13
13
  end
14
- unless @sort_column = options[:sort]
15
- @sort_column = if @table.model.columns_hash[@label_method.to_s]
16
- @label_method
17
- elsif @table.model.columns_hash[@name.to_s]
18
- @name
19
- end
20
- end
14
+ @sort_column = get_sort_column
21
15
  @computation_method = options[:on_select]
22
16
  @column = @table.model.columns_hash[@label_method.to_s]
23
17
  end
@@ -51,9 +45,27 @@ module ActiveList
51
45
  code.c
52
46
  end
53
47
 
48
+ def get_sort_column
49
+ selects = @table.options[:select] || {}
50
+ selects_label = selects.find { |sql_name, name| name.to_s == @label_method.to_s }&.last
51
+ selects_name = selects.find { |sql_name, name| name.to_s == @name.to_s }&.last
52
+ if (selects_label || selects_name) && options[:sort].blank?
53
+ sort_column = (selects_label || selects_name)
54
+ else
55
+ sort_column = options[:sort]
56
+ sort_column ||= if @table.model.columns_hash[@label_method.to_s]
57
+ @label_method
58
+ elsif @table.model.columns_hash[@name.to_s]
59
+ @name
60
+ end
61
+ sort_column &&= "#{@table.model.table_name}.#{sort_column}"
62
+ end
63
+ sort_column
64
+ end
65
+
54
66
  # Returns the class name of the used model
55
67
  def class_name
56
- table.model.name
68
+ "RECORD.class.name.tableize".c
57
69
  end
58
70
 
59
71
  def sortable?
@@ -70,7 +82,7 @@ module ActiveList
70
82
  end
71
83
 
72
84
  def sort_expression
73
- "#{@table.model.table_name}.#{@sort_column}"
85
+ @sort_column
74
86
  end
75
87
  end
76
88
  end
@@ -1,6 +1,10 @@
1
1
  module ActiveList
2
2
  module Definition
3
3
  class EmptyColumn < AbstractColumn
4
+
5
+ def header_code
6
+ "#{name.to_s.strip.inspect}.t(scope: 'labels')".c
7
+ end
4
8
  end
5
9
  end
6
10
  end
@@ -1,6 +1,19 @@
1
1
  module ActiveList
2
2
  module Definition
3
3
  class StatusColumn < AttributeColumn
4
+ def initialize(table, name, options = {})
5
+ super
6
+
7
+ @tooltip_method = options.fetch(:tooltip_method, nil)
8
+ end
9
+
10
+ def tooltip_title_code(record, child)
11
+ c = if @tooltip_method.nil?
12
+ "#{record}.try(:human_status) || #{record}&.try(:human_state_name) || #{datum_value(record, child)}.to_s.capitalize"
13
+ else
14
+ "#{record}.#{@tooltip_method}"
15
+ end
16
+ end
4
17
  end
5
18
  end
6
19
  end
@@ -103,6 +103,10 @@ module ActiveList
103
103
  add :action, name, options
104
104
  end
105
105
 
106
+ # Add a new method in Table which permit to define empty columns
107
+ def empty(name, options = {})
108
+ add :empty, name, options
109
+ end
106
110
  # # Add a new method in Table which permit to define data columns
107
111
  # def attribute(name, options = {})
108
112
  # add :attribute, name, options
@@ -6,7 +6,7 @@ module ActiveList
6
6
  end
7
7
 
8
8
  def mime_type
9
- Mime::CSV
9
+ Mime[:csv]
10
10
  end
11
11
 
12
12
  def send_data_code
@@ -9,7 +9,7 @@ module ActiveList
9
9
  end
10
10
 
11
11
  def mime_type
12
- Mime::XCSV
12
+ Mime[:xcsv]
13
13
  end
14
14
 
15
15
  def send_data_code
@@ -19,7 +19,7 @@ module ActiveList
19
19
  end
20
20
 
21
21
  def mime_type
22
- Mime::ODS
22
+ Mime[:ods]
23
23
  end
24
24
 
25
25
  def send_data_code
@@ -7,7 +7,7 @@ module ActiveList
7
7
  @controller = options[:controller]
8
8
  name = args.shift || @controller.controller_name.to_sym
9
9
  model = (options[:model] || name).to_s.classify.constantize
10
- @collection = !!(model.name == @controller.controller_name.to_s.classify)
10
+ @collection = options[:collection] || !!(model.name == @controller.controller_name.to_s.classify)
11
11
  @controller_method_name = "list#{'_' + name.to_s if name != @controller.controller_name.to_sym}"
12
12
  @view_method_name = "_#{@controller.controller_name}_list_#{name}_tag"
13
13
  @records_variable_name = "@#{name}"
@@ -70,7 +70,7 @@ module ActiveList
70
70
  code = "# encoding: utf-8\n"
71
71
  code << "def #{view_method_name}(options={}, &block)\n"
72
72
  code << session_initialization_code.dig
73
- code << renderer.build_table_code.dig
73
+ code << "#{renderer.build_table_code}(options).dig\n"
74
74
  code << "end\n"
75
75
  # code.split("\n").each_with_index{|l, x| puts((x+1).to_s.rjust(4)+": "+l)}
76
76
  unless ::Rails.env.production?
@@ -83,7 +83,8 @@ module ActiveList
83
83
 
84
84
  def session_initialization_code
85
85
  code = "options = {} unless options.is_a? Hash\n"
86
- code << "options.update(params)\n"
86
+ # For Rails 5
87
+ code << "options.update(params.to_unsafe_h)\n"
87
88
  if defined?(User) && User.instance_methods.include?(:preference)
88
89
  code << "#{var_name(:params)} = YAML::load(current_user.preference('list.#{view_method_name}', YAML::dump({})).value).symbolize_keys\n"
89
90
  code << "#{var_name(:params)} = {} unless #{var_name(:params)}.is_a?(Hash)\n"
@@ -10,13 +10,14 @@ module ActiveList
10
10
  @table.options[:order] = (columns.any? ? columns.first.name.to_sym : { id: :desc })
11
11
  end
12
12
 
13
- class_name = @table.model.name
14
- class_name = "(controller_name != '#{class_name.tableize}' ? controller_name.to_s.classify.constantize : #{class_name})" if collection?
13
+ class_name = "options[\"constant_name\"]&.constantize || #{@table.model.name}"
14
+ class_name = "(controller_name != '#{class_name.tableize}' && !options[\"constant_name\"] ? controller_name.to_s.classify.constantize : #{class_name})" if collection?
15
15
 
16
16
  # Find data
17
17
  query_code = class_name.to_s
18
18
  query_code << scope_code if scope_code
19
19
  query_code << ".select(#{select_code})" if select_code
20
+ query_code << ".from(#{from_code})" if from_code
20
21
  query_code << ".where(#{conditions_code})" unless @table.options[:conditions].blank?
21
22
  query_code << ".joins(#{@table.options[:joins].inspect})" unless @table.options[:joins].blank?
22
23
  unless includes_reflections.empty?
@@ -26,8 +27,14 @@ module ActiveList
26
27
  end
27
28
 
28
29
  code = ''
29
- code << "#{var_name(:count)} = #{query_code}.count\n"
30
+ code << "#{query_code}\n"
30
31
 
32
+ code << if @table.options[:count].present?
33
+ "#{var_name(:count)} = #{query_code}.count(#{@table.options[:count].inspect})\n"
34
+ else
35
+ "#{var_name(:count)} = #{query_code}.count\n"
36
+ end
37
+ query_code << ".group(#{@table.options[:group].inspect})" unless @table.options[:group].blank?
31
38
  query_code << ".reorder(#{var_name(:order)})"
32
39
 
33
40
  if paginate
@@ -111,15 +118,33 @@ module ActiveList
111
118
  code
112
119
  end
113
120
 
121
+ def from_code
122
+ return nil unless @table.options[:from]
123
+ from = @table.options[:from]
124
+ code = ''
125
+ code << '(' + from.gsub(/\s*\n\s*/, ';') + ')'
126
+ code
127
+ end
128
+
114
129
  def select_code
115
130
  return nil unless @table.options[:distinct] || @table.options[:select]
116
131
  code = ''
117
132
  code << 'DISTINCT ' if @table.options[:distinct]
118
- code << "#{@table.model.table_name}.*"
119
133
  if @table.options[:select]
120
- code << @table.options[:select].collect { |k, v| ", #{k[0].to_s + '.' + k[1].to_s} AS #{v}" }.join
134
+ # code << @table.options[:select].collect { |k, v| ", #{k[0].to_s + '.' + k[1].to_s} AS #{v}" }.join
135
+ code << @table.options[:select].collect do |k, v|
136
+ c = if k.is_a? Array
137
+ k[0].to_s + '.' + k[1].to_s
138
+ else
139
+ k
140
+ end
141
+ c += " AS #{v}" unless v.blank?
142
+ c
143
+ end.join(', ')
144
+ else
145
+ code << "#{@table.model.table_name}.*"
121
146
  end
122
- ("'" + code + "'").c
147
+ ('"' + code + '"').c
123
148
  end
124
149
 
125
150
  def sanitize_condition(value)
@@ -20,11 +20,12 @@ module ActiveList
20
20
  end
21
21
  end
22
22
 
23
- def urlify(value, record_name)
24
- if value.is_a?(CodeString)
25
- '(' + value.gsub(/RECORD/, record_name) + ')'
23
+ def urlify(key, value, record_name, namespace = nil)
24
+ return value.inspect unless value.is_a?(CodeString)
25
+ if key == :controller && namespace
26
+ '(' + "'/#{namespace}/' + " + value.gsub(/RECORD/, record_name) + ')'
26
27
  else
27
- value.inspect
28
+ '(' + value.gsub(/RECORD/, record_name) + ')'
28
29
  end
29
30
  end
30
31
  end
@@ -34,14 +34,16 @@ module ActiveList
34
34
  code
35
35
  end
36
36
 
37
- def build_table_code
37
+ def build_table_code(options = {})
38
38
  record = 'r'
39
39
 
40
40
  # colgroup = columns_definition_code
41
41
  header = header_code
42
42
  extras = extras_codes
43
43
 
44
- code = generator.select_data_code
44
+ code = "#{generator.select_data_code}(options)\n"
45
+ # Hack for Rails 5
46
+ code << "__params = params.permit!\n"
45
47
  code << "#{var_name(:tbody)} = '<tbody data-total=\"' + #{var_name(:count)}.to_s + '\""
46
48
  if table.paginate?
47
49
  code << " data-per-page=\"' + #{var_name(:limit)}.to_s + '\""
@@ -51,11 +53,17 @@ module ActiveList
51
53
  code << "if #{var_name(:count)} > 0\n"
52
54
  code << " #{generator.records_variable_name}.each do |#{record}|\n"
53
55
  code << " #{var_name(:attrs)} = {id: 'r' + #{record}.id.to_s}\n"
56
+ code << " if #{var_name(:params)}[:data]\n"
57
+ code << " #{var_name(:params)}[:data] = [#{var_name(:params)}[:data]] unless #{var_name(:params)}[:data].is_a?(Array)\n"
58
+ code << " #{var_name(:params)}[:data].each do |attr|\n"
59
+ code << " #{var_name(:attrs)}['data-' + attr.gsub('_', '-')] = #{record}.send(attr)\n"
60
+ code << " end\n"
61
+ code << " end\n"
54
62
  if table.options[:line_class]
55
63
  code << " #{var_name(:attrs)}[:class] = (#{recordify!(table.options[:line_class], record)}).to_s\n"
56
- code << " #{var_name(:attrs)}[:class] << ' focus' if params['#{table.name}-id'].to_i == #{record}.id\n"
64
+ code << " #{var_name(:attrs)}[:class] << ' focus' if __params['#{table.name}-id'].to_i == #{record}.id\n"
57
65
  else
58
- code << " #{var_name(:attrs)}[:class] = 'focus' if params['#{table.name}-id'].to_i == #{record}.id\n"
66
+ code << " #{var_name(:attrs)}[:class] = 'focus' if __params['#{table.name}-id'].to_i == #{record}.id\n"
59
67
  end
60
68
  code << " #{var_name(:tbody)} << content_tag(:tr, #{var_name(:attrs)}) do\n"
61
69
  code << columns_to_cells(:body, record: record).dig(3)
@@ -107,6 +115,7 @@ module ActiveList
107
115
  code << "options[:content_for] ||= {}\n"
108
116
  code << "#{var_name(:extras)} = ''\n"
109
117
  extras.each do |name, ecode|
118
+ next if name == :footer_pagination
110
119
  code << "if options[:content_for][:#{name}]\n"
111
120
  code << " content_for(options[:content_for][:#{name}], (#{ecode}).html_safe)\n"
112
121
  code << "else\n"
@@ -127,10 +136,21 @@ module ActiveList
127
136
  code << "end\n"
128
137
  code << "#{var_name(:content)} << #{var_name(:tbody)}\n"
129
138
  code << "#{var_name(:content)} << '</table></div>'\n"
139
+
140
+ if table.options[:footer_pagination]
141
+ code << " footer_code = ''\n"
142
+ code << " if options[:content_for][:footer_pagination]\n"
143
+ code << " footer_code << content_for(options[:content_for][:pagination])\n"
144
+ code << " else\n"
145
+ code << " footer_code << (#{extras[:footer_pagination]})\n"
146
+ code << " end\n"
147
+ code << " #{var_name(:content)} << content_tag(:div, (footer_code).html_safe, class: 'list-control') unless footer_code.blank?\n"
148
+ end
149
+
130
150
  # code << "return #{var_name(:content)}.html_safe if options[:only] == 'content'\n"
131
151
 
132
152
  # Build whole
133
- code << "return ('<div id=\"#{uid}\" data-list-source=\"'+h(url_for(options.merge(:action => '#{generator.controller_method_name}')))+'\" data-list-redirect=\"' + params[:redirect].to_s + '\" class=\"active-list\">' + #{var_name(:content)} + '</div>').html_safe\n"
153
+ code << "return ('<div id=\"#{uid}\" data-list-source=\"'+h(url_for(options.merge(:action => '#{generator.controller_method_name}')))+'\" data-list-redirect=\"' + __params[:redirect].to_s + '\" class=\"active-list\">' + #{var_name(:content)} + '</div>').html_safe\n"
134
154
  # File.open('debug-activelist', 'w') { |file| file.write code }
135
155
  code
136
156
  end
@@ -150,17 +170,20 @@ module ActiveList
150
170
  children_mode = !!(nature == :children)
151
171
  for column in table.columns
152
172
  value_code = ''
173
+ title_value_code = ''
153
174
  if column.is_a? ActiveList::Definition::EmptyColumn
154
175
  value_code = 'nil'
155
176
  elsif column.is_a? ActiveList::Definition::StatusColumn
156
-
177
+ title_value_code = nil
157
178
  value_code = column.datum_code(record, children_mode)
179
+ title_code = column.tooltip_title_code(record, children_mode)
158
180
  levels = %w[go caution stop]
159
181
  lights = levels.collect do |light|
160
182
  "content_tag(:span, '', :class => #{light.inspect})"
161
183
  end.join(' + ')
162
184
  # Expected value are :valid, :warning, :error
163
- value_code = "content_tag(:span, #{lights}, :class => 'lights lights-' + (#{levels.inspect}.include?(#{value_code}.to_s) ? #{value_code}.to_s : 'undefined'))"
185
+
186
+ value_code = "content_tag(:span, #{lights}, :class => 'lights lights-' + (#{levels.inspect}.include?(#{value_code}.to_s) ? #{value_code}.to_s : 'undefined'), data: { toggle: :tooltip, placement: :top }, title: #{title_code})"
164
187
 
165
188
  elsif column.is_a? ActiveList::Definition::DataColumn
166
189
  if column.options[:children].is_a?(FalseClass) && children_mode
@@ -168,6 +191,7 @@ module ActiveList
168
191
  else
169
192
  value_code = column.datum_code(record, children_mode)
170
193
  if column.datatype == :boolean
194
+ title_value_code = value_code
171
195
  value_code = "content_tag(:div, '', :class => 'checkbox-'+(" + value_code.to_s + " ? 'true' : 'false'))"
172
196
  elsif %i[date datetime timestamp measure].include? column.datatype
173
197
  value_code = "(#{value_code}.nil? ? '' : #{value_code}.l)"
@@ -179,7 +203,7 @@ module ActiveList
179
203
  currency = :currency if currency.is_a?(TrueClass)
180
204
  # currency = "#{record}.#{currency}".c if currency.is_a?(Symbol)
181
205
  currency = "#{column.record_expr(record)}.#{currency}".c if currency.is_a?(Symbol)
182
- value_code = "(#{value_code}.nil? ? '' : #{value_code}.l(currency: #{currency.inspect}))"
206
+ value_code = "(#{value_code}.nil? || #{value_code}.zero? ? ('#{column.options[:default]}'.present? ? '#{column.options[:default]}' : '') : #{value_code}.l(currency: #{currency.inspect}))"
183
207
  elsif column.datatype == :decimal
184
208
  value_code = "(#{value_code}.nil? ? '' : #{value_code}.l)"
185
209
  elsif column.enumerize?
@@ -189,15 +213,21 @@ module ActiveList
189
213
  column.options[:url] = {} unless column.options[:url].is_a?(Hash)
190
214
  column.options[:url][:id] ||= (column.record_expr(record) + '.id').c
191
215
  column.options[:url][:action] ||= :show
192
- column.options[:url][:controller] ||= column.class_name.tableize.to_sym # (self.generator.collection? ? "RECORD.class.name.tableize".c : column.class_name.tableize.to_sym)
193
- # column.options[:url][:controller] ||= "#{value_code}.class.name.tableize".c
194
- url = column.options[:url].collect { |k, v| "#{k}: " + urlify(v, record) }.join(', ')
216
+ default_controller = column.class_name.is_a?(CodeString) ? column.class_name : column.class_name.tableize.to_sym
217
+ column.options[:url][:controller] ||= default_controller
218
+ namespace = column.options[:url].delete(:namespace)
219
+ url = column.options[:url].collect { |k, v| "#{k}: " + urlify(k, v, record, namespace) }.join(', ')
220
+
221
+ title_value_code = value_code
195
222
  value_code = "(#{value_code}.blank? ? '' : link_to(#{value_code}.to_s, #{url}))"
196
223
  elsif column.options[:mode] || column.label_method == :email
224
+ title_value_code = value_code
197
225
  value_code = "(#{value_code}.blank? ? '' : mail_to(#{value_code}))"
198
226
  elsif column.options[:mode] || column.label_method == :website
227
+ title_value_code = value_code
199
228
  value_code = "(#{value_code}.blank? ? '' : link_to(" + value_code + ', ' + value_code + '))'
200
229
  elsif column.label_method == :color
230
+ title_value_code = value_code
201
231
  value_code = "content_tag(:div, #{column.datum_code(record)}, style: 'background: #'+" + column.datum_code(record) + ')'
202
232
  elsif column.label_method.to_s.match(/(^|\_)currency$/) && column.datatype == :string
203
233
  value_code = "(Nomen::Currency[#{value_code}] ? Nomen::Currency[#{value_code}].human_name : #{value_code})"
@@ -207,11 +237,13 @@ module ActiveList
207
237
  value_code = "(Nomen::Country[#{value_code}] ? (image_tag('countries/' + #{value_code}.to_s + '.png') + ' ' + Nomen::Country[#{value_code}].human_name).html_safe : #{value_code})"
208
238
  else # if column.datatype == :string
209
239
  value_code = "h(#{value_code}.to_s)"
240
+ title_value_code = nil
210
241
  end
211
242
 
212
243
  value_code = "if #{record}\n#{value_code.dig}end" if column.is_a?(ActiveList::Definition::AssociationColumn)
213
244
  end
214
245
  elsif column.is_a?(ActiveList::Definition::CheckBoxColumn)
246
+ title_value_code = nil
215
247
  if nature == :body
216
248
  form_name = column.form_name || "'#{table.name}[' + #{record}.id.to_s + '][#{column.name}]'".c
217
249
  value = 'nil'
@@ -226,15 +258,26 @@ module ActiveList
226
258
  value_code << 'nil'
227
259
  end
228
260
  elsif column.is_a?(ActiveList::Definition::TextFieldColumn)
261
+ title_value_code = nil
229
262
  form_name = column.form_name || "'#{table.name}[' + #{record}.id.to_s + '][#{column.name}]'".c
230
263
  value_code = (nature == :body ? "text_field_tag(#{form_name.inspect}, #{recordify!(column.options[:value] || column.name, record)}#{column.options[:size] ? ', size: ' + column.options[:size].to_s : ''})" : 'nil') # , id: '#{table.name}_'+#{record}.id.to_s + '_#{column.name}'
231
264
  elsif column.is_a?(ActiveList::Definition::ActionColumn)
265
+ title_value_code = nil
232
266
  next unless column.use_single?
233
267
  value_code = (nature == :body ? column.operation(record) : 'nil')
234
268
  else
235
269
  value_code = "'&#160;&#8709;&#160;'.html_safe"
236
270
  end
237
- code << "content_tag(:td, :class => \"#{column_classes(column)}\","
271
+
272
+ title_attr_code = if title_value_code.nil?
273
+ ''
274
+ elsif title_value_code.blank?
275
+ ":title => (#{value_code}),"
276
+ else
277
+ ":title => (#{title_value_code}),"
278
+ end
279
+
280
+ code << "content_tag(:td, #{title_attr_code} :class => \"#{column_classes(column)}\","
238
281
  code << " data: { 'list-column-header' => '#{column.short_id}'"
239
282
  code << ", 'list-cell-value' => \"\#{#{column.datum_value(record, children_mode)}.to_f}\"" if column.computable?
240
283
  code << " } ) do\n"
@@ -282,7 +325,7 @@ module ActiveList
282
325
  menu << '<li class="separator"></li>'
283
326
  # Exports
284
327
  ActiveList.exporters.each do |format, _exporter|
285
- menu << "<li class=\"export export-#{format}\">' + link_to(content_tag(:i) + h('list.export_as'.t(exported: :#{format}.t(scope: 'list.export.formats'))), params.merge(action: :#{generator.controller_method_name}, sort: #{var_name(:params)}[:sort], dir: #{var_name(:params)}[:dir], format: '#{format}')) + '</li>"
328
+ menu << "<li class=\"export export-#{format}\">' + link_to(content_tag(:i) + h('list.export_as'.t(exported: :#{format}.t(scope: 'list.export.formats'))), __params.merge(action: :#{generator.controller_method_name}, sort: #{var_name(:params)}[:sort], dir: #{var_name(:params)}[:dir], format: '#{format}')) + '</li>"
286
329
  end
287
330
  menu << '</ul></span>'
288
331
  menu
@@ -299,7 +342,7 @@ module ActiveList
299
342
  end
300
343
  table.columns.each do |column|
301
344
  next if column.is_a?(ActiveList::Definition::ActionColumn) && !column.use_single?
302
- code << "<th data-list-column=\"#{column.sort_id}\""
345
+ code << "<th data-list-column=\"#{column.options[:icon_name] || column.sort_id}\""
303
346
  code << " data-list-column-cells=\"#{column.short_id}\""
304
347
  code << " data-list-column-sort=\"'+(#{var_name(:params)}[:sort] != '#{column.sort_id}' ? 'asc' : #{var_name(:params)}[:dir] == 'asc' ? 'desc' : 'asc')+'\"" if column.sortable?
305
348
  code << " data-list-column-computation=\"#{column.computation_method}\"" if column.computable?
@@ -368,6 +411,26 @@ module ActiveList
368
411
 
369
412
  code << "'#{pagination}'"
370
413
  codes[:pagination] = "'#{pagination}'"
414
+
415
+ if table.options[:footer_pagination]
416
+ pagination = ''
417
+ current_page = var_name(:page).to_s
418
+ last_page = var_name(:last).to_s
419
+
420
+ pagination << "<span class=\"list-footer-pagination\" data-list-ref=\"#{uid}\">"
421
+ pagination << "<span class=\"status\">' + 'list.pagination.x_to_y_of_total'.t(x: (#{var_name(:offset)} + (#{var_name(:count)} > 0 ? 1 : 0)), y: ((#{var_name(:last)} == #{var_name(:page)}) ? #{var_name(:count)} : #{var_name(:offset)} + #{var_name(:limit)}), total: #{var_name(:count)}) + '</span>"
422
+
423
+ pagination << '<span class="paginator">'
424
+ pagination << "<a href=\"#\" data-list-move-to-page=\"' + (#{current_page} - 1).to_s + '\" class=\"btn previous-page\"' + (#{current_page} != 1 ? '' : ' disabled=\"true\"') + '><i></i>' + ::I18n.translate('list.pagination.previous') + '</a>"
425
+
426
+ pagination << "<a href=\"#\" data-list-move-to-page=\"' + (#{current_page} + 1).to_s + '\" class=\"btn next-page\"' + (#{current_page} != #{last_page} ? '' : ' disabled=\"true\"') + '><i></i>' + ::I18n.translate('list.pagination.next')+'</a>"
427
+ pagination << '</span>'
428
+
429
+ pagination << '</span>'
430
+
431
+ code << "'#{pagination}'"
432
+ codes[:footer_pagination] = "'#{pagination}'"
433
+ end
371
434
  end
372
435
  codes
373
436
  end
@@ -389,7 +452,11 @@ module ActiveList
389
452
  classes = []
390
453
  conds = []
391
454
  conds << [:sor, "#{var_name(:params)}[:sort] == '#{column.sort_id}'".c] if column.sortable?
392
- conds << [:hidden, "#{var_name(:params)}[:hidden_columns].include?(:#{column.name})".c] if column.is_a? ActiveList::Definition::DataColumn
455
+ if column.is_a? ActiveList::Definition::DataColumn
456
+ conds << [:hidden, "#{var_name(:params)}[:hidden_columns].include?(:#{column.name})".c]
457
+ elsif column.condition
458
+ conds << [:hidden, "h(#{column.condition}) == 'false'".c]
459
+ end
393
460
  classes << column.options[:class].to_s.strip unless column.options[:class].blank?
394
461
  classes << column.short_id unless without_id
395
462
  if column.is_a? ActiveList::Definition::ActionColumn
@@ -1,3 +1,3 @@
1
1
  module ActiveList
2
- VERSION = '6.9.3'.freeze
2
+ VERSION = '7.2.0'.freeze
3
3
  end
@@ -1,23 +1,25 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rails', '4.2.8'
3
+ gem 'rails', '~> 5.0'
4
4
 
5
5
  # Bundle edge Rails instead:
6
6
  # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
7
 
8
- gem 'sqlite3'
8
+ gem 'sqlite3', '~> 1.3.6'
9
9
  gem 'active_list', path: '../..'
10
10
 
11
+ gem 'sprockets', '< 4'
12
+
11
13
  # Gems used only for assets and not required
12
14
  # in production environments by default.
13
15
  group :assets do
14
- gem 'sass-rails', '~> 4'
15
- gem 'coffee-rails', '~> 4'
16
+ gem 'sass-rails'
17
+ gem 'coffee-rails'
16
18
 
17
19
  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18
20
  gem 'therubyracer', platform: :ruby
19
21
 
20
- gem 'uglifier', '>= 1.0.3'
22
+ gem 'uglifier'
21
23
  end
22
24
 
23
25
  gem 'jquery-rails'
@@ -39,6 +39,7 @@ module Dummy
39
39
  # Configure sensitive parameters which will be filtered from the log file.
40
40
  config.filter_parameters += [:password]
41
41
 
42
+ config.active_record.sqlite3.represent_boolean_as_integer = true
42
43
  # Use SQL instead of Active Record's schema dumper when creating the database.
43
44
  # This is necessary if your schema can't be completely dumped by the schema dumper,
44
45
  # like if you have constraints or database-specific column types
@@ -5,4 +5,3 @@
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
7
  Dummy::Application.config.secret_key_base = '7a06e73398090c095bed02f2dff3808b043e50cb928f7b7bfd02faadd988a0d9cf31dfc74d1bf661ac94c8d0d73c8ceb4d98210d09f251f0c6d70f09923db784'
8
- Dummy::Application.config.secret_token = '7a06e73398090c095bed02f2dff3808b043e50cb928f7b7bfd02faadd988a0d9cf31dfc74d1bf661ac94c8d0d73c8ceb4d98210d09f251f0c6d70f09923db784'
@@ -1,4 +1,4 @@
1
- class CreatePeople < ActiveRecord::Migration
1
+ class CreatePeople < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :people do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class CreateContacts < ActiveRecord::Migration
1
+ class CreateContacts < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :contacts do |t|
4
4
  t.integer :person_id
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -11,26 +10,26 @@
11
10
  #
12
11
  # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(version: 20120510134500) do
13
+ ActiveRecord::Schema.define(version: 2012_05_10_134500) do
15
14
 
16
15
  create_table "contacts", force: :cascade do |t|
17
- t.integer "person_id"
18
- t.text "address"
19
- t.string "phone"
20
- t.string "fax"
21
- t.string "country"
16
+ t.integer "person_id"
17
+ t.text "address"
18
+ t.string "phone"
19
+ t.string "fax"
20
+ t.string "country"
22
21
  t.datetime "created_at", null: false
23
22
  t.datetime "updated_at", null: false
24
23
  end
25
24
 
26
25
  create_table "people", force: :cascade do |t|
27
- t.string "name"
28
- t.date "born_on"
29
- t.decimal "height"
30
- t.decimal "balance_amount"
31
- t.string "currency"
32
- t.datetime "created_at", null: false
33
- t.datetime "updated_at", null: false
26
+ t.string "name"
27
+ t.date "born_on"
28
+ t.decimal "height"
29
+ t.decimal "balance_amount"
30
+ t.string "currency"
31
+ t.datetime "created_at", null: false
32
+ t.datetime "updated_at", null: false
34
33
  end
35
34
 
36
35
  end
@@ -5,10 +5,10 @@ class PeopleControllerTest < ActionController::TestCase
5
5
  get :list
6
6
  assert_response :success
7
7
 
8
- get :list, format: :csv
8
+ get :list, params: {format: :csv}
9
9
  assert_response :success
10
10
 
11
- get :list, format: :ods
11
+ get :list, params: {format: :ods}
12
12
  assert_response :success
13
13
  end
14
14
 
@@ -18,19 +18,19 @@ class PeopleControllerTest < ActionController::TestCase
18
18
  end
19
19
 
20
20
  test 'parameters' do
21
- get :list, 'people-id' => 10
21
+ get :list, params: {'people-id' => 10}
22
22
  assert_response :success
23
23
 
24
- get :list, page: 0
24
+ get :list, params: {page: 0}
25
25
  assert_response :success
26
26
 
27
- get :list, page: 5, per_page: 25
27
+ get :list, params: {page: 5, per_page: 25}
28
28
  assert_response :success
29
29
 
30
- get :list, page: 50, per_page: 25
30
+ get :list, params: {page: 50, per_page: 25}
31
31
  assert_response :success
32
32
 
33
- get :list, page: 500, per_page: 25
33
+ get :list, params: {page: 500, per_page: 25}
34
34
  assert_response :success
35
35
  end
36
36
  end
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require 'bundler/setup'
2
3
  require 'pathname'
3
4
 
@@ -8,7 +9,7 @@ require 'active_list'
8
9
  dummy_path = Pathname.new(__FILE__).dirname.join('dummy')
9
10
 
10
11
  ENV['BUNDLE_GEMFILE'] = ''
11
- Kernel.system("cd #{dummy_path} && bundle install && bundle exec rake db:drop db:create db:migrate db:seed RAILS_ENV=test")
12
+ # Kernel.system("cd #{dummy_path} && bundle install && bundle exec rake db:drop db:create db:migrate db:seed RAILS_ENV=test")
12
13
 
13
14
  # CURRENT FILE :: test/test_helper.rb
14
15
  # Configure Rails Environment
@@ -22,6 +23,22 @@ ActionMailer::Base.delivery_method = :test
22
23
  ActionMailer::Base.perform_deliveries = true
23
24
  ActionMailer::Base.default_url_options[:host] = 'test.com'
24
25
 
26
+ # Patch from https://github.com/rails/rails/issues/34790#issuecomment-450502805
27
+ if RUBY_VERSION >= '2.6.0'
28
+ if Rails.version < '5'
29
+ class ActionController::TestResponse < ActionDispatch::TestResponse
30
+ def recycle!
31
+ # hack to avoid MonitorMixin double-initialize error:
32
+ @mon_mutex_owner_object_id = nil
33
+ @mon_mutex = nil
34
+ initialize
35
+ end
36
+ end
37
+ else
38
+ puts "Monkeypatch for ActionController::TestResponse no longer needed"
39
+ end
40
+ end
41
+
25
42
  module ActionView
26
43
  class Base
27
44
  module Nomen
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: 6.9.3
4
+ version: 7.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brice Texier
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-04 00:00:00.000000000 Z
11
+ date: 2020-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '3.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 5.0.0
22
+ version: '6'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '3.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 5.0.0
32
+ version: '6'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: arel
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.0.0
53
+ version: 0.0.1
54
54
  type: :runtime
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: 0.0.0
60
+ version: 0.0.1
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rubyzip
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -90,16 +90,16 @@ dependencies:
90
90
  name: sqlite3
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ">="
93
+ - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '0'
95
+ version: 1.3.6
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ">="
100
+ - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0'
102
+ version: 1.3.6
103
103
  description: Generates action methods to provide clean tables.
104
104
  email: burisu@oneiros.fr
105
105
  executables: []
@@ -208,11 +208,11 @@ files:
208
208
  - test/people_controller_test.rb
209
209
  - test/table_test.rb
210
210
  - test/test_helper.rb
211
- homepage: http://github.com/ekylibre/active_list
211
+ homepage: http://gitlab.com/ekylibre/active_list
212
212
  licenses:
213
213
  - MIT
214
214
  metadata: {}
215
- post_install_message:
215
+ post_install_message:
216
216
  rdoc_options: []
217
217
  require_paths:
218
218
  - lib
@@ -227,9 +227,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  - !ruby/object:Gem::Version
228
228
  version: '0'
229
229
  requirements: []
230
- rubyforge_project:
231
- rubygems_version: 2.4.5.2
232
- signing_key:
230
+ rubygems_version: 3.0.3
231
+ signing_key:
233
232
  specification_version: 4
234
233
  summary: Simple interactive tables for Rails app
235
234
  test_files: