headmin 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/app/assets/javascripts/headmin/controllers/media_controller.js +1 -39
- data/app/assets/javascripts/headmin/controllers/repeater_controller.js +16 -4
- data/app/assets/javascripts/headmin.js +10 -33
- data/app/assets/stylesheets/headmin.css +1 -1
- data/app/controllers/headmin/media_controller.rb +8 -3
- data/app/models/concerns/headmin/blob.rb +36 -0
- data/app/models/concerns/headmin/field.rb +1 -1
- data/app/models/concerns/headmin/fieldable.rb +4 -1
- data/app/models/headmin/filter/field_view.rb +1 -1
- data/app/models/headmin/form/media_item_view.rb +4 -0
- data/app/models/headmin/form/media_view.rb +5 -1
- data/app/views/headmin/forms/_media.html.erb +3 -5
- data/app/views/headmin/media/_modal.html.erb +1 -1
- data/app/views/headmin/media/index.html.erb +1 -1
- data/config/initializers/extend_active_storage_blob.rb +3 -0
- data/config/locales/headmin/forms/en.yml +0 -8
- data/config/locales/headmin/forms/nl.yml +0 -8
- data/lib/headmin/version.rb +1 -1
- data/package.json +1 -1
- metadata +4 -3
- data/app/views/headmin/forms/media/_validation.html.erb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f5b560711076cca763871af2499728101e4f8d7a27a04f5c702671165e134d7
|
4
|
+
data.tar.gz: ed2d18ec0405786fd9b4f18984e750571062124828fc1102a662f78e0333c03e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8afa230d5e31dad3cbaa288fe46849672af9c4df118b4e9a9ed8024eea60da7d1089865b3678ee67860cfe88d34f67ba3a3db0c2b8ee1e37ebfbe515e2ae07fc
|
7
|
+
data.tar.gz: 106023130df278d025a608345e763aac87b6586736e511fd05866703876b296de9ae08d43ea5fd86d3f7cb75d378935e3aa86ff2d9f519d50434ee02e6453dc8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
headmin (0.5.
|
4
|
+
headmin (0.5.5)
|
5
5
|
closure_tree (~> 7.4)
|
6
6
|
inline_svg (~> 1.7)
|
7
7
|
redcarpet (~> 3.5)
|
@@ -226,7 +226,7 @@ GEM
|
|
226
226
|
actionpack (>= 5.0)
|
227
227
|
railties (>= 5.0)
|
228
228
|
rexml (3.2.5)
|
229
|
-
rouge (3.
|
229
|
+
rouge (3.30.0)
|
230
230
|
route_translator (12.1.0)
|
231
231
|
actionpack (>= 5.2, < 7.1)
|
232
232
|
activesupport (>= 5.2, < 7.1)
|
@@ -3,7 +3,7 @@ import Sortable from 'sortablejs'
|
|
3
3
|
|
4
4
|
export default class extends Controller {
|
5
5
|
static get targets () {
|
6
|
-
return ['item', 'template', 'thumbnails', 'modalButton', 'placeholder', '
|
6
|
+
return ['item', 'template', 'thumbnails', 'modalButton', 'placeholder', 'count', 'editButton']
|
7
7
|
}
|
8
8
|
|
9
9
|
connect () {
|
@@ -17,8 +17,6 @@ export default class extends Controller {
|
|
17
17
|
if (this.hasSorting()) {
|
18
18
|
this.initSortable()
|
19
19
|
}
|
20
|
-
|
21
|
-
this.validate()
|
22
20
|
}
|
23
21
|
|
24
22
|
// Actions
|
@@ -83,42 +81,6 @@ export default class extends Controller {
|
|
83
81
|
|
84
82
|
// Toggle placeholder
|
85
83
|
this.togglePlaceholder()
|
86
|
-
|
87
|
-
// Validate
|
88
|
-
this.validate()
|
89
|
-
}
|
90
|
-
|
91
|
-
validate () {
|
92
|
-
this.clearValidation()
|
93
|
-
if (this.element.dataset.required === '0') return
|
94
|
-
this.validateMinimum()
|
95
|
-
this.validateMaximum()
|
96
|
-
}
|
97
|
-
|
98
|
-
clearValidation () {
|
99
|
-
this.validationInputTarget.setCustomValidity('')
|
100
|
-
}
|
101
|
-
|
102
|
-
validateMinimum () {
|
103
|
-
const count = this.activeItems().length
|
104
|
-
if (count < this.minActiveItems()) {
|
105
|
-
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.minMessage)
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
validateMaximum () {
|
110
|
-
const count = this.activeItems().length
|
111
|
-
if (count > this.maxActiveItems()) {
|
112
|
-
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.maxMessage)
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
minActiveItems () {
|
117
|
-
return parseInt(this.element.dataset.min, 10) || 0
|
118
|
-
}
|
119
|
-
|
120
|
-
maxActiveItems () {
|
121
|
-
return parseInt(this.element.dataset.max, 10) || Infinity
|
122
84
|
}
|
123
85
|
|
124
86
|
resetPositions () {
|
@@ -80,8 +80,8 @@ export default class extends Controller {
|
|
80
80
|
row.remove()
|
81
81
|
} else {
|
82
82
|
// Existing records are hidden and flagged for deletion
|
83
|
-
|
84
|
-
row.
|
83
|
+
this.flagRowForDeletion(row)
|
84
|
+
row.remove()
|
85
85
|
}
|
86
86
|
|
87
87
|
this.resetIndices()
|
@@ -89,6 +89,18 @@ export default class extends Controller {
|
|
89
89
|
this.toggleEmpty()
|
90
90
|
}
|
91
91
|
|
92
|
+
flagRowForDeletion (row) {
|
93
|
+
const destroyInput = row.querySelector('input[name*=\'_destroy\']')
|
94
|
+
const idInput = row.querySelector('input[name*=\'[id]\']')
|
95
|
+
|
96
|
+
// Update _destroy value
|
97
|
+
destroyInput.value = 1
|
98
|
+
|
99
|
+
// Move away from row
|
100
|
+
this.listTarget.parentNode.appendChild(destroyInput)
|
101
|
+
this.listTarget.parentNode.appendChild(idInput)
|
102
|
+
}
|
103
|
+
|
92
104
|
getTemplate (name) {
|
93
105
|
return this.templateTargets.filter((template) => {
|
94
106
|
return template.dataset.templateName === name
|
@@ -107,7 +119,7 @@ export default class extends Controller {
|
|
107
119
|
visibleRows () {
|
108
120
|
const rows = this.rowTargets
|
109
121
|
return rows.filter((row) => {
|
110
|
-
return row.querySelector(
|
122
|
+
return row.querySelector('input[name*=\'_destroy\']').value !== '1'
|
111
123
|
})
|
112
124
|
}
|
113
125
|
|
@@ -121,7 +133,7 @@ export default class extends Controller {
|
|
121
133
|
|
122
134
|
resetPositions () {
|
123
135
|
this.visibleRows().forEach((row, index) => {
|
124
|
-
const positionInput = row.querySelector(
|
136
|
+
const positionInput = row.querySelector('input[name*=\'position\']')
|
125
137
|
if (positionInput) {
|
126
138
|
positionInput.value = index
|
127
139
|
}
|
@@ -10096,7 +10096,7 @@ var hello_controller_default = class extends Controller {
|
|
10096
10096
|
// app/assets/javascripts/headmin/controllers/media_controller.js
|
10097
10097
|
var media_controller_default = class extends Controller {
|
10098
10098
|
static get targets() {
|
10099
|
-
return ["item", "template", "thumbnails", "modalButton", "placeholder", "
|
10099
|
+
return ["item", "template", "thumbnails", "modalButton", "placeholder", "count", "editButton"];
|
10100
10100
|
}
|
10101
10101
|
connect() {
|
10102
10102
|
document.addEventListener("mediaSelectionSubmitted", (event) => {
|
@@ -10107,7 +10107,6 @@ var media_controller_default = class extends Controller {
|
|
10107
10107
|
if (this.hasSorting()) {
|
10108
10108
|
this.initSortable();
|
10109
10109
|
}
|
10110
|
-
this.validate();
|
10111
10110
|
}
|
10112
10111
|
destroy(event) {
|
10113
10112
|
const item = event.currentTarget.closest("[data-media-target='item']");
|
@@ -10148,35 +10147,6 @@ var media_controller_default = class extends Controller {
|
|
10148
10147
|
this.resetPositions();
|
10149
10148
|
this.syncIds();
|
10150
10149
|
this.togglePlaceholder();
|
10151
|
-
this.validate();
|
10152
|
-
}
|
10153
|
-
validate() {
|
10154
|
-
this.clearValidation();
|
10155
|
-
if (this.element.dataset.required === "0")
|
10156
|
-
return;
|
10157
|
-
this.validateMinimum();
|
10158
|
-
this.validateMaximum();
|
10159
|
-
}
|
10160
|
-
clearValidation() {
|
10161
|
-
this.validationInputTarget.setCustomValidity("");
|
10162
|
-
}
|
10163
|
-
validateMinimum() {
|
10164
|
-
const count = this.activeItems().length;
|
10165
|
-
if (count < this.minActiveItems()) {
|
10166
|
-
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.minMessage);
|
10167
|
-
}
|
10168
|
-
}
|
10169
|
-
validateMaximum() {
|
10170
|
-
const count = this.activeItems().length;
|
10171
|
-
if (count > this.maxActiveItems()) {
|
10172
|
-
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.maxMessage);
|
10173
|
-
}
|
10174
|
-
}
|
10175
|
-
minActiveItems() {
|
10176
|
-
return parseInt(this.element.dataset.min, 10) || 0;
|
10177
|
-
}
|
10178
|
-
maxActiveItems() {
|
10179
|
-
return parseInt(this.element.dataset.max, 10) || Infinity;
|
10180
10150
|
}
|
10181
10151
|
resetPositions() {
|
10182
10152
|
this.activeItems().forEach((item, index2) => {
|
@@ -15559,13 +15529,20 @@ var repeater_controller_default = class extends Controller {
|
|
15559
15529
|
if (row.dataset.newRecord === "true") {
|
15560
15530
|
row.remove();
|
15561
15531
|
} else {
|
15562
|
-
|
15563
|
-
row.
|
15532
|
+
this.flagRowForDeletion(row);
|
15533
|
+
row.remove();
|
15564
15534
|
}
|
15565
15535
|
this.resetIndices();
|
15566
15536
|
this.resetPositions();
|
15567
15537
|
this.toggleEmpty();
|
15568
15538
|
}
|
15539
|
+
flagRowForDeletion(row) {
|
15540
|
+
const destroyInput = row.querySelector("input[name*='_destroy']");
|
15541
|
+
const idInput = row.querySelector("input[name*='[id]']");
|
15542
|
+
destroyInput.value = 1;
|
15543
|
+
this.listTarget.parentNode.appendChild(destroyInput);
|
15544
|
+
this.listTarget.parentNode.appendChild(idInput);
|
15545
|
+
}
|
15569
15546
|
getTemplate(name) {
|
15570
15547
|
return this.templateTargets.filter((template) => {
|
15571
15548
|
return template.dataset.templateName === name;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
@charset "UTF-8";
|
2
2
|
@import "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css";
|
3
3
|
|
4
|
-
/* sass-plugin-0:/
|
4
|
+
/* sass-plugin-0:/opt/homebrew/var/www/headmin/src/scss/headmin.scss */
|
5
5
|
:root {
|
6
6
|
--bs-blue: #0d6efd;
|
7
7
|
--bs-indigo: #6610f2;
|
@@ -4,12 +4,12 @@ class Headmin::MediaController < HeadminController
|
|
4
4
|
def index
|
5
5
|
@blobs =
|
6
6
|
ActiveStorage::Blob
|
7
|
-
.
|
8
|
-
.
|
9
|
-
.or(ActiveStorage::Blob.where(active_storage_attachments: {id: nil})) # Or an orphan
|
7
|
+
.not_attached_to_variant
|
8
|
+
.by_mimetypes_string(media_params[:mimetype])
|
10
9
|
.order(created_at: :desc)
|
11
10
|
.group(:id)
|
12
11
|
.all
|
12
|
+
@mimetypes = media_params[:mimetype]
|
13
13
|
end
|
14
14
|
|
15
15
|
def create
|
@@ -42,6 +42,11 @@ class Headmin::MediaController < HeadminController
|
|
42
42
|
|
43
43
|
def media_params
|
44
44
|
params.permit(
|
45
|
+
:min,
|
46
|
+
:max,
|
47
|
+
:name,
|
48
|
+
:mimetype,
|
49
|
+
ids: [],
|
45
50
|
files: []
|
46
51
|
)
|
47
52
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Blob
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class << self
|
7
|
+
def not_attached_to_variant
|
8
|
+
left_outer_joins(:attachments)
|
9
|
+
.where.not(active_storage_attachments: {record_type: "ActiveStorage::VariantRecord"})
|
10
|
+
.or(is_orphan)
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_orphan
|
14
|
+
left_outer_joins(:attachments)
|
15
|
+
.where(active_storage_attachments: {id: nil})
|
16
|
+
end
|
17
|
+
|
18
|
+
def by_mimetypes_string(mimetype_string)
|
19
|
+
by_mimetypes(mimetype_string.split(","))
|
20
|
+
end
|
21
|
+
|
22
|
+
def by_mimetypes(mimetypes = [])
|
23
|
+
results = self
|
24
|
+
|
25
|
+
mimetypes.map.with_index do |mimetype, index|
|
26
|
+
content_type = mimetype.tr("*", "%")
|
27
|
+
query = where(arel_table[:content_type].matches(content_type))
|
28
|
+
results = index == 0 ? query : results.or(query)
|
29
|
+
end
|
30
|
+
|
31
|
+
results
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -4,7 +4,7 @@ module Headmin
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
# Configuration
|
7
|
-
has_closure_tree order: "position", numeric_order: true
|
7
|
+
has_closure_tree order: "position", numeric_order: true, dependent: :destroy
|
8
8
|
|
9
9
|
# Associations
|
10
10
|
belongs_to :fieldable, polymorphic: true, optional: true, touch: true
|
@@ -28,7 +28,10 @@ module Headmin
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def parse_fields
|
31
|
-
hash_tree =
|
31
|
+
hash_tree = {}
|
32
|
+
fields.roots.includes(default_include_tables | include_tables).each do |field|
|
33
|
+
field.hash_tree.map { |key, value| hash_tree[key] = value }
|
34
|
+
end
|
32
35
|
parse_hash_tree(hash_tree)
|
33
36
|
end
|
34
37
|
|
@@ -27,7 +27,7 @@ module Headmin
|
|
27
27
|
{
|
28
28
|
label: label,
|
29
29
|
name: "field_#{attribute}".to_sym,
|
30
|
-
filter: Headmin::Filter::Field.new(
|
30
|
+
filter: Headmin::Filter::Field.new(attribute.to_s.to_sym, @params),
|
31
31
|
allowed_operators: Headmin::Filter::Field::OPERATORS - %w[in not_in]
|
32
32
|
}
|
33
33
|
end
|
@@ -23,6 +23,7 @@ module Headmin
|
|
23
23
|
min: min,
|
24
24
|
max: max,
|
25
25
|
sort: sort,
|
26
|
+
accept: accept,
|
26
27
|
required: required.nil? ? 0 : required
|
27
28
|
}
|
28
29
|
}).deep_merge(@wrapper || {})
|
@@ -45,7 +46,8 @@ module Headmin
|
|
45
46
|
form: form,
|
46
47
|
attribute: attribute,
|
47
48
|
min: min,
|
48
|
-
max: max
|
49
|
+
max: max,
|
50
|
+
accept: accept
|
49
51
|
}
|
50
52
|
end
|
51
53
|
|
@@ -117,6 +119,8 @@ module Headmin
|
|
117
119
|
end
|
118
120
|
end
|
119
121
|
|
122
|
+
attr_reader :accept
|
123
|
+
|
120
124
|
def required
|
121
125
|
@required ? 1 : nil
|
122
126
|
end
|
@@ -31,16 +31,14 @@
|
|
31
31
|
<%= render "headmin/forms/wrapper", media.wrapper_options do %>
|
32
32
|
<%= render "headmin/forms/label", media.label_options if media.prepend_label? %>
|
33
33
|
<div class="h-form-file-thumbnails" data-media-target="thumbnails">
|
34
|
-
<%= render "headmin/forms/media/validation", media.custom_validation_options %>
|
35
|
-
|
36
34
|
<!-- Render previews for attachments -->
|
37
35
|
<%= form.fields_for(media.nested_attribute, media.association_object) do |ff| %>
|
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)) %>
|
36
|
+
<%= 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, mimetype: media.accept)) %>
|
39
37
|
<% end %>
|
40
38
|
|
41
39
|
<!-- Placeholder -->
|
42
40
|
<div class="<%= "d-none" if media.attachments.any? %>" data-media-target="placeholder">
|
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">
|
41
|
+
<a href="<%= headmin_media_url(name: media.name, ids: media.blob_ids, min: media.min, max: media.max, mimetype: media.accept) %>" data-turbo-frame="remote_modal" data-media-target="modalButton">
|
44
42
|
<%= render "headmin/thumbnail", media.thumbnail_options %>
|
45
43
|
</a>
|
46
44
|
</div>
|
@@ -50,7 +48,7 @@
|
|
50
48
|
<% association_object = ActiveStorage::Attachment.new %>
|
51
49
|
<template data-media-target="template" data-template-id-regex="<%= association_object.object_id %>">
|
52
50
|
<%= form.fields_for(media.nested_attribute, ActiveStorage::Attachment.new, child_index: association_object.object_id) do |ff| %>
|
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)) %>
|
51
|
+
<%= 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, mimetype: media.accept)) %>
|
54
52
|
<% end %>
|
55
53
|
</template>
|
56
54
|
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<%= form.label :files, class: "btn h-btn-outline-light" do %>
|
23
23
|
<%= bootstrap_icon("upload") %>
|
24
24
|
<%= t(".upload") %>
|
25
|
-
<%= form.file_field :files, class: "d-none", multiple: true, data: {action: "change->media-modal#submitForm"} %>
|
25
|
+
<%= form.file_field :files, accept: mimetypes, class: "d-none", multiple: true, data: {action: "change->media-modal#submitForm"} %>
|
26
26
|
<% end %>
|
27
27
|
<% end %>
|
28
28
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><%= t(".close") %></button>
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= turbo_frame_tag "remote_modal" do %>
|
2
|
-
<%= render "headmin/media/modal", blobs: @blobs, name: params[:name], min: params[:min], max: params[:max] %>
|
2
|
+
<%= render "headmin/media/modal", blobs: @blobs, mimetypes: @mimetypes, name: params[:name], min: params[:min], max: params[:max] %>
|
3
3
|
<% end %>
|
@@ -18,14 +18,6 @@ en:
|
|
18
18
|
remove:
|
19
19
|
title: Delete
|
20
20
|
confirm: Are you sure you want to delete this?
|
21
|
-
media:
|
22
|
-
validation:
|
23
|
-
min:
|
24
|
-
one: "Please select at least 1 item"
|
25
|
-
other: "Please select at least %{count} items"
|
26
|
-
max:
|
27
|
-
one: "Please limit your selection to maximum 1 item"
|
28
|
-
other: "Please limit your selection to maximum %{count} items"
|
29
21
|
select:
|
30
22
|
blank: Make a choice
|
31
23
|
repeater:
|
@@ -17,14 +17,6 @@ nl:
|
|
17
17
|
remove:
|
18
18
|
title: Verwijderen
|
19
19
|
confirm: Ben je zeker dat je dit wil verwijderen?
|
20
|
-
media:
|
21
|
-
validation:
|
22
|
-
min:
|
23
|
-
one: "Gelieve minstens 1 item te selecteren"
|
24
|
-
other: "Gelieve minstens %{count} items te selecteren"
|
25
|
-
max:
|
26
|
-
one: "Gelieve maximum 1 item te selecteren"
|
27
|
-
other: "Gelieve maximum %{count} items te selecteren"
|
28
20
|
select:
|
29
21
|
blank: Maak een keuze
|
30
22
|
repeater:
|
data/lib/headmin/version.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: headmin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jef Vlamings
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: closure_tree
|
@@ -244,6 +244,7 @@ files:
|
|
244
244
|
- app/helpers/headmin/form_helper.rb
|
245
245
|
- app/helpers/headmin/notification_helper.rb
|
246
246
|
- app/helpers/headmin/request_helper.rb
|
247
|
+
- app/models/concerns/headmin/blob.rb
|
247
248
|
- app/models/concerns/headmin/block.rb
|
248
249
|
- app/models/concerns/headmin/blockable.rb
|
249
250
|
- app/models/concerns/headmin/field.rb
|
@@ -393,7 +394,6 @@ files:
|
|
393
394
|
- app/views/headmin/forms/fields/_list.html.erb
|
394
395
|
- app/views/headmin/forms/fields/_text.html.erb
|
395
396
|
- app/views/headmin/forms/media/_item.html.erb
|
396
|
-
- app/views/headmin/forms/media/_validation.html.erb
|
397
397
|
- app/views/headmin/forms/repeater/_row.html.erb
|
398
398
|
- app/views/headmin/heading/_title.html.erb
|
399
399
|
- app/views/headmin/layout/_body.html.erb
|
@@ -466,6 +466,7 @@ files:
|
|
466
466
|
- bin/setup
|
467
467
|
- config/importmap.rb
|
468
468
|
- config/initializers/customize_input_error.rb
|
469
|
+
- config/initializers/extend_active_storage_blob.rb
|
469
470
|
- config/locales/activerecord/en.yml
|
470
471
|
- config/locales/activerecord/nl.yml
|
471
472
|
- config/locales/defaults/en.yml
|
@@ -1,10 +0,0 @@
|
|
1
|
-
<!-- Custom validation field -->
|
2
|
-
<%= form.text_field :"validation_#{attribute}",
|
3
|
-
name: nil,
|
4
|
-
value: nil,
|
5
|
-
class: "h-form-media-validation",
|
6
|
-
data: {
|
7
|
-
"media-target": "validationInput",
|
8
|
-
"min-message": t(".min", count: min),
|
9
|
-
"max-message": t(".max", count: max),
|
10
|
-
} %>
|