active_scaffold 4.3.2 → 4.4.1
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 +4 -4
- data/CHANGELOG.rdoc +26 -0
- data/README.md +4 -6
- data/app/assets/javascripts/active_scaffold/active_scaffold.js +104 -12
- data/app/assets/javascripts/active_scaffold/draggable_lists.js +4 -3
- data/app/assets/javascripts/active_scaffold/load.js +20 -5
- data/app/assets/stylesheets/active_scaffold/_images.scss +53 -1
- data/app/assets/stylesheets/active_scaffold/_layout.scss +1 -66
- data/app/views/active_scaffold_overrides/_add_existing_form.html.erb +17 -11
- data/app/views/active_scaffold_overrides/_base_form.html.erb +29 -19
- data/app/views/active_scaffold_overrides/_field_search.html.erb +9 -9
- data/app/views/active_scaffold_overrides/_field_search_columns.html.erb +29 -33
- data/app/views/active_scaffold_overrides/_form.html.erb +43 -34
- data/app/views/active_scaffold_overrides/_form_association.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +20 -16
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +3 -4
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_list.html.erb +6 -4
- data/app/views/active_scaffold_overrides/_list_calculations.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_list_header.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_list_messages.html.erb +19 -19
- data/app/views/active_scaffold_overrides/_list_messages_content.html.erb +5 -5
- data/app/views/active_scaffold_overrides/_list_pagination.html.erb +7 -5
- data/app/views/active_scaffold_overrides/_list_pagination_links.html.erb +5 -3
- data/app/views/active_scaffold_overrides/_list_record.html.erb +13 -8
- data/app/views/active_scaffold_overrides/_list_with_header.html.erb +8 -8
- data/app/views/active_scaffold_overrides/_messages.html.erb +3 -3
- data/app/views/active_scaffold_overrides/_render_field.js.erb +8 -11
- data/app/views/active_scaffold_overrides/_search.html.erb +7 -6
- data/app/views/active_scaffold_overrides/_show.html.erb +4 -4
- data/app/views/active_scaffold_overrides/_show_actions.html.erb +2 -2
- data/app/views/active_scaffold_overrides/_show_columns.html.erb +28 -30
- data/app/views/active_scaffold_overrides/add_existing.js.erb +7 -4
- data/app/views/active_scaffold_overrides/render_field.js.erb +1 -1
- data/config/locales/de.yml +2 -1
- data/config/locales/en.yml +33 -32
- data/config/locales/es.yml +15 -14
- data/config/locales/fr.yml +3 -2
- data/config/locales/hu.yml +3 -2
- data/config/locales/ja.yml +2 -1
- data/config/locales/ro.yml +169 -0
- data/config/locales/ru.yml +8 -7
- data/config/locales/ta.yml +7 -6
- data/config/locales/zh_Hans.yml +14 -13
- data/lib/active_scaffold/actions/common_search.rb +1 -14
- data/lib/active_scaffold/actions/core.rb +55 -16
- data/lib/active_scaffold/actions/field_search.rb +2 -2
- data/lib/active_scaffold/actions/list.rb +35 -13
- data/lib/active_scaffold/actions/nested.rb +31 -7
- data/lib/active_scaffold/actions/show.rb +1 -1
- data/lib/active_scaffold/active_record_permissions.rb +1 -1
- data/lib/active_scaffold/attribute_params.rb +2 -1
- data/lib/active_scaffold/bridges/date_picker/helper.rb +14 -0
- data/lib/active_scaffold/bridges/date_picker.rb +10 -0
- data/lib/active_scaffold/config/list.rb +10 -1
- data/lib/active_scaffold/core.rb +9 -6
- data/lib/active_scaffold/data_structures/action_columns.rb +2 -0
- data/lib/active_scaffold/data_structures/column.rb +27 -6
- data/lib/active_scaffold/data_structures/filter.rb +4 -0
- data/lib/active_scaffold/data_structures/nested_info.rb +8 -1
- data/lib/active_scaffold/data_structures/sorting.rb +1 -1
- data/lib/active_scaffold/engine.rb +6 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +1 -1
- data/lib/active_scaffold/extensions/active_record_session_store.rb +49 -0
- data/lib/active_scaffold/finder.rb +73 -21
- data/lib/active_scaffold/helpers/action_link_helpers.rb +43 -18
- data/lib/active_scaffold/helpers/assets_helpers.rb +4 -4
- data/lib/active_scaffold/helpers/filter_helpers.rb +3 -3
- data/lib/active_scaffold/helpers/form_column_helpers.rb +34 -22
- data/lib/active_scaffold/helpers/form_ui_helpers.rb +15 -10
- data/lib/active_scaffold/helpers/framework_ui_helpers.rb +22 -0
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +19 -0
- data/lib/active_scaffold/helpers/pagination_helpers.rb +28 -7
- data/lib/active_scaffold/helpers/search_column_helpers.rb +32 -5
- data/lib/active_scaffold/helpers/tabs_helpers.rb +7 -7
- data/lib/active_scaffold/helpers/view_helpers.rb +12 -0
- data/lib/active_scaffold/tableless.rb +11 -8
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/active_scaffold.rb +169 -0
- data/lib/generators/active_scaffold/install/install_generator.rb +216 -111
- data/lib/tasks/bundle.rake +2 -1
- data/lib/tasks/mock_app.rake +43 -0
- metadata +21 -7
- data/shoulda_macros/macros.rb +0 -145
|
@@ -79,14 +79,16 @@ module ActiveScaffold
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def active_scaffold_subform_record_actions(association_column, record, locked, scope)
|
|
82
|
-
|
|
82
|
+
# association_column nil when called for batch_create for example
|
|
83
|
+
return if locked || association_column&.association&.singular?
|
|
83
84
|
|
|
84
|
-
auth = %i[destroy delete_all delete].exclude?(association_column
|
|
85
|
+
auth = %i[destroy delete_all delete].exclude?(association_column&.association&.dependent)
|
|
85
86
|
auth, reason = record.authorized_for?(crud_type: :delete, reason: true) unless auth
|
|
86
87
|
if auth
|
|
87
|
-
|
|
88
|
+
attributes = as_element_attributes(:subform_record_remove, class: 'destroy')
|
|
89
|
+
link_to(as_(:remove), '#', attributes)
|
|
88
90
|
else
|
|
89
|
-
|
|
91
|
+
as_element(:subform_record_remove_reason, reason)
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
|
|
@@ -121,7 +123,9 @@ module ActiveScaffold
|
|
|
121
123
|
|
|
122
124
|
collapsible_id = "container_#{id_control}" if (column.form_ui_options || column.options)[:collapsible]
|
|
123
125
|
|
|
124
|
-
{name: name, class: classes, id: id_control, collapsible_id: collapsible_id}.merge(options)
|
|
126
|
+
attributes = {name: name, class: classes, id: id_control, collapsible_id: collapsible_id}.merge(options)
|
|
127
|
+
context = {column: column, form_ui: column.form_ui}
|
|
128
|
+
as_element_attributes(:form_control, proc_options: context, **attributes)
|
|
125
129
|
end
|
|
126
130
|
|
|
127
131
|
def current_form_columns(record, scope, subform_controller = nil)
|
|
@@ -174,10 +178,10 @@ module ActiveScaffold
|
|
|
174
178
|
{}
|
|
175
179
|
end
|
|
176
180
|
|
|
177
|
-
def render_subsection(column, record, scope, form_action, partial: 'form')
|
|
178
|
-
subsection_id
|
|
181
|
+
def render_subsection(column, record, scope, form_action, partial: 'form', subsection_id: nil, &)
|
|
182
|
+
subsection_id ||= sub_section_id(sub_section: column.label)
|
|
179
183
|
locals = {columns: column, form_action: form_action, scope: scope}
|
|
180
|
-
header =
|
|
184
|
+
header = as_element(:form_subsection_header) do
|
|
181
185
|
h(column.label) <<
|
|
182
186
|
link_to_visibility_toggle(subsection_id, default_visible: !column.collapsed)
|
|
183
187
|
end
|
|
@@ -188,6 +192,8 @@ module ActiveScaffold
|
|
|
188
192
|
render partial, locals.merge(subsection_id: "#{subsection_id}-#{tab_id}", tab_id: tab_id, tab_value: tab_value)
|
|
189
193
|
end
|
|
190
194
|
end
|
|
195
|
+
elsif block_given?
|
|
196
|
+
header << capture(subsection_id, &)
|
|
191
197
|
else
|
|
192
198
|
header << render(partial, locals.merge(subsection_id: subsection_id))
|
|
193
199
|
end
|
|
@@ -217,6 +223,8 @@ module ActiveScaffold
|
|
|
217
223
|
end
|
|
218
224
|
end
|
|
219
225
|
|
|
226
|
+
def form_ui_class(form_ui) = form_ui
|
|
227
|
+
|
|
220
228
|
def form_column_is_hidden?(column, record, scope = nil) # rubocop:disable Naming/PredicateMethod
|
|
221
229
|
if column.clear_form_column_if.nil?
|
|
222
230
|
condition_to_hide = column.hide_form_column_if
|
|
@@ -238,35 +246,38 @@ module ActiveScaffold
|
|
|
238
246
|
|
|
239
247
|
def column_description(column, record, scope = nil)
|
|
240
248
|
desc = column.description(record, scope)
|
|
241
|
-
|
|
249
|
+
as_element(:form_field_description, h(desc) + as_element(:form_field_description_close)) if desc.present?
|
|
242
250
|
end
|
|
243
251
|
|
|
244
|
-
def form_attribute(column, record, scope = nil, only_value = false, col_class = nil, form_columns: nil)
|
|
252
|
+
def form_attribute(column, record, scope = nil, only_value = false, col_class = nil, form_columns: nil, field: nil)
|
|
245
253
|
column_options = active_scaffold_input_options(column, scope, object: record)
|
|
246
254
|
collapsible_id = column_options.delete :collapsible_id
|
|
247
255
|
attributes = field_attributes(column, record)
|
|
248
256
|
attributes[:class] = "#{attributes[:class]} #{col_class}" if col_class.present?
|
|
249
257
|
if only_value
|
|
250
|
-
field
|
|
258
|
+
field ||= content_tag(:span, show_column_value(record, column), column_options.except(:name, :object))
|
|
251
259
|
if column.association.nil? || column.association.belongs_to?
|
|
252
260
|
# hidden field probably not needed, but leaving it just in case
|
|
253
261
|
# but it isn't working for assocations which are not belongs_to
|
|
254
|
-
|
|
255
|
-
field << hidden_field(:record, method, column_options)
|
|
262
|
+
field = safe_join([field, hidden_field(:record, column.association&.foreign_key || column.name, column_options)])
|
|
256
263
|
end
|
|
257
264
|
else
|
|
258
|
-
field
|
|
259
|
-
end
|
|
260
|
-
if field
|
|
261
|
-
field << loading_indicator_tag(action: :render_field, id: params[:id]) if column.update_columns
|
|
262
|
-
desc = column_description(column, record, scope)
|
|
263
|
-
field << desc if desc.present?
|
|
265
|
+
field ||= active_scaffold_input_for column, scope, column_options, form_columns: form_columns
|
|
264
266
|
end
|
|
267
|
+
field = safe_join([field, loading_indicator_tag(action: :render_field, id: params[:id])]) if field && column.update_columns
|
|
268
|
+
description = column_description(column, record, scope)
|
|
265
269
|
|
|
266
270
|
label = label_tag(label_for(column, column_options), form_column_label(column, record, scope))
|
|
267
271
|
label << h(' ') << link_to_visibility_toggle(collapsible_id) if collapsible_id
|
|
268
|
-
|
|
269
|
-
|
|
272
|
+
form_attribute_html(column, label, field, description, attributes, collapsible_id: collapsible_id)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def form_attribute_html(column, label, field, description, attributes, collapsible_id: nil)
|
|
276
|
+
field = safe_join([field, description].compact) if description.present?
|
|
277
|
+
context = {column: column}
|
|
278
|
+
as_element :form_attribute, proc_options: context, **attributes do
|
|
279
|
+
as_element(:form_attribute_label, label, proc_options: context) <<
|
|
280
|
+
as_element(:form_attribute_field, field, proc_options: context, id: collapsible_id)
|
|
270
281
|
end
|
|
271
282
|
end
|
|
272
283
|
|
|
@@ -322,7 +333,8 @@ module ActiveScaffold
|
|
|
322
333
|
|
|
323
334
|
# Should this column be displayed in the subform?
|
|
324
335
|
def in_subform?(column, parent_record, parent_column)
|
|
325
|
-
|
|
336
|
+
# parent_column nil when called for batch_create for example
|
|
337
|
+
return true if parent_column.nil? || column.association.nil?
|
|
326
338
|
|
|
327
339
|
if column.association.reverse.nil?
|
|
328
340
|
# Polymorphic associations can't appear because they *might* be the reverse association
|
|
@@ -27,18 +27,23 @@ module ActiveScaffold
|
|
|
27
27
|
|
|
28
28
|
def active_scaffold_input_singular_association(column, html_options, options = {}, ui_options: column.options)
|
|
29
29
|
record = html_options.delete(:object)
|
|
30
|
-
associated = html_options.include?(:associated) ? html_options.delete(:associated) : record.send(column.association.name)
|
|
31
|
-
|
|
32
30
|
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
33
31
|
select_options = send(helper_method, column.association, nil, record)
|
|
34
|
-
|
|
32
|
+
|
|
33
|
+
if html_options.include?(:associated)
|
|
34
|
+
options[:selected] ||= html_options.delete(:associated)
|
|
35
|
+
else
|
|
36
|
+
associated = record.send(column.association.name)
|
|
37
|
+
select_options.unshift(associated) if associated&.persisted? && select_options.exclude?(associated)
|
|
38
|
+
options[:selected] ||= associated&.id
|
|
39
|
+
end
|
|
35
40
|
|
|
36
41
|
method = column.name
|
|
37
|
-
options.
|
|
42
|
+
options.reverse_merge! include_blank: as_(:_select_), object: record
|
|
38
43
|
|
|
39
44
|
html_options.merge!(ui_options[:html_options] || {})
|
|
40
45
|
options.merge!(ui_options)
|
|
41
|
-
html_options
|
|
46
|
+
active_scaffold_select_name_with_multiple html_options # doesn't make sense most of time, but AS_batch use it
|
|
42
47
|
active_scaffold_translate_select_options(options)
|
|
43
48
|
|
|
44
49
|
html =
|
|
@@ -101,7 +106,7 @@ module ActiveScaffold
|
|
|
101
106
|
url_options[:parent_model] ||= record.class.name
|
|
102
107
|
url_options[:parent_column] ||= column.name
|
|
103
108
|
url_options.reverse_merge! options[:url_options] if options[:url_options]
|
|
104
|
-
link_to(link_text, url_options, remote: true, data: {position: :popup}, class: 'as_action')
|
|
109
|
+
link_to(link_text, url_options, as_element_attributes(:field_add_new_popup, remote: true, data: {position: :popup}, class: 'as_action'))
|
|
105
110
|
end
|
|
106
111
|
|
|
107
112
|
def active_scaffold_new_record_subform(column, record, html_options, options: {}, new_record_attributes: nil, locals: {}, skip_link: false)
|
|
@@ -141,7 +146,7 @@ module ActiveScaffold
|
|
|
141
146
|
create_new = active_scaffold_add_new_text(options, :add_new_text, :create_new)
|
|
142
147
|
data = {select_id: select_id, subform_id: subform_id, subform_text: add_existing, select_text: create_new}
|
|
143
148
|
label = data[record.send(column.name)&.new_record? ? :subform_text : :select_text]
|
|
144
|
-
link_to(label, '#', data: data, class: 'show-new-subform')
|
|
149
|
+
link_to(label, '#', as_element_attributes(:field_add_new_subform, data: data, class: 'show-new-subform'))
|
|
145
150
|
end
|
|
146
151
|
|
|
147
152
|
def active_scaffold_file_with_content(column, options, content, remove_file_prefix, controls_class, ui_options: column.options)
|
|
@@ -237,8 +242,8 @@ module ActiveScaffold
|
|
|
237
242
|
end
|
|
238
243
|
end
|
|
239
244
|
|
|
240
|
-
def active_scaffold_checkbox_option(option, label_method, associated_ids, checkbox_options,
|
|
241
|
-
content_tag(:li,
|
|
245
|
+
def active_scaffold_checkbox_option(option, label_method, associated_ids, checkbox_options, item_options = {})
|
|
246
|
+
content_tag(:li, item_options) do
|
|
242
247
|
option_id = option.is_a?(Array) ? option[1] : option.id
|
|
243
248
|
label = option.is_a?(Array) ? option[0] : option.send(label_method)
|
|
244
249
|
check_box_tag(checkbox_options[:name], option_id, associated_ids.include?(option_id), checkbox_options) <<
|
|
@@ -261,7 +266,7 @@ module ActiveScaffold
|
|
|
261
266
|
html << content_tag(:ul, options.merge(class: "#{options[:class]} checkbox-list#{' draggable-lists' if draggable}")) do
|
|
262
267
|
content = []
|
|
263
268
|
select_options.each_with_index do |option, i|
|
|
264
|
-
content << active_scaffold_checkbox_option(option, label_method, associated_ids, name: "#{options[:name]}[]", id: "#{options[:id]}_#{i}_id")
|
|
269
|
+
content << active_scaffold_checkbox_option(option, label_method, associated_ids, {name: "#{options[:name]}[]", id: "#{options[:id]}_#{i}_id"}, ui_options[:item_options] || {})
|
|
265
270
|
end
|
|
266
271
|
safe_join content
|
|
267
272
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveScaffold
|
|
4
|
+
module Helpers
|
|
5
|
+
module FrameworkUiHelpers
|
|
6
|
+
def as_element(key, content = nil, proc_options: {}, **options, &)
|
|
7
|
+
tag, attributes = as_tag_and_attributes(key, options, proc_options)
|
|
8
|
+
content_tag(tag, content, attributes, &)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def as_element_attributes(key, proc_options: {}, **options)
|
|
12
|
+
as_tag_and_attributes(key, options, proc_options).last
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def as_tag_and_attributes(key, options, proc_options = {})
|
|
16
|
+
tag, attributes, proc = ActiveScaffold.ui_elements[key]&.values_at(:tag, :attributes, :proc)
|
|
17
|
+
tag, attributes = instance_exec(proc_options, &proc) if proc
|
|
18
|
+
[tag, attributes&.smart_merge(options) || options&.as_html_attrs]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -72,6 +72,7 @@ module ActiveScaffold
|
|
|
72
72
|
alias active_scaffold_human_condition_time active_scaffold_human_condition_datetime
|
|
73
73
|
alias active_scaffold_human_condition_date active_scaffold_human_condition_datetime
|
|
74
74
|
alias active_scaffold_human_condition_timestamp active_scaffold_human_condition_datetime
|
|
75
|
+
alias active_scaffold_human_condition_timestamptz active_scaffold_human_condition_datetime
|
|
75
76
|
|
|
76
77
|
def active_scaffold_human_condition_datetime_range_format(range_type, range)
|
|
77
78
|
case range
|
|
@@ -431,6 +431,24 @@ module ActiveScaffold
|
|
|
431
431
|
data
|
|
432
432
|
end
|
|
433
433
|
|
|
434
|
+
def local_sorting?
|
|
435
|
+
@page&.pager&.number_of_pages == 1 && active_scaffold_config.list.local_sorting
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def column_sort_value(record, column)
|
|
439
|
+
value = record.send(column.name)
|
|
440
|
+
return if value.nil?
|
|
441
|
+
|
|
442
|
+
case column.column.type
|
|
443
|
+
when :time, :datetime, Time then value.to_i
|
|
444
|
+
when :boolean then value ? 1 : 0
|
|
445
|
+
when :binary then nil
|
|
446
|
+
when :integer then value
|
|
447
|
+
when :float, :decimal then (value % 1).zero? ? value.to_i : value
|
|
448
|
+
else value.to_s
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
434
452
|
# MARK
|
|
435
453
|
|
|
436
454
|
def all_marked?
|
|
@@ -465,6 +483,7 @@ module ActiveScaffold
|
|
|
465
483
|
elsif column.inplace_edit
|
|
466
484
|
tag_options[:data] = inplace_edit_data(column)
|
|
467
485
|
end
|
|
486
|
+
|
|
468
487
|
content_tag(:th, column_heading_value(column, sorting, sort_direction) + inplace_edit_control(column), tag_options)
|
|
469
488
|
end
|
|
470
489
|
|
|
@@ -3,8 +3,13 @@
|
|
|
3
3
|
module ActiveScaffold
|
|
4
4
|
module Helpers
|
|
5
5
|
module PaginationHelpers
|
|
6
|
-
def pagination_ajax_link(page_number, url_options, options)
|
|
7
|
-
|
|
6
|
+
def pagination_ajax_link(page_number, url_options, options, text: nil)
|
|
7
|
+
attributes = as_element_attributes(
|
|
8
|
+
:pagination_link,
|
|
9
|
+
proc_options: {page_number: page_number, text: text},
|
|
10
|
+
**options.smart_merge(class: 'as_paginate')
|
|
11
|
+
)
|
|
12
|
+
link_to text ? as_(text) : page_number, url_options.merge(page: page_number), attributes
|
|
8
13
|
end
|
|
9
14
|
|
|
10
15
|
def pagination_url_options(url_options = nil)
|
|
@@ -17,6 +22,22 @@ module ActiveScaffold
|
|
|
17
22
|
url_options
|
|
18
23
|
end
|
|
19
24
|
|
|
25
|
+
def pagination_active_page(page_number, url_options, options)
|
|
26
|
+
attributes = options.slice(:id, :class).smart_merge(class: 'as_paginate current')
|
|
27
|
+
as_element :pagination_active_page, page_number,
|
|
28
|
+
proc_options: {page_number: page_number}, **attributes
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def pagination_gap(options)
|
|
32
|
+
'..'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Wraps the complete pagination sequence, including previous and next links.
|
|
36
|
+
# UI adapters may override this method and call +super+ to add nested markup.
|
|
37
|
+
def pagination_html(&)
|
|
38
|
+
capture(&)
|
|
39
|
+
end
|
|
40
|
+
|
|
20
41
|
def pagination_ajax_links(current_page, url_options, options, inner_window, outer_window)
|
|
21
42
|
start_number = current_page.number - inner_window
|
|
22
43
|
end_number = current_page.number + inner_window
|
|
@@ -42,16 +63,16 @@ module ActiveScaffold
|
|
|
42
63
|
page = current_page.number - offset
|
|
43
64
|
next unless page < start_number && page > last_page
|
|
44
65
|
|
|
45
|
-
html <<
|
|
66
|
+
html << pagination_gap(options) if page > last_page + 1
|
|
46
67
|
html << pagination_ajax_link(page, url_options, options)
|
|
47
68
|
last_page = page
|
|
48
69
|
end
|
|
49
70
|
end
|
|
50
|
-
html <<
|
|
71
|
+
html << pagination_gap(options) if start_number > last_page + 1
|
|
51
72
|
|
|
52
73
|
[start_number, last_page + 1].max.upto(end_number) do |num|
|
|
53
74
|
html << if current_page.number == num
|
|
54
|
-
|
|
75
|
+
pagination_active_page(num, url_options, options)
|
|
55
76
|
else
|
|
56
77
|
pagination_ajax_link(num, url_options, options)
|
|
57
78
|
end
|
|
@@ -59,10 +80,10 @@ module ActiveScaffold
|
|
|
59
80
|
|
|
60
81
|
if current_page.pager.infinite?
|
|
61
82
|
offsets.each do |offset|
|
|
62
|
-
html <<
|
|
83
|
+
html << pagination_gap(options) << pagination_ajax_link(current_page.number + offset, url_options, options)
|
|
63
84
|
end
|
|
64
85
|
else
|
|
65
|
-
html <<
|
|
86
|
+
html << pagination_gap(options) unless end_number >= current_page.pager.last.number - outer_window - 1
|
|
66
87
|
[end_number + 1, current_page.pager.last.number - outer_window].max.upto(current_page.pager.last.number) do |num|
|
|
67
88
|
html << pagination_ajax_link(num, url_options, options)
|
|
68
89
|
end
|
|
@@ -50,14 +50,29 @@ module ActiveScaffold
|
|
|
50
50
|
|
|
51
51
|
# the standard active scaffold options used for class, name and scope
|
|
52
52
|
def active_scaffold_search_options(column)
|
|
53
|
-
|
|
53
|
+
attributes = {
|
|
54
|
+
name: "search[#{column.name}]",
|
|
55
|
+
class: "#{column.name}-input",
|
|
56
|
+
id: "search_#{column.name}",
|
|
57
|
+
value: field_search_params[column.name.to_s]
|
|
58
|
+
}
|
|
59
|
+
as_element_attributes(:search_control, proc_options: {column: column, search_ui: column.search_ui}, **attributes)
|
|
54
60
|
end
|
|
55
61
|
|
|
56
62
|
def search_attribute(column, record)
|
|
57
63
|
column_options = active_scaffold_search_options(column).merge(object: record)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
search_attribute_html(
|
|
65
|
+
column,
|
|
66
|
+
label_tag(search_label_for(column, column_options), search_column_label(column, record)),
|
|
67
|
+
active_scaffold_search_for(column, column_options)
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def search_attribute_html(column, label, field)
|
|
72
|
+
context = {column: column}
|
|
73
|
+
as_element :search_attribute, proc_options: context do
|
|
74
|
+
as_element(:search_attribute_label, label, proc_options: context) <<
|
|
75
|
+
as_element(:search_attribute_field, field, proc_options: context)
|
|
61
76
|
end
|
|
62
77
|
end
|
|
63
78
|
|
|
@@ -156,7 +171,7 @@ module ActiveScaffold
|
|
|
156
171
|
select_options << [as_(:true), true] # rubocop:disable Lint/BooleanSymbol
|
|
157
172
|
select_options << [as_(:false), false] # rubocop:disable Lint/BooleanSymbol
|
|
158
173
|
|
|
159
|
-
select_tag(options[:name], options_for_select(select_options, ActiveScaffold::Core.column_type_cast(options[:value], column.column)), id: options[:id])
|
|
174
|
+
select_tag(options[:name], options_for_select(select_options, ActiveScaffold::Core.column_type_cast(options[:value], column.column, column.model)), id: options[:id])
|
|
160
175
|
end
|
|
161
176
|
# we can't use checkbox ui because it's not possible to decide whether search for this field or not
|
|
162
177
|
alias active_scaffold_search_checkbox active_scaffold_search_boolean
|
|
@@ -296,6 +311,7 @@ module ActiveScaffold
|
|
|
296
311
|
def active_scaffold_search_timestamp(column, options, ui_options: column.options)
|
|
297
312
|
active_scaffold_search_datetime(column, options, ui_options: ui_options, field_ui: :datetime)
|
|
298
313
|
end
|
|
314
|
+
alias active_scaffold_search_timestamptz active_scaffold_search_timestamp
|
|
299
315
|
|
|
300
316
|
def active_scaffold_search_time(column, options, ui_options: column.options)
|
|
301
317
|
active_scaffold_search_datetime(column, options, ui_options: ui_options, field_ui: :time)
|
|
@@ -425,6 +441,17 @@ module ActiveScaffold
|
|
|
425
441
|
[visibles, hiddens]
|
|
426
442
|
end
|
|
427
443
|
|
|
444
|
+
def render_field_search_column(column, record)
|
|
445
|
+
column_css_class = column.css_class unless column.css_class.is_a?(Proc)
|
|
446
|
+
if column.respond_to? :each_column
|
|
447
|
+
as_element :field_search_subsection, class: column_css_class do
|
|
448
|
+
render_subsection column, record, nil, :field_search, partial: 'field_search_columns'
|
|
449
|
+
end
|
|
450
|
+
else
|
|
451
|
+
as_element :field_search_element, search_attribute(column, record), class: "form-element #{column_css_class}"
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
428
455
|
def searched_by?(column)
|
|
429
456
|
value = field_search_params[column.name.to_s]
|
|
430
457
|
case value
|
|
@@ -10,9 +10,11 @@ module ActiveScaffold
|
|
|
10
10
|
tab_options = send(override_helper_per_model(:active_scaffold_tab_options, record.class), column, record)
|
|
11
11
|
used_tabs = send(override_helper_per_model(:active_scaffold_current_tabs, record.class), column, record, tab_options)
|
|
12
12
|
input_helper = override_helper_per_model(:active_scaffold_input_for_tabbed, record.class)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
safe_join([
|
|
14
|
+
send(input_helper, column, record, subsection_id, tab_options, used_tabs.map { |v, _| v }),
|
|
15
|
+
active_scaffold_refresh_link(nil, {'data-update_url' => url_for(add_tab_url)}, record, refresh_opts),
|
|
16
|
+
active_scaffold_tabs_for(column, record, subsection_id, tab_options, used_tabs, &)
|
|
17
|
+
])
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def active_scaffold_input_for_tabbed(column, record, subsection_id, tab_options, used_tabs)
|
|
@@ -32,8 +34,6 @@ module ActiveScaffold
|
|
|
32
34
|
tab_values = record.send(col.name).map(&tabbed_by).compact
|
|
33
35
|
if tabbed_by_association(col, tabbed_by)
|
|
34
36
|
tab_values.map! { |value| [value, value.id.to_s] }
|
|
35
|
-
else
|
|
36
|
-
tab_values.map! { |value| [tab_options.find { |_, tab_value, _| value == tab_value }&.first || value, value] }
|
|
37
37
|
end
|
|
38
38
|
used_choices.merge tab_values
|
|
39
39
|
end
|
|
@@ -41,7 +41,7 @@ module ActiveScaffold
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def active_scaffold_tab_options(column, record)
|
|
44
|
-
subform_column = column.first
|
|
44
|
+
subform_column = column.visible_columns.first
|
|
45
45
|
if subform_column
|
|
46
46
|
tabbed_by = subform_column.options[:tabbed_by] || column.tabbed_by
|
|
47
47
|
if tabbed_by_association(subform_column, tabbed_by)
|
|
@@ -51,7 +51,7 @@ module ActiveScaffold
|
|
|
51
51
|
end
|
|
52
52
|
if tab_column
|
|
53
53
|
label_method = (tab_column.form_ui_options || tab_column.options)[:label_method] || :to_label
|
|
54
|
-
helper_method = association_helper_method(
|
|
54
|
+
helper_method = association_helper_method(tab_column.association, :sorted_association_options_find)
|
|
55
55
|
send(helper_method, tab_column.association, nil, subform_record).map do |opt_record|
|
|
56
56
|
[opt_record.send(label_method), opt_record.id, opt_record]
|
|
57
57
|
end
|
|
@@ -18,6 +18,7 @@ module ActiveScaffold
|
|
|
18
18
|
include ActiveScaffold::Helpers::SearchColumnHelpers
|
|
19
19
|
include ActiveScaffold::Helpers::HumanConditionHelpers
|
|
20
20
|
include ActiveScaffold::Helpers::FilterHelpers
|
|
21
|
+
include ActiveScaffold::Helpers::FrameworkUiHelpers
|
|
21
22
|
|
|
22
23
|
##
|
|
23
24
|
## Delegates
|
|
@@ -31,6 +32,12 @@ module ActiveScaffold
|
|
|
31
32
|
## Uncategorized
|
|
32
33
|
##
|
|
33
34
|
|
|
35
|
+
# UI adapters may override this method and call +super+ to wrap the table,
|
|
36
|
+
# for example in a responsive-table container.
|
|
37
|
+
def list_table_html(&)
|
|
38
|
+
capture(&)
|
|
39
|
+
end
|
|
40
|
+
|
|
34
41
|
def handle_exception_on_column(exception, column, record = nil)
|
|
35
42
|
raise exception if exception.instance_variable_get(:@_active_scaffold_wrapped)
|
|
36
43
|
|
|
@@ -126,6 +133,7 @@ module ActiveScaffold
|
|
|
126
133
|
def column_heading_class(column, sorting)
|
|
127
134
|
classes = "#{column.name}-column_heading "
|
|
128
135
|
classes << "sorted #{sorting.direction_of(column).downcase} " if sorting.sorts_on? column
|
|
136
|
+
classes << 'skip-local-sorting' if column.skip_local_sorting?
|
|
129
137
|
classes << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
|
|
130
138
|
classes
|
|
131
139
|
end
|
|
@@ -140,6 +148,10 @@ module ActiveScaffold
|
|
|
140
148
|
params[:eid] ? {eid: id_from_controller(params[:eid])} : {}
|
|
141
149
|
end
|
|
142
150
|
|
|
151
|
+
def server_error_msg(content = nil, **attributes, &)
|
|
152
|
+
as_element :server_error, content, **attributes, &
|
|
153
|
+
end
|
|
154
|
+
|
|
143
155
|
def column_empty?(column_value)
|
|
144
156
|
@_empty_values ||= [' ', empty_field_text].compact
|
|
145
157
|
empty = column_value.nil?
|
|
@@ -24,16 +24,19 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
|
|
|
24
24
|
|
|
25
25
|
class Column < ActiveRecord::ConnectionAdapters::Column
|
|
26
26
|
def initialize(name, default, type, null = true, *, **) # rubocop:disable Style/OptionalBooleanParameter,Metrics/ParameterLists
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
connection = ActiveRecord::Base.connection
|
|
28
|
+
sql_type = type.is_a?(Symbol) ? connection.type_to_sql(type) : type.to_s
|
|
29
|
+
cast_type = connection.send(:lookup_cast_type, sql_type)
|
|
30
|
+
metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(
|
|
31
|
+
sql_type: sql_type,
|
|
32
|
+
type: cast_type.type,
|
|
33
|
+
limit: cast_type.limit,
|
|
34
|
+
precision: cast_type.precision,
|
|
35
|
+
scale: cast_type.scale
|
|
36
|
+
)
|
|
37
|
+
if ActiveRecord.version >= Gem::Version.new('8.1')
|
|
34
38
|
super(name, cast_type, default, metadata, null, *, **)
|
|
35
39
|
else
|
|
36
|
-
metadata = ActiveRecord::Base.connection.send :fetch_type_metadata, type.to_s
|
|
37
40
|
super(name, default, metadata, null, *, **)
|
|
38
41
|
end
|
|
39
42
|
end
|