headmin 0.3.3 → 0.4.1
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/.github/workflows/ci.yml +27 -0
- data/.gitignore +14 -0
- data/.nvmrc +1 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +7 -4
- data/Gemfile.lock +171 -3
- data/README.md +9 -1
- data/Rakefile +1 -7
- data/app/assets/javascripts/headmin/config/i18n.js +9 -9
- data/app/assets/javascripts/headmin/controllers/autocomplete_controller.js +318 -0
- data/app/assets/javascripts/headmin/controllers/blocks_controller.js +74 -79
- data/app/assets/javascripts/headmin/controllers/date_range_controller.js +24 -24
- data/app/assets/javascripts/headmin/controllers/dropzone_controller.js +23 -25
- data/app/assets/javascripts/headmin/controllers/file_preview_controller.js +237 -237
- data/app/assets/javascripts/headmin/controllers/filter_controller.js +44 -44
- data/app/assets/javascripts/headmin/controllers/filters_controller.js +57 -61
- data/app/assets/javascripts/headmin/controllers/flatpickr_controller.js +29 -29
- data/app/assets/javascripts/headmin/controllers/hello_controller.js +3 -3
- data/app/assets/javascripts/headmin/controllers/notification_controller.js +7 -6
- data/app/assets/javascripts/headmin/controllers/popup_controller.js +57 -51
- data/app/assets/javascripts/headmin/controllers/redactorx_controller.js +36 -9
- data/app/assets/javascripts/headmin/controllers/repeater_controller.js +122 -125
- data/app/assets/javascripts/headmin/controllers/select_controller.js +40 -39
- data/app/assets/javascripts/headmin/controllers/table_actions_controller.js +88 -77
- data/app/assets/javascripts/headmin/controllers/table_controller.js +115 -116
- data/app/assets/javascripts/headmin/index.js +38 -35
- data/app/assets/javascripts/headmin.js +309 -42
- data/app/assets/stylesheets/headmin/forms/autocomplete.scss +21 -0
- data/app/assets/stylesheets/headmin/forms/file.scss +46 -0
- data/app/assets/stylesheets/headmin/forms/repeater.scss +62 -0
- data/app/assets/stylesheets/headmin/forms/search.scss +12 -0
- data/app/assets/stylesheets/headmin/forms.scss +11 -0
- data/app/assets/stylesheets/headmin/general.scss +14 -0
- data/app/assets/stylesheets/headmin/overrides/bootstrap.scss +5 -3
- data/app/assets/stylesheets/headmin/overrides/redactorx.scss +74 -0
- data/app/assets/stylesheets/headmin/popup.scss +1 -0
- data/app/assets/stylesheets/headmin/syntax.scss +36 -349
- data/app/assets/stylesheets/headmin/table.scss +1 -1
- data/app/assets/stylesheets/headmin/utilities/buttons.scss +19 -0
- data/app/assets/stylesheets/headmin/utilities/dropzone.scss +72 -0
- data/app/assets/stylesheets/headmin/utilities.scss +2 -68
- data/app/assets/stylesheets/headmin.css +209 -205
- data/app/assets/stylesheets/headmin.scss +1 -1
- data/app/helpers/headmin/admin_helper.rb +0 -1
- data/app/helpers/headmin/form_helper.rb +2 -8
- data/app/models/concerns/headmin/blockable.rb +1 -1
- data/app/models/concerns/headmin/field.rb +1 -0
- data/app/models/concerns/headmin/form/autocompletable.rb +38 -0
- data/app/models/concerns/headmin/form/hintable.rb +19 -0
- data/app/models/concerns/headmin/form/input_groupable.rb +23 -0
- data/app/models/concerns/headmin/form/labelable.rb +33 -0
- data/app/models/concerns/headmin/form/listable.rb +28 -0
- data/app/models/concerns/headmin/form/placeholderable.rb +13 -0
- data/app/models/concerns/headmin/form/validatable.rb +40 -0
- data/app/models/concerns/headmin/form/wrappable.rb +21 -0
- data/app/models/headmin/.DS_Store +0 -0
- data/app/models/headmin/blocks_view.rb +15 -0
- data/app/models/headmin/form/blocks_view.rb +29 -0
- data/app/models/headmin/form/checkbox_view.rb +52 -0
- data/app/models/headmin/form/date_range_view.rb +25 -0
- data/app/models/headmin/form/date_view.rb +45 -0
- data/app/models/headmin/form/email_view.rb +48 -0
- data/app/models/headmin/form/file_view.rb +116 -0
- data/app/models/headmin/form/flatpickr_range_view.rb +102 -0
- data/app/models/headmin/form/flatpickr_view.rb +37 -0
- data/app/models/headmin/form/hidden_view.rb +10 -0
- data/app/models/headmin/form/hint_view.rb +6 -0
- data/app/models/headmin/form/input_group_view.rb +19 -0
- data/app/models/headmin/form/label_view.rb +24 -0
- data/app/models/headmin/form/number_view.rb +49 -0
- data/app/models/headmin/form/password_view.rb +44 -0
- data/app/models/headmin/form/redactorx_view.rb +59 -0
- data/app/models/headmin/form/search_view.rb +48 -0
- data/app/models/headmin/form/select_view.rb +62 -0
- data/app/models/headmin/form/switch_view.rb +23 -0
- data/app/models/headmin/form/text_view.rb +48 -0
- data/app/models/headmin/form/textarea_view.rb +44 -0
- data/app/models/headmin/form/url_view.rb +48 -0
- data/app/models/headmin/form/wrapper_view.rb +19 -0
- data/app/models/headmin/form/wysiwyg_view.rb +17 -0
- data/app/models/headmin/{thumbnail.rb → thumbnail_view.rb} +6 -1
- data/app/models/view_model.rb +58 -0
- data/app/views/headmin/_blocks.html.erb +13 -9
- data/app/views/headmin/_heading.html.erb +7 -1
- data/app/views/headmin/_thumbnail.html.erb +1 -37
- data/app/views/headmin/forms/_autocomplete.html.erb +11 -0
- data/app/views/headmin/forms/_blocks.html.erb +16 -17
- data/app/views/headmin/forms/_checkbox.html.erb +24 -29
- data/app/views/headmin/forms/_datalist.html.erb +3 -0
- data/app/views/headmin/forms/_date.html.erb +24 -24
- data/app/views/headmin/forms/_date_range.html.erb +19 -21
- data/app/views/headmin/forms/_email.html.erb +27 -32
- data/app/views/headmin/forms/_errors.html.erb +2 -3
- data/app/views/headmin/forms/_file.html.erb +84 -181
- data/app/views/headmin/forms/_flatpickr.html.erb +19 -20
- data/app/views/headmin/forms/_flatpickr_range.html.erb +28 -37
- data/app/views/headmin/forms/_hidden.html.erb +9 -10
- data/app/views/headmin/forms/_hint.html.erb +16 -0
- data/app/views/headmin/forms/_input_group.html.erb +21 -0
- data/app/views/headmin/forms/_label.html.erb +5 -13
- data/app/views/headmin/forms/_number.html.erb +23 -35
- data/app/views/headmin/forms/_password.html.erb +21 -30
- data/app/views/headmin/forms/_redactorx.html.erb +21 -40
- data/app/views/headmin/forms/_repeater.html.erb +55 -60
- data/app/views/headmin/forms/_search.html.erb +43 -0
- data/app/views/headmin/forms/_select.html.erb +24 -49
- data/app/views/headmin/forms/_switch.html.erb +29 -0
- data/app/views/headmin/forms/_text.html.erb +42 -96
- data/app/views/headmin/forms/_textarea.html.erb +21 -32
- data/app/views/headmin/forms/_url.html.erb +26 -31
- data/app/views/headmin/forms/_validation.html.erb +10 -13
- data/app/views/headmin/forms/_wrapper.html.erb +9 -0
- data/app/views/headmin/forms/_wysiwyg.html.erb +28 -0
- data/app/views/headmin/forms/autocomplete/_item.html.erb +3 -0
- data/app/views/headmin/forms/autocomplete/_list.html.erb +3 -0
- data/app/views/headmin/forms/fields/_group.html.erb +9 -2
- data/app/views/headmin/forms/repeater/_row.html.erb +4 -4
- data/app/views/headmin/table/_actions.html.erb +1 -1
- data/app/views/headmin/table/actions/_action.html.erb +2 -1
- data/app/views/headmin/table/actions/_delete.html.erb +1 -1
- data/bin/console +0 -1
- data/config/locales/headmin/forms/en.yml +1 -12
- data/config/locales/headmin/forms/nl.yml +1 -12
- data/esbuild-css.js +18 -18
- data/esbuild-js.js +8 -8
- data/headmin.gemspec +1 -3
- data/lib/generators/templates/controllers/auth/confirmations_controller.rb +0 -2
- data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +0 -2
- data/lib/generators/templates/controllers/auth/passwords_controller.rb +0 -2
- data/lib/generators/templates/controllers/auth/registrations_controller.rb +0 -2
- data/lib/generators/templates/controllers/auth/sessions_controller.rb +0 -2
- data/lib/generators/templates/controllers/auth/unlocks_controller.rb +0 -2
- data/lib/headmin/version.rb +1 -3
- data/lib/headmin.rb +0 -2
- data/package-lock.json +5359 -0
- data/package.json +13 -6
- data/view_model_benchmark.rb +74 -0
- data/yarn-error.log +367 -0
- data/yarn.lock +1575 -31
- metadata +63 -24
- data/app/assets/stylesheets/headmin/form.scss +0 -132
- data/app/assets/stylesheets/headmin/overrides/redactorx.css +0 -3
- data/app/helpers/headmin/documentation_helper.rb +0 -35
- data/app/models/headmin/documentation_renderer.rb +0 -32
- data/app/models/headmin/form/base.rb +0 -78
- data/app/models/headmin/form/text.rb +0 -51
- data/app/services/block_service.rb +0 -72
- data/app/views/headmin/_card.html.erb +0 -52
- data/app/views/headmin/forms/_actions.html.erb +0 -28
- data/app/views/headmin/forms/_base.html.erb +0 -114
- data/app/views/headmin/forms/_image.html.erb +0 -21
- data/app/views/headmin/forms/_video.html.erb +0 -21
- data/app/views/headmin/forms/actions/_destroy.html.erb +0 -13
- data/app/views/headmin/forms/actions/_save.html.erb +0 -12
- data/app/views/headmin/forms/actions/_view.html.erb +0 -15
- data/docs/blocks-and-fields.md +0 -54
- data/docs/blocks.md +0 -48
- data/docs/devise.md +0 -41
- data/docs/fields.md +0 -79
@@ -0,0 +1,44 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class PasswordView < ViewModel
|
4
|
+
include Headmin::Form::Hintable
|
5
|
+
include Headmin::Form::InputGroupable
|
6
|
+
include Headmin::Form::Labelable
|
7
|
+
include Headmin::Form::Placeholderable
|
8
|
+
include Headmin::Form::Validatable
|
9
|
+
include Headmin::Form::Wrappable
|
10
|
+
|
11
|
+
def input_options
|
12
|
+
keys = attributes - %i[append attribute float form input_group label prepend validate wrapper]
|
13
|
+
options = to_h.slice(*keys)
|
14
|
+
default_input_options.deep_merge(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def input_group_options
|
18
|
+
default_input_group_options
|
19
|
+
.deep_merge(label_input_group_options)
|
20
|
+
.deep_merge(@input_group || {})
|
21
|
+
end
|
22
|
+
|
23
|
+
def wrapper_options
|
24
|
+
default_wrapper_options.deep_merge({
|
25
|
+
class: ["mb-3", ("form-floating" if float)]
|
26
|
+
}).deep_merge(@wrapper || {})
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def default_input_options
|
32
|
+
{
|
33
|
+
aria: {describedby: validation_id},
|
34
|
+
class: [form_control_class, validation_class],
|
35
|
+
placeholder: placeholder
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def form_control_class
|
40
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class RedactorxView < ViewModel
|
4
|
+
def options
|
5
|
+
default_options.deep_merge(to_h)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def default_options
|
11
|
+
{
|
12
|
+
data: {
|
13
|
+
controller: "redactorx",
|
14
|
+
"redactor-options": redactor_options
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def control
|
20
|
+
@control || (hybrid ? true : nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
def context
|
24
|
+
@context || (hybrid ? true : nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def toolbar
|
28
|
+
@toolbar || (hybrid ? false : nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def addbar
|
32
|
+
@addbar || %w[paragraph image embed table quote pre line]
|
33
|
+
end
|
34
|
+
|
35
|
+
def plugins
|
36
|
+
@plugins || %w[shortcut]
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :topbar
|
40
|
+
|
41
|
+
def redactor_options
|
42
|
+
default_redactor_options.deep_merge(redactor || {})
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_redactor_options
|
46
|
+
{
|
47
|
+
control: control,
|
48
|
+
context: context,
|
49
|
+
toolbar: toolbar,
|
50
|
+
buttons: {
|
51
|
+
addbar: addbar,
|
52
|
+
plugins: plugins,
|
53
|
+
topbar: topbar
|
54
|
+
}
|
55
|
+
}.delete_if { |k, v| v.nil? }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class SearchView < ViewModel
|
4
|
+
include Headmin::Form::Autocompletable
|
5
|
+
include Headmin::Form::Hintable
|
6
|
+
include Headmin::Form::InputGroupable
|
7
|
+
include Headmin::Form::Labelable
|
8
|
+
include Headmin::Form::Listable
|
9
|
+
include Headmin::Form::Placeholderable
|
10
|
+
include Headmin::Form::Validatable
|
11
|
+
include Headmin::Form::Wrappable
|
12
|
+
|
13
|
+
def input_options
|
14
|
+
keys = attributes - %i[append attribute collection float form input_group label prepend validate wrapper]
|
15
|
+
options = to_h.slice(*keys)
|
16
|
+
options = default_input_options.deep_merge(options)
|
17
|
+
options.deep_merge(autocomplete_input_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def input_group_options
|
21
|
+
default_input_group_options
|
22
|
+
.deep_merge(autocomplete_input_group_options)
|
23
|
+
.deep_merge(label_input_group_options)
|
24
|
+
.deep_merge(@input_group || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrapper_options
|
28
|
+
default_wrapper_options.deep_merge({
|
29
|
+
class: ["mb-3", ("form-floating" if float)]
|
30
|
+
}).deep_merge(@wrapper || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def default_input_options
|
36
|
+
{
|
37
|
+
aria: {describedby: validation_id},
|
38
|
+
class: [form_control_class, validation_class],
|
39
|
+
placeholder: placeholder
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def form_control_class
|
44
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class SelectView < ViewModel
|
4
|
+
include Headmin::Form::Hintable
|
5
|
+
include Headmin::Form::InputGroupable
|
6
|
+
include Headmin::Form::Labelable
|
7
|
+
include Headmin::Form::Listable
|
8
|
+
include Headmin::Form::Placeholderable
|
9
|
+
include Headmin::Form::Validatable
|
10
|
+
include Headmin::Form::Wrappable
|
11
|
+
|
12
|
+
def input_options
|
13
|
+
keys = attributes - %i[append attribute collection float form input_group include_blank label prepend validate selected tags wrapper]
|
14
|
+
options = to_h.slice(*keys)
|
15
|
+
default_input_options.deep_merge(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def input_group_options
|
19
|
+
default_input_group_options
|
20
|
+
.deep_merge(label_input_group_options)
|
21
|
+
.deep_merge(@input_group || {})
|
22
|
+
end
|
23
|
+
|
24
|
+
def wrapper_options
|
25
|
+
default_wrapper_options.deep_merge({
|
26
|
+
class: ["mb-3", ("form-floating" if float)]
|
27
|
+
}).deep_merge(@wrapper || {})
|
28
|
+
end
|
29
|
+
|
30
|
+
def select_options
|
31
|
+
keys = %i[include_blank selected]
|
32
|
+
options = to_h.slice(*keys)
|
33
|
+
default_options.deep_merge(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def default_options
|
39
|
+
{
|
40
|
+
selected: form.object&.send(attribute)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_input_options
|
45
|
+
{
|
46
|
+
aria: {describedby: validation_id},
|
47
|
+
class: [form_control_class, validation_class],
|
48
|
+
data: {
|
49
|
+
tags: tags,
|
50
|
+
controller: "select"
|
51
|
+
},
|
52
|
+
multiple: tags,
|
53
|
+
placeholder: placeholder
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def form_control_class
|
58
|
+
plaintext ? "form-control-plaintext" : "form-select"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class SwitchView < ViewModel
|
4
|
+
def options
|
5
|
+
default_options.deep_merge(to_h)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def default_options
|
11
|
+
{
|
12
|
+
wrapper: default_wrapper_options
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_wrapper_options
|
17
|
+
{
|
18
|
+
class: %w[form-check form-switch mb-3]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class TextView < ViewModel
|
4
|
+
include Headmin::Form::Autocompletable
|
5
|
+
include Headmin::Form::Hintable
|
6
|
+
include Headmin::Form::InputGroupable
|
7
|
+
include Headmin::Form::Labelable
|
8
|
+
include Headmin::Form::Listable
|
9
|
+
include Headmin::Form::Placeholderable
|
10
|
+
include Headmin::Form::Validatable
|
11
|
+
include Headmin::Form::Wrappable
|
12
|
+
|
13
|
+
def input_options
|
14
|
+
keys = attributes - %i[append attribute collection float form input_group label prepend validate wrapper]
|
15
|
+
options = to_h.slice(*keys)
|
16
|
+
options = default_input_options.deep_merge(options)
|
17
|
+
options.deep_merge(autocomplete_input_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def input_group_options
|
21
|
+
default_input_group_options
|
22
|
+
.deep_merge(autocomplete_input_group_options)
|
23
|
+
.deep_merge(label_input_group_options)
|
24
|
+
.deep_merge(@input_group || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrapper_options
|
28
|
+
default_wrapper_options.deep_merge({
|
29
|
+
class: ["mb-3", ("form-floating" if float)]
|
30
|
+
}).deep_merge(@wrapper || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def default_input_options
|
36
|
+
{
|
37
|
+
aria: {describedby: validation_id},
|
38
|
+
class: [form_control_class, validation_class],
|
39
|
+
placeholder: placeholder
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def form_control_class
|
44
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class TextareaView < ViewModel
|
4
|
+
include Headmin::Form::Hintable
|
5
|
+
include Headmin::Form::InputGroupable
|
6
|
+
include Headmin::Form::Labelable
|
7
|
+
include Headmin::Form::Placeholderable
|
8
|
+
include Headmin::Form::Validatable
|
9
|
+
include Headmin::Form::Wrappable
|
10
|
+
|
11
|
+
def input_options
|
12
|
+
keys = attributes - %i[attribute float form input_group label validate wrapper]
|
13
|
+
options = to_h.slice(*keys)
|
14
|
+
default_input_options.deep_merge(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def input_group_options
|
18
|
+
default_input_group_options
|
19
|
+
.deep_merge(label_input_group_options)
|
20
|
+
.deep_merge(@input_group || {})
|
21
|
+
end
|
22
|
+
|
23
|
+
def wrapper_options
|
24
|
+
default_wrapper_options.deep_merge({
|
25
|
+
class: ["mb-3", ("form-floating" if float)]
|
26
|
+
}).deep_merge(@wrapper || {})
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def default_input_options
|
32
|
+
{
|
33
|
+
aria: {describedby: validation_id},
|
34
|
+
class: [form_control_class, validation_class],
|
35
|
+
placeholder: placeholder
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def form_control_class
|
40
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class UrlView < ViewModel
|
4
|
+
include Headmin::Form::Autocompletable
|
5
|
+
include Headmin::Form::Hintable
|
6
|
+
include Headmin::Form::InputGroupable
|
7
|
+
include Headmin::Form::Labelable
|
8
|
+
include Headmin::Form::Listable
|
9
|
+
include Headmin::Form::Placeholderable
|
10
|
+
include Headmin::Form::Validatable
|
11
|
+
include Headmin::Form::Wrappable
|
12
|
+
|
13
|
+
def input_options
|
14
|
+
keys = attributes - %i[append attribute collection float form input_group label prepend validate wrapper]
|
15
|
+
options = to_h.slice(*keys)
|
16
|
+
options = default_input_options.deep_merge(options)
|
17
|
+
options.deep_merge(autocomplete_input_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def input_group_options
|
21
|
+
default_input_group_options
|
22
|
+
.deep_merge(autocomplete_input_group_options)
|
23
|
+
.deep_merge(label_input_group_options)
|
24
|
+
.deep_merge(@input_group || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrapper_options
|
28
|
+
default_wrapper_options.deep_merge({
|
29
|
+
class: ["mb-3", ("form-floating" if float)]
|
30
|
+
}).deep_merge(@wrapper || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def default_input_options
|
36
|
+
{
|
37
|
+
aria: {describedby: validation_id},
|
38
|
+
class: [form_control_class, validation_class],
|
39
|
+
placeholder: placeholder
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def form_control_class
|
44
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Headmin
|
2
|
+
module Form
|
3
|
+
class WrapperView < ViewModel
|
4
|
+
def options
|
5
|
+
keys = attributes - %i[bypass]
|
6
|
+
options = to_h.slice(*keys)
|
7
|
+
default_options.deep_merge(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_options
|
13
|
+
{
|
14
|
+
class: ["mb-3"]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Headmin
|
2
|
-
class
|
2
|
+
class ThumbnailView
|
3
3
|
def initialize(local_assigns)
|
4
4
|
@local_assigns = local_assigns
|
5
5
|
end
|
@@ -22,6 +22,10 @@ module Headmin
|
|
22
22
|
@local_assigns[:src]
|
23
23
|
end
|
24
24
|
|
25
|
+
def icon
|
26
|
+
@local_assigns[:icon]
|
27
|
+
end
|
28
|
+
|
25
29
|
def mime_type
|
26
30
|
if src
|
27
31
|
stripped_path = URI.parse(src).path
|
@@ -36,6 +40,7 @@ module Headmin
|
|
36
40
|
|
37
41
|
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
|
38
42
|
def icon_name
|
43
|
+
return icon if icon
|
39
44
|
type_map = {
|
40
45
|
image: %w[image/bmp image/gif image/vnd.microsoft.icon image/jpeg image/png image/svg+xml image/tiff image/webp],
|
41
46
|
play: %w[video/mp4 video/mpeg video/ogg video/mp2t video/webm video/3gpp video/3gpp2],
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ViewModel
|
4
|
+
# = View Model
|
5
|
+
#
|
6
|
+
# A View Model is a class that allows you to set an arbitrary hash of attributes and access all values by calling
|
7
|
+
# attribute methods.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# model = ViewModel.new(a: 1, b: {b1: 1, b2: 2}, c: 3)
|
12
|
+
#
|
13
|
+
# model.a # => 1
|
14
|
+
# model.b # => {b1: 1, b2: 2}
|
15
|
+
# model.c # => 3
|
16
|
+
#
|
17
|
+
# Reserved methods or attributes are left untouched. If you want to access an attribute that collides with a reserved
|
18
|
+
# method, you can do it via the +to_hash+ method.
|
19
|
+
#
|
20
|
+
# model = ViewModel.new(class: "test")
|
21
|
+
#
|
22
|
+
# model.class # => ViewModel
|
23
|
+
# model.to_hash[:class] # => "test"
|
24
|
+
|
25
|
+
def initialize(hash = {})
|
26
|
+
hash.each do |key, value|
|
27
|
+
instance_variable_set("@#{key}", value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def attributes
|
32
|
+
instance_variables.map { |instance_variable| instance_variable.to_s.delete("@").to_sym }
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_hash
|
36
|
+
attributes.map { |attribute| {attribute => value_for(attribute)} }.inject(:merge)
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_method :to_h, :to_hash
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def value_for(attribute)
|
44
|
+
reserved_methods.include?(attribute) ? instance_variable_get("@#{attribute}") : send(attribute)
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(m, *args, &block)
|
48
|
+
instance_variable_get("@#{m}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def respond_to_missing?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def reserved_methods
|
56
|
+
Class.methods + Class.private_methods
|
57
|
+
end
|
58
|
+
end
|
@@ -1,24 +1,28 @@
|
|
1
1
|
<%
|
2
2
|
# headmin/blocks
|
3
3
|
#
|
4
|
-
# ====
|
4
|
+
# ==== Required parameters
|
5
5
|
# * +blockable</tt> - Object with blocks association
|
6
|
-
#
|
6
|
+
#
|
7
|
+
# ==== Optional parameters
|
8
|
+
# * +paths</tt> - Directories where to look for block templates
|
7
9
|
#
|
8
10
|
# ==== Examples
|
9
|
-
# Basic version.
|
11
|
+
# Basic version. (looks in views/website/blocks, views/blocks or views directory )
|
10
12
|
# <%= render "headmin/blocks", blockable: @page %#>
|
11
13
|
#
|
12
|
-
# Define
|
13
|
-
# <%= render "headmin/blocks", blockable: @page,
|
14
|
+
# Define one ore more path where the templates could be located:
|
15
|
+
# <%= render "headmin/blocks", blockable: @page, paths: %w(website/pages/blocks) %#>
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
blocks = Headmin::BlocksView.new(local_assigns)
|
18
|
+
@lookup_context.prefixes = @lookup_context.prefixes + blocks.prefixes
|
17
19
|
%>
|
18
20
|
|
19
21
|
<% if blockable && blockable.respond_to?(:blocks) %>
|
20
22
|
<% blockable.blocks.order(:position).each do |block| %>
|
21
|
-
|
22
|
-
<%=
|
23
|
+
|
24
|
+
<!-- <%= block.name %> -->
|
25
|
+
<%= render block.name, block: block %>
|
26
|
+
|
23
27
|
<% end %>
|
24
28
|
<% end %>
|
@@ -1,10 +1,16 @@
|
|
1
1
|
<%
|
2
2
|
# headmin/heading
|
3
3
|
#
|
4
|
+
# Accepts a block
|
5
|
+
#
|
6
|
+
# ==== References
|
7
|
+
# https://headmin.dev/docs/heading
|
8
|
+
# https://headmin.dev/preview/heading
|
9
|
+
#
|
4
10
|
# ==== Examples
|
5
11
|
# Basic version
|
6
12
|
# <%= render "headmin/heading" do %#>
|
7
|
-
#
|
13
|
+
# Title
|
8
14
|
# <% end %#>
|
9
15
|
%>
|
10
16
|
|
@@ -1,40 +1,4 @@
|
|
1
|
-
|
2
|
-
<% documentation do %>
|
3
|
-
# Thumbnail
|
4
|
-
Render thumbnails for files. Whenever possible (e.g. images) previews are generated. Icons are used instead for other file types.
|
5
|
-
|
6
|
-
```erbx
|
7
|
-
<%= render 'headmin/thumbnail', src: image_path("image.jpg") %>
|
8
|
-
```
|
9
|
-
|
10
|
-
## Parameters
|
11
|
-
| Name | Required | Type | Description |
|
12
|
-
| ------------ | -------- | ---------------- | ----------- |
|
13
|
-
| src | yes | String | Source of the file. Can be a local or external URL |
|
14
|
-
| width | no | Integer | Width of the thumbnail in px |
|
15
|
-
| height | no | Integer | Height of the thumbnail in px |
|
16
|
-
|
17
|
-
## Examples
|
18
|
-
|
19
|
-
### Sizing
|
20
|
-
```erbx
|
21
|
-
<%= render 'headmin/thumbnail', src: image_path("image.jpg"), width: 300, height: 100 %>
|
22
|
-
```
|
23
|
-
|
24
|
-
### Types
|
25
|
-
```erbx
|
26
|
-
<%= render 'headmin/thumbnail', src: asset_path("document.pdf"), width: 100, height: 100 %>
|
27
|
-
<%= render 'headmin/thumbnail', src: asset_path("document.docx"), width: 100, height: 100 %>
|
28
|
-
<%= render 'headmin/thumbnail', src: asset_path("spreadsheet.xls"), width: 100, height: 100 %>
|
29
|
-
<%= render 'headmin/thumbnail', src: asset_path("video.mp4"), width: 100, height: 100 %>
|
30
|
-
```
|
31
|
-
|
32
|
-
## References
|
33
|
-
- [Bootstrap](https://getbootstrap.com/docs/5.1/content/images/#image-thumbnails)
|
34
|
-
<% end %>
|
35
|
-
-->
|
36
|
-
|
37
|
-
<% thumbnail = Headmin::Thumbnail.new(local_assigns) %>
|
1
|
+
<% thumbnail = Headmin::ThumbnailView.new(local_assigns) %>
|
38
2
|
|
39
3
|
<div class="<%= thumbnail.class_names %>" style="width: <%= thumbnail.width %>px; height: <%= thumbnail.height %>px;">
|
40
4
|
<% if thumbnail.image? %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class="h-autocomplete d-none" data-autocomplete-target="dropdown">
|
2
|
+
<% if collection.any? %>
|
3
|
+
<%= render "headmin/forms/autocomplete/list" do %>
|
4
|
+
<% collection.each do |value, name| %>
|
5
|
+
<%= render "headmin/forms/autocomplete/item", value: value do %>
|
6
|
+
<%= name %>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
@@ -1,39 +1,38 @@
|
|
1
1
|
<%
|
2
2
|
# headmin/forms/blocks
|
3
3
|
#
|
4
|
-
# ====
|
4
|
+
# ==== Required parameters
|
5
5
|
# * +form</tt> - Form object
|
6
|
-
# * +
|
7
|
-
#
|
6
|
+
# * +names</tt> - Names of block templates that can be added
|
7
|
+
#
|
8
|
+
# ==== Optional parameters
|
9
|
+
# * +paths</tt> - Directories where to look for block templates
|
8
10
|
#
|
9
11
|
# ==== Examples
|
10
|
-
# Basic version.
|
11
|
-
# <%= render "headmin/forms/blocks", form: form %#>
|
12
|
+
# Basic version. (looks in views/admin/blocks, views/blocks or views directory )
|
13
|
+
# <%= render "headmin/forms/blocks", form: form, names: %w(text image button) %#>
|
12
14
|
#
|
13
|
-
# Define
|
14
|
-
# <%= render "headmin/forms/blocks", form: form,
|
15
|
+
# Define one ore more path where the templates could be located:
|
16
|
+
# <%= render "headmin/forms/blocks", form: form, names: %w(text image button), paths: %w(admin/pages/blocks) %#>
|
15
17
|
#
|
16
18
|
# Limit the types of blocks
|
17
|
-
# <%= render "headmin/forms/blocks", form: form,
|
18
|
-
|
19
|
-
path = local_assigns.has_key?(:path) ? path : nil
|
20
|
-
allowed_block_names = local_assigns.has_key?(:allow) ? allow.map(&:to_s) : BlockService.block_names(path: path)
|
19
|
+
# <%= render "headmin/forms/blocks", form: form, names: %w(text text_image list) %#>
|
21
20
|
|
22
|
-
|
21
|
+
blocks = Headmin::Form::BlocksView.new(local_assigns)
|
22
|
+
@lookup_context.prefixes = @lookup_context.prefixes + blocks.prefixes
|
23
23
|
%>
|
24
24
|
|
25
|
-
<%= render 'headmin/forms/repeater',
|
26
|
-
<% name = template
|
25
|
+
<%= render 'headmin/forms/repeater', blocks.repeater_options do |block_form, template| %>
|
26
|
+
<% name = template || block_form.object.name %>
|
27
27
|
|
28
28
|
<!-- Name input of the block -->
|
29
29
|
<%= block_form.hidden_field :name, value: name %>
|
30
30
|
|
31
31
|
<!-- Render block form fields -->
|
32
|
-
|
33
|
-
<%= render view_path, form: block_form %>
|
32
|
+
<%= render name, form: block_form %>
|
34
33
|
|
35
34
|
<!-- Label -->
|
36
35
|
<span class="position-absolute top-0 end-0 badge bg-light text-dark">
|
37
|
-
<%= name.
|
36
|
+
<%= t("blocks.#{name}", default: name).humanize %>
|
38
37
|
</span>
|
39
38
|
<% end %>
|