formstrap 0.1.0
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 +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,11 @@
|
|
1
|
+
// Tom select
|
2
|
+
@import "formstrap/vendor/tom-select-bootstrap";
|
3
|
+
|
4
|
+
// Flatpickr
|
5
|
+
@import "formstrap/vendor/flatpickr";
|
6
|
+
|
7
|
+
// Formstrap
|
8
|
+
@import "formstrap/forms";
|
9
|
+
@import "formstrap/general";
|
10
|
+
@import "formstrap/utilities";
|
11
|
+
@import "formstrap/media";
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Pagination
|
3
|
+
def paginate(collection)
|
4
|
+
@records_filtered = collection.count
|
5
|
+
if collection.is_a?(Array)
|
6
|
+
Kaminari.paginate_array(collection).page(page).per(per_page)
|
7
|
+
else
|
8
|
+
collection.page(page).per(per_page)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def page
|
13
|
+
if params[:page]
|
14
|
+
params[:page]
|
15
|
+
elsif params[:start]
|
16
|
+
(params[:start].to_i / per_page) + 1
|
17
|
+
else
|
18
|
+
1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def per_page
|
23
|
+
length = params[:per_page].to_i
|
24
|
+
(length > 0) ? length : 24
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Formstrap::MediaController < FormstrapController
|
2
|
+
include Formstrap::Pagination
|
3
|
+
layout false
|
4
|
+
|
5
|
+
def index
|
6
|
+
@blobs =
|
7
|
+
ActiveStorage::Blob
|
8
|
+
.not_attached_to_variant
|
9
|
+
.by_mimetypes_string(media_params[:mimetype])
|
10
|
+
.order(created_at: :desc)
|
11
|
+
.group(:id)
|
12
|
+
.all
|
13
|
+
@blobs = paginate(@blobs)
|
14
|
+
@mimetypes = media_params[:mimetype]
|
15
|
+
|
16
|
+
respond_to do |format|
|
17
|
+
format.html
|
18
|
+
format.turbo_stream
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
blobs = []
|
24
|
+
media_params[:files].reject { |c| c.blank? }.each do |file|
|
25
|
+
blobs << ActiveStorage::Blob.create_and_upload!(io: file, filename: file.original_filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
respond_to do |format|
|
29
|
+
format.turbo_stream {
|
30
|
+
@blobs = blobs
|
31
|
+
}
|
32
|
+
format.html { redirect_to root_path }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
@blob = ActiveStorage::Blob.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
def update
|
41
|
+
@blob = ActiveStorage::Blob.find(params[:id])
|
42
|
+
media_item_params[:filename] = media_item_params[:filename] + "." + @blob.filename.to_s.rpartition(".").last
|
43
|
+
if @blob.update(media_item_params)
|
44
|
+
flash.now[:notice] = t("admin.flash.updated", name: @blob.filename)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def thumbnail
|
49
|
+
@blob = ActiveStorage::Blob.find(params[:id])
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def media_params
|
55
|
+
params.permit(
|
56
|
+
:min,
|
57
|
+
:max,
|
58
|
+
:name,
|
59
|
+
:mimetype,
|
60
|
+
ids: [],
|
61
|
+
files: []
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def media_item_params
|
66
|
+
params.require(:blob).permit!
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Autocompletable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def autocomplete?
|
7
|
+
collection.is_a?(String) || collection.is_a?(Array)
|
8
|
+
end
|
9
|
+
|
10
|
+
def autocomplete_options
|
11
|
+
{
|
12
|
+
collection: collection.is_a?(Array) ? collection : []
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def autocomplete_input_options
|
17
|
+
{
|
18
|
+
data: {
|
19
|
+
autocomplete_target: autocomplete? ? "input" : nil
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def autocomplete_input_group_options
|
25
|
+
options = {
|
26
|
+
data: {
|
27
|
+
controller: autocomplete? ? "autocomplete" : nil,
|
28
|
+
autocomplete_url_value: collection.is_a?(String) ? collection : nil
|
29
|
+
}
|
30
|
+
}
|
31
|
+
options = options.merge(bypass: false) if autocomplete?
|
32
|
+
options
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Hintable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def hint?
|
7
|
+
hint.present?
|
8
|
+
end
|
9
|
+
|
10
|
+
def maxlength?
|
11
|
+
maxlength.present?
|
12
|
+
end
|
13
|
+
|
14
|
+
def hint_options
|
15
|
+
{
|
16
|
+
content: hint,
|
17
|
+
maxlength: maxlength
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module InputGroupable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def input_group_options
|
7
|
+
default_input_group_options.merge(@input_group || {})
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_input_group_options
|
13
|
+
{
|
14
|
+
bypass: !(prepend || append || @input_group),
|
15
|
+
prepend: prepend,
|
16
|
+
append: append
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Labelable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
def label?
|
6
|
+
label != false
|
7
|
+
end
|
8
|
+
|
9
|
+
def prepend_label?
|
10
|
+
label != false && !float
|
11
|
+
end
|
12
|
+
|
13
|
+
def append_label?
|
14
|
+
label != false && float
|
15
|
+
end
|
16
|
+
|
17
|
+
def label_input_group_options
|
18
|
+
float ? {bypass: true} : {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def label_options
|
22
|
+
{
|
23
|
+
attribute: attribute,
|
24
|
+
form: form,
|
25
|
+
required: required,
|
26
|
+
text: label
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Listable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def list
|
7
|
+
datalist_id if @list
|
8
|
+
end
|
9
|
+
|
10
|
+
def datalist?
|
11
|
+
@list.present?
|
12
|
+
end
|
13
|
+
|
14
|
+
def datalist_options
|
15
|
+
{
|
16
|
+
collection: @list,
|
17
|
+
id: datalist_id
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def datalist_id
|
22
|
+
"#{attribute}_list"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Validatable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def validation_options
|
7
|
+
{
|
8
|
+
id: validation_id,
|
9
|
+
message: validation_message,
|
10
|
+
valid: valid?
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate?
|
15
|
+
form.object&.errors&.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
!form.object&.errors&.has_key?(attribute)
|
22
|
+
end
|
23
|
+
|
24
|
+
def validation_message
|
25
|
+
form.object&.errors&.full_messages_for(attribute)&.join(", ")
|
26
|
+
end
|
27
|
+
|
28
|
+
def validation_id
|
29
|
+
[attribute.to_s, "validation"].join("_").parameterize.underscore
|
30
|
+
end
|
31
|
+
|
32
|
+
def validation_class
|
33
|
+
return unless validate?
|
34
|
+
valid? ? "is-valid" : "is-invalid"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Formstrap
|
2
|
+
module Wrappable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def wrapper_options
|
7
|
+
default_wrapper_options.merge(@wrapper || {})
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_wrapper_options
|
13
|
+
{
|
14
|
+
bypass: @wrapper == false
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
Binary file
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class AssociationView < 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 collection float form input_group include_blank label prepend validate selected tags wrapper]
|
13
|
+
options = to_h.slice(*keys)
|
14
|
+
def_input_options = default_input_options
|
15
|
+
def_input_options = def_input_options.deep_merge(options)
|
16
|
+
def_input_options = def_input_options.merge({multiple: true}) if collection?
|
17
|
+
def_input_options
|
18
|
+
end
|
19
|
+
|
20
|
+
def input_group_options
|
21
|
+
default_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
|
+
def select_options
|
33
|
+
keys = %i[include_blank selected]
|
34
|
+
options = to_h.slice(*keys)
|
35
|
+
default_options.deep_merge(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def attribute_with_id
|
39
|
+
attribute_with_id = collection? ? "#{association_foreign_key}s" : foreign_key
|
40
|
+
|
41
|
+
if attribute_with_id.nil?
|
42
|
+
raise(AssociationDoesNotExistError, "Association attribute that was passed does not exist.")
|
43
|
+
else
|
44
|
+
attribute_with_id
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection
|
49
|
+
association_class.all.map { |item| [item.to_s, item.id] }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def association_foreign_key
|
55
|
+
reflection.association_foreign_key
|
56
|
+
end
|
57
|
+
|
58
|
+
def foreign_key
|
59
|
+
reflection.foreign_key
|
60
|
+
end
|
61
|
+
|
62
|
+
def reflection
|
63
|
+
form.object.class.reflect_on_association(attribute)
|
64
|
+
end
|
65
|
+
|
66
|
+
def association_class
|
67
|
+
reflection.klass
|
68
|
+
end
|
69
|
+
|
70
|
+
def collection?
|
71
|
+
reflection.collection?
|
72
|
+
end
|
73
|
+
|
74
|
+
def default_options
|
75
|
+
{
|
76
|
+
selected: form.object&.send(attribute_with_id)
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def default_input_options
|
81
|
+
{
|
82
|
+
aria: {describedby: validation_id},
|
83
|
+
class: [form_control_class, validation_class],
|
84
|
+
data: {
|
85
|
+
tags: tags,
|
86
|
+
controller: "select"
|
87
|
+
},
|
88
|
+
multiple: tags,
|
89
|
+
placeholder: placeholder
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def form_control_class
|
94
|
+
plaintext ? "form-control-plaintext" : "form-select"
|
95
|
+
end
|
96
|
+
|
97
|
+
class AssociationDoesNotExistError < StandardError
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class BlocksView < ViewModel
|
3
|
+
def repeater_options
|
4
|
+
keys = %i[form attribute names label]
|
5
|
+
options = to_h.slice(*keys)
|
6
|
+
default_repeater_options.deep_merge(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def paths
|
10
|
+
@paths || []
|
11
|
+
end
|
12
|
+
|
13
|
+
def prefixes
|
14
|
+
paths + ["admin/blocks", "blocks", ""]
|
15
|
+
end
|
16
|
+
|
17
|
+
def badge_style(object)
|
18
|
+
visible = object.visible?
|
19
|
+
errors = object.errors.present?
|
20
|
+
|
21
|
+
if !visible && !errors
|
22
|
+
"bg-light text-secondary"
|
23
|
+
elsif errors
|
24
|
+
"bg-danger text-white"
|
25
|
+
else
|
26
|
+
"bg-light text-dark"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def default_repeater_options
|
33
|
+
{
|
34
|
+
attribute: "blocks",
|
35
|
+
label: false,
|
36
|
+
templates: names,
|
37
|
+
row: {
|
38
|
+
class: "repeater-row list-group-item pt-3"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class CheckboxView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::Labelable
|
5
|
+
include Formstrap::Validatable
|
6
|
+
include Formstrap::Wrappable
|
7
|
+
|
8
|
+
def checked_value
|
9
|
+
@checked_value || "1"
|
10
|
+
end
|
11
|
+
|
12
|
+
def unchecked_value
|
13
|
+
@unchecked_value || "0"
|
14
|
+
end
|
15
|
+
|
16
|
+
def input_options
|
17
|
+
keys = attributes - %i[attribute form label validate wrapper checked_value unchecked_value]
|
18
|
+
options = to_h.slice(*keys)
|
19
|
+
default_input_options.deep_merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def label_options
|
23
|
+
{
|
24
|
+
class: ["form-check-label"],
|
25
|
+
attribute: attribute,
|
26
|
+
form: form,
|
27
|
+
required: required,
|
28
|
+
text: label
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def wrapper_options
|
33
|
+
default_wrapper_options.deep_merge(
|
34
|
+
{
|
35
|
+
class: %w[form-check mb-3]
|
36
|
+
}
|
37
|
+
).deep_merge(@wrapper || {})
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def default_input_options
|
43
|
+
{
|
44
|
+
aria: {describedby: validation_id},
|
45
|
+
class: ["form-check-input", validation_class],
|
46
|
+
placeholder: placeholder
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class ColorView < ViewModel
|
3
|
+
include Formstrap::Hintable
|
4
|
+
include Formstrap::Labelable
|
5
|
+
include Formstrap::Validatable
|
6
|
+
include Formstrap::Wrappable
|
7
|
+
|
8
|
+
def input_options
|
9
|
+
keys = attributes - %i[attribute form label validate wrapper]
|
10
|
+
options = to_h.slice(*keys)
|
11
|
+
default_input_options.deep_merge(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def label_options
|
15
|
+
{
|
16
|
+
class: ["form-label"],
|
17
|
+
attribute: attribute,
|
18
|
+
form: form,
|
19
|
+
required: required,
|
20
|
+
text: label
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def value
|
25
|
+
@form.object&.send(@attribute) || "#000000"
|
26
|
+
end
|
27
|
+
|
28
|
+
def wrapper_options
|
29
|
+
default_wrapper_options.deep_merge(
|
30
|
+
{}
|
31
|
+
).deep_merge(@wrapper || {})
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def default_input_options
|
37
|
+
{
|
38
|
+
aria: {describedby: validation_id},
|
39
|
+
class: ["form-control form-control-color", validation_class],
|
40
|
+
placeholder: placeholder,
|
41
|
+
title: value
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class DateRangeView < ViewModel
|
3
|
+
def start_options
|
4
|
+
default_start_options.deep_merge(@start || {})
|
5
|
+
end
|
6
|
+
|
7
|
+
def end_options
|
8
|
+
default_end_options.deep_merge(@end || {})
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_start_options
|
14
|
+
keys = attributes - %i[start]
|
15
|
+
to_h.slice(*keys)
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_end_options
|
19
|
+
keys = attributes - %i[end]
|
20
|
+
to_h.slice(*keys)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class DateView < 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,23 @@
|
|
1
|
+
module Formstrap
|
2
|
+
class DatetimeRangeView < ViewModel
|
3
|
+
def start_options
|
4
|
+
default_start_options.deep_merge(@start || {})
|
5
|
+
end
|
6
|
+
|
7
|
+
def end_options
|
8
|
+
default_end_options.deep_merge(@end || {})
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_start_options
|
14
|
+
keys = attributes - %i[start]
|
15
|
+
to_h.slice(*keys)
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_end_options
|
19
|
+
keys = attributes - %i[end]
|
20
|
+
to_h.slice(*keys)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|