formstrap 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +33 -0
- data/CHANGELOG.md +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +118 -0
- data/Rakefile +10 -0
- data/app/assets/config/headmin_manifest.js +2 -0
- data/app/assets/images/avatar.jpg +0 -0
- data/app/assets/images/document.docx +0 -0
- data/app/assets/images/document.pdf +0 -0
- data/app/assets/images/image.jpg +0 -0
- data/app/assets/images/spreadsheet.xls +0 -0
- data/app/assets/images/video.mp4 +0 -0
- data/app/assets/javascripts/formstrap/config/i18n.js +11 -0
- data/app/assets/javascripts/formstrap/controllers/autocomplete_controller.js +318 -0
- data/app/assets/javascripts/formstrap/controllers/date_range_controller.js +38 -0
- data/app/assets/javascripts/formstrap/controllers/dropzone_controller.js +31 -0
- data/app/assets/javascripts/formstrap/controllers/file_preview_controller.js +244 -0
- data/app/assets/javascripts/formstrap/controllers/flatpickr_controller.js +35 -0
- data/app/assets/javascripts/formstrap/controllers/infinite_scroller_controller.js +28 -0
- data/app/assets/javascripts/formstrap/controllers/media_controller.js +252 -0
- data/app/assets/javascripts/formstrap/controllers/media_modal_controller.js +147 -0
- data/app/assets/javascripts/formstrap/controllers/redactorx_controller.js +40 -0
- data/app/assets/javascripts/formstrap/controllers/repeater_controller.js +148 -0
- data/app/assets/javascripts/formstrap/controllers/select_controller.js +49 -0
- data/app/assets/javascripts/formstrap/controllers/textarea_controller.js +48 -0
- data/app/assets/javascripts/formstrap/index.js +32 -0
- data/app/assets/javascripts/formstrap.js +11515 -0
- data/app/assets/stylesheets/formstrap/forms/autocomplete.scss +27 -0
- data/app/assets/stylesheets/formstrap/forms/file.scss +83 -0
- data/app/assets/stylesheets/formstrap/forms/media.scss +10 -0
- data/app/assets/stylesheets/formstrap/forms/repeater.scss +62 -0
- data/app/assets/stylesheets/formstrap/forms/search.scss +12 -0
- data/app/assets/stylesheets/formstrap/forms.scss +12 -0
- data/app/assets/stylesheets/formstrap/general.scss +18 -0
- data/app/assets/stylesheets/formstrap/media/index.scss +9 -0
- data/app/assets/stylesheets/formstrap/media.scss +1 -0
- data/app/assets/stylesheets/formstrap/utilities/buttons.scss +27 -0
- data/app/assets/stylesheets/formstrap/utilities/dropzone.scss +72 -0
- data/app/assets/stylesheets/formstrap/utilities.scss +2 -0
- data/app/assets/stylesheets/formstrap/vendor/flatpickr.css +903 -0
- data/app/assets/stylesheets/formstrap/vendor/tom-select-bootstrap.scss +535 -0
- data/app/assets/stylesheets/formstrap.css +1559 -0
- data/app/assets/stylesheets/formstrap.scss +11 -0
- data/app/controllers/concerns/formstrap/pagination.rb +27 -0
- data/app/controllers/formstrap/media_controller.rb +68 -0
- data/app/controllers/formstrap_controller.rb +2 -0
- data/app/models/concerns/formstrap/autocompletable.rb +36 -0
- data/app/models/concerns/formstrap/hintable.rb +22 -0
- data/app/models/concerns/formstrap/input_groupable.rb +21 -0
- data/app/models/concerns/formstrap/labelable.rb +31 -0
- data/app/models/concerns/formstrap/listable.rb +26 -0
- data/app/models/concerns/formstrap/placeholderable.rb +11 -0
- data/app/models/concerns/formstrap/validatable.rb +38 -0
- data/app/models/concerns/formstrap/wrappable.rb +19 -0
- data/app/models/formstrap/.DS_Store +0 -0
- data/app/models/formstrap/association_view.rb +100 -0
- data/app/models/formstrap/blocks_view.rb +43 -0
- data/app/models/formstrap/checkbox_view.rb +50 -0
- data/app/models/formstrap/color_view.rb +45 -0
- data/app/models/formstrap/date_range_view.rb +23 -0
- data/app/models/formstrap/date_view.rb +43 -0
- data/app/models/formstrap/datetime_range_view.rb +23 -0
- data/app/models/formstrap/datetime_view.rb +43 -0
- data/app/models/formstrap/email_view.rb +46 -0
- data/app/models/formstrap/file_view.rb +106 -0
- data/app/models/formstrap/flatpickr_range_view.rb +89 -0
- data/app/models/formstrap/flatpickr_view.rb +27 -0
- data/app/models/formstrap/hidden_view.rb +8 -0
- data/app/models/formstrap/hint_view.rb +4 -0
- data/app/models/formstrap/input_group_view.rb +17 -0
- data/app/models/formstrap/label_view.rb +22 -0
- data/app/models/formstrap/media_item_view.rb +41 -0
- data/app/models/formstrap/media_view.rb +143 -0
- data/app/models/formstrap/number_view.rb +47 -0
- data/app/models/formstrap/password_view.rb +42 -0
- data/app/models/formstrap/redactorx_view.rb +57 -0
- data/app/models/formstrap/search_view.rb +46 -0
- data/app/models/formstrap/select_view.rb +61 -0
- data/app/models/formstrap/switch_view.rb +21 -0
- data/app/models/formstrap/text_view.rb +46 -0
- data/app/models/formstrap/textarea_view.rb +47 -0
- data/app/models/formstrap/url_view.rb +46 -0
- data/app/models/formstrap/wrapper_view.rb +17 -0
- data/app/models/formstrap/wysiwyg_view.rb +15 -0
- data/app/models/view_model.rb +62 -0
- data/app/views/formstrap/_association.html.erb +30 -0
- data/app/views/formstrap/_autocomplete.html.erb +11 -0
- data/app/views/formstrap/_blocks.html.erb +45 -0
- data/app/views/formstrap/_checkbox.html.erb +34 -0
- data/app/views/formstrap/_color.html.erb +32 -0
- data/app/views/formstrap/_datalist.html.erb +3 -0
- data/app/views/formstrap/_date.html.erb +41 -0
- data/app/views/formstrap/_date_range.html.erb +40 -0
- data/app/views/formstrap/_datetime.html.erb +41 -0
- data/app/views/formstrap/_datetime_range.html.erb +40 -0
- data/app/views/formstrap/_email.html.erb +43 -0
- data/app/views/formstrap/_errors.html.erb +19 -0
- data/app/views/formstrap/_file.html.erb +94 -0
- data/app/views/formstrap/_flatpickr.html.erb +33 -0
- data/app/views/formstrap/_flatpickr_range.html.erb +40 -0
- data/app/views/formstrap/_hidden.html.erb +23 -0
- data/app/views/formstrap/_hint.html.erb +21 -0
- data/app/views/formstrap/_input_group.html.erb +21 -0
- data/app/views/formstrap/_label.html.erb +22 -0
- data/app/views/formstrap/_media.html.erb +60 -0
- data/app/views/formstrap/_number.html.erb +41 -0
- data/app/views/formstrap/_password.html.erb +39 -0
- data/app/views/formstrap/_redactorx.html.erb +31 -0
- data/app/views/formstrap/_repeater.html.erb +128 -0
- data/app/views/formstrap/_search.html.erb +43 -0
- data/app/views/formstrap/_select.html.erb +43 -0
- data/app/views/formstrap/_switch.html.erb +29 -0
- data/app/views/formstrap/_text.html.erb +42 -0
- data/app/views/formstrap/_textarea.html.erb +39 -0
- data/app/views/formstrap/_to_ary.html.erb +0 -0
- data/app/views/formstrap/_url.html.erb +43 -0
- data/app/views/formstrap/_validation.html.erb +18 -0
- data/app/views/formstrap/_wrapper.html.erb +8 -0
- data/app/views/formstrap/_wysiwyg.html.erb +28 -0
- data/app/views/formstrap/autocomplete/_item.html.erb +3 -0
- data/app/views/formstrap/autocomplete/_list.html.erb +3 -0
- data/app/views/formstrap/blocks/_modal.html.erb +20 -0
- data/app/views/formstrap/fields/_base.html.erb +25 -0
- data/app/views/formstrap/fields/_file.html.erb +17 -0
- data/app/views/formstrap/fields/_files.html.erb +17 -0
- data/app/views/formstrap/fields/_group.html.erb +52 -0
- data/app/views/formstrap/fields/_list.html.erb +31 -0
- data/app/views/formstrap/fields/_text.html.erb +17 -0
- data/app/views/formstrap/media/_item.html.erb +38 -0
- data/app/views/formstrap/media/_media_item_modal.html.erb +77 -0
- data/app/views/formstrap/media/_modal.html.erb +40 -0
- data/app/views/formstrap/media/_thumbnail.html.erb +20 -0
- data/app/views/formstrap/media/_validation.html.erb +10 -0
- data/app/views/formstrap/media/create.turbo_stream.erb +5 -0
- data/app/views/formstrap/media/index.html.erb +3 -0
- data/app/views/formstrap/media/index.turbo_stream.erb +11 -0
- data/app/views/formstrap/media/show.html.erb +9 -0
- data/app/views/formstrap/media/thumbnail.html.erb +3 -0
- data/app/views/formstrap/media/update.turbo_stream.erb +3 -0
- data/app/views/formstrap/pagination/_infinite.html.erb +7 -0
- data/app/views/formstrap/repeater/_row.html.erb +53 -0
- data/app/views/formstrap/shared/_notifications.html.erb +20 -0
- data/app/views/formstrap/shared/_popup.html.erb +32 -0
- data/app/views/formstrap/shared/_thumbnail.html.erb +35 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/importmap.rb +2 -0
- data/config/locales/activerecord/en.yml +12 -0
- data/config/locales/activerecord/nl.yml +13 -0
- data/config/locales/defaults/en.yml +215 -0
- data/config/locales/defaults/nl.yml +213 -0
- data/config/locales/devise/en.yml +65 -0
- data/config/locales/devise/nl.yml +85 -0
- data/config/locales/en.yml +6 -0
- data/config/locales/formstrap/forms/en.yml +39 -0
- data/config/locales/formstrap/forms/nl.yml +39 -0
- data/config/locales/formstrap/media/en.yml +24 -0
- data/config/locales/formstrap/media/nl.yml +24 -0
- data/config/locales/formstrap/thumbnail/en.yml +4 -0
- data/config/locales/formstrap/thumbnail/nl.yml +4 -0
- data/config/locales/nl.yml +6 -0
- data/config/routes.rb +11 -0
- data/esbuild-css.js +25 -0
- data/esbuild-js.js +11 -0
- data/formstrap.gemspec +37 -0
- data/formstrap.iml +34 -0
- data/lib/formstrap/engine.rb +27 -0
- data/lib/formstrap/form_builder.rb +177 -0
- data/lib/formstrap/form_helper.rb +19 -0
- data/lib/formstrap/version.rb +3 -0
- data/lib/formstrap.rb +6 -0
- data/package.json +54 -0
- data/src/js/formstrap.js +1 -0
- data/src/scss/formstrap.scss +1 -0
- data/yarn.lock +1998 -0
- metadata +224 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class DatetimeView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::InputGroupable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Listable
|
7
|
+
include Formstrap::Placeholderable
|
8
|
+
include Formstrap::Validatable
|
9
|
+
include Formstrap::Wrappable
|
10
|
+
|
11
|
+
def input_options
|
12
|
+
keys = attributes - %i[append attribute float form input_group 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
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class EmailView < ViewModel
|
3
|
+
include Formstrap::Autocompletable
|
4
|
+
include Formstrap::Hintable
|
5
|
+
include Formstrap::InputGroupable
|
6
|
+
include Formstrap::Labelable
|
7
|
+
include Formstrap::Listable
|
8
|
+
include Formstrap::Placeholderable
|
9
|
+
include Formstrap::Validatable
|
10
|
+
include Formstrap::Wrappable
|
11
|
+
|
12
|
+
def input_options
|
13
|
+
keys = attributes - %i[append attribute collection float form input_group label prepend validate wrapper]
|
14
|
+
options = to_h.slice(*keys)
|
15
|
+
options = default_input_options.deep_merge(options)
|
16
|
+
options.deep_merge(autocomplete_input_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def input_group_options
|
20
|
+
default_input_group_options
|
21
|
+
.deep_merge(autocomplete_input_group_options)
|
22
|
+
.deep_merge(label_input_group_options)
|
23
|
+
.deep_merge(@input_group || {})
|
24
|
+
end
|
25
|
+
|
26
|
+
def wrapper_options
|
27
|
+
default_wrapper_options.deep_merge({
|
28
|
+
class: ["mb-3", ("form-floating" if float)]
|
29
|
+
}).deep_merge(@wrapper || {})
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def default_input_options
|
35
|
+
{
|
36
|
+
aria: {describedby: validation_id},
|
37
|
+
class: [form_control_class, validation_class],
|
38
|
+
placeholder: placeholder
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def form_control_class
|
43
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class FileView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::InputGroupable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Placeholderable
|
7
|
+
include Formstrap::Validatable
|
8
|
+
include Formstrap::Wrappable
|
9
|
+
|
10
|
+
def input_options
|
11
|
+
keys = attributes - %i[append attribute dropzone destroy form input_group label prepend preview validate wrapper]
|
12
|
+
options = to_h.slice(*keys)
|
13
|
+
options = default_input_options.deep_merge(options)
|
14
|
+
options = options.deep_merge(required: false) if attachments.any?
|
15
|
+
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 h-form-file", ("form-floating" if float)],
|
27
|
+
data: {
|
28
|
+
controller: ("file-preview" if preview)
|
29
|
+
}
|
30
|
+
}).deep_merge(@wrapper || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
def preview
|
34
|
+
@preview || dropzone
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy
|
38
|
+
@destroy || false
|
39
|
+
end
|
40
|
+
|
41
|
+
def attached
|
42
|
+
form.object&.send(attribute)
|
43
|
+
end
|
44
|
+
|
45
|
+
def attachments
|
46
|
+
attached&.attachments || []
|
47
|
+
end
|
48
|
+
|
49
|
+
def number_of_files
|
50
|
+
multiple ? 2 : 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def nested_attribute
|
54
|
+
attached.is_a?(ActiveStorage::Attached::Many) ? :"#{attribute}_attachments" : :"#{attribute}_attachment"
|
55
|
+
end
|
56
|
+
|
57
|
+
def dropzone_options
|
58
|
+
if dropzone
|
59
|
+
{
|
60
|
+
class: ["h-dropzone", validation_class],
|
61
|
+
data: {
|
62
|
+
controller: "dropzone"
|
63
|
+
}
|
64
|
+
}
|
65
|
+
else
|
66
|
+
{
|
67
|
+
class: validation_class
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# def input_group_options
|
73
|
+
# {
|
74
|
+
# prepend: prepend,
|
75
|
+
# append: append,
|
76
|
+
# class: "h-form-file",
|
77
|
+
# data: {
|
78
|
+
# controller: "#{"file-preview" if preview} #{"dropzone" if dropzone}"
|
79
|
+
# }
|
80
|
+
# }
|
81
|
+
# end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def default_input_options
|
86
|
+
{
|
87
|
+
aria: {describedby: validation_id},
|
88
|
+
class: ["form-control", validation_class],
|
89
|
+
placeholder: placeholder,
|
90
|
+
data: preview_data
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def preview_data
|
95
|
+
if preview
|
96
|
+
{
|
97
|
+
"file-preview-target": "input",
|
98
|
+
"dropzone-target": "input",
|
99
|
+
action: "change->file-preview#preview dropEnd->file-preview#preview"
|
100
|
+
}
|
101
|
+
else
|
102
|
+
{}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class FlatpickrRangeView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::InputGroupable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Listable
|
7
|
+
include Formstrap::Placeholderable
|
8
|
+
include Formstrap::Validatable
|
9
|
+
include Formstrap::Wrappable
|
10
|
+
|
11
|
+
def attribute
|
12
|
+
@attribute || :period
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_attribute
|
16
|
+
@start.dig(:attribute) || :start_date
|
17
|
+
end
|
18
|
+
|
19
|
+
def end_attribute
|
20
|
+
@end.dig(:attribute) || :end_date
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_options
|
24
|
+
default_start_options.deep_merge(@start || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_options
|
28
|
+
default_end_options.deep_merge(@end || {})
|
29
|
+
end
|
30
|
+
|
31
|
+
def input_options
|
32
|
+
keys = attributes - %i[append attribute end float form input_group label prepend start validate wrapper]
|
33
|
+
options = to_h.slice(*keys)
|
34
|
+
default_input_options.deep_merge(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def input_group_options
|
38
|
+
default_input_group_options
|
39
|
+
.deep_merge(label_input_group_options)
|
40
|
+
.deep_merge(@input_group || {})
|
41
|
+
end
|
42
|
+
|
43
|
+
def wrapper_options
|
44
|
+
default_wrapper_options.deep_merge({
|
45
|
+
class: ["mb-3", ("form-floating" if float)]
|
46
|
+
}).deep_merge(@wrapper || {})
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def default_options
|
52
|
+
{
|
53
|
+
name: nil
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_start_options
|
58
|
+
{}
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_end_options
|
62
|
+
{}
|
63
|
+
end
|
64
|
+
|
65
|
+
def default_input_options
|
66
|
+
{
|
67
|
+
aria: {describedby: validation_id},
|
68
|
+
class: [form_control_class, validation_class],
|
69
|
+
placeholder: placeholder,
|
70
|
+
name: nil,
|
71
|
+
data: {
|
72
|
+
controller: "flatpickr date-range",
|
73
|
+
action: "change->date-range#update",
|
74
|
+
flatpickr: {
|
75
|
+
mode: "range",
|
76
|
+
defaultDate: [
|
77
|
+
form.object&.send(start_attribute)&.strftime("%d/%m/%Y"),
|
78
|
+
form.object&.send(end_attribute)&.strftime("%d/%m/%Y")
|
79
|
+
]
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def form_control_class
|
86
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class FlatpickrView < ViewModel
|
3
|
+
def options
|
4
|
+
keys = attributes - %i[data]
|
5
|
+
options = to_h.slice(*keys)
|
6
|
+
default_options.deep_merge(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_options
|
12
|
+
{
|
13
|
+
data: default_data.deep_merge(data || {})
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_data
|
18
|
+
{
|
19
|
+
controller: "flatpickr",
|
20
|
+
|
21
|
+
flatpickr: {
|
22
|
+
defaultDate: attribute.nil? ? Date.today : form.object&.send(attribute)&.strftime("%d/%m/%Y")
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class InputGroupView < ViewModel
|
3
|
+
def options
|
4
|
+
keys = attributes - %i[bypass append prepend]
|
5
|
+
options = to_h.slice(*keys)
|
6
|
+
default_options.deep_merge(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_options
|
12
|
+
{
|
13
|
+
class: ["input-group"]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class LabelView < ViewModel
|
3
|
+
def form
|
4
|
+
@form.object_id
|
5
|
+
end
|
6
|
+
|
7
|
+
def options
|
8
|
+
keys = attributes - %i[attribute form text]
|
9
|
+
options = to_h.slice(*keys)
|
10
|
+
default_options.deep_merge(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def default_options
|
16
|
+
{
|
17
|
+
class: "form-label",
|
18
|
+
required: required
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class MediaItemView < ViewModel
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
|
5
|
+
def thumbnail_options
|
6
|
+
options = {
|
7
|
+
file: attachment
|
8
|
+
}
|
9
|
+
|
10
|
+
# Don't pass width or height if it was not defined
|
11
|
+
options = options.merge(width: width) if is_defined?(:width)
|
12
|
+
options = options.merge(height: height) if is_defined?(:height)
|
13
|
+
|
14
|
+
options
|
15
|
+
end
|
16
|
+
|
17
|
+
def attachment
|
18
|
+
form.object
|
19
|
+
end
|
20
|
+
|
21
|
+
def position_value
|
22
|
+
attachment.new_record? ? nil : attachment.position
|
23
|
+
end
|
24
|
+
|
25
|
+
def id
|
26
|
+
attachment.blob ? attachment.blob.id : "$1"
|
27
|
+
end
|
28
|
+
|
29
|
+
def filename
|
30
|
+
attachment.blob&.filename&.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def content_type
|
34
|
+
attachment.blob&.content_type
|
35
|
+
end
|
36
|
+
|
37
|
+
def size
|
38
|
+
number_to_human_size(attachment.blob&.byte_size || 0)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class MediaView < ViewModel
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
include Formstrap::Hintable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Placeholderable
|
7
|
+
include Formstrap::Validatable
|
8
|
+
include Formstrap::Wrappable
|
9
|
+
|
10
|
+
def input_group_options
|
11
|
+
default_input_group_options
|
12
|
+
.deep_merge(label_input_group_options)
|
13
|
+
.deep_merge(@input_group || {})
|
14
|
+
end
|
15
|
+
|
16
|
+
def wrapper_options
|
17
|
+
default_wrapper_options.deep_merge({
|
18
|
+
class: ["mb-3", ("form-floating" if float)],
|
19
|
+
data: {
|
20
|
+
controller: "media",
|
21
|
+
name: name,
|
22
|
+
min: min,
|
23
|
+
max: max,
|
24
|
+
sort: sort,
|
25
|
+
accept: accept,
|
26
|
+
required: required.nil? ? 0 : required
|
27
|
+
}
|
28
|
+
}).deep_merge(@wrapper || {})
|
29
|
+
end
|
30
|
+
|
31
|
+
def item_options
|
32
|
+
options = {
|
33
|
+
sort: sort
|
34
|
+
}
|
35
|
+
|
36
|
+
# Don't pass width or height if it was not defined
|
37
|
+
options = options.merge(width: width) if is_defined?(:width)
|
38
|
+
options = options.merge(height: height) if is_defined?(:height)
|
39
|
+
|
40
|
+
options
|
41
|
+
end
|
42
|
+
|
43
|
+
def custom_validation_options
|
44
|
+
{
|
45
|
+
form: form,
|
46
|
+
attribute: attribute,
|
47
|
+
min: min,
|
48
|
+
max: max,
|
49
|
+
accept: accept
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def thumbnail_options
|
54
|
+
options = {
|
55
|
+
icon: "plus"
|
56
|
+
}
|
57
|
+
|
58
|
+
# Don't pass width or height if it was not defined
|
59
|
+
options = options.merge(width: width) unless is_defined?(:width)
|
60
|
+
options = options.merge(height: height) unless is_defined?(:height)
|
61
|
+
|
62
|
+
options
|
63
|
+
end
|
64
|
+
|
65
|
+
def association_object
|
66
|
+
if attached.is_a?(ActiveStorage::Attached::Many)
|
67
|
+
result = form.object.send(nested_attribute)
|
68
|
+
|
69
|
+
# We sort the collection with ruby to prevent a new query to be made that would dispose of the objects in memory
|
70
|
+
result = result.sort_by { |item| item.position } if sort
|
71
|
+
result
|
72
|
+
else
|
73
|
+
form.object.send(nested_attribute)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def attachments
|
78
|
+
if attached.is_a?(ActiveStorage::Attached::Many)
|
79
|
+
result = form.object.send(nested_attribute)
|
80
|
+
|
81
|
+
# We sort the collection with ruby to prevent a new query to be made that would dispose of the objects in memory
|
82
|
+
result = result.sort_by { |item| item.position } if sort
|
83
|
+
result.to_a.compact
|
84
|
+
else
|
85
|
+
[form.object.send(nested_attribute)].compact
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def attached
|
90
|
+
form.object.send(attribute)
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_nested_attribute
|
94
|
+
if attached.is_a?(ActiveStorage::Attached::Many)
|
95
|
+
form.object.send(nested_attribute).build
|
96
|
+
else
|
97
|
+
form.object.send("build_#{nested_attribute}")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def nested_attribute
|
102
|
+
if attached.is_a?(ActiveStorage::Attached::Many)
|
103
|
+
:"#{attribute}_attachments"
|
104
|
+
else
|
105
|
+
:"#{attribute}_attachment"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def min
|
110
|
+
if @required
|
111
|
+
(@min.to_i < 1) ? 1 : @min.to_i
|
112
|
+
else
|
113
|
+
(@min.to_i < 1) ? 0 : @min.to_i
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def max
|
118
|
+
if attached.is_a?(ActiveStorage::Attached::Many)
|
119
|
+
@max
|
120
|
+
else
|
121
|
+
1
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
attr_reader :accept
|
126
|
+
|
127
|
+
def required
|
128
|
+
@required ? 1 : nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def blob_ids
|
132
|
+
attachments.map { |attachment| attachment.blob_id }
|
133
|
+
end
|
134
|
+
|
135
|
+
def name
|
136
|
+
"#{attribute}_#{object_id}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def sort
|
140
|
+
@sort == true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class NumberView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::InputGroupable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Listable
|
7
|
+
include Formstrap::Placeholderable
|
8
|
+
include Formstrap::Validatable
|
9
|
+
include Formstrap::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", float_class]
|
26
|
+
}).deep_merge(@wrapper || {})
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def float_class
|
32
|
+
"form-floating" if float
|
33
|
+
end
|
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
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class PasswordView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::InputGroupable
|
5
|
+
include Formstrap::Labelable
|
6
|
+
include Formstrap::Placeholderable
|
7
|
+
include Formstrap::Validatable
|
8
|
+
include Formstrap::Wrappable
|
9
|
+
|
10
|
+
def input_options
|
11
|
+
keys = attributes - %i[append attribute float form input_group label prepend validate wrapper]
|
12
|
+
options = to_h.slice(*keys)
|
13
|
+
default_input_options.deep_merge(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def input_group_options
|
17
|
+
default_input_group_options
|
18
|
+
.deep_merge(label_input_group_options)
|
19
|
+
.deep_merge(@input_group || {})
|
20
|
+
end
|
21
|
+
|
22
|
+
def wrapper_options
|
23
|
+
default_wrapper_options.deep_merge({
|
24
|
+
class: ["mb-3", ("form-floating" if float)]
|
25
|
+
}).deep_merge(@wrapper || {})
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def default_input_options
|
31
|
+
{
|
32
|
+
aria: {describedby: validation_id},
|
33
|
+
class: [form_control_class, validation_class],
|
34
|
+
placeholder: placeholder
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def form_control_class
|
39
|
+
plaintext ? "form-control-plaintext" : "form-control"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class RedactorxView < ViewModel
|
3
|
+
def options
|
4
|
+
default_options.deep_merge(to_h)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def default_options
|
10
|
+
{
|
11
|
+
data: {
|
12
|
+
controller: "redactorx",
|
13
|
+
"redactor-options": redactor_options
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def control
|
19
|
+
@control || (hybrid ? true : nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def context
|
23
|
+
@context || (hybrid ? true : nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
def toolbar
|
27
|
+
@toolbar || (hybrid ? false : nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
def addbar
|
31
|
+
@addbar || %w[paragraph image embed table quote pre line]
|
32
|
+
end
|
33
|
+
|
34
|
+
def plugins
|
35
|
+
@plugins || %w[shortcut]
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :topbar
|
39
|
+
|
40
|
+
def redactor_options
|
41
|
+
default_redactor_options.deep_merge(redactor || {})
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_redactor_options
|
45
|
+
{
|
46
|
+
control: control,
|
47
|
+
context: context,
|
48
|
+
toolbar: toolbar,
|
49
|
+
buttons: {
|
50
|
+
addbar: addbar,
|
51
|
+
plugins: plugins,
|
52
|
+
topbar: topbar
|
53
|
+
}
|
54
|
+
}.delete_if { |k, v| v.nil? }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|