headmin 0.2.3 → 0.2.7
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/.nvmrc +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +10 -7
- data/app/helpers/headmin/admin_helper.rb +3 -59
- data/app/helpers/headmin/bootstrap_helper.rb +9 -0
- data/app/helpers/headmin/filter_helper.rb +7 -3
- data/app/helpers/headmin/form_helper.rb +36 -0
- data/app/helpers/headmin/request_helper.rb +39 -0
- data/app/models/concerns/headmin/fieldable.rb +53 -23
- data/app/services/block_service.rb +8 -4
- data/app/views/headmin/_blocks.html.erb +1 -1
- data/app/views/headmin/_filters.html.erb +1 -1
- data/app/views/headmin/_pagination.html.erb +4 -1
- data/app/views/headmin/dropdown/_devise.html.erb +20 -10
- data/app/views/headmin/dropdown/_list.html.erb +17 -7
- data/app/views/headmin/filters/_select.html.erb +3 -2
- data/app/views/headmin/filters/filter/_button.html.erb +0 -1
- data/app/views/headmin/forms/_blocks.html.erb +11 -4
- data/app/views/headmin/forms/_date.html.erb +1 -1
- data/app/views/headmin/forms/_label.html.erb +2 -2
- data/app/views/headmin/forms/_repeater.html.erb +6 -10
- data/app/views/headmin/table/_actions.html.erb +37 -11
- data/app/views/headmin/views/devise/confirmations/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/passwords/_edit.html.erb +2 -2
- data/app/views/headmin/views/devise/passwords/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/registrations/_edit.html.erb +4 -4
- data/app/views/headmin/views/devise/registrations/_new.html.erb +3 -3
- data/app/views/headmin/views/devise/shared/_links.html.erb +7 -7
- data/app/views/headmin/views/devise/unlocks/_new.html.erb +1 -1
- data/config/locales/activerecord/en.yml +9 -0
- data/config/locales/activerecord/nl.yml +9 -0
- data/config/locales/headmin/table/en.yml +5 -1
- data/config/locales/headmin/table/nl.yml +5 -1
- data/config/locales/headmin/views/en.yml +1 -1
- data/config/locales/headmin/views/nl.yml +14 -14
- data/dist/css/headmin.css +54 -13
- data/dist/js/headmin.js +45 -513
- data/docs/blocks-and-fields.md +54 -0
- data/docs/blocks.md +1 -54
- data/docs/devise.md +40 -2
- data/docs/fields.md +31 -9
- data/headmin.gemspec +1 -1
- data/lib/generators/headmin/blocks_generator.rb +4 -1
- data/lib/generators/headmin/devise_generator.rb +16 -0
- data/lib/generators/headmin/fields_generator.rb +5 -1
- data/lib/generators/templates/controllers/auth/confirmations_controller.rb +31 -0
- data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +31 -0
- data/lib/generators/templates/controllers/auth/passwords_controller.rb +35 -0
- data/lib/generators/templates/controllers/auth/registrations_controller.rb +63 -0
- data/lib/generators/templates/controllers/auth/sessions_controller.rb +28 -0
- data/lib/generators/templates/controllers/auth/unlocks_controller.rb +31 -0
- data/lib/generators/templates/migrations/create_field_hierarchies.rb +16 -0
- data/lib/generators/templates/views/auth/confirmations/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/confirmation_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/email_changed.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/password_change.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/reset_password_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/unlock_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/passwords/edit.html.erb +1 -0
- data/lib/generators/templates/views/auth/passwords/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/registrations/edit.html.erb +1 -0
- data/lib/generators/templates/views/auth/registrations/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/sessions/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/unlocks/new.html.erb +1 -0
- data/lib/generators/templates/views/layouts/auth.html.erb +20 -0
- data/lib/headmin/version.rb +1 -1
- data/package.json +4 -3
- data/src/js/headmin/controllers/blocks_controller.js +1 -1
- data/src/js/headmin/controllers/filter_controller.js +1 -1
- data/src/js/headmin/controllers/filters_controller.js +1 -1
- data/src/js/headmin/controllers/popup_controller.js +1 -1
- data/src/js/headmin/controllers/repeater_controller.js +9 -10
- data/src/js/headmin/controllers/table_actions_controller.js +104 -9
- data/src/js/headmin/controllers/table_controller.js +28 -57
- data/src/js/headmin/headmin.js +2 -2
- data/src/scss/headmin/table.scss +1 -0
- data/yarn.lock +1159 -1237
- metadata +33 -7
- data/docs/README.md +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75079b879cee8f51cc97f715f1714d29554519f30ad046aa5c391ae663fb5ea0
|
4
|
+
data.tar.gz: b7e38afe69ddfb236653170172d8bfa74ddb972071cfb6644d460a89a0581b48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 052d363086709d82b0f526dec7a9a80fb05845d3da62b8aee65f35d3b5e5c7e6a4431c3a9f079491d12eca8387fabf06338cc6a14c950728db910605409195dd
|
7
|
+
data.tar.gz: b83c34883e5ca7719e14a1282412b836e8bbf706071283c07d2ec6dcd0a2317737c43044f5e0fe138d406fd14b930b6d72a1b9cac11d9ed6237477d3b4220083
|
data/.nvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
lts
|
1
|
+
lts/gallium
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
headmin (0.2.
|
5
|
-
closure_tree
|
4
|
+
headmin (0.2.6)
|
5
|
+
closure_tree
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -23,7 +23,7 @@ GEM
|
|
23
23
|
activerecord (>= 4.2.10)
|
24
24
|
with_advisory_lock (>= 4.0.0)
|
25
25
|
concurrent-ruby (1.1.9)
|
26
|
-
i18n (1.8.
|
26
|
+
i18n (1.8.11)
|
27
27
|
concurrent-ruby (~> 1.0)
|
28
28
|
minitest (5.14.4)
|
29
29
|
parallel (1.20.1)
|
data/README.md
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# Headmin
|
2
2
|
A complete library of commonly used components to build an admin interface in your Ruby on Rails project.
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
- [Rubygems](https://rubygems.org/gems/headmin)
|
7
|
-
- [NPM](https://www.npmjs.com/package/headmin)
|
4
|
+
[](https://rubygems.org/gems/headmin)
|
5
|
+
[](https://www.npmjs.com/package/headmin)
|
8
6
|
|
9
7
|
## Installation
|
10
8
|
|
@@ -47,6 +45,12 @@ Finally import Headmin in your stylesheet.
|
|
47
45
|
@import '~headmin/src/scss/headmin.scss';
|
48
46
|
```
|
49
47
|
|
48
|
+
### Integrations
|
49
|
+
- [Blocks](docs/blocks.md)
|
50
|
+
- [Fields](docs/fields.md)
|
51
|
+
- [Blocks + Fields = Magic](docs/blocks-and-fields.md)
|
52
|
+
- [Devise](docs/devise.md)
|
53
|
+
|
50
54
|
## Development
|
51
55
|
For development purposes it's helpful to have both the test project and Headmin located in the same directory.
|
52
56
|
|
@@ -59,7 +63,7 @@ In package.json
|
|
59
63
|
```json
|
60
64
|
{
|
61
65
|
"dependencies": {
|
62
|
-
"bar": "
|
66
|
+
"bar": "file:../headmin"
|
63
67
|
}
|
64
68
|
}
|
65
69
|
```
|
@@ -99,8 +103,7 @@ $ bundle
|
|
99
103
|
$ git push
|
100
104
|
|
101
105
|
# Update the version number and tag the release
|
102
|
-
$ gem bump -v {patch,minor,major,...}
|
103
|
-
$ gem tag -p
|
106
|
+
$ gem bump -v {patch,minor,major,...} --push --tag
|
104
107
|
|
105
108
|
# Release to Rubygems
|
106
109
|
$ gem release
|
@@ -1,65 +1,9 @@
|
|
1
1
|
module Headmin
|
2
2
|
module AdminHelper
|
3
|
+
include Headmin::BootstrapHelper
|
3
4
|
include Headmin::FilterHelper
|
5
|
+
include Headmin::FormHelper
|
4
6
|
include Headmin::NotificationHelper
|
5
|
-
|
6
|
-
def current_model
|
7
|
-
controller_name.classify.constantize
|
8
|
-
end
|
9
|
-
|
10
|
-
def bootstrap_icon(icon, options = {})
|
11
|
-
data = options.has_key?(:data) ? options[:data] : nil
|
12
|
-
klass = options.has_key?(:class) ? options[:class] : nil
|
13
|
-
content_tag(:i, class: "bi bi-#{icon} #{klass}", data: data) {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def current_url?(url)
|
17
|
-
uri = URI(url)
|
18
|
-
path = uri.path
|
19
|
-
query_string = uri.query
|
20
|
-
matches_path = request.path.include?(path)
|
21
|
-
matches_query = uri.query ? request.query_string.include?(query_string) : true
|
22
|
-
is_root = request.fullpath == url
|
23
|
-
if url == admin_root_path
|
24
|
-
is_root
|
25
|
-
else
|
26
|
-
matches_path && matches_query
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def form_field_valid?(form, name)
|
31
|
-
!form.object.errors.has_key?(name)
|
32
|
-
end
|
33
|
-
|
34
|
-
def form_field_validation_id(form, name)
|
35
|
-
[form.object_name, name.to_s, 'validation'].join('_').parameterize.underscore
|
36
|
-
end
|
37
|
-
|
38
|
-
def form_field_validation_class(form, name)
|
39
|
-
return nil if request.get?
|
40
|
-
form.object.errors.has_key?(name) ? 'is-invalid' : 'is-valid'
|
41
|
-
end
|
42
|
-
|
43
|
-
def default_params
|
44
|
-
params.select { |key, value| is_default_param?(key) }
|
45
|
-
end
|
46
|
-
|
47
|
-
def add_default_param_key(key)
|
48
|
-
keys = default_param_keys || []
|
49
|
-
keys.push(key)
|
50
|
-
@default_param_keys = keys
|
51
|
-
end
|
52
|
-
|
53
|
-
def default_param_keys
|
54
|
-
@default_param_keys ||= [:page, :start, :length, :per_page]
|
55
|
-
end
|
56
|
-
|
57
|
-
def is_default_param?(key)
|
58
|
-
default_param_keys.include?(key.to_sym) || is_sort_param_key?(key)
|
59
|
-
end
|
60
|
-
|
61
|
-
def is_sort_param_key?(key)
|
62
|
-
key.to_s.include?('sort_')
|
63
|
-
end
|
7
|
+
include Headmin::RequestHelper
|
64
8
|
end
|
65
9
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Headmin
|
2
|
+
module BootstrapHelper
|
3
|
+
def bootstrap_icon(icon, options = {})
|
4
|
+
data = options.has_key?(:data) ? options[:data] : nil
|
5
|
+
klass = options.has_key?(:class) ? options[:class] : nil
|
6
|
+
content_tag(:i, class: "bi bi-#{icon} #{klass}", data: data) {}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
module Headmin
|
2
2
|
module FilterHelper
|
3
3
|
def filter_param_exists?(name)
|
4
|
-
|
4
|
+
filter_param(name).present?
|
5
|
+
end
|
6
|
+
|
7
|
+
def filter_param(name)
|
8
|
+
return nil unless params.has_key?(name)
|
5
9
|
if params[name].is_a?(Array)
|
6
|
-
params[name].reject { |c| c.empty? }
|
10
|
+
params[name].reject { |c| c.empty? }
|
7
11
|
else
|
8
|
-
params[name]
|
12
|
+
params[name]
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Headmin
|
2
|
+
module FormHelper
|
3
|
+
def form_field_valid?(form, name)
|
4
|
+
!form.object.errors.has_key?(name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def form_field_validation_id(form, name)
|
8
|
+
[form.object_name, name.to_s, 'validation'].join('_').parameterize.underscore
|
9
|
+
end
|
10
|
+
|
11
|
+
def form_field_validation_class(form, name)
|
12
|
+
return nil if request.get?
|
13
|
+
form.object.errors.has_key?(name) ? 'is-invalid' : 'is-valid'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Outputs currently present query parameters as hidden fields for a given form
|
17
|
+
#
|
18
|
+
# https://example.com/products?amount=1&type[]=food&type[]=beverage
|
19
|
+
#
|
20
|
+
# <%= form.hidden_input :amount, value: 1 %>
|
21
|
+
# <%= form.hidden_input :'type[]', value: 'food' %>
|
22
|
+
# <%= form.hidden_input :'type[]', value: 'beverage' %>
|
23
|
+
def query_parameter_fields(form)
|
24
|
+
test = request.query_parameters.map do |name, value|
|
25
|
+
if value.is_a?(Array)
|
26
|
+
value.map do |value_element|
|
27
|
+
form.hidden_field "#{name}[]", value: value_element
|
28
|
+
end.join
|
29
|
+
else
|
30
|
+
form.hidden_field name, value: value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
test.join.html_safe
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Headmin
|
2
|
+
module RequestHelper
|
3
|
+
def current_url?(url)
|
4
|
+
uri = URI(url)
|
5
|
+
path = uri.path
|
6
|
+
query_string = uri.query
|
7
|
+
matches_path = request.path.include?(path)
|
8
|
+
matches_query = uri.query ? request.query_string.include?(query_string) : true
|
9
|
+
is_root = request.fullpath == url
|
10
|
+
if url == admin_root_path
|
11
|
+
is_root
|
12
|
+
else
|
13
|
+
matches_path && matches_query
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_params
|
18
|
+
params.select { |key, value| is_default_param?(key) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_default_param_key(key)
|
22
|
+
keys = default_param_keys || []
|
23
|
+
keys.push(key)
|
24
|
+
@default_param_keys = keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_param_keys
|
28
|
+
@default_param_keys ||= [:page, :start, :length, :per_page]
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_default_param?(key)
|
32
|
+
default_param_keys.include?(key.to_sym) || is_sort_param_key?(key)
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_sort_param_key?(key)
|
36
|
+
key.to_s.include?('sort_')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -7,37 +7,67 @@ module Headmin
|
|
7
7
|
accepts_nested_attributes_for :fields, allow_destroy: true
|
8
8
|
|
9
9
|
def fields_hash
|
10
|
-
|
10
|
+
fields.order(position: :asc).map do |field|
|
11
|
+
parse_hash_tree(field.hash_tree)
|
12
|
+
end.reduce({}, :merge)
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields_hash=(hash)
|
16
|
+
parse_fields_hash(hash)
|
11
17
|
end
|
12
18
|
|
13
19
|
private
|
14
20
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
def parse_fields_hash(hash)
|
22
|
+
hash.map do |key, value|
|
23
|
+
case value
|
24
|
+
when Hash
|
25
|
+
fields.build(
|
26
|
+
name: key,
|
27
|
+
field_type: 'group',
|
28
|
+
fields: parse_fields_hash(value)
|
29
|
+
)
|
30
|
+
when Array
|
31
|
+
fields.build(
|
32
|
+
name: key,
|
33
|
+
field_type: 'list',
|
34
|
+
fields: value.map do |item|
|
35
|
+
fields.new(name: 'item', field_type: 'group', fields: parse_fields_hash(item))
|
30
36
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
)
|
38
|
+
when String
|
39
|
+
fields.build(
|
40
|
+
name: key,
|
41
|
+
field_type: 'text',
|
42
|
+
value: value
|
43
|
+
)
|
44
|
+
else
|
45
|
+
fields.build(
|
46
|
+
name: key,
|
47
|
+
field_type: 'file',
|
48
|
+
file: value
|
49
|
+
)
|
50
|
+
end
|
35
51
|
end
|
36
52
|
end
|
37
53
|
|
38
|
-
|
39
|
-
|
40
|
-
|
54
|
+
def parse_hash_tree(hash_tree)
|
55
|
+
Hash[hash_tree.map do |field, children|
|
56
|
+
case field.field_type.to_sym
|
57
|
+
when :group
|
58
|
+
children = children.any? ? children : field.hash_tree
|
59
|
+
[field.name, parse_hash_tree(children)]
|
60
|
+
when :list
|
61
|
+
children = children.any? ? children : field.hash_tree
|
62
|
+
[field.name, children.map { |child, grand_children| parse_hash_tree(grand_children) }]
|
63
|
+
when :image
|
64
|
+
[field.name, field.file]
|
65
|
+
when :file
|
66
|
+
[field.name, field.file]
|
67
|
+
else
|
68
|
+
[field.name, field.value]
|
69
|
+
end
|
70
|
+
end]
|
41
71
|
end
|
42
72
|
end
|
43
73
|
end
|
@@ -1,10 +1,7 @@
|
|
1
1
|
class BlockService
|
2
2
|
def self.block_names(path:)
|
3
3
|
form_views(path: path).map do |view|
|
4
|
-
|
5
|
-
|
6
|
-
# Removes leading _ if exists
|
7
|
-
filename.sub!(/^_/, '')
|
4
|
+
view_name(view)
|
8
5
|
end
|
9
6
|
end
|
10
7
|
|
@@ -24,6 +21,13 @@ class BlockService
|
|
24
21
|
views(form_view_paths(path))
|
25
22
|
end
|
26
23
|
|
24
|
+
def self.view_name(view)
|
25
|
+
filename = File.basename(view, '.html.erb')
|
26
|
+
|
27
|
+
# Removes leading _ if exists
|
28
|
+
filename.sub(/^_/, '')
|
29
|
+
end
|
30
|
+
|
27
31
|
private
|
28
32
|
|
29
33
|
# Looks for a block view by its name.
|
@@ -18,7 +18,7 @@
|
|
18
18
|
|
19
19
|
<% if blockable && blockable.respond_to?(:blocks) %>
|
20
20
|
<% blockable.blocks.order(:position).each do |block| %>
|
21
|
-
<% view_path = BlockService.frontend_view(block.name, path: path).gsub('/_', '/') %>
|
21
|
+
<% view_path = BlockService.frontend_view(block.name, path: path).gsub('/_', '/').split('.').first %>
|
22
22
|
<%= render view_path, block: block %>
|
23
23
|
<% end %>
|
24
24
|
<% end %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
# With custom URL
|
12
12
|
# <%= render "headmin/filters", url: admin_polls_path %#>
|
13
13
|
|
14
|
-
action = local_assigns.has_key?(:url) ? url : request.
|
14
|
+
action = local_assigns.has_key?(:url) ? url : request.path
|
15
15
|
%>
|
16
16
|
|
17
17
|
<form action="<%= action %>" data-controller="filters" data-filters-target="form">
|
@@ -10,8 +10,11 @@
|
|
10
10
|
%>
|
11
11
|
|
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
|
+
<% content_for :collection_total_count do %>
|
14
|
+
<%= collection.total_count %>
|
15
|
+
<% end %>
|
13
16
|
<div class="ms-2 me-md-2 text-secondary">
|
14
|
-
<%= t('.items', count:
|
17
|
+
<%= t('.items', count: content_for(:collection_total_count)) %>
|
15
18
|
</div>
|
16
19
|
<%= paginate collection, views_prefix: 'headmin/pagination' %>
|
17
20
|
</div>
|
@@ -1,19 +1,29 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<%
|
2
|
+
# headmin/dropdown/devise
|
3
|
+
#
|
4
|
+
# ==== Options
|
5
|
+
# * <tt>scope</tt> - (symbol) devise scope, i.e. ':users' => current_user
|
6
|
+
# * <tt>class</tt> - Custom class names to put on the dropdown
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
# Basic version
|
10
|
+
# <%= render "headmin/dropdown/devise" %#>
|
11
|
+
#
|
12
|
+
# Custom scope
|
13
|
+
# <%= render "headmin/dropdown/devise", scope: :admins %#>
|
14
|
+
|
15
|
+
class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : ''
|
16
|
+
scope = local_assigns.has_key?(:scope) ? scope : :users
|
17
|
+
singular = scope.to_s.singularize.to_sym
|
18
|
+
user = send("current_#{singular}")
|
6
19
|
%>
|
7
20
|
|
8
|
-
<% scope = local_assigns.has_key?(:scope) ? scope : :users %>
|
9
|
-
<% singular = scope.to_s.singularize.to_sym %>
|
10
|
-
<% user = send("current_#{singular}") %>
|
11
21
|
|
12
|
-
<%= render 'headmin/dropdown' do %>
|
22
|
+
<%= render 'headmin/dropdown', class: class_names do %>
|
13
23
|
<%= render 'headmin/dropdown/button' do %>
|
14
24
|
<%= user.to_s %>
|
15
25
|
<% end %>
|
16
|
-
<%= render 'headmin/dropdown/list' do %>
|
26
|
+
<%= render 'headmin/dropdown/list', class: 'dropdown-menu-end' do %>
|
17
27
|
<%= render 'headmin/dropdown/item', name: t('.edit_profile'), url: polymorphic_path([:edit, singular, :registration]) %>
|
18
28
|
<%= render 'headmin/dropdown/divider' %>
|
19
29
|
<%= render 'headmin/dropdown/item', name: t('.log_out'), url: polymorphic_path([:destroy, singular, :session]), method: :delete %>
|
@@ -1,11 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<%
|
2
|
+
# headmin/dropdown/list
|
3
|
+
#
|
4
|
+
# ==== Options
|
5
|
+
# * <tt>id</tt> - unique identifier for the dropdown
|
6
|
+
# * <tt>class</tt> - Custom class names to put on the dropdown menu
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
# Basic version
|
10
|
+
# <%= render "headmin/dropdown/devise" %#>
|
11
|
+
#
|
12
|
+
# Custom scope
|
13
|
+
# <%= render "headmin/dropdown/devise", scope: :admins %#>
|
14
|
+
|
15
|
+
class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : ''
|
16
|
+
id = local_assigns.has_key?(:id) ? id : 'dropdown-1'
|
6
17
|
%>
|
7
|
-
<% id = local_assigns.has_key?(:id) ? id : 'dropdown-1' %>
|
8
18
|
|
9
|
-
<ul class="dropdown-menu" aria-labelledby="<%= id %>">
|
19
|
+
<ul class="dropdown-menu <%= class_names %>" aria-labelledby="<%= id %>">
|
10
20
|
<%= yield %>
|
11
21
|
</ul>
|
@@ -36,8 +36,9 @@
|
|
36
36
|
|
37
37
|
<%= content_for :filters_buttons do %>
|
38
38
|
<% (params[name] || []).each_with_index do |param, index| %>
|
39
|
-
<%
|
40
|
-
|
39
|
+
<% selected_option = options.detect { |value, key, config| (key.present? ? key : value) == param } %>
|
40
|
+
<% selected_value = selected_option.is_a?(Array) ? selected_option.first : selected_option %>
|
41
|
+
<%= render 'headmin/filters/filter/button', name: name, label: label, value: selected_value, id: "#{name}_#{index}" do %>
|
41
42
|
<%= select_tag("#{name}[]", options_for_select(options, param), select_options) %>
|
42
43
|
<% end %>
|
43
44
|
<% end %>
|
@@ -22,11 +22,18 @@
|
|
22
22
|
templates = allowed_block_names.map { |name| BlockService.form_view(name, path: path) }
|
23
23
|
%>
|
24
24
|
|
25
|
-
<%= render 'headmin/forms/repeater', form: form, attribute: :blocks, templates: templates, label: false do |
|
26
|
-
<%
|
27
|
-
<%= render view_path, form: block, name: block.object.name %>
|
25
|
+
<%= render 'headmin/forms/repeater', form: form, attribute: :blocks, templates: templates, label: false do |block_form, template| %>
|
26
|
+
<% name = template ? BlockService.view_name(template) : block_form.object.name %>
|
28
27
|
|
28
|
+
<!-- Name input of the block -->
|
29
|
+
<%= block_form.hidden_field :name, value: name %>
|
30
|
+
|
31
|
+
<!-- Render block form fields -->
|
32
|
+
<% view_path = BlockService.form_view(name, path: path).gsub('/_', '/') %>
|
33
|
+
<%= render view_path, form: block_form %>
|
34
|
+
|
35
|
+
<!-- Label -->
|
29
36
|
<span class="position-absolute top-0 end-0 badge bg-light text-dark">
|
30
|
-
<%=
|
37
|
+
<%= name.titleize %>
|
31
38
|
</span>
|
32
39
|
<% end %>
|
@@ -27,7 +27,7 @@
|
|
27
27
|
required = local_assigns.has_key?(:required) ? required : false
|
28
28
|
datepicker = local_assigns.has_key?(:datepicker) ? local_assigns[:datepicker] : false
|
29
29
|
|
30
|
-
class_names = "#{class_names}
|
30
|
+
class_names = "#{class_names} flatpickr" if datepicker
|
31
31
|
|
32
32
|
options = {
|
33
33
|
'aria-describedby': form_field_validation_id(form, attribute),
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# <%= render 'headmin/forms/label', form: form, attribute: :image %#>
|
13
13
|
|
14
14
|
class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : false
|
15
|
-
|
15
|
+
custom_name = local_assigns.has_key?(:name) && name ? name.to_s.humanize : nil
|
16
16
|
required = local_assigns.has_key?(:required) ? required : false
|
17
17
|
|
18
18
|
options = {
|
@@ -21,4 +21,4 @@
|
|
21
21
|
}
|
22
22
|
%>
|
23
23
|
|
24
|
-
<%= form.label
|
24
|
+
<%= form.label attribute, custom_name, options %>
|
@@ -39,14 +39,14 @@
|
|
39
39
|
|
40
40
|
template_names = templates.map { |template| File.basename(template, '.html.erb') }
|
41
41
|
template_names = template_names.any? ? template_names : ['new']
|
42
|
-
multiple_templates = template_names.count > 1
|
43
42
|
object_model = form.object.class
|
44
43
|
association_model = object_model.reflect_on_association(attribute).class_name.constantize
|
45
|
-
|
44
|
+
association_object = association_model.new
|
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
|
49
|
-
pass_thru =
|
49
|
+
pass_thru = template_names.count == 1 ? "[data-template-name=\"#{template_names.first}\"]" : nil
|
50
50
|
show_label = label != false
|
51
51
|
%>
|
52
52
|
|
@@ -115,15 +115,11 @@
|
|
115
115
|
|
116
116
|
<!-- Templates -->
|
117
117
|
<% template_names.each do |name| %>
|
118
|
-
<template data-repeater-target="template" data-template-name="<%= name %>">
|
119
|
-
<%= form.fields_for attribute,
|
118
|
+
<template data-repeater-target="template" data-template-name="<%= name %>" data-template-id-regex="<%= association_object.object_id %>">
|
119
|
+
<%= form.fields_for attribute, association_object, child_index: association_object.object_id do |ff| %>
|
120
120
|
<%= render 'headmin/forms/repeater/row', form: ff, pass_thru: pass_thru, repeater_id: repeater_id do %>
|
121
121
|
<% template = templates.detect { |t| t.include?("/#{name}.") } %>
|
122
|
-
<%
|
123
|
-
<%= render(template.gsub('/_', '/'), form: ff) %>
|
124
|
-
<% else %>
|
125
|
-
<% yield(ff) %>
|
126
|
-
<% end %>
|
122
|
+
<% yield(ff, template&.gsub('/_', '/')) %>
|
127
123
|
<% end %>
|
128
124
|
<% end %>
|
129
125
|
</template>
|
@@ -1,19 +1,45 @@
|
|
1
|
+
<%
|
2
|
+
# headmin/table/actions
|
3
|
+
#
|
4
|
+
# The form action url is dynamically set when switching between actions.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
# Basic version
|
8
|
+
# <%= render 'headmin/table/actions' do %#>
|
9
|
+
# <%= render 'headmin/table/actions/delete', url: destroy_admin_pages_path %#>
|
10
|
+
# <% end %#>
|
11
|
+
|
12
|
+
selection_count = content_for(:collection_total_count).to_i || 0
|
13
|
+
%>
|
14
|
+
|
1
15
|
<% content_for :table_actions do %>
|
2
|
-
<th class="h-table-actions d-none" data-controller="table-actions" data-table-target="actions">
|
3
|
-
|
4
|
-
<%=
|
5
|
-
<%=
|
16
|
+
<th class="h-table-actions d-none" data-controller="table-actions" data-table-actions-target="wrapper" data-table-target="actions">
|
17
|
+
<%= form_with url: '', data: { 'table-actions-target': 'form' } do |form| %>
|
18
|
+
<%= form.hidden_field :authenticity_token, value: form_authenticity_token %>
|
19
|
+
<%= form.hidden_field :_method, value: 'POST', 'data-table-actions-target': 'method' %>
|
20
|
+
<%= query_parameter_fields(form) %>
|
6
21
|
|
7
|
-
<template data-table-target="
|
8
|
-
<%=
|
22
|
+
<template data-table-actions-target="idInputTemplate">
|
23
|
+
<%= form.hidden_field :ids, value: 'ID', multiple: true, 'data-table-actions-target': 'id' %>
|
9
24
|
</template>
|
10
25
|
|
11
26
|
<div class="row g-1">
|
12
27
|
<div class="col-6 col-sm-auto">
|
13
|
-
<
|
14
|
-
<
|
15
|
-
|
16
|
-
|
28
|
+
<div class="d-flex align-items-center gap-3">
|
29
|
+
<label class="text-nowrap"
|
30
|
+
data-table-actions-target="counter"
|
31
|
+
data-total-count="<%= selection_count %>"
|
32
|
+
data-items-zero="<%= t('.items_html', count: 0) %>"
|
33
|
+
data-items-one="<%= t('.items_html', count: 1) %>"
|
34
|
+
data-items-other="<%= t('.items_html', count: 2) %>"
|
35
|
+
>
|
36
|
+
<%= t('.items_html', count: selection_count) %>
|
37
|
+
</label>
|
38
|
+
<select class="form-select me-1" data-table-actions-target="select" data-action="change->table-actions#update">
|
39
|
+
<option disabled selected="selected"><%= t('.selection') %></option>
|
40
|
+
<%= yield if block_given? %>
|
41
|
+
</select>
|
42
|
+
</div>
|
17
43
|
</div>
|
18
44
|
<div class="col-6 col-sm-auto">
|
19
45
|
<button class="btn h-btn-outline-light w-100" type="submit" data-table-actions-target="button" disabled>
|
@@ -21,6 +47,6 @@
|
|
21
47
|
</button>
|
22
48
|
</div>
|
23
49
|
</div>
|
24
|
-
|
50
|
+
<% end %>
|
25
51
|
</th>
|
26
52
|
<% end %>
|