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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -2
  3. data/Gemfile +14 -0
  4. data/Gemfile.lock +79 -2
  5. data/app/assets/javascripts/headmin/controllers/media_controller.js +237 -0
  6. data/app/assets/javascripts/headmin/controllers/media_modal_controller.js +110 -0
  7. data/app/assets/javascripts/headmin/controllers/remote_modal_controller.js +10 -0
  8. data/app/assets/javascripts/headmin/controllers/textarea_controller.js +34 -0
  9. data/app/assets/javascripts/headmin/index.js +8 -0
  10. data/app/assets/javascripts/headmin.js +294 -0
  11. data/app/assets/stylesheets/headmin/forms/file.scss +40 -5
  12. data/app/assets/stylesheets/headmin/forms/media.scss +10 -0
  13. data/app/assets/stylesheets/headmin/forms/repeater.scss +4 -0
  14. data/app/assets/stylesheets/headmin/forms.scss +7 -0
  15. data/app/assets/stylesheets/headmin/layout/sidebar.scss +0 -1
  16. data/app/assets/stylesheets/headmin/media/index.scss +9 -0
  17. data/app/assets/stylesheets/headmin/media.scss +1 -0
  18. data/app/assets/stylesheets/headmin/table.scss +15 -0
  19. data/app/assets/stylesheets/headmin.css +70 -7
  20. data/app/assets/stylesheets/headmin.scss +1 -0
  21. data/app/controllers/headmin/media_controller.rb +52 -0
  22. data/app/controllers/headmin_controller.rb +2 -0
  23. data/app/helpers/headmin/form_helper.rb +2 -2
  24. data/app/models/concerns/headmin/field.rb +1 -1
  25. data/app/models/concerns/headmin/fieldable.rb +19 -10
  26. data/app/models/concerns/headmin/form/hintable.rb +6 -1
  27. data/app/models/headmin/blocks_view.rb +1 -1
  28. data/app/models/headmin/filter/date.rb +49 -1
  29. data/app/models/headmin/form/color_view.rb +48 -0
  30. data/app/models/headmin/form/media_view.rb +113 -0
  31. data/app/models/headmin/form/textarea_view.rb +6 -1
  32. data/app/views/examples/admin.html.erb +8 -8
  33. data/app/views/examples/auth.html.erb +2 -2
  34. data/app/views/headmin/_blocks.html.erb +1 -1
  35. data/app/views/headmin/_breadcrumbs.html.erb +2 -2
  36. data/app/views/headmin/_dropdown.html.erb +1 -1
  37. data/app/views/headmin/_filters.html.erb +5 -5
  38. data/app/views/headmin/_pagination.html.erb +2 -2
  39. data/app/views/headmin/_popup.html.erb +4 -4
  40. data/app/views/headmin/_table.html.erb +1 -1
  41. data/app/views/headmin/_thumbnail.html.erb +1 -1
  42. data/app/views/headmin/dropdown/_button.html.erb +2 -2
  43. data/app/views/headmin/dropdown/_item.html.erb +2 -2
  44. data/app/views/headmin/dropdown/_list.html.erb +3 -3
  45. data/app/views/headmin/dropdown/_locale.html.erb +5 -5
  46. data/app/views/headmin/filters/filter/_button.html.erb +2 -2
  47. data/app/views/headmin/filters/filter/_null_select.html.erb +2 -2
  48. data/app/views/headmin/forms/_color.html.erb +32 -0
  49. data/app/views/headmin/forms/_errors.html.erb +1 -1
  50. data/app/views/headmin/forms/_file.html.erb +7 -7
  51. data/app/views/headmin/forms/_hint.html.erb +6 -1
  52. data/app/views/headmin/forms/_media.html.erb +58 -0
  53. data/app/views/headmin/forms/_repeater.html.erb +9 -9
  54. data/app/views/headmin/forms/_textarea.html.erb +1 -1
  55. data/app/views/headmin/forms/media/_item.html.erb +32 -0
  56. data/app/views/headmin/forms/media/_validation.html.erb +10 -0
  57. data/app/views/headmin/forms/repeater/_row.html.erb +15 -14
  58. data/app/views/headmin/heading/_title.html.erb +2 -2
  59. data/app/views/headmin/layout/_main.html.erb +2 -0
  60. data/app/views/headmin/layout/_remote_modal.html.erb +1 -0
  61. data/app/views/headmin/layout/_sidebar.html.erb +1 -1
  62. data/app/views/headmin/media/_item.html.erb +17 -0
  63. data/app/views/headmin/media/_media_item_modal.html.erb +51 -0
  64. data/app/views/headmin/media/_modal.html.erb +35 -0
  65. data/app/views/headmin/media/create.turbo_stream.erb +5 -0
  66. data/app/views/headmin/media/index.html.erb +3 -0
  67. data/app/views/headmin/media/show.html.erb +9 -0
  68. data/app/views/headmin/media/update.turbo_stream.erb +3 -0
  69. data/app/views/headmin/nav/_dropdown.html.erb +7 -7
  70. data/app/views/headmin/nav/_item.html.erb +5 -5
  71. data/app/views/headmin/nav/item/_locale.html.erb +6 -6
  72. data/app/views/headmin/pagination/_per_page.html.erb +7 -7
  73. data/app/views/headmin/pagination/kaminari/_first_page.html.erb +2 -2
  74. data/app/views/headmin/pagination/kaminari/_gap.html.erb +1 -1
  75. data/app/views/headmin/pagination/kaminari/_last_page.html.erb +2 -2
  76. data/app/views/headmin/pagination/kaminari/_next_page.html.erb +3 -3
  77. data/app/views/headmin/pagination/kaminari/_page.html.erb +2 -2
  78. data/app/views/headmin/pagination/kaminari/_paginator.html.erb +1 -1
  79. data/app/views/headmin/pagination/kaminari/_prev_page.html.erb +2 -2
  80. data/app/views/headmin/table/_actions.html.erb +9 -9
  81. data/app/views/headmin/table/_body.html.erb +1 -1
  82. data/app/views/headmin/table/actions/_action.html.erb +4 -4
  83. data/app/views/headmin/table/actions/_export.html.erb +1 -1
  84. data/app/views/headmin/table/body/_association.html.erb +1 -1
  85. data/app/views/headmin/table/body/_boolean.erb +4 -4
  86. data/app/views/headmin/table/body/_color.html.erb +10 -0
  87. data/app/views/headmin/table/body/_date.html.erb +2 -2
  88. data/app/views/headmin/table/body/_image.html.erb +18 -0
  89. data/app/views/headmin/table/body/_string.html.erb +1 -1
  90. data/app/views/headmin/table/head/_cell.html.erb +1 -1
  91. data/app/views/headmin/table/head/cell/_asc.html.erb +2 -2
  92. data/app/views/headmin/table/head/cell/_default.html.erb +1 -1
  93. data/app/views/headmin/table/head/cell/_desc.html.erb +1 -1
  94. data/app/views/headmin/views/devise/confirmations/_new.html.erb +1 -1
  95. data/app/views/headmin/views/devise/passwords/_edit.html.erb +1 -1
  96. data/app/views/headmin/views/devise/passwords/_new.html.erb +1 -1
  97. data/app/views/headmin/views/devise/registrations/_edit.html.erb +5 -5
  98. data/app/views/headmin/views/devise/registrations/_new.html.erb +1 -1
  99. data/app/views/headmin/views/devise/sessions/_new.html.erb +1 -1
  100. data/app/views/headmin/views/devise/shared/_links.html.erb +11 -11
  101. data/app/views/headmin/views/devise/unlocks/_new.html.erb +1 -1
  102. data/config/locales/devise/nl.yml +1 -1
  103. data/config/locales/headmin/forms/en.yml +8 -0
  104. data/config/locales/headmin/forms/nl.yml +8 -0
  105. data/config/locales/headmin/media/en.yml +23 -0
  106. data/config/locales/headmin/media/nl.yml +22 -0
  107. data/config/locales/headmin/table/en.yml +2 -0
  108. data/config/locales/headmin/table/nl.yml +2 -0
  109. data/config/routes.rb +10 -0
  110. data/lib/generators/templates/views/layouts/auth.html.erb +2 -2
  111. data/lib/headmin/version.rb +1 -1
  112. data/package.json +1 -1
  113. metadata +30 -2
@@ -4,7 +4,7 @@ module Headmin
4
4
 
5
5
  included do
6
6
  # Configuration
7
- has_closure_tree
7
+ has_closure_tree order: "position", numeric_order: true
8
8
 
9
9
  # Associations
10
10
  belongs_to :fieldable, polymorphic: true, optional: true, touch: true
@@ -17,10 +17,19 @@ module Headmin
17
17
  @fields_hash = hash
18
18
  end
19
19
 
20
+ def include_tables
21
+ []
22
+ end
23
+
24
+ def default_include_tables
25
+ [files_attachments: :blob]
26
+ end
27
+
20
28
  private
21
29
 
22
30
  def parse_fields
23
- fields.where(parent: nil).order(position: :asc).map { |field| parse_hash_tree(field.hash_tree) }.reduce({}, :merge)
31
+ hash_tree = fields.includes(default_include_tables | include_tables).hash_tree
32
+ parse_hash_tree(hash_tree)
24
33
  end
25
34
 
26
35
  def build_fields
@@ -95,10 +104,11 @@ module Headmin
95
104
  name: name,
96
105
  field_type: "file",
97
106
  value: nil,
98
- files: [ActiveStorage::Blob.create_and_upload!(
99
- io: file,
100
- filename: File.basename(file.path)
101
- )]
107
+ files_attachments_attributes: [
108
+ {
109
+ blob: ActiveStorage::Blob.create_and_upload!(io: file, filename: File.basename(file.path))
110
+ }
111
+ ]
102
112
  )
103
113
  end
104
114
 
@@ -108,11 +118,10 @@ module Headmin
108
118
  name: name,
109
119
  field_type: "files",
110
120
  value: nil,
111
- files: files.map { |file|
112
- ActiveStorage::Blob.create_and_upload!(
113
- io: file,
114
- filename: File.basename(file.path)
115
- )
121
+ files_attachments_attributes: files.map { |file|
122
+ {
123
+ blob: ActiveStorage::Blob.create_and_upload!(io: file, filename: File.basename(file.path))
124
+ }
116
125
  }
117
126
  )
118
127
  end
@@ -8,9 +8,14 @@ module Headmin
8
8
  hint.present?
9
9
  end
10
10
 
11
+ def maxlength?
12
+ maxlength.present?
13
+ end
14
+
11
15
  def hint_options
12
16
  {
13
- content: hint
17
+ content: hint,
18
+ maxlength: maxlength
14
19
  }
15
20
  end
16
21
  end
@@ -9,7 +9,7 @@ module Headmin
9
9
  end
10
10
 
11
11
  def prefixes
12
- paths + ["website/blocks", "blocks", ""]
12
+ paths + ["website/blocks", "blocks"]
13
13
  end
14
14
  end
15
15
  end
@@ -3,16 +3,64 @@ module Headmin
3
3
  class Date < Headmin::Filter::Base
4
4
  OPERATORS = %w[eq not_eq gt gteq lt lteq between not_between in not_in is_null is_not_null]
5
5
 
6
+ QUERY_OPERATOR_CONVERT_TO = {
7
+ between: %w[eq],
8
+ not_between: %w[not_eq]
9
+ }
10
+
11
+ OPERATORS_CONVERT_TO = {
12
+ convert_to_range: %w[between not_between],
13
+ convert_to_array: %w[in not_in],
14
+ convert_to_value: %w[matches does_not_match is_null is_not_null starts_with ends_with],
15
+ convert_to_datetime_equals: %w[eq not_eq],
16
+ convert_to_datetime_begin: %w[lt gteq],
17
+ convert_to_datetime_end: %w[gt lteq]
18
+ }
19
+
6
20
  def cast_value(value)
7
21
  value.present? ? value.to_date : ::Date.current
8
22
  rescue
9
23
  raise TypeError, "The value that was passed to this filter is not a date"
10
24
  end
11
25
 
26
+ def values
27
+ @instructions.map { |instruction| output_value(instruction) }.compact
28
+ end
29
+
30
+ def output_value(instruction)
31
+ if %w[eq not_eq].include?(instruction[:operator])
32
+ instruction[:value].last.to_date
33
+ elsif %w[lt lteq gt gteq].include?(instruction[:operator])
34
+ instruction[:value].to_date
35
+ else
36
+ instruction[:value]
37
+ end
38
+ end
39
+
40
+ def convert_to_datetime_equals(value)
41
+ casted_date = cast_value(value)
42
+
43
+ (casted_date - 1.day).end_of_day..casted_date.end_of_day
44
+ end
45
+
46
+ def convert_to_datetime_begin(value)
47
+ casted_date = cast_value(value)
48
+ casted_date.beginning_of_day
49
+ end
50
+
51
+ def convert_to_datetime_end(value)
52
+ casted_date = cast_value(value)
53
+ casted_date.end_of_day
54
+ end
55
+
12
56
  def display_value(value)
13
57
  # This uses the default date format of headmin.
14
58
  # Can be overwritten by setting default date format of the application.
15
- I18n.l(value)
59
+ if value.class.to_s == "Range"
60
+ I18n.l(value.last.to_date)
61
+ else
62
+ I18n.l(value.to_date)
63
+ end
16
64
  end
17
65
  end
18
66
  end
@@ -0,0 +1,48 @@
1
+ module Headmin
2
+ module Form
3
+ class ColorView < ViewModel
4
+ include Headmin::Form::Hintable
5
+ include Headmin::Form::Labelable
6
+ include Headmin::Form::Validatable
7
+ include Headmin::Form::Wrappable
8
+
9
+ def input_options
10
+ keys = attributes - %i[attribute form label validate wrapper]
11
+ options = to_h.slice(*keys)
12
+ default_input_options.deep_merge(options)
13
+ end
14
+
15
+ def label_options
16
+ {
17
+ class: ["form-label"],
18
+ attribute: attribute,
19
+ form: form,
20
+ required: required,
21
+ text: label
22
+ }
23
+ end
24
+
25
+ def value
26
+ @form.object&.send(@attribute) || "#000000"
27
+ end
28
+
29
+ def wrapper_options
30
+ default_wrapper_options.deep_merge(
31
+ {
32
+ }
33
+ ).deep_merge(@wrapper || {})
34
+ end
35
+
36
+ private
37
+
38
+ def default_input_options
39
+ {
40
+ aria: {describedby: validation_id},
41
+ class: ["form-control form-control-color", validation_class],
42
+ placeholder: placeholder,
43
+ title: value
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,113 @@
1
+ module Headmin
2
+ module Form
3
+ class MediaView < ViewModel
4
+ include Rails.application.routes.url_helpers
5
+ include Headmin::Form::Hintable
6
+ include Headmin::Form::Labelable
7
+ include Headmin::Form::Placeholderable
8
+ include Headmin::Form::Validatable
9
+ include Headmin::Form::Wrappable
10
+
11
+ def input_group_options
12
+ default_input_group_options
13
+ .deep_merge(label_input_group_options)
14
+ .deep_merge(@input_group || {})
15
+ end
16
+
17
+ def wrapper_options
18
+ default_wrapper_options.deep_merge({
19
+ class: ["mb-3", ("form-floating" if float)],
20
+ data: {
21
+ controller: "media",
22
+ name: "#{attribute}_#{object_id}",
23
+ min: min,
24
+ max: max,
25
+ sort: sort,
26
+ required: required.nil? ? 0 : required
27
+ }
28
+ }).deep_merge(@wrapper || {})
29
+ end
30
+
31
+ def custom_validation_options
32
+ {
33
+ form: form,
34
+ attribute: attribute,
35
+ min: min,
36
+ max: max
37
+ }
38
+ end
39
+
40
+ def association_object
41
+ if attached.is_a?(ActiveStorage::Attached::Many)
42
+ result = form.object.send(nested_attribute)
43
+ result = result.order(position: :asc) if sort
44
+ result
45
+ else
46
+ form.object.send(nested_attribute)
47
+ end
48
+ end
49
+
50
+ def attachments
51
+ if attached.is_a?(ActiveStorage::Attached::Many)
52
+ result = form.object.send(nested_attribute)
53
+ result = result.order(position: :asc) if sort
54
+ result.to_a.compact
55
+ else
56
+ [form.object.send(nested_attribute)].compact
57
+ end
58
+ end
59
+
60
+ def attached
61
+ form.object.send(attribute)
62
+ end
63
+
64
+ def build_nested_attribute
65
+ if attached.is_a?(ActiveStorage::Attached::Many)
66
+ form.object.send(nested_attribute).build
67
+ else
68
+ form.object.send("build_#{nested_attribute}")
69
+ end
70
+ end
71
+
72
+ def nested_attribute
73
+ if attached.is_a?(ActiveStorage::Attached::Many)
74
+ :"#{attribute}_attachments"
75
+ else
76
+ :"#{attribute}_attachment"
77
+ end
78
+ end
79
+
80
+ def min
81
+ if @required
82
+ @min.to_i < 1 ? 1 : @min.to_i
83
+ else
84
+ @min.to_i < 1 ? 0 : @min.to_i
85
+ end
86
+ end
87
+
88
+ def max
89
+ if attached.is_a?(ActiveStorage::Attached::Many)
90
+ @max
91
+ else
92
+ 1
93
+ end
94
+ end
95
+
96
+ def required
97
+ @required ? 1 : nil
98
+ end
99
+
100
+ def blob_ids
101
+ attachments.map { |attachment| attachment.blob_id }
102
+ end
103
+
104
+ def media_modal_url
105
+ headmin_media_url(name: "#{attribute}_#{object_id}", ids: blob_ids, min: min, max: max)
106
+ end
107
+
108
+ def sort
109
+ @sort == true
110
+ end
111
+ end
112
+ end
113
+ end
@@ -22,7 +22,8 @@ module Headmin
22
22
 
23
23
  def wrapper_options
24
24
  default_wrapper_options.deep_merge({
25
- class: ["mb-3", ("form-floating" if float)]
25
+ class: ["mb-3", ("form-floating" if float)],
26
+ data: {controller: :textarea}
26
27
  }).deep_merge(@wrapper || {})
27
28
  end
28
29
 
@@ -32,6 +33,10 @@ module Headmin
32
33
  {
33
34
  aria: {describedby: validation_id},
34
35
  class: [form_control_class, validation_class],
36
+ data: {
37
+ textarea_target: :textarea,
38
+ action: "input->textarea#update"
39
+ },
35
40
  placeholder: placeholder
36
41
  }
37
42
  end
@@ -6,15 +6,15 @@
6
6
  <%= csrf_meta_tags %>
7
7
  <%= csp_meta_tag %>
8
8
 
9
- <%= stylesheet_pack_tag 'admin', media: 'all', 'data-turbo-track': 'reload' %>
10
- <%= javascript_pack_tag 'admin', 'data-turbo-track': 'reload' %>
9
+ <%= stylesheet_pack_tag "admin", media: "all", "data-turbo-track": "reload" %>
10
+ <%= javascript_pack_tag "admin", "data-turbo-track": "reload" %>
11
11
  </head>
12
12
 
13
13
  <body>
14
14
  <%= render "headmin/layout/main" do %>
15
- <%= render "headmin/layout/sidebar", logo: inline_svg_tag('logo.svg') do %>
15
+ <%= render "headmin/layout/sidebar", logo: inline_svg_tag("logo.svg") do %>
16
16
  <%= render "headmin/layout/sidebar/menu" do %>
17
- <%= render "headmin/layout/sidebar/menu/item", name: t('.dashboard'), link: admin_root_path, icon: 'speedometer' %>
17
+ <%= render "headmin/layout/sidebar/menu/item", name: t(".dashboard"), link: admin_root_path, icon: "speedometer" %>
18
18
  <div class="d-block d-md-none">
19
19
  <%= render "headmin/layout/sidebar/menu/locale" do end %>
20
20
  <%= render "headmin/layout/sidebar/menu/account" do end %>
@@ -30,10 +30,10 @@
30
30
  <%= render "headmin/notifications" %>
31
31
  <%= yield %>
32
32
  <% end %>
33
- <%= render "headmin/layout/footer", class: 'text-secondary' do %>
34
- <%= bootstrap_icon('question-circle') %>
35
- <a class="text-secondary" href="mailto:info@insiting.com" title="<%= t('.help') %>">
36
- <%= t('.help') %>
33
+ <%= render "headmin/layout/footer", class: "text-secondary" do %>
34
+ <%= bootstrap_icon("question-circle") %>
35
+ <a class="text-secondary" href="mailto:info@insiting.com" title="<%= t(".help") %>">
36
+ <%= t(".help") %>
37
37
  </a>
38
38
  <% end %>
39
39
  <% end %>
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
6
  <%= csrf_meta_tags %>
7
7
  <%= csp_meta_tag %>
8
- <%= stylesheet_pack_tag 'admin', media: 'all', 'data-turbolinks-track': 'reload' %>
9
- <%= javascript_pack_tag 'admin', 'data-turbolinks-track': 'reload' %>
8
+ <%= stylesheet_pack_tag "admin", media: "all", "data-turbolinks-track": "reload" %>
9
+ <%= javascript_pack_tag "admin", "data-turbolinks-track": "reload" %>
10
10
  </head>
11
11
  <body class="bg-light w-100 vh-100">
12
12
 
@@ -15,7 +15,7 @@
15
15
  # <%= render "headmin/blocks", blockable: @page, paths: %w(website/pages/blocks) %#>
16
16
 
17
17
  blocks = Headmin::BlocksView.new(local_assigns)
18
- @lookup_context.prefixes = @lookup_context.prefixes + blocks.prefixes
18
+ @lookup_context.prefixes = blocks.prefixes + @lookup_context.prefixes
19
19
  %>
20
20
 
21
21
  <% if blockable && blockable.respond_to?(:blocks) %>
@@ -14,11 +14,11 @@
14
14
  <% breadcrumb_count = breadcrumbs.count %>
15
15
  <% breadcrumbs.each_with_index do |breadcrumb, index| %>
16
16
  <% last = (index == breadcrumb_count - 1) %>
17
- <li class="breadcrumb-item text-muted" aria-current="<%= last ? 'page' : nil %>">
17
+ <li class="breadcrumb-item text-muted" aria-current="<%= last ? "page" : nil %>">
18
18
  <% if last %>
19
19
  <%= breadcrumb.name %>
20
20
  <% else %>
21
- <%= link_to_unless_current(breadcrumb.name, breadcrumb.path, class: 'text-muted text-decoration-none') %>
21
+ <%= link_to_unless_current(breadcrumb.name, breadcrumb.path, class: "text-muted text-decoration-none") %>
22
22
  <% end %>
23
23
  </li>
24
24
  <% end %>
@@ -10,7 +10,7 @@
10
10
  # Your content
11
11
  # <% end %#>
12
12
 
13
- class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : 'btn-group'
13
+ class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : "btn-group"
14
14
  %>
15
15
 
16
16
  <div class="dropdown <%= class_names %>">
@@ -7,7 +7,7 @@
7
7
  # ==== Examples
8
8
  # Basic version
9
9
  # <%= render "headmin/filters" do %#>
10
- # <%= render "headmin/filters/select", name: 'color', options: ['red', 'green', 'blue'] %#>
10
+ # <%= render "headmin/filters/select", name: "color", options: ["red", "green", "blue"] %#>
11
11
  # <% end %#>
12
12
  #
13
13
  # With custom URL
@@ -22,7 +22,7 @@
22
22
  <%= yield(form) %>
23
23
 
24
24
  <!-- Default parameters (e.g. sorting, pagination) -->
25
- <% default_params.except('page').each do |name, value| %>
25
+ <% default_params.except("page").each do |name, value| %>
26
26
  <%= form.hidden_field name.to_sym, value: value %>
27
27
  <% end %>
28
28
 
@@ -44,8 +44,8 @@
44
44
  <% if content_for?(:filters_menu) %>
45
45
  <div class="btn-group">
46
46
  <button type="button" class="btn h-btn-outline-light dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
47
- <%= bootstrap_icon('funnel') %>
48
- <%= t('.button') %>
47
+ <%= bootstrap_icon("funnel") %>
48
+ <%= t(".button") %>
49
49
  </button>
50
50
  <ul class="dropdown-menu">
51
51
  <%= content_for :filters_menu %>
@@ -53,7 +53,7 @@
53
53
  <hr class="dropdown-divider">
54
54
  </li>
55
55
  <li>
56
- <a class="dropdown-item text-danger" href="#" data-action="click->filters#removeAll"><%= t('.remove_all') %></a>
56
+ <a class="dropdown-item text-danger" href="#" data-action="click->filters#removeAll"><%= t(".remove_all") %></a>
57
57
  </li>
58
58
  </ul>
59
59
  </div>
@@ -12,7 +12,7 @@
12
12
  <div class="d-flex flex-row-reverse flex-md-row align-items-center justify-content-between justify-content-md-end my-1">
13
13
  <% content_for :collection_total_count, collection.total_count.to_s unless content_for?(:collection_total_count) %>
14
14
  <div class="ms-2 me-md-2 text-secondary flex-grow-1 flex-shrink-0">
15
- <%= t('.items', count: content_for(:collection_total_count).to_i) %>
15
+ <%= t(".items", count: content_for(:collection_total_count).to_i) %>
16
16
  </div>
17
- <%= paginate collection, views_prefix: 'headmin/pagination' %>
17
+ <%= paginate collection, views_prefix: "headmin/pagination" %>
18
18
  </div>
@@ -8,7 +8,7 @@
8
8
  # To trigger this popup create an element with a data attribute like this
9
9
  #
10
10
  # <button data-popup-id="popupId">open Popup</button>
11
- # <%= render "headmin/popup", id: 'popupId' do %#>
11
+ # <%= render "headmin/popup", id: "popupId" do %#>
12
12
  # popup Content
13
13
  # <% end %#>
14
14
  #
@@ -16,14 +16,14 @@
16
16
  # "data-popup-pass-thru" attribute.
17
17
  #
18
18
  # <button data-popup-id="popupId" data-popup-pass-thru="#link">open Popup</button>
19
- # <%= render "headmin/popup", id: 'popupId' do %#>
19
+ # <%= render "headmin/popup", id: "popupId" do %#>
20
20
  # <a href="https://example.com" id="link">
21
21
  # <% end %#>
22
22
  data = local_assigns.has_key?(:data) ? data : {}
23
23
 
24
24
  options = {
25
- class: ['h-popup', 'closed'],
26
- data: data.merge('popup-target': 'popup', 'popup-id': id)
25
+ class: ["h-popup", "closed"],
26
+ data: data.merge("popup-target": "popup", "popup-id": id)
27
27
  }
28
28
  %>
29
29
 
@@ -13,7 +13,7 @@
13
13
  total_count = content_for(:collection_total_count).to_i || nil
14
14
  %>
15
15
 
16
- <div class="h-table card my-2 shadow-sm <%= 'table-drag-sort' if sort_url %>" data-sort-url="<%= sort_url %>">
16
+ <div class="h-table card my-2 shadow-sm <%= "table-drag-sort" if sort_url %>" data-sort-url="<%= sort_url %>">
17
17
  <div class="table-responsive">
18
18
  <table class="table table-hover m-0"
19
19
  data-controller="table"
@@ -5,7 +5,7 @@
5
5
  <div class="h-thumbnail-bg" style="background-image: url('<%= thumbnail.src %>');"></div>
6
6
  <% else %>
7
7
  <div class="h-thumbnail-bg">
8
- <%= bootstrap_icon(thumbnail.icon_name, class: 'h-thumbnail-icon') %>
8
+ <%= bootstrap_icon(thumbnail.icon_name, class: "h-thumbnail-icon") %>
9
9
  </div>
10
10
  <% end %>
11
11
  </div>
@@ -5,8 +5,8 @@
5
5
  id: unique identifier for the dropdown
6
6
  class: css class names as string
7
7
  %>
8
- <% id = local_assigns.has_key?(:id) ? id : 'dropdown-1' %>
9
- <% class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : 'btn' %>
8
+ <% id = local_assigns.has_key?(:id) ? id : "dropdown-1" %>
9
+ <% class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : "btn" %>
10
10
 
11
11
  <a class="dropdown-toggle d-flex align-items-center <%= class_names %>" type="button" id="<%= id %>" data-bs-toggle="dropdown" aria-expanded="false">
12
12
  <%= yield %>
@@ -8,8 +8,8 @@
8
8
  %>
9
9
 
10
10
  <% method = local_assigns.has_key?(:method) ? method : nil %>
11
- <% url = local_assigns.has_key?(:url) ? url : '' %>
12
- <% name = local_assigns.has_key?(:name) ? name : '' %>
11
+ <% url = local_assigns.has_key?(:url) ? url : "" %>
12
+ <% name = local_assigns.has_key?(:name) ? name : "" %>
13
13
 
14
14
  <li>
15
15
  <a class="dropdown-item" href="<%= url %>" <%= "data-turbo-method=#{method}" if method %>>
@@ -7,10 +7,10 @@
7
7
  #
8
8
  # ==== Examples
9
9
  # Basic version
10
- # <%= render "headmin/dropdown/list", id: 'dropdown-1' %#>
10
+ # <%= render "headmin/dropdown/list", id: "dropdown-1" %#>
11
11
 
12
- class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : ''
13
- id = local_assigns.has_key?(:id) ? id : 'dropdown-1'
12
+ class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : ""
13
+ id = local_assigns.has_key?(:id) ? id : "dropdown-1"
14
14
  %>
15
15
 
16
16
  <ul class="dropdown-menu <%= class_names %>" aria-labelledby="<%= id %>">
@@ -5,13 +5,13 @@
5
5
  %>
6
6
 
7
7
  <%= render "headmin/dropdown" do %>
8
- <%= render "headmin/dropdown/button", id: 'locale-dropdown' do %>
9
- <%= bootstrap_icon('globe', class: 'me-2') %>
10
- <%= t('language_name', locale: ::I18n.locale) %>
8
+ <%= render "headmin/dropdown/button", id: "locale-dropdown" do %>
9
+ <%= bootstrap_icon("globe", class: "me-2") %>
10
+ <%= t("language_name", locale: ::I18n.locale) %>
11
11
  <% end %>
12
- <%= render "headmin/dropdown/list", id: 'locale-dropdown' do %>
12
+ <%= render "headmin/dropdown/list", id: "locale-dropdown" do %>
13
13
  <% I18n.available_locales.each do |locale| %>
14
- <%= render "headmin/dropdown/item", name: t('language_name', locale: locale), url: url_for({locale: locale.to_s}) %>
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 %>
@@ -19,11 +19,11 @@
19
19
  >
20
20
  <%= raw("#{button_view.label} #{button_view.filter&.string(display_values: button_view.display_values)}") %>
21
21
  <span class="h-filter-remove" data-action="click->filters#remove">
22
- <%= bootstrap_icon('x-lg') %>
22
+ <%= bootstrap_icon("x-lg") %>
23
23
  </span>
24
24
  </button>
25
25
 
26
- <%= render "headmin/popup", id: "#{button_view.id}", data: {'filter-target': 'popup'} do %>
26
+ <%= render "headmin/popup", id: "#{button_view.id}", data: {"filter-target": "popup"} do %>
27
27
  <%= yield %>
28
28
  <% end %>
29
29
  </div>
@@ -1,8 +1,8 @@
1
1
  <select class="form-select" data-filter-row-target="null" data-action="change->filter#updateHiddenValue" data-filter-target="value">
2
2
  <option value="1" <%= value == 1 ? "selected" : "" %>>
3
- <%= t('headmin.filters.values.yes') %>
3
+ <%= t("headmin.filters.values.yes") %>
4
4
  </option>
5
5
  <option value="0" <%= value == 0 ? "selected" : "" %>>
6
- <%= t('headmin.filters.values.no') %>
6
+ <%= t("headmin.filters.values.no") %>
7
7
  </option>
8
8
  </select>
@@ -0,0 +1,32 @@
1
+ <%
2
+ # headmin/forms/color
3
+ #
4
+ # ==== Required parameters
5
+ # * +attribute+ - Name of the attribute of the form model
6
+ # * +form+ - Form object
7
+ #
8
+ # ==== Optional parameters
9
+ # * +hint+ - Informative text to assist with data input. HTML markup is allowed.
10
+ # * +label+ - Text to display inside label tag. Defaults to the attribute name. Set to false if you don"t want to show a label.
11
+ # * +wrapper+ - Hash with all options for the surrounding html tag
12
+ #
13
+ # ==== References
14
+ # https://headmin.dev/docs/forms/color
15
+ # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/color
16
+ # https://apidock.com/rails/v5.2.3/ActionView/Helpers/FormHelper/color_field
17
+ #
18
+ # ==== Examples
19
+ # Basic version
20
+ # <%= form_with do |form| %#>
21
+ # <%= render "headmin/forms/color", form: form, attribute: :active %#>
22
+ # <% end %#>
23
+
24
+ color = Headmin::Form::ColorView.new(local_assigns)
25
+ %>
26
+
27
+ <%= render "headmin/forms/wrapper", color.wrapper_options do %>
28
+ <%= render "headmin/forms/label", color.label_options if color.label? %>
29
+ <%= form.color_field(color.attribute, color.input_options) %>
30
+ <%= render "headmin/forms/validation", color.validation_options if color.validate? %>
31
+ <%= render "headmin/forms/hint", color.hint_options if color.hint? %>
32
+ <% end %>
@@ -8,7 +8,7 @@
8
8
  <% if form.object.errors.any? %>
9
9
  <div class="alert alert-danger" role="alert">
10
10
  <h5 class="alert-heading d-flex align-items-center">
11
- <%= t('errors.template.header', count: form.object.errors.size, model: form.object.model_name.human) %>
11
+ <%= t("errors.template.header", count: form.object.errors.size, model: form.object.model_name.human) %>
12
12
  </h5>
13
13
  <ul class="mb-0">
14
14
  <% form.object.errors.full_messages.each do |message| %>