beyond_canvas 0.22.0.pre → 0.23.0.pre
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/app/assets/images/icons/adblocker.svg +5 -0
- data/app/assets/images/icons/checkbox_checked.svg +1 -1
- data/app/assets/images/icons/checkbox_unchecked.svg +1 -1
- data/app/assets/images/icons/external_link.svg +1 -0
- data/app/assets/images/icons/toggle.svg +1 -0
- data/app/assets/images/icons/toggle_checked.svg +3 -0
- data/app/assets/images/icons/toggle_unchecked.svg +3 -0
- data/app/assets/javascripts/beyond_canvas/base.js +77 -31
- data/app/assets/stylesheets/beyond_canvas/base.scss +19 -18
- data/app/assets/stylesheets/beyond_canvas/components/_action_bar.scss +11 -6
- data/app/assets/stylesheets/beyond_canvas/components/_breadcrumbs.scss +5 -5
- data/app/assets/stylesheets/beyond_canvas/components/_buttons.scss +45 -95
- data/app/assets/stylesheets/beyond_canvas/components/_cards.scss +20 -12
- data/app/assets/stylesheets/beyond_canvas/components/_collapse.scss +6 -3
- data/app/assets/stylesheets/beyond_canvas/components/_flash.scss +11 -11
- data/app/assets/stylesheets/beyond_canvas/components/_forms.scss +2 -2
- data/app/assets/stylesheets/beyond_canvas/components/_inputs.scss +182 -40
- data/app/assets/stylesheets/beyond_canvas/components/_links.scss +51 -3
- data/app/assets/stylesheets/beyond_canvas/components/_main.scss +3 -3
- data/app/assets/stylesheets/beyond_canvas/components/_menu.scss +13 -0
- data/app/assets/stylesheets/beyond_canvas/components/_modals.scss +48 -18
- data/app/assets/stylesheets/beyond_canvas/components/_notices.scss +11 -11
- data/app/assets/stylesheets/beyond_canvas/components/_scrollbox.scss +5 -4
- data/app/assets/stylesheets/beyond_canvas/components/_select2.scss +13 -13
- data/app/assets/stylesheets/beyond_canvas/components/_statuses.scss +9 -8
- data/app/assets/stylesheets/beyond_canvas/components/_step_list.scss +67 -0
- data/app/assets/stylesheets/beyond_canvas/components/_tables.scss +10 -5
- data/app/assets/stylesheets/beyond_canvas/components/_titles.scss +1 -1
- data/app/assets/stylesheets/beyond_canvas/mailer.scss +2 -1
- data/app/assets/stylesheets/beyond_canvas/settings/_base_variables.scss +241 -0
- data/app/assets/stylesheets/beyond_canvas/settings/{_variables.scss → _constant_variables.scss} +30 -64
- data/app/assets/stylesheets/beyond_canvas/settings/_custom_variables.scss +233 -0
- data/app/assets/stylesheets/beyond_canvas/settings/_typography.scss +7 -3
- data/app/assets/stylesheets/beyond_canvas/utilities/_mixins.scss +30 -3
- data/app/controllers/beyond_canvas/authentications_controller.rb +18 -2
- data/app/controllers/beyond_canvas/system_controller.rb +3 -1
- data/app/controllers/beyond_canvas/webhooks_controller.rb +49 -0
- data/app/controllers/concerns/beyond_canvas/add_blocker_check.rb +17 -0
- data/app/controllers/concerns/beyond_canvas/custom_styles.rb +54 -0
- data/app/controllers/concerns/beyond_canvas/locale_management.rb +31 -8
- data/app/controllers/concerns/beyond_canvas/request_validation.rb +6 -0
- data/app/form_builders/beyond_canvas/form_builder.rb +62 -49
- data/app/helpers/beyond_canvas/application_helper.rb +27 -4
- data/app/helpers/beyond_canvas/form_tag_helper.rb +130 -0
- data/app/javascript/beyond_canvas/base.js +0 -1
- data/app/javascript/beyond_canvas/initializers/buttons.js +10 -2
- data/app/javascript/beyond_canvas/initializers/flash.js +32 -10
- data/app/javascript/beyond_canvas/initializers/inputs.js +9 -4
- data/app/javascript/beyond_canvas/initializers/modals.js +46 -10
- data/app/views/beyond_canvas/mailer/_header.html.erb +2 -2
- data/app/views/beyond_canvas/shared/_flash.html.erb +14 -10
- data/app/views/beyond_canvas/shared/_head.html.erb +4 -0
- data/app/views/beyond_canvas/shared/_locales.html.erb +1 -1
- data/app/views/layouts/beyond_canvas/application.html.erb +0 -1
- data/app/views/layouts/beyond_canvas/public.html.erb +1 -1
- data/config/initializers/beyond_canvas/constants.rb +13 -0
- data/config/initializers/beyond_canvas/session_store.rb +8 -0
- data/lib/beyond_canvas/configuration.rb +9 -1
- data/lib/beyond_canvas/engine.rb +7 -0
- data/lib/beyond_canvas/rails/routes.rb +27 -7
- data/lib/beyond_canvas/version.rb +1 -1
- data/lib/beyond_canvas/webhook_event_registration.rb +19 -0
- data/lib/beyond_canvas.rb +6 -4
- data/lib/generators/beyond_canvas/install/install_generator.rb +6 -0
- data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +38 -1
- data/lib/generators/beyond_canvas/model/model_generator.rb +3 -0
- data/lib/generators/beyond_canvas/webhook/templates/webhooks_controller.rb +22 -0
- data/lib/generators/beyond_canvas/webhook/webhook_generator.rb +15 -0
- data/lib/models/concerns/authentication.rb +10 -3
- data/lib/models/concerns/utils.rb +1 -1
- data/lib/models/concerns/webhook.rb +123 -0
- data/lib/models/shop.rb +1 -0
- metadata +68 -39
- data/app/assets/stylesheets/beyond_canvas/components/_comments.scss +0 -6
- data/app/views/beyond_canvas/shared/_modal.html.erb +0 -6
- data/config/routes.rb +0 -12
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BeyondCanvas
|
4
|
+
module CustomStyles
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :check_custom_styles!, if: -> { BeyondCanvas.configuration.cockpit_app } # rubocop:disable Rails/LexicallyScopedActionFilter
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
#
|
14
|
+
# Checks if the custom styles url set on `custom_styles_url` cookie is valid. If it's not, it generates a new custom
|
15
|
+
# styles url and stores it on `custom_styles_url` cookie.
|
16
|
+
#
|
17
|
+
def check_custom_styles!
|
18
|
+
return if valid_custom_styles_stylesheet?(cookies[:custom_styles_url])
|
19
|
+
|
20
|
+
set_custom_styles_url
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Validates if the `custom_styles_url` cookie is set and if it's a valid url.
|
25
|
+
#
|
26
|
+
def valid_custom_styles_stylesheet?(custom_styles_url)
|
27
|
+
custom_styles_url.present? && existing_url?(custom_styles_url)
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Checks if the given url exists.
|
32
|
+
#
|
33
|
+
def existing_url?(url)
|
34
|
+
URI.open(url).status.first.to_i.between?(200, 299)
|
35
|
+
rescue
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Stores a newly generated custom_styles_url on the cookie.
|
41
|
+
#
|
42
|
+
def set_custom_styles_url(shop = nil)
|
43
|
+
shop ||= current_shop
|
44
|
+
|
45
|
+
return if shop.blank?
|
46
|
+
|
47
|
+
reseller = shop.to_session.shop.current[:reseller_name]
|
48
|
+
|
49
|
+
cookies[:custom_styles_url] = {
|
50
|
+
value: shop.url("cockpit/assets/reseller-styles/#{reseller}-variables.css")
|
51
|
+
}.merge COOKIES_ATTRIBUTES
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -16,7 +16,9 @@ module BeyondCanvas
|
|
16
16
|
#
|
17
17
|
def switch_locale(&action)
|
18
18
|
unless valid_locale?(cookies[:locale])
|
19
|
-
cookies[:locale] = {
|
19
|
+
cookies[:locale] = {
|
20
|
+
value: app_locale,
|
21
|
+
}.merge COOKIES_ATTRIBUTES
|
20
22
|
end
|
21
23
|
|
22
24
|
I18n.with_locale(cookies[:locale], &action)
|
@@ -24,6 +26,34 @@ module BeyondCanvas
|
|
24
26
|
logger.debug "[BeyondCanvas] Locale set to: #{cookies[:locale]}".yellow if debug_mode?
|
25
27
|
end
|
26
28
|
|
29
|
+
#
|
30
|
+
# Checks if the given locale parameter is included on +I18n.available_locales+
|
31
|
+
#
|
32
|
+
def valid_locale?(locale)
|
33
|
+
I18n.available_locales.map(&:to_s).include? locale
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# If it is a cockpit app, it returns the shop default locale.
|
38
|
+
# Otherwise it returns the browser compatible locale.
|
39
|
+
#
|
40
|
+
# @return [String] the local that the app will use (e.g. +'en-GB'+)
|
41
|
+
#
|
42
|
+
def app_locale
|
43
|
+
BeyondCanvas.configuration.cockpit_app ? shop_locale : browser_compatible_locale
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Retrieves the shop default locale from the Beyond API.
|
48
|
+
#
|
49
|
+
# @return [String] the shop default locale (e.g. +'en-GB'+)
|
50
|
+
#
|
51
|
+
def shop_locale
|
52
|
+
BeyondApi::Session.new(api_url: current_shop.beyond_api_url).shop.current.default_locale
|
53
|
+
rescue
|
54
|
+
browser_compatible_locale
|
55
|
+
end
|
56
|
+
|
27
57
|
#
|
28
58
|
# Reads the +HTTP_ACCEPT_LANGUAGE+ header and searches a compatible locale
|
29
59
|
# on +I18n.available_locales+. If no compatible language is found, it
|
@@ -44,12 +74,5 @@ module BeyondCanvas
|
|
44
74
|
rescue
|
45
75
|
I18n.default_locale
|
46
76
|
end
|
47
|
-
|
48
|
-
#
|
49
|
-
# Checks if the given locale parameter is included on +I18n.available_locales+
|
50
|
-
#
|
51
|
-
def valid_locale?(locale)
|
52
|
-
I18n.available_locales.map(&:to_s).include? locale
|
53
|
-
end
|
54
77
|
end
|
55
78
|
end
|
@@ -33,5 +33,11 @@ module BeyondCanvas
|
|
33
33
|
hmac = OpenSSL::HMAC.digest(digest, secret, data)
|
34
34
|
URI.decode(signature) == Base64.encode64(hmac).chop
|
35
35
|
end
|
36
|
+
|
37
|
+
def signature_params
|
38
|
+
data = URI.parse(request.original_url).to_s
|
39
|
+
data << ":#{request.body.read}" if request.body.read.present?
|
40
|
+
data
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
@@ -2,38 +2,6 @@
|
|
2
2
|
|
3
3
|
module BeyondCanvas
|
4
4
|
class FormBuilder < ActionView::Helpers::FormBuilder # :nodoc:
|
5
|
-
def field_wrapper(attribute, args, &block)
|
6
|
-
label = args[:label] == false ? nil : args[:label].presence || attribute.to_s.humanize
|
7
|
-
|
8
|
-
errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
|
9
|
-
|
10
|
-
@template.content_tag(:div, class: 'form__row') do
|
11
|
-
@template.content_tag(:label, label, class: 'input__label') +
|
12
|
-
@template.content_tag(:div, class: 'relative') do
|
13
|
-
block.call +
|
14
|
-
(@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
|
15
|
-
end +
|
16
|
-
(@template.content_tag(:div, args[:hint].html_safe, class: 'input__hint') if args[:hint].present?)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def inline_wrapper(attribute, args, &block)
|
21
|
-
label = args[:label] == false ? nil : args[:label].presence || attribute.to_s.humanize
|
22
|
-
|
23
|
-
errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
|
24
|
-
|
25
|
-
@template.content_tag(:div, class: 'form__row') do
|
26
|
-
@template.content_tag(:div, class: 'relative', style: 'display: flex; align-items: center;') do
|
27
|
-
block.call +
|
28
|
-
@template.content_tag(:div) do
|
29
|
-
@template.content_tag(:label, label, class: 'input__label') +
|
30
|
-
(@template.content_tag(:div, args[:hint].html_safe, class: 'input__hint') if args[:hint].present?)
|
31
|
-
end +
|
32
|
-
(@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
5
|
%i[email_field text_field number_field password_field text_area].each do |method|
|
38
6
|
define_method method do |attribute, args = {}|
|
39
7
|
field_wrapper(attribute, args) do
|
@@ -42,39 +10,41 @@ module BeyondCanvas
|
|
42
10
|
end
|
43
11
|
end
|
44
12
|
|
45
|
-
def select(attribute, choices, options
|
13
|
+
def select(attribute, choices, options = {}, args = {})
|
46
14
|
field_wrapper(attribute, args) do
|
47
15
|
super(attribute, choices, options, args)
|
48
16
|
end
|
49
17
|
end
|
50
18
|
|
51
|
-
def check_box(attribute, args = {})
|
52
|
-
|
53
|
-
filed_identifyer = filed_identifyer(attribute)
|
19
|
+
def check_box(attribute, args = {}, checked_value = '1', unchecked_value = '0')
|
20
|
+
filed_identifyer = filed_identifyer(attribute)
|
54
21
|
|
22
|
+
inline_wrapper(attribute, args, filed_identifyer) do
|
55
23
|
args.merge!(id: filed_identifyer)
|
56
24
|
.merge!(hidden: true)
|
25
|
+
.merge!(class: 'input__checkbox')
|
57
26
|
|
58
|
-
|
59
|
-
|
60
|
-
@template.
|
61
|
-
|
27
|
+
super(attribute, args, checked_value, unchecked_value) +
|
28
|
+
@template.content_tag(:label, class: 'input__checkbox__control', for: filed_identifyer) do
|
29
|
+
@template.inline_svg_tag('icons/checkbox_checked.svg', style: 'display: none;', class: 'input__checkbox--checked') +
|
30
|
+
@template.inline_svg_tag('icons/checkbox_unchecked.svg', style: 'display: none;', class: 'input__checkbox--unchecked')
|
31
|
+
end
|
62
32
|
end
|
63
33
|
end
|
64
34
|
|
65
35
|
def radio_button(attribute, value, args = {})
|
66
|
-
|
67
|
-
|
68
|
-
inline_wrapper(attribute, args) do
|
69
|
-
filed_identifyer = filed_identifyer(attribute)
|
36
|
+
filed_identifyer = filed_identifyer(attribute)
|
70
37
|
|
38
|
+
inline_wrapper(attribute, args, filed_identifyer) do
|
71
39
|
args.merge!(id: filed_identifyer)
|
72
40
|
.merge!(hidden: true)
|
41
|
+
.merge!(class: 'input__radio')
|
73
42
|
|
74
|
-
|
75
|
-
|
76
|
-
@template.
|
77
|
-
|
43
|
+
super(attribute, value, args) +
|
44
|
+
@template.content_tag(:label, class: 'input__radio__control', for: filed_identifyer) do
|
45
|
+
@template.inline_svg_tag('icons/radiobutton_checked.svg', style: 'display: none;', class: 'input__radio--checked') +
|
46
|
+
@template.inline_svg_tag('icons/radiobutton_unchecked.svg', style: 'display: none;', class: 'input__radio--unchecked')
|
47
|
+
end
|
78
48
|
end
|
79
49
|
end
|
80
50
|
|
@@ -83,7 +53,7 @@ module BeyondCanvas
|
|
83
53
|
filed_identifyer = filed_identifyer(attribute)
|
84
54
|
|
85
55
|
args.merge!(id: filed_identifyer)
|
86
|
-
.merge!(hidden:
|
56
|
+
.merge!(style: 'visibility: hidden; position: absolute;')
|
87
57
|
|
88
58
|
custom_attributes = { data: { multiple_selection_text: '{count} files selected' } }
|
89
59
|
args = custom_attributes.merge!(args)
|
@@ -104,6 +74,49 @@ module BeyondCanvas
|
|
104
74
|
|
105
75
|
private
|
106
76
|
|
77
|
+
def field_wrapper(attribute, args, &block)
|
78
|
+
label = args.delete(:label)&.html_safe
|
79
|
+
hint = args.delete(:hint)&.html_safe
|
80
|
+
pre = args.delete(:pre)
|
81
|
+
post = args.delete(:post)
|
82
|
+
|
83
|
+
errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
|
84
|
+
|
85
|
+
@template.content_tag(:div, class: 'form__row') do
|
86
|
+
[
|
87
|
+
(@template.content_tag(:label, label, class: 'input__label') if label.present?),
|
88
|
+
(@template.content_tag(:div, class: 'relative', style: "#{'display: flex;' if pre || post}") do
|
89
|
+
[
|
90
|
+
(@template.content_tag(:span, pre, class: 'input__pre') if pre.present?),
|
91
|
+
(@template.content_tag(:span, post, class: 'input__post') if post.present?),
|
92
|
+
block.call,
|
93
|
+
(@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
|
94
|
+
].compact.inject(:+)
|
95
|
+
end),
|
96
|
+
(@template.content_tag(:div, hint, class: 'input__hint') if hint.present?)
|
97
|
+
].compact.inject(:+)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def inline_wrapper(attribute, args, filed_identifyer, &block)
|
102
|
+
label = args.delete(:label)&.html_safe
|
103
|
+
hint = args.delete(:hint)&.html_safe
|
104
|
+
errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
|
105
|
+
|
106
|
+
@template.content_tag(:div, class: 'form__row') do
|
107
|
+
@template.content_tag(:div, class: 'relative', style: 'display: flex; align-items: center;') do
|
108
|
+
block.call +
|
109
|
+
(@template.content_tag(:div) do
|
110
|
+
[
|
111
|
+
(@template.content_tag(:label, label, class: "input__label", for: filed_identifyer) if label.present?),
|
112
|
+
(@template.content_tag(:label, hint, class: 'input__hint', for: filed_identifyer) if hint.present?)
|
113
|
+
].compact.inject(:+)
|
114
|
+
end if label.present? || hint.present?) +
|
115
|
+
(@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
107
120
|
def filed_identifyer(attribute)
|
108
121
|
"#{attribute}_#{DateTime.now.strftime('%Q') + rand(10_000).to_s}"
|
109
122
|
end
|
@@ -28,11 +28,13 @@ module BeyondCanvas
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def logo_image_tag(logo_path)
|
31
|
+
def logo_image_tag(logo_path, options = {})
|
32
|
+
html_options = { class: 'logo', alt: 'logo' }.merge options
|
33
|
+
|
32
34
|
if File.extname(logo_path) == '.svg'
|
33
|
-
inline_svg_tag logo_path,
|
35
|
+
inline_svg_tag logo_path, html_options
|
34
36
|
else
|
35
|
-
image_tag logo_path,
|
37
|
+
image_tag logo_path, html_options
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -44,7 +46,7 @@ module BeyondCanvas
|
|
44
46
|
html_options.merge!(id: id)
|
45
47
|
|
46
48
|
content_tag('div', class: 'collapse') do
|
47
|
-
content_tag('a', class: 'collapse__button', data: { toggle: 'collapse', target: "##{id}" }) do
|
49
|
+
content_tag('a', class: 'collapse__button', title: name, data: { toggle: 'collapse', target: "##{id}" }) do
|
48
50
|
(inline_svg_tag('icons/arrow_right.svg', class: 'collapse__icon') + name).html_safe
|
49
51
|
end +
|
50
52
|
content_tag('div', html_options) do
|
@@ -53,6 +55,27 @@ module BeyondCanvas
|
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
58
|
+
def step_list(title, steps = [])
|
59
|
+
content_tag('div', class: 'step-list__container') do
|
60
|
+
content_tag('h4', title, class: 'step-list__title') +
|
61
|
+
content_tag('table', class: 'step-list__items') do
|
62
|
+
content_tag('tbody') do
|
63
|
+
steps.each_with_index.collect do |step, index|
|
64
|
+
content_tag('tr') do
|
65
|
+
content_tag('td', class: 'step-list__bubble-column') do
|
66
|
+
content_tag('div', index + 1, class: 'step-list__bubble')
|
67
|
+
end +
|
68
|
+
content_tag('td') do
|
69
|
+
content_tag('strong', step.dig(:headline)&.html_safe, class: 'step-list__headline') +
|
70
|
+
content_tag('p', step.dig(:description)&.html_safe, class: 'step-list__description')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end.join.html_safe
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
56
79
|
private
|
57
80
|
|
58
81
|
def unique_id(attribute)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BeyondCanvas
|
4
|
+
module FormTagHelper
|
5
|
+
%i[email_field_tag text_field_tag password_field_tag text_area_tag].each do |method|
|
6
|
+
define_method method do |name, value = nil, options = {}|
|
7
|
+
field_wrapper(name, options) do
|
8
|
+
super(name, value, options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def select_tag(name, option_tags = nil, options = {})
|
14
|
+
field_wrapper(name, options) do
|
15
|
+
super(name, option_tags, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def check_box_tag(name, value = 1, checked = false, options = {})
|
20
|
+
filed_identifyer = filed_identifyer(name)
|
21
|
+
|
22
|
+
inline_wrapper(name, options, filed_identifyer) do
|
23
|
+
|
24
|
+
options.merge!(id: filed_identifyer)
|
25
|
+
.merge!(hidden: true)
|
26
|
+
.merge!(class: 'input__checkbox')
|
27
|
+
|
28
|
+
super(name, value, checked, options) +
|
29
|
+
content_tag(:label, class: 'input__checkbox__control', for: filed_identifyer) do
|
30
|
+
inline_svg_tag('icons/checkbox_checked.svg', style: 'display: none;', class: 'input__checkbox--checked') +
|
31
|
+
inline_svg_tag('icons/checkbox_unchecked.svg', style: 'display: none;', class: 'input__checkbox--unchecked')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def radio_button_tag(name, value, checked = false, options = {})
|
37
|
+
filed_identifyer = filed_identifyer(name)
|
38
|
+
|
39
|
+
inline_wrapper(name, options, filed_identifyer) do
|
40
|
+
|
41
|
+
options.merge!(id: filed_identifyer)
|
42
|
+
.merge!(hidden: true)
|
43
|
+
.merge!(class: 'input__radio')
|
44
|
+
|
45
|
+
super(name, value, checked, options) +
|
46
|
+
content_tag(:label, class: 'input__radio__control', for: filed_identifyer) do
|
47
|
+
inline_svg_tag('icons/radiobutton_checked.svg', style: 'display: none;', class: 'input__radio--checked') +
|
48
|
+
inline_svg_tag('icons/radiobutton_unchecked.svg', style: 'display: none;', class: 'input__radio--unchecked')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def toggle_tag(name, value = 1, checked = false, options = {})
|
54
|
+
filed_identifyer = filed_identifyer(name)
|
55
|
+
|
56
|
+
inline_wrapper(name, options, filed_identifyer) do
|
57
|
+
|
58
|
+
options.merge!(id: filed_identifyer)
|
59
|
+
.merge!(hidden: true)
|
60
|
+
.merge!(class: 'input__toggle')
|
61
|
+
|
62
|
+
html_options = { type: 'checkbox', name: name, value: value }.update(options.stringify_keys)
|
63
|
+
html_options['checked'] = 'checked' if checked
|
64
|
+
|
65
|
+
tag(:input, html_options) +
|
66
|
+
content_tag(:label, class: 'input__toggle__control', for: filed_identifyer) do
|
67
|
+
inline_svg_tag('icons/toggle.svg')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def hidden_field_tag(name, value = nil, options = {})
|
73
|
+
tag :input, { type: :text, name: name, id: sanitize_to_id(name), value: value }.update(options.stringify_keys.merge(type: :hidden))
|
74
|
+
end
|
75
|
+
|
76
|
+
def number_field_tag(name, value = nil, options = {})
|
77
|
+
field_wrapper(name, options) do
|
78
|
+
options = options.stringify_keys
|
79
|
+
if (range = options.delete('in') || options.delete('within'))
|
80
|
+
options.update(min: range.min, max: range.max)
|
81
|
+
end
|
82
|
+
tag :input, { type: 'number', name: name, id: sanitize_to_id(name), value: value }.update(options.stringify_keys)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def field_wrapper(attribute, args, &block)
|
89
|
+
label = args.delete(:label)&.html_safe
|
90
|
+
hint = args.delete(:hint)&.html_safe
|
91
|
+
pre = args.delete(:pre)
|
92
|
+
post = args.delete(:post)
|
93
|
+
|
94
|
+
content_tag(:div, class: 'form__row') do
|
95
|
+
[
|
96
|
+
(content_tag(:label, label, class: 'input__label') if label.present?),
|
97
|
+
(content_tag(:div, class: 'relative', style: "#{'display: flex;' if pre || post}") do
|
98
|
+
[
|
99
|
+
(content_tag(:span, pre, class: 'input__pre') if pre.present?),
|
100
|
+
(content_tag(:span, post, class: 'input__post') if post.present?),
|
101
|
+
block.call
|
102
|
+
].compact.inject(:+)
|
103
|
+
end),
|
104
|
+
(content_tag(:div, hint, class: 'input__hint') if hint.present?)
|
105
|
+
].compact.inject(:+)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def inline_wrapper(attribute, args, filed_identifyer, &block)
|
110
|
+
label = args.delete(:label)&.html_safe
|
111
|
+
hint = args.delete(:hint)&.html_safe
|
112
|
+
|
113
|
+
content_tag(:div, class: 'form__row') do
|
114
|
+
content_tag(:div, class: 'relative', style: 'display: flex; align-items: center;') do
|
115
|
+
block.call +
|
116
|
+
(content_tag(:div) do
|
117
|
+
[
|
118
|
+
(content_tag(:label, label, class: "input__label", for: filed_identifyer) if label.present?),
|
119
|
+
(content_tag(:label, hint, class: 'input__hint', for: filed_identifyer) if hint.present?)
|
120
|
+
].compact.inject(:+)
|
121
|
+
end if label.present? || hint.present?)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def filed_identifyer(attribute)
|
127
|
+
"#{attribute.to_s.delete('[]')}_#{DateTime.now.strftime('%Q') + rand(10_000).to_s}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|