headmin 0.5.0 → 0.5.3
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.md +2 -2
- data/Gemfile +14 -0
- data/Gemfile.lock +79 -2
- data/app/assets/javascripts/headmin/controllers/media_controller.js +237 -0
- data/app/assets/javascripts/headmin/controllers/media_modal_controller.js +110 -0
- data/app/assets/javascripts/headmin/controllers/remote_modal_controller.js +10 -0
- data/app/assets/javascripts/headmin/controllers/textarea_controller.js +34 -0
- data/app/assets/javascripts/headmin/index.js +8 -0
- data/app/assets/javascripts/headmin.js +294 -0
- data/app/assets/stylesheets/headmin/forms/file.scss +40 -5
- data/app/assets/stylesheets/headmin/forms/media.scss +10 -0
- data/app/assets/stylesheets/headmin/forms/repeater.scss +4 -0
- data/app/assets/stylesheets/headmin/forms.scss +7 -0
- data/app/assets/stylesheets/headmin/layout/sidebar.scss +0 -1
- data/app/assets/stylesheets/headmin/media/index.scss +9 -0
- data/app/assets/stylesheets/headmin/media.scss +1 -0
- data/app/assets/stylesheets/headmin/table.scss +15 -0
- data/app/assets/stylesheets/headmin.css +70 -7
- data/app/assets/stylesheets/headmin.scss +1 -0
- data/app/controllers/headmin/media_controller.rb +52 -0
- data/app/controllers/headmin_controller.rb +2 -0
- data/app/helpers/headmin/form_helper.rb +2 -2
- data/app/models/concerns/headmin/field.rb +1 -1
- data/app/models/concerns/headmin/fieldable.rb +19 -10
- data/app/models/concerns/headmin/form/hintable.rb +6 -1
- data/app/models/headmin/blocks_view.rb +1 -1
- data/app/models/headmin/filter/date.rb +49 -1
- data/app/models/headmin/form/color_view.rb +48 -0
- data/app/models/headmin/form/media_view.rb +113 -0
- data/app/models/headmin/form/textarea_view.rb +6 -1
- data/app/views/examples/admin.html.erb +8 -8
- data/app/views/examples/auth.html.erb +2 -2
- data/app/views/headmin/_blocks.html.erb +1 -1
- data/app/views/headmin/_breadcrumbs.html.erb +2 -2
- data/app/views/headmin/_dropdown.html.erb +1 -1
- data/app/views/headmin/_filters.html.erb +5 -5
- data/app/views/headmin/_pagination.html.erb +2 -2
- data/app/views/headmin/_popup.html.erb +4 -4
- data/app/views/headmin/_table.html.erb +1 -1
- data/app/views/headmin/_thumbnail.html.erb +1 -1
- data/app/views/headmin/dropdown/_button.html.erb +2 -2
- data/app/views/headmin/dropdown/_item.html.erb +2 -2
- data/app/views/headmin/dropdown/_list.html.erb +3 -3
- data/app/views/headmin/dropdown/_locale.html.erb +5 -5
- data/app/views/headmin/filters/filter/_button.html.erb +2 -2
- data/app/views/headmin/filters/filter/_null_select.html.erb +2 -2
- data/app/views/headmin/forms/_color.html.erb +32 -0
- data/app/views/headmin/forms/_errors.html.erb +1 -1
- data/app/views/headmin/forms/_file.html.erb +7 -7
- data/app/views/headmin/forms/_hint.html.erb +6 -1
- data/app/views/headmin/forms/_media.html.erb +58 -0
- data/app/views/headmin/forms/_repeater.html.erb +9 -9
- data/app/views/headmin/forms/_textarea.html.erb +1 -1
- data/app/views/headmin/forms/media/_item.html.erb +32 -0
- data/app/views/headmin/forms/media/_validation.html.erb +10 -0
- data/app/views/headmin/forms/repeater/_row.html.erb +15 -14
- data/app/views/headmin/heading/_title.html.erb +2 -2
- data/app/views/headmin/layout/_main.html.erb +2 -0
- data/app/views/headmin/layout/_remote_modal.html.erb +1 -0
- data/app/views/headmin/layout/_sidebar.html.erb +1 -1
- data/app/views/headmin/media/_item.html.erb +17 -0
- data/app/views/headmin/media/_media_item_modal.html.erb +51 -0
- data/app/views/headmin/media/_modal.html.erb +35 -0
- data/app/views/headmin/media/create.turbo_stream.erb +5 -0
- data/app/views/headmin/media/index.html.erb +3 -0
- data/app/views/headmin/media/show.html.erb +9 -0
- data/app/views/headmin/media/update.turbo_stream.erb +3 -0
- data/app/views/headmin/nav/_dropdown.html.erb +7 -7
- data/app/views/headmin/nav/_item.html.erb +5 -5
- data/app/views/headmin/nav/item/_locale.html.erb +6 -6
- data/app/views/headmin/pagination/_per_page.html.erb +7 -7
- data/app/views/headmin/pagination/kaminari/_first_page.html.erb +2 -2
- data/app/views/headmin/pagination/kaminari/_gap.html.erb +1 -1
- data/app/views/headmin/pagination/kaminari/_last_page.html.erb +2 -2
- data/app/views/headmin/pagination/kaminari/_next_page.html.erb +3 -3
- data/app/views/headmin/pagination/kaminari/_page.html.erb +2 -2
- data/app/views/headmin/pagination/kaminari/_paginator.html.erb +1 -1
- data/app/views/headmin/pagination/kaminari/_prev_page.html.erb +2 -2
- data/app/views/headmin/table/_actions.html.erb +9 -9
- data/app/views/headmin/table/_body.html.erb +1 -1
- data/app/views/headmin/table/actions/_action.html.erb +4 -4
- data/app/views/headmin/table/actions/_export.html.erb +1 -1
- data/app/views/headmin/table/body/_association.html.erb +1 -1
- data/app/views/headmin/table/body/_boolean.erb +4 -4
- data/app/views/headmin/table/body/_color.html.erb +10 -0
- data/app/views/headmin/table/body/_date.html.erb +2 -2
- data/app/views/headmin/table/body/_image.html.erb +18 -0
- data/app/views/headmin/table/body/_string.html.erb +1 -1
- data/app/views/headmin/table/head/_cell.html.erb +1 -1
- data/app/views/headmin/table/head/cell/_asc.html.erb +2 -2
- data/app/views/headmin/table/head/cell/_default.html.erb +1 -1
- data/app/views/headmin/table/head/cell/_desc.html.erb +1 -1
- data/app/views/headmin/views/devise/confirmations/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/passwords/_edit.html.erb +1 -1
- data/app/views/headmin/views/devise/passwords/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/registrations/_edit.html.erb +5 -5
- data/app/views/headmin/views/devise/registrations/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/sessions/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/shared/_links.html.erb +11 -11
- data/app/views/headmin/views/devise/unlocks/_new.html.erb +1 -1
- data/config/locales/devise/nl.yml +1 -1
- data/config/locales/headmin/forms/en.yml +8 -0
- data/config/locales/headmin/forms/nl.yml +8 -0
- data/config/locales/headmin/media/en.yml +23 -0
- data/config/locales/headmin/media/nl.yml +22 -0
- data/config/locales/headmin/table/en.yml +2 -0
- data/config/locales/headmin/table/nl.yml +2 -0
- data/config/routes.rb +10 -0
- data/lib/generators/templates/views/layouts/auth.html.erb +2 -2
- data/lib/headmin/version.rb +1 -1
- data/package.json +1 -1
- metadata +30 -2
@@ -48,13 +48,13 @@
|
|
48
48
|
src = attachment.image? ? url_for(attachment.variant(resize_to_fill: [file.thumbnail_width, file.thumbnail_height])) : url_for(attachment)
|
49
49
|
%>
|
50
50
|
<div class="h-form-file-thumbnail" title="<%= "#{filename} (#{size})" %>" data-file-preview-target="thumbnail">
|
51
|
-
<%= ff.hidden_field(:id, disabled: file.destroy) %>
|
52
|
-
<%= ff.hidden_field(:_destroy, data: {
|
51
|
+
<%= ff.hidden_field(:id, disabled: !file.destroy) %>
|
52
|
+
<%= ff.hidden_field(:_destroy, data: {"file-preview-target": "thumbnailDestroy"}, disabled: !file.destroy) %>
|
53
53
|
<%= render "headmin/thumbnail", src: src, width: file.thumbnail_width, height: file.thumbnail_height %>
|
54
54
|
|
55
55
|
<% if file.destroy %>
|
56
56
|
<div class="h-form-file-thumbnail-remove" data-action="click->file-preview#remove" data-file-preview-name-param="<%= filename %>">
|
57
|
-
<%= bootstrap_icon(
|
57
|
+
<%= bootstrap_icon("x") %>
|
58
58
|
</div>
|
59
59
|
<% end %>
|
60
60
|
</div>
|
@@ -62,11 +62,11 @@
|
|
62
62
|
|
63
63
|
<!-- Placeholder -->
|
64
64
|
<% if file.dropzone %>
|
65
|
-
<div class="h-dropzone-placeholder <%=
|
66
|
-
<%= t(
|
65
|
+
<div class="h-dropzone-placeholder <%= "d-none" if file.attachments.any? %>" data-file-preview-target="placeholder" style="height: <%= file.thumbnail_height %>px;">
|
66
|
+
<%= t("headmin.forms.file.placeholder", count: file.number_of_files) %>
|
67
67
|
</div>
|
68
68
|
<% else %>
|
69
|
-
<div class="h-form-file-thumbnail <%=
|
69
|
+
<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
70
|
<%= render "headmin/thumbnail", width: file.thumbnail_width, height: file.thumbnail_height, icon: "plus" %>
|
71
71
|
</div>
|
72
72
|
<% end %>
|
@@ -80,7 +80,7 @@
|
|
80
80
|
|
81
81
|
<% if file.destroy %>
|
82
82
|
<div class="h-form-file-thumbnail-remove" data-action="click->file-preview#remove">
|
83
|
-
<%= bootstrap_icon(
|
83
|
+
<%= bootstrap_icon("x") %>
|
84
84
|
</div>
|
85
85
|
<% end %>
|
86
86
|
</div>
|
@@ -13,4 +13,9 @@
|
|
13
13
|
hint = Headmin::Form::HintView.new(local_assigns)
|
14
14
|
%>
|
15
15
|
|
16
|
-
<div class="form-text
|
16
|
+
<div class="form-text d-flex justify-content-between">
|
17
|
+
<div><%= raw(hint.content) %></div>
|
18
|
+
<% if hint.maxlength %>
|
19
|
+
<div data-textarea-target="count"></div>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<%
|
2
|
+
# headmin/forms/file
|
3
|
+
#
|
4
|
+
# ==== Required parameters
|
5
|
+
# * +attribute+ - Name of the attribute of the form model
|
6
|
+
# * +form+ - Form object
|
7
|
+
#
|
8
|
+
# ==== Optional parameters
|
9
|
+
# * +destroy+ - Adds delete buttons to the preview thumbnails
|
10
|
+
# * +hint+ - Informative text to assist with data input. HTML markup is allowed.
|
11
|
+
# * +label+ - Text to display inside label tag. Defaults to the attribute name. Set to false if you don"t want to show a label.
|
12
|
+
# * +min+ - Limit the selection to a minimum amount of items.
|
13
|
+
# * +max+ - Limit the selection to a maximum amount of items.
|
14
|
+
# * +sort+ - Allow sorting by dragging items. `active_storage_attachments` must have a position column.
|
15
|
+
# * +wrapper+ - Hash with all options for the surrounding html tag
|
16
|
+
#
|
17
|
+
# ==== References
|
18
|
+
# https://headmin.dev/docs/forms/media
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
# Basic version
|
22
|
+
# <%= form_with do |form| %#>
|
23
|
+
# <%= render "headmin/forms/media", form: form, attribute: :file %#>
|
24
|
+
# <% end %#>
|
25
|
+
|
26
|
+
media = Headmin::Form::MediaView.new(local_assigns)
|
27
|
+
%>
|
28
|
+
|
29
|
+
<%= render "headmin/forms/wrapper", media.wrapper_options do %>
|
30
|
+
<%= render "headmin/forms/label", media.label_options if media.prepend_label? %>
|
31
|
+
<div class="h-form-file-thumbnails" data-media-target="thumbnails">
|
32
|
+
<%= render "headmin/forms/media/validation", media.custom_validation_options %>
|
33
|
+
|
34
|
+
<!-- Render previews for attachments -->
|
35
|
+
<%= form.fields_for(media.nested_attribute, media.association_object) do |ff| %>
|
36
|
+
<%= render "headmin/forms/media/item", form: ff, url: media.media_modal_url, sort: media.sort %>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<!-- Placeholder -->
|
40
|
+
<div class="<%= "d-none" if media.attachments.any? %>" data-media-target="placeholder">
|
41
|
+
<a href="<%= media.media_modal_url %>" data-turbo-frame="remote_modal" data-media-target="modalButton">
|
42
|
+
<%= render "headmin/thumbnail", src: nil, width: 100, height: 100, icon: "plus" %>
|
43
|
+
</a>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<!-- Template -->
|
48
|
+
<% association_object = ActiveStorage::Attachment.new %>
|
49
|
+
<template data-media-target="template" data-template-id-regex="<%= association_object.object_id %>">
|
50
|
+
<%= 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.media_modal_url, sort: media.sort %>
|
52
|
+
<% end %>
|
53
|
+
</template>
|
54
|
+
|
55
|
+
<%= render "headmin/forms/validation", media.validation_options if media.validate? %>
|
56
|
+
<%= render "headmin/forms/hint", media.hint_options if media.hint? %>
|
57
|
+
<%= render "headmin/forms/label", media.label_options if media.append_label? %>
|
58
|
+
<% end %>
|
@@ -21,12 +21,12 @@
|
|
21
21
|
# <% end %#>
|
22
22
|
#
|
23
23
|
# # With fixed header row. A header row can be used to show the labels, so you can omit them in the repeated fields
|
24
|
-
# <% render "headmin/forms/repeater", form: form, attribute: :questions, header:
|
24
|
+
# <% render "headmin/forms/repeater", form: form, attribute: :questions, header: "admin/questions/header" do |question| %#>
|
25
25
|
# <% render "admin/questions/fields, form: :question" %#>
|
26
26
|
# <% end %#>
|
27
27
|
#
|
28
28
|
# # Allow more than one type of fields to be inserted. You must specify the templates as an array of view paths
|
29
|
-
# <% templates = [
|
29
|
+
# <% templates = ["admin/questions/fields/type_1", "admin/questions/fields/type_2"] %#>
|
30
30
|
# <% render "headmin/forms/repeater", form: form, attribute: :questions, templates: templates do |question| %#>
|
31
31
|
# <% render "admin/questions/fields, form: :question" %#>
|
32
32
|
# <% end %#>
|
@@ -37,12 +37,12 @@
|
|
37
37
|
templates = local_assigns.has_key?(:templates) ? templates : []
|
38
38
|
flush = local_assigns.has_key?(:flush) ? flush : true
|
39
39
|
|
40
|
-
template_names = templates.map { |template| File.basename(template,
|
41
|
-
template_names = template_names.any? ? template_names : [
|
40
|
+
template_names = templates.map { |template| File.basename(template, ".html.erb") }
|
41
|
+
template_names = template_names.any? ? template_names : ["new"]
|
42
42
|
object_model = form.object.class
|
43
43
|
association_model = object_model.reflect_on_association(attribute).class_name.constantize
|
44
44
|
association_object = association_model.new
|
45
|
-
with_positions = association_object.attributes.keys.include?(
|
45
|
+
with_positions = association_object.attributes.keys.include?("position")
|
46
46
|
associations = form.object.send(attribute)
|
47
47
|
associations = with_positions ? associations.order(:position) : associations
|
48
48
|
repeater_id = form.object_id
|
@@ -55,7 +55,7 @@
|
|
55
55
|
<%= render "headmin/forms/label", form: form, attribute: attribute, text: label, required: required %>
|
56
56
|
<% end %>
|
57
57
|
|
58
|
-
<ul class="repeater list-group <%=
|
58
|
+
<ul class="repeater list-group <%= "list-group-flush" if flush %>" data-controller="repeater" data-repeater-target="list" data-repeater-id-value="<%= repeater_id %>">
|
59
59
|
|
60
60
|
<!-- Header -->
|
61
61
|
<% if header %>
|
@@ -76,7 +76,7 @@
|
|
76
76
|
|
77
77
|
<!-- Empty notice -->
|
78
78
|
<div class="text-secondary invisible" data-repeater-target="empty">
|
79
|
-
<%= t(
|
79
|
+
<%= t(".empty") %>
|
80
80
|
</div>
|
81
81
|
|
82
82
|
<!-- Button -->
|
@@ -88,8 +88,8 @@
|
|
88
88
|
data-popup-pass-thru="<%= pass_thru %>"
|
89
89
|
data-action="click->repeater#resetButtonIndices click->popup#open"
|
90
90
|
>
|
91
|
-
<%= bootstrap_icon(
|
92
|
-
<%= t(
|
91
|
+
<%= bootstrap_icon("plus") %>
|
92
|
+
<%= t(".add", name: association_model.model_name.human) %>
|
93
93
|
</div>
|
94
94
|
|
95
95
|
<!-- Popup -->
|
@@ -34,6 +34,6 @@
|
|
34
34
|
<%= form.text_area(textarea.attribute, textarea.input_options) %>
|
35
35
|
<% end %>
|
36
36
|
<%= render "headmin/forms/validation", textarea.validation_options if textarea.validate? %>
|
37
|
-
<%= render "headmin/forms/hint", textarea.hint_options if textarea.hint? %>
|
37
|
+
<%= render "headmin/forms/hint", textarea.hint_options if textarea.hint? || textarea.maxlength? %>
|
38
38
|
<%= render "headmin/forms/label", textarea.label_options if textarea.append_label? %>
|
39
39
|
<% end %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<%
|
2
|
+
attachment = form.object
|
3
|
+
filename = attachment.blob&.filename&.to_s
|
4
|
+
size = number_to_human_size(attachment.blob&.byte_size || 0)
|
5
|
+
src = nil
|
6
|
+
if attachment.blob
|
7
|
+
src = attachment.image? ? url_for(attachment.variant(resize_to_fill: [100, 100])) : url_for(attachment)
|
8
|
+
end
|
9
|
+
%>
|
10
|
+
|
11
|
+
<div class="h-form-file-thumbnail media-drag-sort-handle" title="<%= "#{filename} (#{size})" %>" data-media-target="item">
|
12
|
+
<%= form.hidden_field(:id) %>
|
13
|
+
<%= form.hidden_field(:blob_id) %>
|
14
|
+
<%= form.hidden_field(:position, value: attachment.new_record? ? nil : attachment.position) if sort %>
|
15
|
+
<%= form.hidden_field(:_destroy) %>
|
16
|
+
|
17
|
+
<a href="<%= url %>" data-turbo-frame="remote_modal" data-media-target="modalButton">
|
18
|
+
<%= render "headmin/thumbnail", src: src, width: 100, height: 100 %>
|
19
|
+
</a>
|
20
|
+
|
21
|
+
<div class="h-form-file-thumbnail-actions">
|
22
|
+
<!-- Edit -->
|
23
|
+
<a href="<%= headmin_media_item_url(id: attachment.blob ? attachment.blob.id : "$1") %>" class="h-form-file-thumbnail-edit" data-turbo-frame="remote_modal" data-media-target="editButton">
|
24
|
+
<%= bootstrap_icon("pencil") %>
|
25
|
+
</a>
|
26
|
+
|
27
|
+
<!-- Remove -->
|
28
|
+
<div class="h-form-file-thumbnail-remove" data-action="click->media#destroy">
|
29
|
+
<%= bootstrap_icon("x") %>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
</div>
|
@@ -0,0 +1,10 @@
|
|
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
|
+
} %>
|
@@ -18,34 +18,35 @@
|
|
18
18
|
<%= form.hidden_field :id %>
|
19
19
|
<%= form.hidden_field :_destroy if destroyable %>
|
20
20
|
<%= form.hidden_field :position if draggable %>
|
21
|
-
<%= yield %>
|
22
21
|
|
23
22
|
<!-- Drag handle -->
|
24
23
|
<% if draggable %>
|
25
24
|
<div class="repeater-row-handle">
|
26
|
-
<%= bootstrap_icon(
|
25
|
+
<%= bootstrap_icon("grip-vertical") %>
|
27
26
|
</div>
|
28
27
|
<% end %>
|
29
28
|
|
30
29
|
<!-- Add button-->
|
31
30
|
<div
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
class="repeater-row-add btn btn-link"
|
32
|
+
title="<%= t(".add") %>"
|
33
|
+
data-repeater-target="addButton"
|
34
|
+
data-popup-target="button"
|
35
|
+
data-popup-id="<%= "repeater-buttons-#{repeater_id}" %>"
|
36
|
+
data-popup-pass-thru="<%= pass_thru %>"
|
37
|
+
data-action="click->repeater#resetButtonIndices click->popup#open"
|
39
38
|
>
|
40
|
-
<%= bootstrap_icon(
|
39
|
+
<%= bootstrap_icon("plus-circle") %>
|
41
40
|
</div>
|
42
41
|
|
43
42
|
<!-- Remove button-->
|
44
43
|
<div
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
class="repeater-row-remove btn btn-link"
|
45
|
+
title="<%= t(".remove") %>"
|
46
|
+
data-action="click->repeater#removeRow"
|
48
47
|
>
|
49
|
-
<%= bootstrap_icon(
|
48
|
+
<%= bootstrap_icon("dash-circle") %>
|
50
49
|
</div>
|
50
|
+
|
51
|
+
<%= yield %>
|
51
52
|
</div>
|
@@ -13,11 +13,11 @@
|
|
13
13
|
<div class="h-heading-title">
|
14
14
|
<div class="d-flex align-items-center">
|
15
15
|
<h1 class="me-2">
|
16
|
-
<%= title ? title : t(
|
16
|
+
<%= title ? title : t(".new") %>
|
17
17
|
</h1>
|
18
18
|
<% if new_link %>
|
19
19
|
<a href="<%= new_link %>" class="btn btn-outline-primary btn-sm">
|
20
|
-
<%= t(
|
20
|
+
<%= t(".new") %>
|
21
21
|
</a>
|
22
22
|
<% end %>
|
23
23
|
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= turbo_frame_tag "remote_modal", target: "_top" %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
<div class="sidebar col-sm-12 col-md-1 col-lg-2 bg-dark overflow-y d-print-none">
|
9
9
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark w-100 h-100 flex-md-column">
|
10
|
-
<a href="<%= local_assigns[:url] %>" class="nav-brand mb-
|
10
|
+
<a href="<%= local_assigns[:url] %>" class="nav-brand mb-4 mt-3 me-lg-auto">
|
11
11
|
<%= local_assigns[:logo] %>
|
12
12
|
</a>
|
13
13
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-nav" aria-controls="sidebar-nav" aria-expanded="false" aria-label="Toggle navigation">
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<div data-media-modal-target="item" title="<%= "#{blob.filename} (#{l(blob.created_at, format: :long)})" %>">
|
2
|
+
<!-- Input -->
|
3
|
+
<input
|
4
|
+
id="media-item-<%= blob.id %>"
|
5
|
+
type="checkbox"
|
6
|
+
value="<%= blob.id %>"
|
7
|
+
<%= "checked" if params[:ids]&.include?(blob.id.to_s) %>
|
8
|
+
data-action="change->media-modal#inputChange"
|
9
|
+
data-media-modal-target="idCheckbox"
|
10
|
+
hidden>
|
11
|
+
|
12
|
+
<!-- Label -->
|
13
|
+
<label for="media-item-<%= blob.id %>">
|
14
|
+
<% src = blob.image? ? url_for(blob.variant(resize_to_fill: [100, 100])) : url_for(blob) %>
|
15
|
+
<%= render "headmin/thumbnail", src: src, width: 100, height: 100 %>
|
16
|
+
</label>
|
17
|
+
</div>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<%= turbo_frame_tag "modal_content" do %>
|
2
|
+
<%= form_with url: headmin_media_item_url(id: @blob.id), model: @blob do |form| %>
|
3
|
+
<div class="modal-header">
|
4
|
+
<h5 class="modal-title"><%= t(".edit") %></h5>
|
5
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<%= t(".close") %>"></button>
|
6
|
+
</div>
|
7
|
+
<div class="modal-body">
|
8
|
+
<%= render "headmin/notifications" %>
|
9
|
+
<div class="row">
|
10
|
+
<div class="col-3">
|
11
|
+
<%= render "headmin/thumbnail", src: url_for(@blob), width: 100, height: 100 %>
|
12
|
+
</div>
|
13
|
+
<div class="col-8 d-flex flex-column justify-content-center">
|
14
|
+
<p class="small text-secondary m-0">
|
15
|
+
<strong><%= t(".uploaded_at") %>:</strong>
|
16
|
+
<%= l(@blob.created_at, format: :long) %>
|
17
|
+
</p>
|
18
|
+
<p class="small text-secondary m-0">
|
19
|
+
<strong><%= t(".type") %>:</strong>
|
20
|
+
<%= @blob.content_type %>
|
21
|
+
</p>
|
22
|
+
<p class="small text-secondary m-0">
|
23
|
+
<strong><%= t(".dimensions") %>:</strong>
|
24
|
+
<% if @blob.metadata[:width] && @blob.metadata[:height] %>
|
25
|
+
<%= "#{@blob.metadata[:width]}px x #{@blob.metadata[:height]}px" %>
|
26
|
+
<% else %>
|
27
|
+
<%= t(".not_analysed") %>
|
28
|
+
<% end %>
|
29
|
+
</p>
|
30
|
+
<p class="small text-secondary m-0">
|
31
|
+
<strong><%= t(".size") %>:</strong>
|
32
|
+
<% if @blob.byte_size > 0 %>
|
33
|
+
<%= number_to_human_size(@blob.byte_size) %>
|
34
|
+
<% else %>
|
35
|
+
<%= t(".not_analysed") %>
|
36
|
+
<% end %>
|
37
|
+
</p>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
<div class="row mt-3">
|
41
|
+
<div class="col-12">
|
42
|
+
<%= render "headmin/forms/text", form: form, attribute: :filename, append: "." + form.object.filename.to_s.rpartition(".").last, value: form.object.filename.to_s.rpartition(".").first %>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
<div class="modal-footer">
|
47
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><%= t(".close") %></button>
|
48
|
+
<%= form.submit t(".update"), class: "btn btn-primary" %>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<div class="media-modal modal fade" tabindex="-1" data-controller="remote-modal media-modal" data-name="<%= name %>" data-min="<%= min %>" data-max="<%= max %>">
|
2
|
+
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
3
|
+
<div class="modal-content">
|
4
|
+
<div class="modal-header">
|
5
|
+
<h5 class="modal-title">
|
6
|
+
<%= t(".title", count: min.to_i < 1 ? 1 : min.to_i) %>
|
7
|
+
</h5>
|
8
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<%= t(".close") %>"></button>
|
9
|
+
</div>
|
10
|
+
<div class="modal-body">
|
11
|
+
<%= turbo_frame_tag "thumbnails", class: "d-flex flex-wrap gap-2" do %>
|
12
|
+
<% @blobs.each do |blob| %>
|
13
|
+
<%= render "headmin/media/item", blob: blob %>
|
14
|
+
<% end %>
|
15
|
+
<div data-media-modal-target="placeholder" class="<%= "d-none" if !@blobs.empty? %>">
|
16
|
+
<p><%= t(".placeholder") %></p>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
<div class="modal-footer">
|
21
|
+
<%= form_with url: headmin_media_path, multipart: true, data: {"media-modal-target": "form"}, class: "me-auto" do |form| %>
|
22
|
+
<%= form.label :files, class: "btn h-btn-outline-light" do %>
|
23
|
+
<%= bootstrap_icon("upload") %>
|
24
|
+
<%= t(".upload") %>
|
25
|
+
<%= form.file_field :files, class: "d-none", multiple: true, data: {action: "change->media-modal#submitForm"} %>
|
26
|
+
<% end %>
|
27
|
+
<% end %>
|
28
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><%= t(".close") %></button>
|
29
|
+
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" data-action="click->media-modal#select" data-media-modal-target="selectButton">
|
30
|
+
<%= t(".select") %> (<span data-media-modal-target="count">0</span><%= t(".maximum", count: max.to_i) if max.present? %>)
|
31
|
+
</button>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%= turbo_frame_tag "remote_modal" do %>
|
2
|
+
<div class="media-item-modal modal fade" tabindex="-1" data-controller="remote-modal">
|
3
|
+
<div class="modal-dialog modal-md modal-dialog-scrollable">
|
4
|
+
<div class="modal-content">
|
5
|
+
<%= render "headmin/media/media_item_modal" %>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
@@ -9,12 +9,12 @@
|
|
9
9
|
#
|
10
10
|
# ==== Examples
|
11
11
|
# Basic version.
|
12
|
-
# <%= render "headmin/nav/dropdown", name:
|
13
|
-
# <%= render "headmin/nav/item", name:
|
14
|
-
# <%= render "headmin/nav/item", name:
|
12
|
+
# <%= render "headmin/nav/dropdown", name: "My Account", url: admin_user_path, icon: "person-circle" do %#>
|
13
|
+
# <%= render "headmin/nav/item", name: "Edit info", url: edit_admin_user_path(current_user) %#>
|
14
|
+
# <%= render "headmin/nav/item", name: "Log out", url: destroy_user_session_path(current_user) %#>
|
15
15
|
# <% end %#>
|
16
16
|
|
17
|
-
name = local_assigns.has_key?(:name) ? name :
|
17
|
+
name = local_assigns.has_key?(:name) ? name : ""
|
18
18
|
icon = local_assigns.has_key?(:icon) ? icon : nil
|
19
19
|
collapse_id = "nav-dropdown-#{name.parameterize}"
|
20
20
|
url = local_assigns.has_key?(:url) ? url : request.url
|
@@ -22,13 +22,13 @@
|
|
22
22
|
%>
|
23
23
|
|
24
24
|
<li class="nav-item">
|
25
|
-
<a class="nav-link d-flex align-items-center dropdown-toggle <%=
|
26
|
-
<%= bootstrap_icon(icon, class:
|
25
|
+
<a class="nav-link d-flex align-items-center dropdown-toggle <%= "active" if active %>" href="#<%= collapse_id %>" role="button" data-bs-toggle="collapse" aria-expanded="<%= active.to_s %>" aria-controls="<%= collapse_id %>">
|
26
|
+
<%= bootstrap_icon(icon, class: "me-2") if icon %>
|
27
27
|
<span class="d-block d-md-none d-lg-block">
|
28
28
|
<%= name %>
|
29
29
|
</span>
|
30
30
|
</a>
|
31
|
-
<ul class="collapse <%=
|
31
|
+
<ul class="collapse <%= "show" if active %>" id="<%= collapse_id %>">
|
32
32
|
<%= yield %>
|
33
33
|
</ul>
|
34
34
|
</li>
|
@@ -9,20 +9,20 @@
|
|
9
9
|
#
|
10
10
|
# ==== Examples
|
11
11
|
# Basic version.
|
12
|
-
# <%= render "headmin/nav/item", name:
|
12
|
+
# <%= render "headmin/nav/item", name: "Dashboard", url: admin_root_path %#>
|
13
13
|
#
|
14
14
|
# With icon
|
15
|
-
# <%= render "headmin/nav/item", name:
|
15
|
+
# <%= render "headmin/nav/item", name: "Dashboard", url: admin_root_path, icon: "speedometer" %#>
|
16
16
|
|
17
|
-
name = local_assigns.has_key?(:name) ? name :
|
17
|
+
name = local_assigns.has_key?(:name) ? name : ""
|
18
18
|
icon = local_assigns.has_key?(:icon) ? icon : nil
|
19
19
|
url = local_assigns.has_key?(:url) ? url : request.url
|
20
20
|
active = local_assigns.has_key?(:active) ? active : current_url?(url)
|
21
21
|
%>
|
22
22
|
|
23
23
|
<li class="nav-item">
|
24
|
-
<a class="nav-link d-flex align-items-center <%=
|
25
|
-
<%= bootstrap_icon(icon, class:
|
24
|
+
<a class="nav-link d-flex align-items-center <%= "active" if active %>" aria-current="page" href="<%= url %>">
|
25
|
+
<%= bootstrap_icon(icon, class: "me-2") if icon %>
|
26
26
|
<span class="d-block d-md-none d-lg-block">
|
27
27
|
<%= name %>
|
28
28
|
</span>
|
@@ -4,14 +4,14 @@
|
|
4
4
|
parameters: none
|
5
5
|
%>
|
6
6
|
|
7
|
-
<%= render "headmin/dropdown", class:
|
8
|
-
<%= render "headmin/dropdown/button", class:
|
9
|
-
<%= bootstrap_icon(
|
10
|
-
<%= t(
|
7
|
+
<%= render "headmin/dropdown", class: "nav-item" do %>
|
8
|
+
<%= render "headmin/dropdown/button", class: "nav-link", id: "nav-item-locale" do %>
|
9
|
+
<%= bootstrap_icon("globe", class: "me-2") %>
|
10
|
+
<%= t("language_name", locale: ::I18n.locale) %>
|
11
11
|
<% end %>
|
12
|
-
<%= render "headmin/dropdown/list", id:
|
12
|
+
<%= render "headmin/dropdown/list", id: "nav-item-locale" do %>
|
13
13
|
<% I18n.available_locales.each do |locale| %>
|
14
|
-
<%= render "headmin/dropdown/item", name: t(
|
14
|
+
<%= render "headmin/dropdown/item", name: t("language_name", locale: locale), url: url_for({locale: locale.to_s}) %>
|
15
15
|
<% end %>
|
16
16
|
<% end %>
|
17
17
|
<% end %>
|
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
<div class="d-flex flex-row-reverse flex-md-row align-items-center justify-content-between justify-content-md-end my-1">
|
4
4
|
<ul class="pagination pagination-sm my-0" role="group" aria-label="...">
|
5
|
-
<li class="page-item <%=
|
6
|
-
<%= link_to 12, url_for(params.merge(per_page: 12)), class:
|
5
|
+
<li class="page-item <%= "active" if per_page == 12 %>">
|
6
|
+
<%= link_to 12, url_for(params.merge(per_page: 12)), class: "page-link" %>
|
7
7
|
</li>
|
8
|
-
<li class="page-item <%=
|
9
|
-
<%= link_to 24, url_for(params.merge(per_page: nil)), class:
|
8
|
+
<li class="page-item <%= "active" if per_page == 24 %>">
|
9
|
+
<%= link_to 24, url_for(params.merge(per_page: nil)), class: "page-link" %>
|
10
10
|
</li>
|
11
|
-
<li class="page-item <%=
|
12
|
-
<%= link_to 48, url_for(params.merge(per_page: 48)), class:
|
11
|
+
<li class="page-item <%= "active" if per_page == 48 %>">
|
12
|
+
<%= link_to 48, url_for(params.merge(per_page: 48)), class: "page-link" %>
|
13
13
|
</li>
|
14
14
|
</ul>
|
15
15
|
<div class="d-none d-md-block ms-2 me-md-2 text-secondary">
|
16
|
-
<%= t(
|
16
|
+
<%= t(".title") %>
|
17
17
|
</div>
|
18
18
|
</div>
|
@@ -6,6 +6,6 @@
|
|
6
6
|
per_page: number of items to fetch per page
|
7
7
|
remote: data-remote
|
8
8
|
-%>
|
9
|
-
<li class="page-item <%= (
|
10
|
-
<%= link_to raw(t
|
9
|
+
<li class="page-item <%= ("disabled" if current_page.first?) %>">
|
10
|
+
<%= link_to raw(t ".button"), url, class: "page-link", remote: remote %>
|
11
11
|
</li>
|
@@ -7,6 +7,6 @@
|
|
7
7
|
remote: data-remote
|
8
8
|
-%>
|
9
9
|
<li class="page-item
|
10
|
-
<%= (
|
11
|
-
<%= link_to raw(t
|
10
|
+
<%= ("disabled" if current_page.last?) %>">
|
11
|
+
<%= link_to raw(t ".button"), url, class: "page-link", remote: remote %>
|
12
12
|
</li>
|
@@ -6,8 +6,8 @@
|
|
6
6
|
per_page: number of items to fetch per page
|
7
7
|
remote: data-remote
|
8
8
|
-%>
|
9
|
-
<li class="page-item <%= (
|
10
|
-
<%= link_to url, class:
|
11
|
-
<%= raw(t
|
9
|
+
<li class="page-item <%= ("disabled" if current_page.last?) %>">
|
10
|
+
<%= link_to url, class: "page-link", rel: "next", remote: remote do %>
|
11
|
+
<%= raw(t ".button") %>
|
12
12
|
<% end %>
|
13
13
|
</li>
|
@@ -7,6 +7,6 @@
|
|
7
7
|
per_page: number of items to fetch per page
|
8
8
|
remote: data-remote
|
9
9
|
-%>
|
10
|
-
<li class="page-item <%=
|
11
|
-
<%= link_to page, url, opts = {remote: remote, class:
|
10
|
+
<li class="page-item <%= "active" if page.current? %>">
|
11
|
+
<%= link_to page, url, opts = {remote: remote, class: "page-link", rel: page.next? ? "next" : page.prev? ? "prev" : nil} %>
|
12
12
|
</li>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
paginator: the paginator that renders the pagination tags inside
|
8
8
|
-%>
|
9
9
|
<%= paginator.render do %>
|
10
|
-
<nav aria-label="<%= t(
|
10
|
+
<nav aria-label="<%= t(".title") %>">
|
11
11
|
<ul class="pagination pagination-sm m-0">
|
12
12
|
<%= first_page_tag %>
|
13
13
|
<%= prev_page_tag %>
|