headmin 0.5.3 → 0.5.4
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/Gemfile.lock +1 -1
- data/app/assets/javascripts/headmin/controllers/media_controller.js +14 -14
- data/app/assets/javascripts/headmin/controllers/media_modal_controller.js +5 -5
- data/app/assets/javascripts/headmin/controllers/remote_modal_controller.js +1 -2
- data/app/assets/javascripts/headmin/controllers/textarea_controller.js +3 -3
- data/app/assets/javascripts/headmin.js +11 -11
- data/app/assets/stylesheets/headmin/forms/repeater.scss +0 -4
- data/app/assets/stylesheets/headmin/forms.scss +0 -6
- data/app/assets/stylesheets/headmin/overrides/redactorx.scss +1 -1
- data/app/assets/stylesheets/headmin/vendor/{tom-select-bootstrap.css → tom-select-bootstrap.scss} +0 -1
- data/app/assets/stylesheets/headmin.css +5 -9
- data/app/models/concerns/headmin/field.rb +1 -1
- data/app/models/headmin/filter/association.rb +86 -0
- data/app/models/headmin/filter/association_view.rb +74 -0
- data/app/models/headmin/filter/base.rb +5 -2
- data/app/models/headmin/filter/boolean_view.rb +1 -0
- data/app/models/headmin/filter/date_view.rb +1 -0
- data/app/models/headmin/filter/flatpickr_view.rb +1 -0
- data/app/models/headmin/filter/number_view.rb +1 -0
- data/app/models/headmin/filter/operator_view.rb +3 -1
- data/app/models/headmin/filter/options_view.rb +1 -0
- data/app/models/headmin/filter/text_view.rb +1 -0
- data/app/models/headmin/form/association_view.rb +102 -0
- data/app/models/headmin/form/blocks_view.rb +4 -1
- data/app/models/headmin/form/file_view.rb +0 -8
- data/app/models/headmin/form/flatpickr_view.rb +2 -1
- data/app/models/headmin/form/media_item_view.rb +39 -0
- data/app/models/headmin/form/media_view.rb +27 -3
- data/app/models/headmin/form/select_view.rb +2 -1
- data/app/models/headmin/thumbnail_view.rb +40 -19
- data/app/models/view_model.rb +4 -0
- data/app/views/headmin/_filters.html.erb +7 -2
- data/app/views/headmin/_thumbnail.html.erb +32 -8
- data/app/views/headmin/filters/_association.html.erb +24 -0
- data/app/views/headmin/filters/_options.html.erb +1 -1
- data/app/views/headmin/forms/_association.html.erb +30 -0
- data/app/views/headmin/forms/_file.html.erb +4 -5
- data/app/views/headmin/forms/_media.html.erb +7 -5
- data/app/views/headmin/forms/_repeater.html.erb +10 -8
- data/app/views/headmin/forms/_wrapper.html.erb +0 -1
- data/app/views/headmin/forms/fields/_list.html.erb +6 -4
- data/app/views/headmin/forms/media/_item.html.erb +18 -12
- data/app/views/headmin/forms/repeater/_row.html.erb +2 -1
- data/app/views/headmin/media/_item.html.erb +1 -2
- data/app/views/headmin/media/_media_item_modal.html.erb +2 -2
- data/app/views/headmin/table/body/_association.html.erb +17 -3
- data/app/views/headmin/views/devise/shared/_links.html.erb +14 -20
- data/config/locales/activerecord/en.yml +1 -0
- data/config/locales/activerecord/nl.yml +1 -0
- data/config/locales/headmin/filters/en.yml +3 -1
- data/config/locales/headmin/filters/nl.yml +2 -0
- data/config/locales/headmin/media/en.yml +2 -2
- data/config/locales/headmin/media/nl.yml +2 -1
- data/lib/headmin/version.rb +1 -1
- data/package.json +1 -1
- metadata +9 -3
@@ -0,0 +1,102 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class AssociationView < ViewModel
|
4
|
+
include Headmin::Form::Hintable
|
5
|
+
include Headmin::Form::InputGroupable
|
6
|
+
include Headmin::Form::Labelable
|
7
|
+
include Headmin::Form::Listable
|
8
|
+
include Headmin::Form::Placeholderable
|
9
|
+
include Headmin::Form::Validatable
|
10
|
+
include Headmin::Form::Wrappable
|
11
|
+
|
12
|
+
def input_options
|
13
|
+
keys = attributes - %i[append attribute collection float form input_group include_blank label prepend validate selected tags wrapper]
|
14
|
+
options = to_h.slice(*keys)
|
15
|
+
def_input_options = default_input_options
|
16
|
+
def_input_options = def_input_options.deep_merge(options)
|
17
|
+
def_input_options = def_input_options.merge({multiple: true}) if collection?
|
18
|
+
def_input_options
|
19
|
+
end
|
20
|
+
|
21
|
+
def input_group_options
|
22
|
+
default_input_group_options
|
23
|
+
.deep_merge(label_input_group_options)
|
24
|
+
.deep_merge(@input_group || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrapper_options
|
28
|
+
default_wrapper_options.deep_merge({
|
29
|
+
class: ["mb-3", ("form-floating" if float)]
|
30
|
+
}).deep_merge(@wrapper || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
def select_options
|
34
|
+
keys = %i[include_blank selected]
|
35
|
+
options = to_h.slice(*keys)
|
36
|
+
default_options.deep_merge(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def attribute_with_id
|
40
|
+
attribute_with_id = collection? ? "#{association_foreign_key}s" : foreign_key
|
41
|
+
|
42
|
+
if attribute_with_id.nil?
|
43
|
+
raise(AssociationDoesNotExistError, "Association attribute that was passed does not exist.")
|
44
|
+
else
|
45
|
+
attribute_with_id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def collection
|
50
|
+
association_class.all.map { |item| [item.to_s, item.id] }
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def association_foreign_key
|
56
|
+
reflection.association_foreign_key
|
57
|
+
end
|
58
|
+
|
59
|
+
def foreign_key
|
60
|
+
reflection.foreign_key
|
61
|
+
end
|
62
|
+
|
63
|
+
def reflection
|
64
|
+
form.object.class.reflect_on_association(attribute)
|
65
|
+
end
|
66
|
+
|
67
|
+
def association_class
|
68
|
+
reflection.klass
|
69
|
+
end
|
70
|
+
|
71
|
+
def collection?
|
72
|
+
reflection.collection?
|
73
|
+
end
|
74
|
+
|
75
|
+
def default_options
|
76
|
+
{
|
77
|
+
selected: form.object&.send(attribute_with_id)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def default_input_options
|
82
|
+
{
|
83
|
+
aria: {describedby: validation_id},
|
84
|
+
class: [form_control_class, validation_class],
|
85
|
+
data: {
|
86
|
+
tags: tags,
|
87
|
+
controller: "select"
|
88
|
+
},
|
89
|
+
multiple: tags,
|
90
|
+
placeholder: placeholder
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def form_control_class
|
95
|
+
plaintext ? "form-control-plaintext" : "form-select"
|
96
|
+
end
|
97
|
+
|
98
|
+
class AssociationDoesNotExistError < StandardError
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -55,14 +55,6 @@ module Headmin
|
|
55
55
|
attached.is_a?(ActiveStorage::Attached::Many) ? :"#{attribute}_attachments" : :"#{attribute}_attachment"
|
56
56
|
end
|
57
57
|
|
58
|
-
def thumbnail_width
|
59
|
-
100
|
60
|
-
end
|
61
|
-
|
62
|
-
def thumbnail_height
|
63
|
-
100
|
64
|
-
end
|
65
|
-
|
66
58
|
def dropzone_options
|
67
59
|
if dropzone
|
68
60
|
{
|
@@ -18,8 +18,9 @@ module Headmin
|
|
18
18
|
def default_data
|
19
19
|
{
|
20
20
|
controller: "flatpickr",
|
21
|
+
|
21
22
|
flatpickr: {
|
22
|
-
defaultDate: form.object&.send(attribute)&.strftime("%d/%m/%Y")
|
23
|
+
defaultDate: attribute.nil? ? Date.today : form.object&.send(attribute)&.strftime("%d/%m/%Y")
|
23
24
|
}
|
24
25
|
}
|
25
26
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class MediaItemView < ViewModel
|
4
|
+
include Rails.application.routes.url_helpers
|
5
|
+
|
6
|
+
def thumbnail_options
|
7
|
+
options = {
|
8
|
+
file: attachment
|
9
|
+
}
|
10
|
+
|
11
|
+
# Don't pass width or height if it was not defined
|
12
|
+
options = options.merge(width: width) if is_defined?(:width)
|
13
|
+
options = options.merge(height: height) if is_defined?(:height)
|
14
|
+
|
15
|
+
options
|
16
|
+
end
|
17
|
+
|
18
|
+
def attachment
|
19
|
+
form.object
|
20
|
+
end
|
21
|
+
|
22
|
+
def position_value
|
23
|
+
attachment.new_record? ? nil : attachment.position
|
24
|
+
end
|
25
|
+
|
26
|
+
def id
|
27
|
+
attachment.blob ? attachment.blob.id : "$1"
|
28
|
+
end
|
29
|
+
|
30
|
+
def filename
|
31
|
+
attachment.blob&.filename&.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def size
|
35
|
+
number_to_human_size(attachment.blob&.byte_size || 0)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -19,7 +19,7 @@ module Headmin
|
|
19
19
|
class: ["mb-3", ("form-floating" if float)],
|
20
20
|
data: {
|
21
21
|
controller: "media",
|
22
|
-
name:
|
22
|
+
name: name,
|
23
23
|
min: min,
|
24
24
|
max: max,
|
25
25
|
sort: sort,
|
@@ -28,6 +28,18 @@ module Headmin
|
|
28
28
|
}).deep_merge(@wrapper || {})
|
29
29
|
end
|
30
30
|
|
31
|
+
def item_options
|
32
|
+
options = {
|
33
|
+
sort: sort
|
34
|
+
}
|
35
|
+
|
36
|
+
# Don't pass width or height if it was not defined
|
37
|
+
options = options.merge(width: width) if is_defined?(:width)
|
38
|
+
options = options.merge(height: height) if is_defined?(:height)
|
39
|
+
|
40
|
+
options
|
41
|
+
end
|
42
|
+
|
31
43
|
def custom_validation_options
|
32
44
|
{
|
33
45
|
form: form,
|
@@ -37,6 +49,18 @@ module Headmin
|
|
37
49
|
}
|
38
50
|
end
|
39
51
|
|
52
|
+
def thumbnail_options
|
53
|
+
options = {
|
54
|
+
icon: "plus"
|
55
|
+
}
|
56
|
+
|
57
|
+
# Don't pass width or height if it was not defined
|
58
|
+
options = options.merge(width: width) unless is_defined?(:width)
|
59
|
+
options = options.merge(height: height) unless is_defined?(:height)
|
60
|
+
|
61
|
+
options
|
62
|
+
end
|
63
|
+
|
40
64
|
def association_object
|
41
65
|
if attached.is_a?(ActiveStorage::Attached::Many)
|
42
66
|
result = form.object.send(nested_attribute)
|
@@ -101,8 +125,8 @@ module Headmin
|
|
101
125
|
attachments.map { |attachment| attachment.blob_id }
|
102
126
|
end
|
103
127
|
|
104
|
-
def
|
105
|
-
|
128
|
+
def name
|
129
|
+
"#{attribute}_#{object_id}"
|
106
130
|
end
|
107
131
|
|
108
132
|
def sort
|
@@ -1,41 +1,62 @@
|
|
1
1
|
module Headmin
|
2
|
-
class ThumbnailView
|
3
|
-
def initialize(local_assigns)
|
4
|
-
@local_assigns = local_assigns
|
5
|
-
end
|
6
|
-
|
2
|
+
class ThumbnailView < ViewModel
|
7
3
|
def class_names
|
8
|
-
class_names = [@
|
4
|
+
class_names = [@class]
|
9
5
|
class_names << "img-thumbnail h-thumbnail"
|
10
6
|
class_names.join(" ")
|
11
7
|
end
|
12
8
|
|
13
9
|
def width
|
14
|
-
|
10
|
+
if is_defined?(:width)
|
11
|
+
@width
|
12
|
+
else
|
13
|
+
@width || 100
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def height
|
18
|
-
|
18
|
+
if is_defined?(:height)
|
19
|
+
@height
|
20
|
+
else
|
21
|
+
@height || 100
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
|
-
def
|
22
|
-
|
25
|
+
def blob
|
26
|
+
file.is_a?(ActiveStorage::Blob) ? file : file&.blob
|
23
27
|
end
|
24
28
|
|
25
|
-
def
|
26
|
-
|
29
|
+
def mime_type
|
30
|
+
blob&.content_type
|
27
31
|
end
|
28
32
|
|
29
|
-
def
|
30
|
-
if
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
def variant_options
|
34
|
+
if width.nil? || height.nil?
|
35
|
+
default_variant_options.merge({
|
36
|
+
resize_to_fit: [width, height]
|
37
|
+
})
|
38
|
+
else
|
39
|
+
default_variant_options.merge({
|
40
|
+
resize_to_fill: [width, height, crop: :attention]
|
41
|
+
})
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
37
|
-
def
|
38
|
-
|
45
|
+
def default_variant_options
|
46
|
+
{
|
47
|
+
saver: {
|
48
|
+
quality: 80
|
49
|
+
}
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Is it possible to create a ActiveStorage::Variant?
|
54
|
+
def variable?
|
55
|
+
blob&.variable?
|
56
|
+
end
|
57
|
+
|
58
|
+
def icon?
|
59
|
+
is_defined?(:icon)
|
39
60
|
end
|
40
61
|
|
41
62
|
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
|
data/app/models/view_model.rb
CHANGED
@@ -14,10 +14,15 @@
|
|
14
14
|
# <%= render "headmin/filters", url: admin_polls_path %#>
|
15
15
|
|
16
16
|
action = local_assigns.has_key?(:url) ? url : request.path
|
17
|
-
%>
|
18
17
|
|
19
|
-
|
18
|
+
begin
|
19
|
+
model = controller_name.singularize.capitalize.constantize
|
20
|
+
rescue
|
21
|
+
raise "Cannot find class!"
|
22
|
+
end
|
23
|
+
%>
|
20
24
|
|
25
|
+
<%= form_with model: model.new, url: action, method: :get, data: {controller: "filters", filters_target: "form"} do |form| %>
|
21
26
|
<%# Perform yield in order to capture content blocks, pass form so we can use headmin form inputs %>
|
22
27
|
<%= yield(form) %>
|
23
28
|
|
@@ -1,11 +1,35 @@
|
|
1
|
-
<%
|
1
|
+
<%
|
2
|
+
# headmin/thumbnail
|
3
|
+
#
|
4
|
+
# ==== Required parameters
|
5
|
+
# * +file+ - Name of the attribute of the form model
|
6
|
+
#
|
7
|
+
# ==== Optional parameters
|
8
|
+
# * +width+ - Width of the thumbnail. Set to nil to fill according to the original aspect ratio
|
9
|
+
# * +height+ - Height of the thumbnail. Set to nil to fill according to the original aspect ratio
|
10
|
+
# * +icon+ - Force icon to be shown instead of a thumbnail
|
11
|
+
#
|
12
|
+
# ==== References
|
13
|
+
# https://headmin.dev/docs/thumbnail
|
14
|
+
#
|
15
|
+
# ==== Examples
|
16
|
+
# Basic version
|
17
|
+
# <%= render "headmin/thumbnail", file: file %#>
|
18
|
+
#
|
19
|
+
# Custom size (200px x 100px)
|
20
|
+
# <%= render "headmin/thumbnail", file: file, width: 200, height: 100 %#>
|
21
|
+
#
|
22
|
+
# Custom (bootstrap) icon
|
23
|
+
# <%= render "headmin/thumbnail", file: file, icon: "file-earmark-excel" %#>
|
24
|
+
thumbnail = Headmin::ThumbnailView.new(local_assigns)
|
25
|
+
%>
|
2
26
|
|
3
|
-
<div class="<%= thumbnail.class_names %>"
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
27
|
+
<div class="<%= thumbnail.class_names %>">
|
28
|
+
<div class="h-thumbnail-bg" style="min-width: <%= thumbnail.width || 100 %>px; min-height: <%= thumbnail.height || 100 %>px;">
|
29
|
+
<% if thumbnail.variable? && !thumbnail.icon? %>
|
30
|
+
<%= image_tag(thumbnail.file.variant(thumbnail.variant_options)) %>
|
31
|
+
<% else %>
|
8
32
|
<%= bootstrap_icon(thumbnail.icon_name, class: "h-thumbnail-icon") %>
|
9
|
-
|
10
|
-
|
33
|
+
<% end %>
|
34
|
+
</div>
|
11
35
|
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%
|
2
|
+
# headmin/filters/association
|
3
|
+
#
|
4
|
+
# ==== Required parameters
|
5
|
+
# * +attribute+ - Name of the attribute to be filtered
|
6
|
+
# * +collection+ - Values to create option tags for
|
7
|
+
# * +form+ - Form object
|
8
|
+
#
|
9
|
+
# ==== Optional parameters
|
10
|
+
# * +label+ - Display label
|
11
|
+
# * +name+ - Name of the filter parameter
|
12
|
+
#
|
13
|
+
# ==== Examples
|
14
|
+
# Basic version
|
15
|
+
# <%= render "headmin/filters", url: admin_orders_path do |form| %#>
|
16
|
+
# <%= render "headmin/filters/association", form: form, attribute: :product %#>
|
17
|
+
# <% end %#>
|
18
|
+
|
19
|
+
association = Headmin::Filter::AssociationView.new(local_assigns.merge(params: params))
|
20
|
+
%>
|
21
|
+
|
22
|
+
<%= render "headmin/filters/base", association.base_options do |value| %>
|
23
|
+
<%= render "headmin/forms/select", association.input_options.merge(selected: value) %>
|
24
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<%
|
2
|
+
# headmin/forms/association
|
3
|
+
#
|
4
|
+
# ==== Required parameters
|
5
|
+
# * +attribute+ - Name of the association
|
6
|
+
# * +form+ - Form object
|
7
|
+
#
|
8
|
+
# ==== Optional parameters
|
9
|
+
# * +collection+ - Values to create option tags for
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
# Basic version
|
14
|
+
# <%= form_with do |form| %#>
|
15
|
+
# <%= render "headmin/forms/association", form: form, attribute: :product %#>
|
16
|
+
# <% end %#>
|
17
|
+
|
18
|
+
association = Headmin::Form::AssociationView.new(local_assigns)
|
19
|
+
|
20
|
+
%>
|
21
|
+
|
22
|
+
<%= render "headmin/forms/wrapper", association.wrapper_options do %>
|
23
|
+
<%= render "headmin/forms/label", association.label_options if association.prepend_label? %>
|
24
|
+
<%= render "headmin/forms/input_group", association.input_group_options do %>
|
25
|
+
<%= form.select(association.attribute_with_id, association.collection, association.select_options, association.input_options) %>
|
26
|
+
<% end %>
|
27
|
+
<%= render "headmin/forms/validation", association.validation_options if association.validate? %>
|
28
|
+
<%= render "headmin/forms/hint", association.hint_options if association.hint? %>
|
29
|
+
<%= render "headmin/forms/label", association.label_options if association.append_label? %>
|
30
|
+
<% end %>
|
@@ -45,12 +45,11 @@
|
|
45
45
|
next unless attachment
|
46
46
|
filename = attachment.blob.filename.to_s
|
47
47
|
size = number_to_human_size(attachment.blob.byte_size)
|
48
|
-
src = attachment.image? ? url_for(attachment.variant(resize_to_fill: [file.thumbnail_width, file.thumbnail_height])) : url_for(attachment)
|
49
48
|
%>
|
50
49
|
<div class="h-form-file-thumbnail" title="<%= "#{filename} (#{size})" %>" data-file-preview-target="thumbnail">
|
51
50
|
<%= ff.hidden_field(:id, disabled: !file.destroy) %>
|
52
51
|
<%= ff.hidden_field(:_destroy, data: {"file-preview-target": "thumbnailDestroy"}, disabled: !file.destroy) %>
|
53
|
-
<%= render "headmin/thumbnail",
|
52
|
+
<%= render "headmin/thumbnail", file: attachment %>
|
54
53
|
|
55
54
|
<% if file.destroy %>
|
56
55
|
<div class="h-form-file-thumbnail-remove" data-action="click->file-preview#remove" data-file-preview-name-param="<%= filename %>">
|
@@ -62,12 +61,12 @@
|
|
62
61
|
|
63
62
|
<!-- Placeholder -->
|
64
63
|
<% if file.dropzone %>
|
65
|
-
<div class="h-dropzone-placeholder <%= "d-none" if file.attachments.any? %>" data-file-preview-target="placeholder" style="height:
|
64
|
+
<div class="h-dropzone-placeholder <%= "d-none" if file.attachments.any? %>" data-file-preview-target="placeholder" style="height: 100px;">
|
66
65
|
<%= t("headmin.forms.file.placeholder", count: file.number_of_files) %>
|
67
66
|
</div>
|
68
67
|
<% else %>
|
69
68
|
<div class="h-form-file-thumbnail <%= "d-none" if file.attachments.any? %>" title="<%= t("headmin.forms.file.not_found") %>" data-file-preview-target="placeholder">
|
70
|
-
<%= render "headmin/thumbnail",
|
69
|
+
<%= render "headmin/thumbnail", icon: "plus" %>
|
71
70
|
</div>
|
72
71
|
<% end %>
|
73
72
|
</div>
|
@@ -76,7 +75,7 @@
|
|
76
75
|
<!-- Template -->
|
77
76
|
<template data-file-preview-target="template">
|
78
77
|
<div class="h-form-file-thumbnail" title="" data-file-preview-target="thumbnail">
|
79
|
-
<%= render "headmin/thumbnail"
|
78
|
+
<%= render "headmin/thumbnail" %>
|
80
79
|
|
81
80
|
<% if file.destroy %>
|
82
81
|
<div class="h-form-file-thumbnail-remove" data-action="click->file-preview#remove">
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%
|
2
|
-
# headmin/forms/
|
2
|
+
# headmin/forms/media
|
3
3
|
#
|
4
4
|
# ==== Required parameters
|
5
5
|
# * +attribute+ - Name of the attribute of the form model
|
@@ -13,6 +13,8 @@
|
|
13
13
|
# * +max+ - Limit the selection to a maximum amount of items.
|
14
14
|
# * +sort+ - Allow sorting by dragging items. `active_storage_attachments` must have a position column.
|
15
15
|
# * +wrapper+ - Hash with all options for the surrounding html tag
|
16
|
+
# * +width+ - Width of the thumbnail
|
17
|
+
# * +height+ - Height of the thumbnail
|
16
18
|
#
|
17
19
|
# ==== References
|
18
20
|
# https://headmin.dev/docs/forms/media
|
@@ -33,13 +35,13 @@
|
|
33
35
|
|
34
36
|
<!-- Render previews for attachments -->
|
35
37
|
<%= form.fields_for(media.nested_attribute, media.association_object) do |ff| %>
|
36
|
-
<%= render "headmin/forms/media/item", form: ff, url: media.
|
38
|
+
<%= render "headmin/forms/media/item", media.item_options.merge(form: ff, url: headmin_media_url(name: media.name, ids: media.blob_ids, min: media.min, max: media.max)) %>
|
37
39
|
<% end %>
|
38
40
|
|
39
41
|
<!-- Placeholder -->
|
40
42
|
<div class="<%= "d-none" if media.attachments.any? %>" data-media-target="placeholder">
|
41
|
-
<a href="<%= media.
|
42
|
-
<%= render "headmin/thumbnail",
|
43
|
+
<a href="<%= headmin_media_url(name: media.name, ids: media.blob_ids, min: media.min, max: media.max) %>" data-turbo-frame="remote_modal" data-media-target="modalButton">
|
44
|
+
<%= render "headmin/thumbnail", media.thumbnail_options %>
|
43
45
|
</a>
|
44
46
|
</div>
|
45
47
|
</div>
|
@@ -48,7 +50,7 @@
|
|
48
50
|
<% association_object = ActiveStorage::Attachment.new %>
|
49
51
|
<template data-media-target="template" data-template-id-regex="<%= association_object.object_id %>">
|
50
52
|
<%= form.fields_for(media.nested_attribute, ActiveStorage::Attachment.new, child_index: association_object.object_id) do |ff| %>
|
51
|
-
<%= render "headmin/forms/media/item", form: ff, url: media.
|
53
|
+
<%= render "headmin/forms/media/item", media.item_options.merge(form: ff, url: headmin_media_url(name: media.name, ids: media.blob_ids, min: media.min, max: media.max)) %>
|
52
54
|
<% end %>
|
53
55
|
</template>
|
54
56
|
|
@@ -2,12 +2,13 @@
|
|
2
2
|
# headmin/forms/repeater
|
3
3
|
#
|
4
4
|
# ==== Options
|
5
|
-
# * +form
|
6
|
-
# * +attribute
|
7
|
-
# * +header
|
5
|
+
# * +form+ - Form object
|
6
|
+
# * +attribute+ - Name of the attribute of the form model
|
7
|
+
# * +header+ - Name of the template to use as header
|
8
8
|
# * +label+ - Text to show as label. Label will be hidden if value is false
|
9
|
-
# * +templates
|
10
|
-
# * +flush
|
9
|
+
# * +templates+ - List of all views that can be used as a template for a new block
|
10
|
+
# * +flush+ - Set to true if you want the list items to sit flush with its parent.
|
11
|
+
# * +row+ - Pass hash with options to pass to the row template.
|
11
12
|
#
|
12
13
|
# ==== Examples
|
13
14
|
# # Basic version
|
@@ -36,6 +37,7 @@
|
|
36
37
|
header = local_assigns.has_key?(:header) ? header : nil
|
37
38
|
templates = local_assigns.has_key?(:templates) ? templates : []
|
38
39
|
flush = local_assigns.has_key?(:flush) ? flush : true
|
40
|
+
row_options = local_assigns.has_key?(:row) ? row : {}
|
39
41
|
|
40
42
|
template_names = templates.map { |template| File.basename(template, ".html.erb") }
|
41
43
|
template_names = template_names.any? ? template_names : ["new"]
|
@@ -55,7 +57,7 @@
|
|
55
57
|
<%= render "headmin/forms/label", form: form, attribute: attribute, text: label, required: required %>
|
56
58
|
<% end %>
|
57
59
|
|
58
|
-
<ul class="repeater list-group <%= "list-group-flush" if flush %>" data-controller="repeater" data-repeater-target="list" data-repeater-id-value="<%= repeater_id %>">
|
60
|
+
<ul class="repeater list-group <%= "list-group-flush" if flush %> mb-3" data-controller="repeater" data-repeater-target="list" data-repeater-id-value="<%= repeater_id %>">
|
59
61
|
|
60
62
|
<!-- Header -->
|
61
63
|
<% if header %>
|
@@ -66,7 +68,7 @@
|
|
66
68
|
|
67
69
|
<!-- Rows -->
|
68
70
|
<%= form.fields_for attribute, associations do |ff| %>
|
69
|
-
<%= render "headmin/forms/repeater/row", pass_thru: pass_thru, form: ff, repeater_id: repeater_id do %>
|
71
|
+
<%= render "headmin/forms/repeater/row", row_options.merge(pass_thru: pass_thru, form: ff, repeater_id: repeater_id) do %>
|
70
72
|
<%= yield(ff) %>
|
71
73
|
<% end %>
|
72
74
|
<% end %>
|
@@ -114,7 +116,7 @@
|
|
114
116
|
<% template_names.each do |name| %>
|
115
117
|
<template data-repeater-target="template" data-template-name="<%= name %>" data-template-id-regex="<%= association_object.object_id %>">
|
116
118
|
<%= form.fields_for attribute, association_object, child_index: association_object.object_id do |ff| %>
|
117
|
-
<%= render "headmin/forms/repeater/row", form: ff, pass_thru: pass_thru, repeater_id: repeater_id do %>
|
119
|
+
<%= render "headmin/forms/repeater/row", row_options.merge(form: ff, pass_thru: pass_thru, repeater_id: repeater_id) do %>
|
118
120
|
<% yield(ff, name) %>
|
119
121
|
<% end %>
|
120
122
|
<% end %>
|
@@ -19,8 +19,10 @@
|
|
19
19
|
%>
|
20
20
|
|
21
21
|
<%= render "headmin/forms/fields/base", form: form, name: name, field_type: :list do |list, field_label| %>
|
22
|
-
|
23
|
-
<%=
|
24
|
-
|
25
|
-
|
22
|
+
<div class="mb-3">
|
23
|
+
<%= render "headmin/forms/repeater", form: list, attribute: :fields, label: show_label ? label || field_label : false, flush: false do |field| %>
|
24
|
+
<%= field.hidden_field :field_type, value: :group %>
|
25
|
+
<%= yield field %>
|
26
|
+
<% end %>
|
27
|
+
</div>
|
26
28
|
<% end %>
|