beyond_canvas 0.22.0.pre → 0.23.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|