active_list 6.9.3 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: