active_scaffold 3.7.0 → 3.7.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 +20 -0
- data/README.md +2 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +68 -62
- data/app/assets/stylesheets/active_scaffold_layout.css +1 -1
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_render_field.js.erb +9 -6
- data/config/locales/de.yml +6 -3
- data/config/locales/en.yml +3 -0
- data/config/locales/es.yml +3 -0
- data/config/locales/fr.yml +9 -6
- data/config/locales/hu.yml +20 -17
- data/config/locales/ja.yml +25 -22
- data/config/locales/ru.yml +17 -14
- data/lib/active_scaffold/actions/update.rb +3 -3
- data/lib/active_scaffold/attribute_params.rb +7 -17
- data/lib/active_scaffold/bridges/active_storage/form_ui.rb +6 -6
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +7 -7
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -2
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +12 -14
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +2 -2
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen/helpers.rb +10 -10
- data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +7 -7
- data/lib/active_scaffold/bridges/date_picker/ext.rb +20 -9
- data/lib/active_scaffold/bridges/date_picker/helper.rb +5 -5
- data/lib/active_scaffold/bridges/date_picker.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -3
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +5 -5
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +3 -3
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -3
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -15
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +6 -6
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +5 -5
- data/lib/active_scaffold/bridges.rb +0 -3
- data/lib/active_scaffold/constraints.rb +22 -7
- data/lib/active_scaffold/core.rb +5 -3
- data/lib/active_scaffold/data_structures/column.rb +108 -23
- data/lib/active_scaffold/engine.rb +15 -0
- data/lib/active_scaffold/extensions/routing_mapper.rb +1 -0
- data/lib/active_scaffold/finder.rb +142 -27
- data/lib/active_scaffold/helpers/controller_helpers.rb +9 -4
- data/lib/active_scaffold/helpers/form_column_helpers.rb +114 -94
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +48 -14
- data/lib/active_scaffold/helpers/list_column_helpers.rb +34 -18
- data/lib/active_scaffold/helpers/search_column_helpers.rb +131 -55
- data/lib/active_scaffold/helpers/show_column_helpers.rb +6 -6
- data/lib/active_scaffold/orm_checks.rb +21 -1
- data/lib/active_scaffold/version.rb +1 -1
- data/lib/active_scaffold.rb +3 -2
- data/test/bridges/date_picker_test.rb +3 -2
- data/test/bridges/paperclip_test.rb +3 -2
- data/test/bridges/tiny_mce_test.rb +4 -2
- data/test/helpers/form_column_helpers_test.rb +7 -5
- data/test/helpers/search_column_helpers_test.rb +2 -1
- data/test/misc/constraints_test.rb +1 -0
- data/test/misc/finder_test.rb +38 -0
- metadata +2 -6
- data/config/brakeman.ignore +0 -26
- data/config/brakeman.yml +0 -3
- data/config/i18n-tasks.yml +0 -121
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +0 -221
@@ -5,8 +5,13 @@ module ActiveScaffold
|
|
5
5
|
def get_column_value(record, column)
|
6
6
|
record = record.send(column.delegated_association.name) if column.delegated_association
|
7
7
|
if record
|
8
|
-
method = get_column_method(record, column)
|
9
|
-
value =
|
8
|
+
method, list_ui = get_column_method(record, column)
|
9
|
+
value =
|
10
|
+
if list_ui
|
11
|
+
send(method, record, column, ui_options: column.list_ui_options || column.options)
|
12
|
+
else
|
13
|
+
send(method, record, column)
|
14
|
+
end
|
10
15
|
else
|
11
16
|
value = nil
|
12
17
|
end
|
@@ -27,8 +32,8 @@ module ActiveScaffold
|
|
27
32
|
method
|
28
33
|
# second, check if the dev has specified a valid list_ui for this column
|
29
34
|
elsif column.list_ui && (method = override_column_ui(column.list_ui))
|
30
|
-
method
|
31
|
-
elsif column.column && (method = override_column_ui(column.
|
35
|
+
[method, true]
|
36
|
+
elsif column.column && (method = override_column_ui(column.column_type))
|
32
37
|
method
|
33
38
|
else
|
34
39
|
:format_column_value
|
@@ -76,39 +81,49 @@ module ActiveScaffold
|
|
76
81
|
##
|
77
82
|
## Overrides
|
78
83
|
##
|
79
|
-
def active_scaffold_column_text(record, column)
|
84
|
+
def active_scaffold_column_text(record, column, ui_options: column.options)
|
80
85
|
# `to_s` is necessary to convert objects in serialized columns to string before truncation.
|
81
|
-
clean_column_value(truncate(record.send(column.name).to_s, :
|
86
|
+
clean_column_value(truncate(record.send(column.name).to_s, length: ui_options[:truncate] || 50))
|
82
87
|
end
|
83
88
|
|
84
|
-
def active_scaffold_column_fulltext(record, column)
|
89
|
+
def active_scaffold_column_fulltext(record, column, ui_options: column.options)
|
85
90
|
clean_column_value(record.send(column.name))
|
86
91
|
end
|
87
92
|
|
88
|
-
def active_scaffold_column_marked(record, column)
|
93
|
+
def active_scaffold_column_marked(record, column, ui_options: column.options)
|
89
94
|
options = {:id => nil, :object => record}
|
90
95
|
content_tag(:span, check_box(:record, column.name, options), :class => 'in_place_editor_field', :data => {:ie_id => record.to_param})
|
91
96
|
end
|
92
97
|
|
93
|
-
def active_scaffold_column_checkbox(record, column)
|
98
|
+
def active_scaffold_column_checkbox(record, column, ui_options: column.options)
|
94
99
|
options = {:disabled => true, :id => nil, :object => record}
|
95
100
|
options.delete(:disabled) if inplace_edit?(record, column)
|
96
101
|
check_box(:record, column.name, options)
|
97
102
|
end
|
98
103
|
|
99
|
-
def
|
100
|
-
|
104
|
+
def active_scaffold_column_boolean(record, column, ui_options: column.options)
|
105
|
+
value = record.send(column.name)
|
106
|
+
if value.nil? && ui_options[:include_blank]
|
107
|
+
value = ui_options[:include_blank]
|
108
|
+
value.is_a?(Symbol) ? as_(value) : value
|
109
|
+
else
|
110
|
+
format_column_value(record, column, value)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def active_scaffold_column_percentage(record, column, ui_options: column.options)
|
115
|
+
options = ui_options[:slider] || {}
|
101
116
|
options = options.merge(min: record.send(options[:min_method])) if options[:min_method]
|
102
117
|
options = options.merge(max: record.send(options[:max_method])) if options[:max_method]
|
103
118
|
value = record.send(options[:value_method]) if options[:value_method]
|
104
119
|
as_slider options.merge(value: value || record.send(column.name))
|
105
120
|
end
|
106
121
|
|
107
|
-
def active_scaffold_column_month(record, column)
|
122
|
+
def active_scaffold_column_month(record, column, ui_options: column.options)
|
108
123
|
l record.send(column.name), format: :year_month
|
109
124
|
end
|
110
125
|
|
111
|
-
def active_scaffold_column_week(record, column)
|
126
|
+
def active_scaffold_column_week(record, column, ui_options: column.options)
|
112
127
|
l record.send(column.name), format: :week
|
113
128
|
end
|
114
129
|
|
@@ -119,10 +134,10 @@ module ActiveScaffold
|
|
119
134
|
link_to text, "tel:#{[groups.join('-'), extension].compact.join(',')}"
|
120
135
|
end
|
121
136
|
|
122
|
-
def active_scaffold_column_telephone(record, column)
|
137
|
+
def active_scaffold_column_telephone(record, column, ui_options: column.options)
|
123
138
|
phone = record.send column.name
|
124
139
|
return if phone.blank?
|
125
|
-
phone = number_to_phone(phone) unless
|
140
|
+
phone = number_to_phone(phone) unless ui_options[:format] == false
|
126
141
|
tel_to phone
|
127
142
|
end
|
128
143
|
|
@@ -147,8 +162,9 @@ module ActiveScaffold
|
|
147
162
|
def format_column_value(record, column, value = nil)
|
148
163
|
value ||= record.send(column.name) unless record.nil?
|
149
164
|
if column.association.nil?
|
150
|
-
if FORM_UI_WITH_OPTIONS.include?(column.form_ui)
|
151
|
-
|
165
|
+
form_ui_options = column.form_ui_options || column.options if FORM_UI_WITH_OPTIONS.include?(column.form_ui)
|
166
|
+
if form_ui_options&.dig(:options)
|
167
|
+
text, val = form_ui_options[:options].find { |t, v| (v.nil? ? t : v).to_s == value.to_s }
|
152
168
|
value = active_scaffold_translated_option(column, text, val).first if text
|
153
169
|
end
|
154
170
|
if grouped_search? && column == search_group_column && search_group_function
|
@@ -303,7 +319,7 @@ module ActiveScaffold
|
|
303
319
|
end
|
304
320
|
|
305
321
|
def inplace_edit_cloning?(column)
|
306
|
-
column.inplace_edit != :ajax && (override_form_field?(column) || column.form_ui || (column.column && override_input?(column.
|
322
|
+
column.inplace_edit != :ajax && (override_form_field?(column) || column.form_ui || (column.column && override_input?(column.column_type)))
|
307
323
|
end
|
308
324
|
|
309
325
|
def active_scaffold_inplace_edit_tag_options(record, column)
|
@@ -20,11 +20,11 @@ module ActiveScaffold
|
|
20
20
|
|
21
21
|
# second, check if the dev has specified a valid search_ui for this column, using specific ui for searches
|
22
22
|
elsif column.search_ui && (method = override_search(column.search_ui))
|
23
|
-
send(method, column, options)
|
23
|
+
send(method, column, options, ui_options: column.search_ui_options || column.options)
|
24
24
|
|
25
25
|
# third, check if the dev has specified a valid search_ui for this column, using generic ui for forms
|
26
26
|
elsif column.search_ui && (method = override_input(column.search_ui))
|
27
|
-
send(method, column, options)
|
27
|
+
send(method, column, options, ui_options: column.search_ui_options || column.options)
|
28
28
|
|
29
29
|
# fourth, check if the dev has created an override for this specific field
|
30
30
|
elsif (method = override_form_field(column))
|
@@ -34,11 +34,11 @@ module ActiveScaffold
|
|
34
34
|
elsif column.association || column.virtual?
|
35
35
|
active_scaffold_search_text(column, options)
|
36
36
|
|
37
|
-
elsif (method = override_search(column.
|
37
|
+
elsif (method = override_search(column.column_type))
|
38
38
|
# if we (or someone else) have created a custom render option for the column type, use that
|
39
39
|
send(method, column, options)
|
40
40
|
|
41
|
-
elsif (method = override_input(column.
|
41
|
+
elsif (method = override_input(column.column_type))
|
42
42
|
# if we (or someone else) have created a custom render option for the column type, use that
|
43
43
|
send(method, column, options)
|
44
44
|
|
@@ -73,28 +73,28 @@ module ActiveScaffold
|
|
73
73
|
## Search input methods
|
74
74
|
##
|
75
75
|
|
76
|
-
def active_scaffold_search_multi_select(column, options)
|
76
|
+
def active_scaffold_search_multi_select(column, options, ui_options: column.options)
|
77
77
|
record = options.delete(:object)
|
78
78
|
associated = options.delete :value
|
79
79
|
associated = [associated].compact unless associated.is_a? Array
|
80
80
|
|
81
81
|
if column.association
|
82
82
|
associated.collect!(&:to_i)
|
83
|
-
method =
|
83
|
+
method = ui_options[:label_method] || :to_label
|
84
84
|
select_options = sorted_association_options_find(column.association, nil, record).collect do |r|
|
85
85
|
[r.send(method), r.id]
|
86
86
|
end
|
87
87
|
else
|
88
|
-
select_options = column
|
88
|
+
select_options = active_scaffold_enum_options(column, record, ui_options: ui_options).collect do |text, value|
|
89
89
|
active_scaffold_translated_option(column, text, value)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
return as_(:no_options) if select_options.empty?
|
93
93
|
|
94
|
-
active_scaffold_checkbox_list(column, select_options, associated, options)
|
94
|
+
active_scaffold_checkbox_list(column, select_options, associated, options, ui_options: ui_options)
|
95
95
|
end
|
96
96
|
|
97
|
-
def active_scaffold_search_select(column, html_options, options = {})
|
97
|
+
def active_scaffold_search_select(column, html_options, options = {}, ui_options: column.options)
|
98
98
|
record = html_options.delete(:object)
|
99
99
|
associated = html_options.delete :value
|
100
100
|
if column.association
|
@@ -103,13 +103,13 @@ module ActiveScaffold
|
|
103
103
|
select_options = sorted_association_options_find(column.association, false, record)
|
104
104
|
else
|
105
105
|
method = column.name
|
106
|
-
select_options = active_scaffold_enum_options(column, record).collect do |text, value|
|
106
|
+
select_options = active_scaffold_enum_options(column, record, ui_options: ui_options).collect do |text, value|
|
107
107
|
active_scaffold_translated_option(column, text, value)
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
-
options = options.merge(:
|
112
|
-
html_options.merge!
|
111
|
+
options = options.merge(selected: associated).merge ui_options
|
112
|
+
html_options.merge! ui_options[:html_options] || {}
|
113
113
|
if html_options[:multiple]
|
114
114
|
active_scaffold_select_name_with_multiple html_options
|
115
115
|
else
|
@@ -120,23 +120,31 @@ module ActiveScaffold
|
|
120
120
|
if (optgroup = options.delete(:optgroup))
|
121
121
|
select(:record, method, active_scaffold_grouped_options(column, select_options, optgroup), options, html_options)
|
122
122
|
elsif column.association
|
123
|
-
collection_select(:record, method, select_options, :id,
|
123
|
+
collection_select(:record, method, select_options, :id, ui_options[:label_method] || :to_label, options, html_options)
|
124
124
|
else
|
125
125
|
select(:record, method, select_options, options, html_options)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
def
|
129
|
+
def active_scaffold_search_select_multiple(column, options, ui_options: column.options)
|
130
|
+
active_scaffold_search_select(column, options.merge(multiple: true), ui_options: ui_options)
|
131
|
+
end
|
132
|
+
|
133
|
+
def active_scaffold_search_draggable(column, options, ui_options: column.options)
|
134
|
+
active_scaffold_search_multi_select(column, options.merge(draggable_lists: true), ui_options: ui_options)
|
135
|
+
end
|
136
|
+
|
137
|
+
def active_scaffold_search_text(column, options, ui_options: column.options)
|
130
138
|
text_field :record, column.name, active_scaffold_input_text_options(options)
|
131
139
|
end
|
132
140
|
|
133
141
|
# we can't use active_scaffold_input_boolean because we need to have a nil value even when column can't be null
|
134
142
|
# to decide whether search for this field or not
|
135
|
-
def active_scaffold_search_boolean(column, options)
|
143
|
+
def active_scaffold_search_boolean(column, options, ui_options: column.options)
|
136
144
|
select_options = []
|
137
145
|
select_options << [as_(:_select_), nil]
|
138
|
-
if column.
|
139
|
-
null_label =
|
146
|
+
if column.null?
|
147
|
+
null_label = ui_options[:include_blank] || :null
|
140
148
|
null_label = as_(null_label) if null_label.is_a?(Symbol)
|
141
149
|
select_options << [null_label, 'null']
|
142
150
|
end
|
@@ -168,7 +176,7 @@ module ActiveScaffold
|
|
168
176
|
end
|
169
177
|
end
|
170
178
|
|
171
|
-
def active_scaffold_search_null(column, options)
|
179
|
+
def active_scaffold_search_null(column, options, ui_options: column.options)
|
172
180
|
select_options = []
|
173
181
|
select_options << [as_(:_select_), nil]
|
174
182
|
select_options.concat(ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] })
|
@@ -185,38 +193,38 @@ module ActiveScaffold
|
|
185
193
|
column.text? || column.search_ui == :string
|
186
194
|
end
|
187
195
|
|
188
|
-
def active_scaffold_search_range_comparator_options(column)
|
196
|
+
def active_scaffold_search_range_comparator_options(column, ui_options: column.options)
|
189
197
|
select_options = ActiveScaffold::Finder::NUMERIC_COMPARATORS.collect { |comp| [as_(comp.downcase.to_sym), comp] }
|
190
198
|
if active_scaffold_search_range_string?(column)
|
191
199
|
comparators = ActiveScaffold::Finder::STRING_COMPARATORS.collect { |title, comp| [as_(title), comp] }
|
192
200
|
select_options.unshift(*comparators)
|
193
201
|
end
|
194
|
-
if include_null_comparators? column
|
202
|
+
if include_null_comparators? column, ui_options: ui_options
|
195
203
|
select_options.concat(ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] })
|
196
204
|
end
|
197
205
|
select_options
|
198
206
|
end
|
199
207
|
|
200
|
-
def include_null_comparators?(column)
|
201
|
-
return
|
208
|
+
def include_null_comparators?(column, ui_options: column.options)
|
209
|
+
return ui_options[:null_comparators] if ui_options.key? :null_comparators
|
202
210
|
if column.association
|
203
|
-
!column.association.belongs_to? || active_scaffold_config.columns[column.association.foreign_key].
|
211
|
+
!column.association.belongs_to? || active_scaffold_config.columns[column.association.foreign_key].null?
|
204
212
|
else
|
205
|
-
column.
|
213
|
+
column.null?
|
206
214
|
end
|
207
215
|
end
|
208
216
|
|
209
|
-
def active_scaffold_search_range(column, options, input_method = :text_field_tag, input_options = {})
|
217
|
+
def active_scaffold_search_range(column, options, input_method = :text_field_tag, input_options = {}, ui_options: column.options)
|
210
218
|
opt_value, from_value, to_value = field_search_params_range_values(column)
|
211
219
|
|
212
|
-
select_options = active_scaffold_search_range_comparator_options(column)
|
220
|
+
select_options = active_scaffold_search_range_comparator_options(column, ui_options: ui_options)
|
213
221
|
text_field_size = active_scaffold_search_range_string?(column) ? 15 : 10
|
214
222
|
opt_value ||= select_options[0][1]
|
215
223
|
|
216
224
|
from_value = controller.class.condition_value_for_numeric(column, from_value)
|
217
225
|
to_value = controller.class.condition_value_for_numeric(column, to_value)
|
218
|
-
from_value = format_number_value(from_value,
|
219
|
-
to_value = format_number_value(to_value,
|
226
|
+
from_value = format_number_value(from_value, ui_options) if from_value.is_a?(Numeric)
|
227
|
+
to_value = format_number_value(to_value, ui_options) if to_value.is_a?(Numeric)
|
220
228
|
html = select_tag("#{options[:name]}[opt]", options_for_select(select_options, opt_value),
|
221
229
|
:id => "#{options[:id]}_opt", :class => 'as_search_range_option')
|
222
230
|
from_options = active_scaffold_input_text_options(input_options.merge(:id => options[:id], :size => text_field_size))
|
@@ -233,51 +241,119 @@ module ActiveScaffold
|
|
233
241
|
end
|
234
242
|
alias active_scaffold_search_string active_scaffold_search_range
|
235
243
|
|
236
|
-
def active_scaffold_search_integer(column, options)
|
237
|
-
active_scaffold_search_range(column, options, :number_field_tag, step: '1')
|
244
|
+
def active_scaffold_search_integer(column, options, ui_options: column.options)
|
245
|
+
active_scaffold_search_range(column, options, :number_field_tag, {step: '1'}, ui_options: ui_options) # rubocop:disable Style/BracesAroundHashParameters
|
238
246
|
end
|
239
247
|
|
240
|
-
def active_scaffold_search_decimal(column, options)
|
241
|
-
active_scaffold_search_range(column, options, :number_field_tag, step: :any)
|
248
|
+
def active_scaffold_search_decimal(column, options, ui_options: column.options)
|
249
|
+
active_scaffold_search_range(column, options, :number_field_tag, {step: :any}, ui_options: ui_options) # rubocop:disable Style/BracesAroundHashParameters
|
242
250
|
end
|
243
251
|
alias active_scaffold_search_float active_scaffold_search_decimal
|
244
252
|
|
253
|
+
def active_scaffold_search_datetime(column, options, ui_options: column.options, field_ui: column.search_ui || :datetime)
|
254
|
+
current_search = {'from' => nil, 'to' => nil, 'opt' => 'BETWEEN',
|
255
|
+
'number' => 1, 'unit' => 'DAYS', 'range' => nil}
|
256
|
+
current_search.merge!(options[:value]) unless options[:value].nil?
|
257
|
+
tags = [
|
258
|
+
active_scaffold_search_datetime_comparator_tag(column, options, current_search),
|
259
|
+
active_scaffold_search_datetime_trend_tag(column, options, current_search),
|
260
|
+
active_scaffold_search_datetime_numeric_tag(column, options, current_search, ui_options: ui_options, field_ui: field_ui),
|
261
|
+
active_scaffold_search_datetime_range_tag(column, options, current_search)
|
262
|
+
]
|
263
|
+
safe_join tags, ' '.html_safe # rubocop:disable Rails/OutputSafety
|
264
|
+
end
|
265
|
+
|
266
|
+
def active_scaffold_search_timestamp(column, options, ui_options: column.options)
|
267
|
+
active_scaffold_search_datetime(column, options, ui_options: ui_options, field_ui: :datetime)
|
268
|
+
end
|
269
|
+
|
270
|
+
def active_scaffold_search_time(column, options, ui_options: column.options)
|
271
|
+
active_scaffold_search_datetime(column, options, ui_options: ui_options, field_ui: :time)
|
272
|
+
end
|
273
|
+
|
274
|
+
def active_scaffold_search_date(column, options, ui_options: column.options)
|
275
|
+
active_scaffold_search_datetime(column, options, ui_options: ui_options, field_ui: :date)
|
276
|
+
end
|
277
|
+
|
278
|
+
def active_scaffold_search_datetime_comparator_options(column)
|
279
|
+
select_options = ActiveScaffold::Finder::DATE_COMPARATORS.collect { |comp| [as_(comp.downcase.to_sym), comp] }
|
280
|
+
select_options + ActiveScaffold::Finder::NUMERIC_COMPARATORS.collect { |comp| [as_(comp.downcase.to_sym), comp] }
|
281
|
+
end
|
282
|
+
|
283
|
+
def active_scaffold_search_datetime_comparator_tag(column, options, current_search)
|
284
|
+
choices = options_for_select(active_scaffold_search_datetime_comparator_options(column), current_search['opt'])
|
285
|
+
select_tag("#{options[:name]}[opt]", choices, id: "#{options[:id]}_opt", class: 'as_search_range_option as_search_date_time_option')
|
286
|
+
end
|
287
|
+
|
288
|
+
def active_scaffold_search_datetime_numeric_tag(column, options, current_search, ui_options: column.options, field_ui: column.search_ui)
|
289
|
+
helper = "active_scaffold_search_#{field_ui}_field"
|
290
|
+
numeric_controls = [
|
291
|
+
send(helper, column, options, current_search, 'from', ui_options: ui_options),
|
292
|
+
content_tag(:span, id: "#{options[:id]}_between", class: 'as_search_range_between',
|
293
|
+
style: ('display: none' unless current_search['opt'] == 'BETWEEN')) do
|
294
|
+
safe_join([' - ', send(helper, column, options, current_search, 'to', ui_options: ui_options)])
|
295
|
+
end
|
296
|
+
]
|
297
|
+
content_tag('span', safe_join(numeric_controls),
|
298
|
+
:id => "#{options[:id]}_numeric", :class => 'search-date-numeric',
|
299
|
+
:style => ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(current_search['opt']) ? nil : 'display: none')
|
300
|
+
end
|
301
|
+
|
302
|
+
def active_scaffold_search_datetime_trend_tag(column, options, current_search)
|
303
|
+
trend_controls = [
|
304
|
+
text_field_tag("#{options[:name]}[number]", current_search['number'], class: 'text-input', size: 10, autocomplete: 'off'),
|
305
|
+
select_tag("#{options[:name]}[unit]",
|
306
|
+
options_for_select(active_scaffold_search_datetime_trend_units(column), current_search['unit']),
|
307
|
+
class: 'text-input')
|
308
|
+
]
|
309
|
+
content_tag('span', safe_join(trend_controls, ' '),
|
310
|
+
id: "#{options[:id]}_trend", class: 'search-date-trend',
|
311
|
+
style: ('display: none' unless current_search['opt'] == 'PAST' || current_search['opt'] == 'FUTURE'))
|
312
|
+
end
|
313
|
+
|
314
|
+
def active_scaffold_search_datetime_trend_units(column)
|
315
|
+
options = ActiveScaffold::Finder::DATE_UNITS.collect { |unit| [as_(unit.downcase.to_sym), unit] }
|
316
|
+
options = ActiveScaffold::Finder::TIME_UNITS.collect { |unit| [as_(unit.downcase.to_sym), unit] } + options if column_datetime?(column)
|
317
|
+
options
|
318
|
+
end
|
319
|
+
|
320
|
+
def active_scaffold_search_datetime_range_tag(column, options, current_search)
|
321
|
+
values = ActiveScaffold::Finder::DATE_RANGES.collect { |range| [as_(range.downcase.to_sym), range] }
|
322
|
+
range_controls = select_tag("#{options[:name]}[range]",
|
323
|
+
options_for_select(values, current_search['range']),
|
324
|
+
class: 'text-input', id: nil)
|
325
|
+
content_tag('span', range_controls,
|
326
|
+
id: "#{options[:id]}_range", class: 'search-date-range',
|
327
|
+
style: ('display: none' unless current_search['opt'] == 'RANGE'))
|
328
|
+
end
|
329
|
+
|
330
|
+
def column_datetime?(column)
|
331
|
+
(!column.column.nil? && %i[datetime time].include?(column.column_type))
|
332
|
+
end
|
333
|
+
|
245
334
|
def field_search_datetime_value(value)
|
246
335
|
Time.zone.local(value[:year].to_i, value[:month].to_i, value[:day].to_i, value[:hour].to_i, value[:minute].to_i, value[:second].to_i) unless value.nil? || value[:year].blank?
|
247
336
|
end
|
248
337
|
|
249
|
-
def
|
250
|
-
|
251
|
-
options = column.options.merge(options)
|
338
|
+
def active_scaffold_search_datetime_field(column, options, current_search, name, ui_options: column.options)
|
339
|
+
options = ui_options.merge(options)
|
252
340
|
type = "#{'date' unless options[:discard_date]}#{'time' unless options[:discard_time]}"
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
if use_select
|
257
|
-
helper = "select_#{type}"
|
258
|
-
fields = [
|
259
|
-
send(helper, field_search_datetime_value(from_value), options.reverse_merge(include_blank: true, prefix: from_name)),
|
260
|
-
send(helper, field_search_datetime_value(to_value), options.reverse_merge(include_blank: true, prefix: to_name))
|
261
|
-
]
|
341
|
+
field_name = "#{options[:name]}[#{name}]"
|
342
|
+
if options[:use_select]
|
343
|
+
send("select_#{type}", current_search[name], options.reverse_merge(include_blank: true, prefix: field_name))
|
262
344
|
else
|
263
345
|
helper = "#{type}#{'_local' if type == 'datetime'}_field_tag"
|
264
|
-
|
265
|
-
send(helper, from_name, field_search_datetime_value(from_value), options.except(:name, :object).merge(id: "#{options[:id]}_from")),
|
266
|
-
send(helper, to_name, field_search_datetime_value(to_value), options.except(:name, :object).merge(id: "#{options[:id]}_to"))
|
267
|
-
]
|
346
|
+
send(helper, field_name, current_search[name], options.except(:name, :object, :use_select).merge(id: "#{options[:id]}_#{name}"))
|
268
347
|
end
|
269
|
-
|
270
|
-
safe_join fields, ' - '
|
271
348
|
end
|
272
349
|
|
273
|
-
def
|
274
|
-
|
350
|
+
def active_scaffold_search_date_field(column, options, current_search, name, ui_options: column.options)
|
351
|
+
active_scaffold_search_datetime_field(column, options.merge!(:discard_time => true), current_search, name, ui_options: ui_options)
|
275
352
|
end
|
276
353
|
|
277
|
-
def
|
278
|
-
|
354
|
+
def active_scaffold_search_time_field(column, options, current_search, name, ui_options: column.options)
|
355
|
+
active_scaffold_search_datetime_field(column, options.merge!(:discard_date => true), current_search, name, ui_options: ui_options)
|
279
356
|
end
|
280
|
-
alias active_scaffold_search_timestamp active_scaffold_search_datetime
|
281
357
|
|
282
358
|
##
|
283
359
|
## Search column override signatures
|
@@ -13,24 +13,24 @@ module ActiveScaffold
|
|
13
13
|
send(method, value_record, column)
|
14
14
|
# second, check if the dev has specified a valid list_ui for this column
|
15
15
|
elsif column.show_ui && (method = override_show_column_ui(column.show_ui))
|
16
|
-
send(method, value_record, column)
|
17
|
-
elsif column.column && (method = override_show_column_ui(column.
|
16
|
+
send(method, value_record, column, ui_options: column.show_ui_options || column.options)
|
17
|
+
elsif column.column && (method = override_show_column_ui(column.column_type))
|
18
18
|
send(method, value_record, column)
|
19
19
|
else
|
20
20
|
get_column_value(record, column)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def active_scaffold_show_text(record, column)
|
25
|
-
simple_format(clean_column_value(record.send(column.name)))
|
24
|
+
def active_scaffold_show_text(record, column, ui_options: column.options)
|
25
|
+
simple_format(clean_column_value(record.send(column.name)), ui_options[:html_options], ui_options)
|
26
26
|
end
|
27
27
|
|
28
|
-
def active_scaffold_show_horizontal(record, column)
|
28
|
+
def active_scaffold_show_horizontal(record, column, ui_options: column.options)
|
29
29
|
raise ':horizontal show_ui must be used on association column' unless column.association
|
30
30
|
render :partial => 'show_association', :locals => {:column => column, :parent_record => record, :show_partial => :horizontal}
|
31
31
|
end
|
32
32
|
|
33
|
-
def active_scaffold_show_vertical(record, column)
|
33
|
+
def active_scaffold_show_vertical(record, column, ui_options: column.options)
|
34
34
|
raise ':vertical show_ui must be used on association column' unless column.association
|
35
35
|
render :partial => 'show_association', :locals => {:column => column, :parent_record => record, :show_partial => :vertical}
|
36
36
|
end
|
@@ -82,6 +82,22 @@ module ActiveScaffold
|
|
82
82
|
type_for_attribute(klass, column_name)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
def default_value(klass, column_name)
|
87
|
+
if ActiveScaffold::OrmChecks.mongoid? klass
|
88
|
+
columns_hash(klass)[column_name]&.default_val
|
89
|
+
elsif ActiveScaffold::OrmChecks.active_record? klass
|
90
|
+
klass._default_attributes[column_name]&.value
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def cast(klass, column_name, value)
|
95
|
+
if active_record? klass
|
96
|
+
type_for_attribute(klass, column_name).cast value
|
97
|
+
elsif mongoid? klass
|
98
|
+
type_for_attribute(klass, column_name)&.evolve value
|
99
|
+
end
|
100
|
+
end
|
85
101
|
end
|
86
102
|
|
87
103
|
%i[active_record? mongoid? tableless?].each do |method|
|
@@ -96,10 +112,14 @@ module ActiveScaffold
|
|
96
112
|
end
|
97
113
|
end
|
98
114
|
|
99
|
-
%i[type_for_attribute column_type].each do |method|
|
115
|
+
%i[type_for_attribute column_type default_value].each do |method|
|
100
116
|
define_method method do |column_name|
|
101
117
|
ActiveScaffold::OrmChecks.send method, active_record_class, column_name
|
102
118
|
end
|
103
119
|
end
|
120
|
+
|
121
|
+
def cast(column_name, value)
|
122
|
+
ActiveScaffold::OrmChecks.cast active_record_class, column_name, value
|
123
|
+
end
|
104
124
|
end
|
105
125
|
end
|
data/lib/active_scaffold.rb
CHANGED
@@ -3,6 +3,7 @@ module ActiveScaffold
|
|
3
3
|
autoload :AttributeParams, 'active_scaffold/attribute_params'
|
4
4
|
autoload :Bridges, 'active_scaffold/bridges'
|
5
5
|
autoload :Configurable, 'active_scaffold/configurable'
|
6
|
+
autoload :ConnectionAdapters, 'active_scaffold/extensions/connection_adapter.rb'
|
6
7
|
autoload :Constraints, 'active_scaffold/constraints'
|
7
8
|
autoload :Core, 'active_scaffold/core'
|
8
9
|
autoload :Finder, 'active_scaffold/finder'
|
@@ -78,6 +79,8 @@ module ActiveScaffold
|
|
78
79
|
@@exclude_bridges ||= []
|
79
80
|
end
|
80
81
|
|
82
|
+
mattr_accessor :nested_subforms, instance_writer: false
|
83
|
+
|
81
84
|
def self.root
|
82
85
|
File.dirname(__FILE__) + '/..'
|
83
86
|
end
|
@@ -90,5 +93,3 @@ require 'active_scaffold/engine'
|
|
90
93
|
require 'ice_nine'
|
91
94
|
require 'ice_nine/core_ext/object'
|
92
95
|
require 'request_store'
|
93
|
-
# TODO: clean up extensions. some could be organized for autoloading, and others could be removed entirely.
|
94
|
-
Dir["#{File.dirname __FILE__}/active_scaffold/extensions/*.rb"].each { |file| require file }
|
@@ -24,7 +24,8 @@ class DatePickerTest < ActionView::TestCase
|
|
24
24
|
def test_form_ui
|
25
25
|
config = ActiveScaffold::Config::Core.new(:company)
|
26
26
|
@record = Company.new
|
27
|
-
|
28
|
-
assert active_scaffold_input_date_picker(config.columns[:
|
27
|
+
opts = {object: @record}
|
28
|
+
assert active_scaffold_input_date_picker(config.columns[:date], opts.merge(id: 'record_date', name: 'record[date]'))
|
29
|
+
assert active_scaffold_input_date_picker(config.columns[:datetime], opts.merge(id: 'record_date', name: 'record[datetime]'))
|
29
30
|
end
|
30
31
|
end
|
@@ -58,11 +58,12 @@ class PaperclipTest < ActionView::TestCase
|
|
58
58
|
with_js_framework :jquery do
|
59
59
|
config = PaperclipCore.new(:company)
|
60
60
|
@record = Company.new
|
61
|
+
opts = {name: 'record[logo]', id: 'record_logo', object: @record}
|
61
62
|
|
62
63
|
@record.stubs(:logo).returns(stub(:file? => true, :original_filename => 'file', :url => '/system/file', :styles => Company.attachment_definitions[:logo]))
|
63
64
|
click_js = "jQuery(this).prev().val('true'); jQuery(this).parent().hide().next().show(); return false;"
|
64
65
|
change_js = "jQuery(this).parents('div.paperclip_controls').find('input.remove_file').val('false'); return false;"
|
65
|
-
@document = Nokogiri::HTML::Document.parse(active_scaffold_input_paperclip(config.columns[:logo],
|
66
|
+
@document = Nokogiri::HTML::Document.parse(active_scaffold_input_paperclip(config.columns[:logo], opts))
|
66
67
|
assert_select 'div.paperclip_controls input[type=file]' do |match|
|
67
68
|
assert_equal match[0]['onchange'], change_js
|
68
69
|
end
|
@@ -72,7 +73,7 @@ class PaperclipTest < ActionView::TestCase
|
|
72
73
|
assert_select 'div.paperclip_controls input.remove_file[type=hidden][value=false]'
|
73
74
|
|
74
75
|
@record.stubs(:logo).returns(stub(:file? => false))
|
75
|
-
assert_dom_equal '<input name="record[logo]" class="text-input" autocomplete="off" type="file" id="record_logo" />', active_scaffold_input_paperclip(config.columns[:logo],
|
76
|
+
assert_dom_equal '<input name="record[logo]" class="text-input" autocomplete="off" type="file" id="record_logo" />', active_scaffold_input_paperclip(config.columns[:logo], opts)
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
@@ -35,16 +35,18 @@ class TinyMceTest < ActionView::TestCase
|
|
35
35
|
def test_form_ui
|
36
36
|
config = ActiveScaffold::Config::Core.new(:company)
|
37
37
|
record = Company.new
|
38
|
+
opts = {name: 'record[name]', id: 'record_name', class: 'name-input', object: record}
|
38
39
|
|
39
|
-
assert_dom_equal %(<textarea name=\"record[name]\" class=\"name-input mceEditor\" id=\"record_name\" data-tinymce=\"{"theme":"modern"}\">\n</textarea>), active_scaffold_input_text_editor(config.columns[:name],
|
40
|
+
assert_dom_equal %(<textarea name=\"record[name]\" class=\"name-input mceEditor\" id=\"record_name\" data-tinymce=\"{"theme":"modern"}\">\n</textarea>), active_scaffold_input_text_editor(config.columns[:name], opts)
|
40
41
|
end
|
41
42
|
|
42
43
|
def test_form_ui_alternate
|
43
44
|
config = ActiveScaffold::Config::Core.new(:company)
|
44
45
|
record = Company.new
|
45
46
|
config.columns[:name].options[:tinymce_config] = :alternate
|
47
|
+
opts = {name: 'record[name]', id: 'record_name', class: 'name-input', object: record}
|
46
48
|
|
47
|
-
assert_dom_equal %(<textarea name=\"record[name]\" class=\"name-input mceEditor\" id=\"record_name\" data-tinymce=\"{"theme":"alternate","toolbar":"undo redo | format"}\">\n</textarea>), active_scaffold_input_tinymce(config.columns[:name],
|
49
|
+
assert_dom_equal %(<textarea name=\"record[name]\" class=\"name-input mceEditor\" id=\"record_name\" data-tinymce=\"{"theme":"alternate","toolbar":"undo redo | format"}\">\n</textarea>), active_scaffold_input_tinymce(config.columns[:name], opts)
|
48
50
|
end
|
49
51
|
|
50
52
|
protected
|
@@ -9,23 +9,25 @@ class FormColumnHelpersTest < ActionView::TestCase
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_choices_for_select_form_ui_for_simple_column
|
12
|
+
opts = {object: @record}
|
12
13
|
@column.options[:options] = %i[value_1 value_2 value_3]
|
13
|
-
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Value 1</option>\n<option value=\"value_2\">Value 2</option>\n<option value=\"value_3\">Value 3</option></select>", active_scaffold_input_select(@column,
|
14
|
+
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Value 1</option>\n<option value=\"value_2\">Value 2</option>\n<option value=\"value_3\">Value 3</option></select>", active_scaffold_input_select(@column, opts.dup)
|
14
15
|
|
15
16
|
@column.options[:options] = %w[value_1 value_2 value_3]
|
16
|
-
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">value_1</option>\n<option value=\"value_2\">value_2</option>\n<option value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column,
|
17
|
+
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">value_1</option>\n<option value=\"value_2\">value_2</option>\n<option value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, opts.dup)
|
17
18
|
|
18
19
|
@column.options[:options] = [%w[text_1 value_1], %w[text_2 value_2], %w[text_3 value_3]]
|
19
|
-
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">text_1</option>\n<option value=\"value_2\">text_2</option>\n<option value=\"value_3\">text_3</option></select>", active_scaffold_input_select(@column,
|
20
|
+
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">text_1</option>\n<option value=\"value_2\">text_2</option>\n<option value=\"value_3\">text_3</option></select>", active_scaffold_input_select(@column, opts.dup)
|
20
21
|
|
21
22
|
@column.options[:options] = [%i[text_1 value_1], %i[text_2 value_2], %i[text_3 value_3]]
|
22
|
-
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Text 1</option>\n<option value=\"value_2\">Text 2</option>\n<option value=\"value_3\">Text 3</option></select>", active_scaffold_input_select(@column,
|
23
|
+
assert_dom_equal "<select name=\"record[a]\" id=\"record_a\"><option value=\"value_1\">Text 1</option>\n<option value=\"value_2\">Text 2</option>\n<option value=\"value_3\">Text 3</option></select>", active_scaffold_input_select(@column, opts.dup)
|
23
24
|
end
|
24
25
|
|
25
26
|
def test_options_for_select_form_ui_for_simple_column
|
27
|
+
opts = {object: @record}
|
26
28
|
@column.options = {:include_blank => 'None', :selected => 'value_2', :disabled => %w[value_1 value_3]}
|
27
29
|
@column.options[:options] = %w[value_1 value_2 value_3]
|
28
30
|
@column.options[:html_options] = {:class => 'big'}
|
29
|
-
assert_dom_equal "<select name=\"record[a]\" class=\"big\" id=\"record_a\"><option value=\"\">None</option>\n<option disabled=\"disabled\" value=\"value_1\">value_1</option>\n<option selected=\"selected\" value=\"value_2\">value_2</option>\n<option disabled=\"disabled\" value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column,
|
31
|
+
assert_dom_equal "<select name=\"record[a]\" class=\"big\" id=\"record_a\"><option value=\"\">None</option>\n<option disabled=\"disabled\" value=\"value_1\">value_1</option>\n<option selected=\"selected\" value=\"value_2\">value_2</option>\n<option disabled=\"disabled\" value=\"value_3\">value_3</option></select>", active_scaffold_input_select(@column, opts)
|
30
32
|
end
|
31
33
|
end
|