dry_crud 6.0.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -6
- data/VERSION +1 -1
- data/app/assets/stylesheets/sample.scss +45 -24
- data/app/controllers/crud_controller.rb +24 -26
- data/app/controllers/dry_crud/generic_model.rb +6 -12
- data/app/controllers/dry_crud/nestable.rb +1 -4
- data/app/controllers/dry_crud/rememberable.rb +1 -4
- data/app/controllers/dry_crud/render_callbacks.rb +4 -12
- data/app/controllers/dry_crud/searchable.rb +3 -10
- data/app/controllers/dry_crud/sortable.rb +3 -10
- data/app/controllers/list_controller.rb +1 -3
- data/app/helpers/actions_helper.rb +13 -15
- data/app/helpers/dry_crud/form/builder.rb +56 -62
- data/app/helpers/dry_crud/form/control.rb +12 -19
- data/app/helpers/dry_crud/table/actions.rb +15 -20
- data/app/helpers/dry_crud/table/builder.rb +12 -15
- data/app/helpers/dry_crud/table/col.rb +5 -8
- data/app/helpers/dry_crud/table/sorting.rb +3 -6
- data/app/helpers/form_helper.rb +11 -15
- data/app/helpers/format_helper.rb +18 -20
- data/app/helpers/i18n_helper.rb +13 -15
- data/app/helpers/table_helper.rb +16 -19
- data/app/helpers/utility_helper.rb +12 -14
- data/app/views/crud/new.html.erb +1 -1
- data/app/views/crud/new.html.haml +1 -1
- data/app/views/layouts/application.html.erb +8 -6
- data/app/views/layouts/application.html.haml +6 -5
- data/app/views/list/_search.html.erb +1 -3
- data/app/views/list/_search.html.haml +1 -2
- data/app/views/shared/_error_messages.html.erb +2 -2
- data/lib/dry_crud/engine.rb +1 -3
- data/lib/dry_crud.rb +1 -1
- data/lib/generators/dry_crud/dry_crud_generator.rb +18 -18
- data/lib/generators/dry_crud/dry_crud_generator_base.rb +8 -8
- data/lib/generators/dry_crud/file_generator.rb +6 -6
- data/lib/generators/dry_crud/templates/config/initializers/field_error_proc.rb +1 -1
- data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +122 -122
- data/lib/generators/dry_crud/templates/spec/helpers/dry_crud/form/builder_spec.rb +55 -60
- data/lib/generators/dry_crud/templates/spec/helpers/dry_crud/table/builder_spec.rb +24 -26
- data/lib/generators/dry_crud/templates/spec/helpers/form_helper_spec.rb +16 -18
- data/lib/generators/dry_crud/templates/spec/helpers/format_helper_spec.rb +90 -94
- data/lib/generators/dry_crud/templates/spec/helpers/i18n_helper_spec.rb +33 -34
- data/lib/generators/dry_crud/templates/spec/helpers/table_helper_spec.rb +59 -61
- data/lib/generators/dry_crud/templates/spec/helpers/utility_helper_spec.rb +20 -23
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +66 -68
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +11 -13
- data/lib/generators/dry_crud/templates/test/controllers/crud_test_models_controller_test.rb +63 -65
- data/lib/generators/dry_crud/templates/test/helpers/custom_assertions_test.rb +25 -27
- data/lib/generators/dry_crud/templates/test/helpers/dry_crud/form/builder_test.rb +74 -74
- data/lib/generators/dry_crud/templates/test/helpers/dry_crud/table/builder_test.rb +21 -21
- data/lib/generators/dry_crud/templates/test/helpers/form_helper_test.rb +21 -23
- data/lib/generators/dry_crud/templates/test/helpers/format_helper_test.rb +68 -70
- data/lib/generators/dry_crud/templates/test/helpers/i18n_helper_test.rb +26 -28
- data/lib/generators/dry_crud/templates/test/helpers/table_helper_test.rb +28 -30
- data/lib/generators/dry_crud/templates/test/helpers/utility_helper_test.rb +17 -19
- data/lib/generators/dry_crud/templates/test/support/crud_controller_test_helper.rb +13 -15
- data/lib/generators/dry_crud/templates/test/support/crud_test_helper.rb +15 -19
- data/lib/generators/dry_crud/templates/test/support/crud_test_model.rb +9 -14
- data/lib/generators/dry_crud/templates/test/support/crud_test_models_controller.rb +16 -20
- data/lib/generators/dry_crud/templates/test/support/custom_assertions.rb +8 -10
- metadata +9 -10
@@ -7,7 +7,6 @@
|
|
7
7
|
# Furthermore, it remembers the last search and sort parameters after the
|
8
8
|
# user returns from a displayed or edited entry.
|
9
9
|
class ListController < ApplicationController
|
10
|
-
|
11
10
|
include DryCrud::GenericModel
|
12
11
|
prepend DryCrud::Nestable
|
13
12
|
include DryCrud::RenderCallbacks
|
@@ -32,7 +31,7 @@ class ListController < ApplicationController
|
|
32
31
|
# Helper method to access the entries to be displayed in the current index
|
33
32
|
# page in an uniform way.
|
34
33
|
def entries
|
35
|
-
model_ivar_get(true) || model_ivar_set(list_entries)
|
34
|
+
model_ivar_get(plural: true) || model_ivar_set(list_entries)
|
36
35
|
end
|
37
36
|
|
38
37
|
# The base relation used to filter the entries.
|
@@ -48,5 +47,4 @@ class ListController < ApplicationController
|
|
48
47
|
# Include these modules after the #list_entries method is defined.
|
49
48
|
include DryCrud::Searchable
|
50
49
|
include DryCrud::Sortable
|
51
|
-
|
52
50
|
end
|
@@ -3,19 +3,18 @@
|
|
3
3
|
# of action links, change the method #action_link, e.g. to generate a button.
|
4
4
|
# The common crud actions show, edit, destroy, index and add are provided here.
|
5
5
|
module ActionsHelper
|
6
|
-
|
7
6
|
# A generic helper method to create action links.
|
8
7
|
# These link could be styled to look like buttons, for example.
|
9
8
|
def action_link(label, icon = nil, url = {}, html_options = {})
|
10
|
-
add_css_class html_options,
|
9
|
+
add_css_class html_options, "action btn btn-light"
|
11
10
|
link_to(icon ? action_icon(icon, label) : label,
|
12
11
|
url, html_options)
|
13
12
|
end
|
14
13
|
|
15
14
|
# Outputs an icon for an action with an optional label.
|
16
15
|
def action_icon(icon, label = nil)
|
17
|
-
html =
|
18
|
-
html <<
|
16
|
+
html = tag.i("", class: "bi-#{icon}")
|
17
|
+
html << " " << label if label
|
19
18
|
html
|
20
19
|
end
|
21
20
|
|
@@ -23,40 +22,39 @@ module ActionsHelper
|
|
23
22
|
# Uses the current +entry+ if no path is given.
|
24
23
|
def show_action_link(path = nil)
|
25
24
|
path ||= path_args(entry)
|
26
|
-
action_link(ti(
|
25
|
+
action_link(ti("link.show"), "zoom-in", path)
|
27
26
|
end
|
28
27
|
|
29
28
|
# Standard edit action to given path.
|
30
29
|
# Uses the current +entry+ if no path is given.
|
31
30
|
def edit_action_link(path = nil)
|
32
31
|
path ||= path_args(entry)
|
33
|
-
path = path.is_a?(String)
|
34
|
-
action_link(ti(
|
32
|
+
path = edit_polymorphic_path(path) unless path.is_a?(String)
|
33
|
+
action_link(ti("link.edit"), "pencil", path)
|
35
34
|
end
|
36
35
|
|
37
36
|
# Standard destroy action to the given path.
|
38
37
|
# Uses the current +entry+ if no path is given.
|
39
38
|
def destroy_action_link(path = nil)
|
40
39
|
path ||= path_args(entry)
|
41
|
-
action_link(ti(
|
42
|
-
data: { confirm: ti(:confirm_delete),
|
43
|
-
method: :delete })
|
40
|
+
action_link(ti("link.delete"), "trash", path,
|
41
|
+
data: { 'turbo-confirm': ti(:confirm_delete),
|
42
|
+
'turbo-method': :delete })
|
44
43
|
end
|
45
44
|
|
46
45
|
# Standard list action to the given path.
|
47
46
|
# Uses the current +model_class+ if no path is given.
|
48
47
|
def index_action_link(path = nil, url_options = { returning: true })
|
49
48
|
path ||= path_args(model_class)
|
50
|
-
path = path.is_a?(String)
|
51
|
-
action_link(ti(
|
49
|
+
path = polymorphic_path(path, url_options) unless path.is_a?(String)
|
50
|
+
action_link(ti("link.list"), "list", path)
|
52
51
|
end
|
53
52
|
|
54
53
|
# Standard add action to given path.
|
55
54
|
# Uses the current +model_class+ if no path is given.
|
56
55
|
def add_action_link(path = nil, url_options = {})
|
57
56
|
path ||= path_args(model_class)
|
58
|
-
path = path.is_a?(String)
|
59
|
-
action_link(ti(
|
57
|
+
path = new_polymorphic_path(path, url_options) unless path.is_a?(String)
|
58
|
+
action_link(ti("link.add"), "plus", path)
|
60
59
|
end
|
61
|
-
|
62
60
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module DryCrud
|
2
2
|
module Form
|
3
|
-
|
4
3
|
# A form builder that automatically selects the corresponding input field
|
5
4
|
# for ActiveRecord column types. Convenience methods for each column type
|
6
5
|
# allow one to customize the different fields.
|
@@ -14,14 +13,13 @@ module DryCrud
|
|
14
13
|
# See the Control class for how to customize the html rendered for a
|
15
14
|
# single input field.
|
16
15
|
class Builder < ActionView::Helpers::FormBuilder
|
17
|
-
|
18
16
|
class_attribute :control_class
|
19
17
|
self.control_class = Control
|
20
18
|
|
21
19
|
attr_reader :template
|
22
20
|
|
23
21
|
delegate :association, :column_type, :column_property, :captionize,
|
24
|
-
:ti, :ta, :link_to, :
|
22
|
+
:ti, :ta, :link_to, :tag, :safe_join, :capture,
|
25
23
|
:add_css_class, :assoc_and_id_attr,
|
26
24
|
to: :template
|
27
25
|
|
@@ -29,9 +27,8 @@ module DryCrud
|
|
29
27
|
|
30
28
|
# Render multiple input controls together with a label for the given
|
31
29
|
# attributes.
|
32
|
-
def labeled_input_fields(*attrs)
|
33
|
-
|
34
|
-
safe_join(attrs) { |a| labeled_input_field(a, options.dup) }
|
30
|
+
def labeled_input_fields(*attrs, **options)
|
31
|
+
safe_join(attrs) { |a| labeled_input_field(a, **options.dup) }
|
35
32
|
end
|
36
33
|
|
37
34
|
# Render a corresponding input control and label for the given attribute.
|
@@ -45,8 +42,8 @@ module DryCrud
|
|
45
42
|
# * <tt>:field_method</tt> - Different method to create the input field.
|
46
43
|
#
|
47
44
|
# Use additional html_options for the input element.
|
48
|
-
def labeled_input_field(attr, html_options
|
49
|
-
control_class.new(self, attr, html_options).render_labeled
|
45
|
+
def labeled_input_field(attr, **html_options)
|
46
|
+
control_class.new(self, attr, **html_options).render_labeled
|
50
47
|
end
|
51
48
|
|
52
49
|
# Render a corresponding input control for the given attribute.
|
@@ -59,22 +56,22 @@ module DryCrud
|
|
59
56
|
# * <tt>:field_method</tt> - Different method to create the input field.
|
60
57
|
#
|
61
58
|
# Use additional html_options for the input element.
|
62
|
-
def input_field(attr, html_options
|
63
|
-
control_class.new(self, attr, html_options).render_content
|
59
|
+
def input_field(attr, **html_options)
|
60
|
+
control_class.new(self, attr, **html_options).render_content
|
64
61
|
end
|
65
62
|
|
66
63
|
# Render a standard string field with column contraints.
|
67
|
-
def string_field(attr, html_options
|
64
|
+
def string_field(attr, **html_options)
|
68
65
|
html_options[:maxlength] ||= column_property(@object, attr, :limit)
|
69
|
-
text_field(attr, html_options)
|
66
|
+
text_field(attr, **html_options)
|
70
67
|
end
|
71
68
|
|
72
69
|
# Render a boolean field.
|
73
|
-
def boolean_field(attr, html_options
|
74
|
-
|
75
|
-
|
76
|
-
detail = html_options.delete(:detail) ||
|
77
|
-
safe_join([check_box(attr, html_options),
|
70
|
+
def boolean_field(attr, **html_options)
|
71
|
+
tag.div(class: "checkbox") do
|
72
|
+
tag.label do
|
73
|
+
detail = html_options.delete(:detail) || " ".html_safe
|
74
|
+
safe_join([ check_box(attr, html_options), " ", detail ])
|
78
75
|
end
|
79
76
|
end
|
80
77
|
end
|
@@ -82,33 +79,33 @@ module DryCrud
|
|
82
79
|
# Add form-control class to all input fields.
|
83
80
|
%w[text_field password_field email_field
|
84
81
|
number_field date_field time_field datetime_field].each do |method|
|
85
|
-
define_method(method) do |attr, html_options
|
86
|
-
add_css_class(html_options,
|
82
|
+
define_method(method) do |attr, **html_options|
|
83
|
+
add_css_class(html_options, "form-control")
|
87
84
|
super(attr, html_options)
|
88
85
|
end
|
89
86
|
end
|
90
87
|
|
91
|
-
def integer_field(attr, html_options
|
88
|
+
def integer_field(attr, **html_options)
|
92
89
|
html_options[:step] ||= 1
|
93
|
-
number_field(attr, html_options)
|
90
|
+
number_field(attr, **html_options)
|
94
91
|
end
|
95
92
|
|
96
|
-
def float_field(attr, html_options
|
97
|
-
html_options[:step] ||=
|
98
|
-
number_field(attr, html_options)
|
93
|
+
def float_field(attr, **html_options)
|
94
|
+
html_options[:step] ||= "any"
|
95
|
+
number_field(attr, **html_options)
|
99
96
|
end
|
100
97
|
|
101
|
-
def decimal_field(attr, html_options
|
98
|
+
def decimal_field(attr, **html_options)
|
102
99
|
html_options[:step] ||=
|
103
100
|
(10**-column_property(object, attr, :scale)).to_f
|
104
|
-
number_field(attr, html_options)
|
101
|
+
number_field(attr, **html_options)
|
105
102
|
end
|
106
103
|
|
107
104
|
# Customize the standard text area to have 5 rows by default.
|
108
|
-
def text_area(attr, html_options
|
109
|
-
add_css_class(html_options,
|
105
|
+
def text_area(attr, **html_options)
|
106
|
+
add_css_class(html_options, "form-control")
|
110
107
|
html_options[:rows] ||= 5
|
111
|
-
super
|
108
|
+
super
|
112
109
|
end
|
113
110
|
|
114
111
|
# Render a select element for a :belongs_to association defined by attr.
|
@@ -116,13 +113,13 @@ module DryCrud
|
|
116
113
|
# To pass a custom element list, specify the list with the :list key or
|
117
114
|
# define an instance variable with the pluralized name of the
|
118
115
|
# association.
|
119
|
-
def belongs_to_field(attr, html_options
|
120
|
-
list = association_entries(attr, html_options).to_a
|
116
|
+
def belongs_to_field(attr, **html_options)
|
117
|
+
list = association_entries(attr, **html_options).to_a
|
121
118
|
if list.present?
|
122
|
-
add_css_class(html_options,
|
119
|
+
add_css_class(html_options, "form-control")
|
123
120
|
collection_select(attr, list, :id, :to_s,
|
124
|
-
select_options(attr, html_options),
|
125
|
-
html_options)
|
121
|
+
select_options(attr, **html_options),
|
122
|
+
**html_options)
|
126
123
|
else
|
127
124
|
# rubocop:disable Rails/OutputSafety
|
128
125
|
none = ta(:none_available, association(@object, attr)).html_safe
|
@@ -131,7 +128,7 @@ module DryCrud
|
|
131
128
|
end
|
132
129
|
end
|
133
130
|
|
134
|
-
# rubocop:disable PredicateName
|
131
|
+
# rubocop:disable Naming/PredicateName
|
135
132
|
|
136
133
|
# Render a multi select element for a :has_many or
|
137
134
|
# :has_and_belongs_to_many association defined by attr.
|
@@ -139,63 +136,62 @@ module DryCrud
|
|
139
136
|
# To pass a custom element list, specify the list with the :list key or
|
140
137
|
# define an instance variable with the pluralized name of the
|
141
138
|
# association.
|
142
|
-
def has_many_field(attr, html_options
|
139
|
+
def has_many_field(attr, **html_options)
|
143
140
|
html_options[:multiple] = true
|
144
|
-
add_css_class(html_options,
|
145
|
-
belongs_to_field(attr, html_options)
|
141
|
+
add_css_class(html_options, "multiselect")
|
142
|
+
belongs_to_field(attr, **html_options)
|
146
143
|
end
|
147
|
-
# rubocop:enable PredicateName
|
144
|
+
# rubocop:enable Naming/PredicateName
|
148
145
|
|
149
146
|
### VARIOUS FORM ELEMENTS
|
150
147
|
|
151
148
|
# Render the error messages for the current form.
|
152
149
|
def error_messages
|
153
|
-
@template.render(
|
150
|
+
@template.render("shared/error_messages",
|
154
151
|
errors: @object.errors,
|
155
152
|
object: @object)
|
156
153
|
end
|
157
154
|
|
158
155
|
# Renders the given content with an addon.
|
159
156
|
def with_addon(content, addon)
|
160
|
-
|
161
|
-
|
162
|
-
content + content_tag(:div, html, class: 'input-group-append')
|
157
|
+
tag.div(class: "input-group") do
|
158
|
+
content + tag.span(addon, class: "input-group-text")
|
163
159
|
end
|
164
160
|
end
|
165
161
|
|
166
162
|
# Renders a static text where otherwise form inputs appear.
|
167
163
|
def static_text(text)
|
168
|
-
|
164
|
+
tag.p(text, class: "form-control-static")
|
169
165
|
end
|
170
166
|
|
171
167
|
# Generates a help block for fields
|
172
168
|
def help_block(text)
|
173
|
-
|
169
|
+
tag.p(text, class: "help-block")
|
174
170
|
end
|
175
171
|
|
176
172
|
# Render a submit button and a cancel link for this form.
|
177
|
-
def standard_actions(submit_label = ti(
|
178
|
-
|
179
|
-
safe_join([submit_button(submit_label),
|
180
|
-
cancel_link(cancel_url)],
|
181
|
-
|
173
|
+
def standard_actions(submit_label = ti("button.save"), cancel_url = nil)
|
174
|
+
tag.div(class: "col-md-offset-2 col-md-8") do
|
175
|
+
safe_join([ submit_button(submit_label),
|
176
|
+
cancel_link(cancel_url) ],
|
177
|
+
" ")
|
182
178
|
end
|
183
179
|
end
|
184
180
|
|
185
181
|
# Render a standard submit button with the given label.
|
186
|
-
def submit_button(label = ti(
|
187
|
-
button(label, class:
|
182
|
+
def submit_button(label = ti("button.save"))
|
183
|
+
button(label, class: "btn btn-primary", data: { disable_with: label })
|
188
184
|
end
|
189
185
|
|
190
186
|
# Render a cancel link pointing to the given url.
|
191
187
|
def cancel_link(url = nil)
|
192
188
|
url ||= cancel_url
|
193
|
-
link_to(ti(
|
189
|
+
link_to(ti("button.cancel"), url, class: "cancel")
|
194
190
|
end
|
195
191
|
|
196
192
|
# Depending if the given attribute must be present, return
|
197
193
|
# only an initial selection prompt or a blank option, respectively.
|
198
|
-
def select_options(attr, options
|
194
|
+
def select_options(attr, **options)
|
199
195
|
prompt = options.delete(:prompt)
|
200
196
|
blank = options.delete(:include_blank)
|
201
197
|
if options[:multiple]
|
@@ -239,7 +235,7 @@ module DryCrud
|
|
239
235
|
options = content
|
240
236
|
content = capture(&block)
|
241
237
|
end
|
242
|
-
control = control_class.new(self, attr, options)
|
238
|
+
control = control_class.new(self, attr, **options)
|
243
239
|
control.render_labeled(content)
|
244
240
|
end
|
245
241
|
|
@@ -267,19 +263,18 @@ module DryCrud
|
|
267
263
|
# Checks if the passed name corresponds to a field method with a
|
268
264
|
# 'labeled_' prefix.
|
269
265
|
def labeled_field_method?(name)
|
270
|
-
prefix =
|
266
|
+
prefix = "labeled_"
|
271
267
|
if name.to_s.start_with?(prefix)
|
272
|
-
field_method = name.to_s[prefix.size
|
268
|
+
field_method = name.to_s[prefix.size..]
|
273
269
|
field_method if respond_to?(field_method)
|
274
270
|
end
|
275
271
|
end
|
276
272
|
|
277
273
|
# Renders the corresponding field together with a label, required mark
|
278
274
|
# and an optional help block.
|
279
|
-
def build_labeled_field(field_method, *args)
|
280
|
-
options = args.extract_options!
|
275
|
+
def build_labeled_field(field_method, *args, **options)
|
281
276
|
options[:field_method] = field_method
|
282
|
-
control_class.new(self, *
|
277
|
+
control_class.new(self, *args, **options).render_labeled
|
283
278
|
end
|
284
279
|
|
285
280
|
# Returns the list of association entries, either from options[:list] or
|
@@ -287,7 +282,7 @@ module DryCrud
|
|
287
282
|
# Otherwise, if the association defines a #options_list or #list scope,
|
288
283
|
# this is used to load the entries.
|
289
284
|
# As a last resort, all entries from the association class are returned.
|
290
|
-
def association_entries(attr, options)
|
285
|
+
def association_entries(attr, **options)
|
291
286
|
list = options.delete(:list)
|
292
287
|
unless list
|
293
288
|
assoc = association(@object, attr)
|
@@ -324,7 +319,6 @@ module DryCrud
|
|
324
319
|
options[:cancel_url_edit] || options[:cancel_url]
|
325
320
|
end
|
326
321
|
end
|
327
|
-
|
328
322
|
end
|
329
323
|
end
|
330
324
|
end
|
@@ -1,18 +1,16 @@
|
|
1
1
|
module DryCrud
|
2
2
|
module Form
|
3
|
-
|
4
3
|
# Internal class to handle the rendering of a single form control,
|
5
4
|
# consisting of a label, input field, addon, help text or
|
6
5
|
# required mark.
|
7
6
|
class Control
|
8
|
-
|
9
7
|
attr_reader :builder, :attr, :args, :options, :addon, :help
|
10
8
|
|
11
|
-
delegate :
|
9
|
+
delegate :tag, :object, :add_css_class,
|
12
10
|
to: :builder
|
13
11
|
|
14
12
|
# Html displayed to mark an input as required.
|
15
|
-
REQUIRED_MARK =
|
13
|
+
REQUIRED_MARK = "*".freeze
|
16
14
|
|
17
15
|
# Number of default input field span columns depending
|
18
16
|
# on the #field_method.
|
@@ -39,10 +37,10 @@ module DryCrud
|
|
39
37
|
# (The value for this option usually is 'required').
|
40
38
|
#
|
41
39
|
# All the other options will go to the field_method.
|
42
|
-
def initialize(builder, attr, *args)
|
40
|
+
def initialize(builder, attr, *args, **options)
|
43
41
|
@builder = builder
|
44
42
|
@attr = attr
|
45
|
-
@options =
|
43
|
+
@options = options
|
46
44
|
@args = args
|
47
45
|
|
48
46
|
@addon = options.delete(:addon)
|
@@ -70,11 +68,9 @@ module DryCrud
|
|
70
68
|
|
71
69
|
# Create the HTML markup for any labeled content.
|
72
70
|
def labeled
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
builder.label(attr, caption, class: 'col-md-2 control-label') +
|
77
|
-
content_tag(:div, content, class: "col-md-#{span}")
|
71
|
+
tag.div(class: "row mb-3") do
|
72
|
+
builder.label(attr, caption, class: "col-md-2 col-form-label") +
|
73
|
+
tag.div(content, class: "col-md-#{span}")
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
@@ -100,8 +96,9 @@ module DryCrud
|
|
100
96
|
# depending on the attribute.
|
101
97
|
def input
|
102
98
|
@input ||= begin
|
103
|
-
options[:required] =
|
104
|
-
|
99
|
+
options[:required] = "required" if required
|
100
|
+
add_css_class(options, "is-invalid") if errors?
|
101
|
+
builder.send(field_method, attr, *args, **options)
|
105
102
|
end
|
106
103
|
end
|
107
104
|
|
@@ -137,7 +134,6 @@ module DryCrud
|
|
137
134
|
|
138
135
|
# Defines the field method to use based on the attribute
|
139
136
|
# type, association or name.
|
140
|
-
# rubocop:disable PerceivedComplexity
|
141
137
|
def detect_field_method
|
142
138
|
if type == :text
|
143
139
|
:text_area
|
@@ -145,9 +141,9 @@ module DryCrud
|
|
145
141
|
:belongs_to_field
|
146
142
|
elsif association_kind?(:has_and_belongs_to_many, :has_many)
|
147
143
|
:has_many_field
|
148
|
-
elsif attr.to_s.include?(
|
144
|
+
elsif attr.to_s.include?("password")
|
149
145
|
:password_field
|
150
|
-
elsif attr.to_s.include?(
|
146
|
+
elsif attr.to_s.include?("email")
|
151
147
|
:email_field
|
152
148
|
elsif builder.respond_to?(:"#{type}_field")
|
153
149
|
:"#{type}_field"
|
@@ -155,7 +151,6 @@ module DryCrud
|
|
155
151
|
:text_field
|
156
152
|
end
|
157
153
|
end
|
158
|
-
# rubocop:enable PerceivedComplexity
|
159
154
|
|
160
155
|
# The column type of the attribute.
|
161
156
|
def type
|
@@ -173,8 +168,6 @@ module DryCrud
|
|
173
168
|
false
|
174
169
|
end
|
175
170
|
end
|
176
|
-
|
177
171
|
end
|
178
|
-
|
179
172
|
end
|
180
173
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module DryCrud
|
2
2
|
module Table
|
3
|
-
|
4
3
|
# Adds action columns to the table builder.
|
5
4
|
# Predefined actions are available for show, edit and destroy.
|
6
5
|
# Additionally, a special col type to define cells linked to the show page
|
7
6
|
# of the row entry is provided.
|
8
7
|
module Actions
|
9
|
-
|
10
8
|
extend ActiveSupport::Concern
|
11
9
|
|
12
10
|
included do
|
@@ -26,13 +24,13 @@ module DryCrud
|
|
26
24
|
# Action column to show the row entry.
|
27
25
|
# A block may be given to define the link path for the row entry.
|
28
26
|
# If the block returns nil, no link is rendered.
|
29
|
-
def show_action_col(html_options
|
27
|
+
def show_action_col(**html_options, &block)
|
30
28
|
action_col do |entry|
|
31
29
|
path = action_path(entry, &block)
|
32
30
|
if path
|
33
|
-
table_action_link(
|
31
|
+
table_action_link("zoom-in",
|
34
32
|
path,
|
35
|
-
html_options.clone)
|
33
|
+
**html_options.clone)
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
@@ -40,12 +38,12 @@ module DryCrud
|
|
40
38
|
# Action column to edit the row entry.
|
41
39
|
# A block may be given to define the link path for the row entry.
|
42
40
|
# If the block returns nil, no link is rendered.
|
43
|
-
def edit_action_col(html_options
|
41
|
+
def edit_action_col(**html_options, &block)
|
44
42
|
action_col do |entry|
|
45
43
|
path = action_path(entry, &block)
|
46
44
|
if path
|
47
|
-
path = path.is_a?(String)
|
48
|
-
table_action_link(
|
45
|
+
path = edit_polymorphic_path(path) unless path.is_a?(String)
|
46
|
+
table_action_link("pencil", path, **html_options.clone)
|
49
47
|
end
|
50
48
|
end
|
51
49
|
end
|
@@ -53,16 +51,15 @@ module DryCrud
|
|
53
51
|
# Action column to destroy the row entry.
|
54
52
|
# A block may be given to define the link path for the row entry.
|
55
53
|
# If the block returns nil, no link is rendered.
|
56
|
-
def destroy_action_col(html_options
|
54
|
+
def destroy_action_col(**html_options, &block)
|
57
55
|
action_col do |entry|
|
58
56
|
path = action_path(entry, &block)
|
59
57
|
if path
|
60
|
-
table_action_link(
|
58
|
+
table_action_link("trash",
|
61
59
|
path,
|
62
|
-
html_options
|
63
|
-
|
64
|
-
|
65
|
-
))
|
60
|
+
**html_options,
|
61
|
+
data: { 'turbo-confirm': ti(:confirm_delete),
|
62
|
+
'turbo-method': :delete })
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
@@ -70,13 +67,13 @@ module DryCrud
|
|
70
67
|
# Action column inside a table. No header.
|
71
68
|
# The cell content should be defined in the passed block.
|
72
69
|
def action_col(&block)
|
73
|
-
col(
|
70
|
+
col("", class: "action", &block)
|
74
71
|
end
|
75
72
|
|
76
73
|
# Generic action link inside a table.
|
77
|
-
def table_action_link(icon, url, html_options
|
78
|
-
add_css_class(html_options, "
|
79
|
-
link_to(
|
74
|
+
def table_action_link(icon, url, **html_options)
|
75
|
+
add_css_class(html_options, "bi-#{icon}")
|
76
|
+
link_to("", url, html_options)
|
80
77
|
end
|
81
78
|
|
82
79
|
private
|
@@ -86,8 +83,6 @@ module DryCrud
|
|
86
83
|
def action_path(entry)
|
87
84
|
block_given? ? yield(entry) : path_args(entry)
|
88
85
|
end
|
89
|
-
|
90
86
|
end
|
91
|
-
|
92
87
|
end
|
93
88
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module DryCrud
|
2
2
|
module Table
|
3
|
-
|
4
3
|
# A simple helper to easily define tables listing several rows of the same
|
5
4
|
# data type.
|
6
5
|
#
|
@@ -10,17 +9,16 @@ module DryCrud
|
|
10
9
|
# t.attrs :name, :city
|
11
10
|
# end
|
12
11
|
class Builder
|
13
|
-
|
14
12
|
include Sorting
|
15
13
|
include Actions
|
16
14
|
|
17
15
|
attr_reader :entries, :cols, :options, :template
|
18
16
|
|
19
|
-
delegate :
|
17
|
+
delegate :tag, :format_attr, :column_type, :association, :dom_id,
|
20
18
|
:captionize, :add_css_class, :content_tag_nested,
|
21
19
|
to: :template
|
22
20
|
|
23
|
-
def initialize(entries, template, options
|
21
|
+
def initialize(entries, template, **options)
|
24
22
|
@entries = entries
|
25
23
|
@template = template
|
26
24
|
@options = options
|
@@ -30,8 +28,8 @@ module DryCrud
|
|
30
28
|
# Convenience method to directly generate a table. Renders a row for each
|
31
29
|
# entry in entries. Takes a block that gets the table object as parameter
|
32
30
|
# for configuration. Returns the generated html for the table.
|
33
|
-
def self.table(entries, template, options
|
34
|
-
t = new(entries, template, options)
|
31
|
+
def self.table(entries, template, **options)
|
32
|
+
t = new(entries, template, **options)
|
35
33
|
yield t
|
36
34
|
t.to_html
|
37
35
|
end
|
@@ -39,7 +37,7 @@ module DryCrud
|
|
39
37
|
# Define a column for the table with the given header, the html_options
|
40
38
|
# used for each td and a block rendering the contents of a cell for the
|
41
39
|
# current entry. The columns appear in the order they are defined.
|
42
|
-
def col(header =
|
40
|
+
def col(header = "", **html_options, &block)
|
43
41
|
@cols << Col.new(header, html_options, @template, block)
|
44
42
|
end
|
45
43
|
|
@@ -55,17 +53,17 @@ module DryCrud
|
|
55
53
|
# Define a column for the given attribute and an optional header.
|
56
54
|
# If no header is given, the attribute name is used. The cell will
|
57
55
|
# contain the formatted attribute value for the current entry.
|
58
|
-
def attr(attr, header = nil, html_options
|
56
|
+
def attr(attr, header = nil, **html_options, &block)
|
59
57
|
header ||= attr_header(attr)
|
60
58
|
block ||= ->(e) { format_attr(e, attr) }
|
61
59
|
add_css_class(html_options, align_class(attr))
|
62
|
-
col(header, html_options, &block)
|
60
|
+
col(header, **html_options, &block)
|
63
61
|
end
|
64
62
|
|
65
63
|
# Renders the table as HTML.
|
66
64
|
def to_html
|
67
|
-
|
68
|
-
|
65
|
+
tag.table(**options) do
|
66
|
+
tag.thead(html_header) +
|
69
67
|
content_tag_nested(:tbody, entries) { |e| html_row(e) }
|
70
68
|
end
|
71
69
|
end
|
@@ -76,9 +74,9 @@ module DryCrud
|
|
76
74
|
entry = entries.present? ? entry_class.new : nil
|
77
75
|
case column_type(entry, attr)
|
78
76
|
when :integer, :float, :decimal
|
79
|
-
|
77
|
+
"right" unless association(entry, attr, :belongs_to)
|
80
78
|
when :boolean
|
81
|
-
|
79
|
+
"center"
|
82
80
|
end
|
83
81
|
end
|
84
82
|
|
@@ -98,7 +96,7 @@ module DryCrud
|
|
98
96
|
def html_row(entry)
|
99
97
|
attrs = {}
|
100
98
|
attrs[:id] = dom_id(entry) if entry.respond_to?(:to_key)
|
101
|
-
content_tag_nested(:tr, cols, attrs) { |c| c.html_cell(entry) }
|
99
|
+
content_tag_nested(:tr, cols, **attrs) { |c| c.html_cell(entry) }
|
102
100
|
end
|
103
101
|
|
104
102
|
# Determines the class of the table entries.
|
@@ -110,7 +108,6 @@ module DryCrud
|
|
110
108
|
entries.first.class
|
111
109
|
end
|
112
110
|
end
|
113
|
-
|
114
111
|
end
|
115
112
|
end
|
116
113
|
end
|