wcc-contentful-app 0.4.0.pre.alpha → 1.0.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 +5 -5
- data/.rspec +2 -2
- data/README.md +11 -0
- data/Rakefile +125 -0
- data/app/assets/config/manifest.js +5 -0
- data/app/assets/images/down-arrow-primary.svg +3 -0
- data/app/assets/images/up-arrow-primary.svg +3 -0
- data/app/assets/javascripts/wcc/contentful/app/contact-form.js +70 -0
- data/app/assets/javascripts/wcc/contentful/app/index.js +1 -0
- data/app/assets/stylesheets/_wcc-contentful-app.scss +7 -0
- data/app/assets/stylesheets/components/_menu-item.scss +5 -0
- data/app/assets/stylesheets/sections/_faq.scss +39 -0
- data/app/controllers/wcc/contentful/app/contact_form_controller.rb +39 -0
- data/app/controllers/wcc/contentful/app/pages_controller.rb +48 -0
- data/app/helpers/wcc/contentful/app/menu_helper.rb +85 -0
- data/app/helpers/wcc/contentful/app/section_helper.rb +135 -0
- data/app/mailers/wcc/contentful/app/contact_mailer.rb +11 -0
- data/app/models/concerns/wcc/contentful/app/preview_password.rb +19 -0
- data/app/models/wcc/contentful/app/contact_form_submission.rb +9 -0
- data/app/models/wcc/contentful/app/custom_markdown_render.rb +43 -0
- data/app/views/components/_faq_row.html.erb +21 -0
- data/app/views/components/_menu-item.html.erb +41 -0
- data/app/views/components/_other-menu-item.html.erb +4 -0
- data/app/views/components/_section.html.erb +11 -0
- data/app/views/layouts/mailer.html.erb +9 -0
- data/app/views/layouts/mailer.text.erb +1 -0
- data/app/views/pages/show.html.erb +4 -0
- data/app/views/sections/_block_text.html.erb +5 -0
- data/app/views/sections/_code_widget.html.erb +3 -0
- data/app/views/sections/_contact_form.html.erb +53 -0
- data/app/views/sections/_faq.html.erb +36 -0
- data/app/views/sections/_http_error.html.erb +13 -0
- data/app/views/sections/_marquee_text.html.erb +12 -0
- data/app/views/sections/_testimonials.html.erb +38 -0
- data/app/views/sections/_video.html.erb +12 -0
- data/app/views/sections/_video_highlight.html.erb +18 -0
- data/app/views/wcc/contentful/app/contact_mailer/contact_form_email.html.erb +7 -0
- data/bin/rails +14 -0
- data/config/routes.rb +7 -0
- data/doc +1 -0
- data/lib/generators/wcc/model_generator.rb +16 -6
- data/lib/generators/wcc/templates/menu/migrations/generated_add_menus.ts +285 -0
- data/lib/generators/wcc/templates/menu/models/dropdown_menu.rb +19 -0
- data/lib/generators/wcc/templates/menu/models/menu.rb +0 -4
- data/lib/generators/wcc/templates/menu/models/menu_button.rb +0 -4
- data/lib/generators/wcc/templates/page/migrations/generated_add_pages.ts +147 -0
- data/lib/generators/wcc/templates/page/models/page.rb +0 -4
- data/lib/generators/wcc/templates/page/models/redirect.rb +19 -0
- data/lib/generators/wcc/templates/section-block-text/migrations/generated_add_section-block-texts.ts +40 -0
- data/lib/generators/wcc/templates/section-block-text/models/section_block_text.rb +19 -0
- data/lib/generators/wcc/templates/section-code-widget/migrations/generated_add_section-code-widget.ts +90 -0
- data/lib/generators/wcc/templates/section-code-widget/models/section_code_widget.rb +23 -0
- data/lib/generators/wcc/templates/section-contact-form/migrations/create_wcc_contentful_app_contact_form_submissions.rb +12 -0
- data/lib/generators/wcc/templates/section-contact-form/migrations/generated_add_section-contact-forms.ts +147 -0
- data/lib/generators/wcc/templates/section-contact-form/models/form_field.rb +19 -0
- data/lib/generators/wcc/templates/section-contact-form/models/section_contact_form.rb +19 -0
- data/lib/generators/wcc/templates/section-faq/migrations/generated_add_section-faqs.ts +148 -0
- data/lib/generators/wcc/templates/section-faq/models/section_faq.rb +19 -0
- data/lib/generators/wcc/templates/section-http-error/migrations/generated_add_section-http-errors.ts +87 -0
- data/lib/generators/wcc/templates/section-http-error/models/section_http_error.rb +19 -0
- data/lib/generators/wcc/templates/section-marquee-text/migrations/generated_add_section-marquee-texts.ts +64 -0
- data/lib/generators/wcc/templates/section-marquee-text/models/section_marquee_text.rb +19 -0
- data/lib/generators/wcc/templates/section-testimonial/migrations/generated_add_section-testimonials.ts +182 -0
- data/lib/generators/wcc/templates/section-testimonial/models/section_testimonial.rb +19 -0
- data/lib/generators/wcc/templates/section-video-highlight/migrations/generated_add_section-video-highlights.ts +80 -0
- data/lib/generators/wcc/templates/section-video-highlight/models/section_video_highlight.rb +19 -0
- data/lib/generators/wcc/templates/section-video/migrations/generated_add_section-videos.ts +77 -0
- data/lib/generators/wcc/templates/section-video/models/section_video.rb +19 -0
- data/lib/generators/wcc/templates/site-config/migrations/generated_add_site-configs.ts +97 -0
- data/lib/generators/wcc/templates/site-config/models/site_config.rb +19 -0
- data/lib/generators/wcc/templates/wcc_contentful.rb +1 -1
- data/lib/wcc/contentful/app.rb +46 -3
- data/lib/wcc/contentful/app/configuration.rb +60 -0
- data/lib/wcc/contentful/app/engine.rb +15 -0
- data/lib/wcc/contentful/app/exceptions.rb +9 -0
- data/lib/wcc/contentful/app/rails.rb +6 -0
- data/lib/wcc/contentful/app/version.rb +1 -1
- data/lib/wcc/contentful/model/dropdown_menu.rb +0 -3
- data/lib/wcc/contentful/model/form_field.rb +4 -0
- data/lib/wcc/contentful/model/menu.rb +0 -2
- data/lib/wcc/contentful/model/menu_button.rb +18 -5
- data/lib/wcc/contentful/model/page.rb +0 -4
- data/lib/wcc/contentful/model/redirect.rb +21 -11
- data/lib/wcc/contentful/model/section_contact_form.rb +42 -0
- data/lib/wcc/contentful/model/site_config.rb +7 -0
- data/wcc-contentful-app.gemspec +23 -15
- metadata +169 -106
- data/Gemfile +0 -8
- data/lib/generators/wcc/templates/menu/generated_add_menus.ts +0 -192
- data/lib/generators/wcc/templates/page/generated_add_pages.ts +0 -50
- data/lib/tasks/validate.rake +0 -20
- data/lib/wcc/contentful/app/model_validators.rb +0 -121
- data/lib/wcc/contentful/app/model_validators/dsl.rb +0 -166
- data/lib/wcc/contentful/ext/model.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4d2c8f87432e5df3bfa0ce1438ea0cbc2c89463a2c22c6ebee6a6f766b26b865
|
4
|
+
data.tar.gz: 5899cd069610da0a25a3ff330a4788e5c16f4d25618ca591bc5327678c594a7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a075b9cd2fc956189d8136848856e22aba9f3998e28e3853d4cbfe4c45d916a1f723e3ba4179b619c2da9af90de6b738b1941fb6cb707b9a922d4bb0075666a1
|
7
|
+
data.tar.gz: 689e7ec2251ff44627f5b70af5a8ce41dcc2d8d1305df6b74890ca8bc24a62c580e6f4c5ca0c892004ea8cb32a461ecbc47a57350dbcc758214495a4efd67d1e
|
data/.rspec
CHANGED
data/README.md
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
[](https://rubygems.org/gems/wcc-contentful-app)
|
2
|
+
[](https://travis-ci.org/watermarkchurch/wcc-contentful)
|
3
|
+
[](https://coveralls.io/github/watermarkchurch/wcc-contentful?branch=master)
|
4
|
+
|
5
|
+
# WCC::Contentful::App
|
6
|
+
|
7
|
+
This gem specifies default models, controllers, views, and javascripts that
|
8
|
+
get installed into all Watermarkchurch apps that use contentful. It is a highly
|
9
|
+
opinionated starting point for a very flexible site design using Contentful.
|
10
|
+
|
11
|
+
You probably should not use this.
|
data/Rakefile
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
require 'wcc/contentful'
|
7
|
+
|
8
|
+
# rubocop:disable Metrics/LineLength
|
9
|
+
# Disabling line length for contentful-schema-diff backtick execution
|
10
|
+
|
11
|
+
namespace :app do
|
12
|
+
desc "Imports a set of models from a space as a single template for the ModelGenerator.\n" \
|
13
|
+
'Usage: rake wcc:import_model[content-type-id,space-id?,extra-content-type-1,extra-content-type-2...]'
|
14
|
+
task :import_model, [:model, :space] do |_t, args|
|
15
|
+
raise ArgumentError, 'Must give a content type' unless model = args[:model]
|
16
|
+
|
17
|
+
singular = model.downcase.singularize
|
18
|
+
plural = model.downcase.pluralize
|
19
|
+
|
20
|
+
all_models = [model, *args.extras]
|
21
|
+
|
22
|
+
unless space = args[:space].presence
|
23
|
+
space = ENV['CONTENTFUL_SPACE_ID']
|
24
|
+
space = "#{space}/#{ENV['CONTENTFUL_ENVIRONMENT']}" if ENV['CONTENTFUL_ENVIRONMENT']
|
25
|
+
end
|
26
|
+
raise ArgumentError, 'Must provide a space' unless space
|
27
|
+
unless mgmt_token = ENV['CONTENTFUL_MANAGEMENT_TOKEN']
|
28
|
+
raise ArgumentError, 'Must set CONTENTFUL_MANAGEMENT_TOKEN envvar'
|
29
|
+
end
|
30
|
+
|
31
|
+
client = WCC::Contentful::SimpleClient::Management.new(
|
32
|
+
space: space.split('/').first,
|
33
|
+
environment: space.split('/')[1],
|
34
|
+
management_token: mgmt_token
|
35
|
+
)
|
36
|
+
|
37
|
+
# Update the `content_types_mgmt_api.json` which we use to generate models in specs
|
38
|
+
content_types = JSON.parse(File.read('spec/fixtures/contentful/content_types_mgmt_api.json'))
|
39
|
+
all_models.each do |model_id|
|
40
|
+
content_type = client.content_type(model_id).raw
|
41
|
+
|
42
|
+
if index = content_types['items'].find_index { |ct| ct.dig('sys', 'id').casecmp(model_id) == 0 }
|
43
|
+
content_types['items'][index] = content_type
|
44
|
+
else
|
45
|
+
content_types['items'].push(content_type)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
File.write('spec/fixtures/contentful/content_types_mgmt_api.json',
|
49
|
+
JSON.pretty_generate(content_types))
|
50
|
+
|
51
|
+
# Make the generator directory
|
52
|
+
FileUtils.mkdir_p("lib/generators/wcc/templates/#{singular}/models")
|
53
|
+
|
54
|
+
# Generate a migration for the content type
|
55
|
+
File.write('empty-export.json', <<~HEREDOC)
|
56
|
+
{
|
57
|
+
"contentTypes": [],
|
58
|
+
"editorInterfaces": [],
|
59
|
+
"entries": [],
|
60
|
+
"assets": [],
|
61
|
+
"locales": []
|
62
|
+
}
|
63
|
+
HEREDOC
|
64
|
+
begin
|
65
|
+
result = `contentful-schema-diff --from empty-export.json --to #{space} #{all_models.map { |m| "-c #{m}" }.join(' ')} -a '#{mgmt_token}' --out './' --one-file`
|
66
|
+
result = result.strip
|
67
|
+
raise StandardError, 'Error writing diff!' unless result.present?
|
68
|
+
|
69
|
+
FileUtils.mv(result, "lib/generators/wcc/templates/#{singular}/generated_add_#{plural}.ts")
|
70
|
+
ensure
|
71
|
+
File.unlink('empty-export.json')
|
72
|
+
end
|
73
|
+
|
74
|
+
const = WCC::Contentful::Helpers.constant_from_content_type(model)
|
75
|
+
|
76
|
+
# Write a model for the content type
|
77
|
+
File.write("lib/generators/wcc/templates/#{singular}/models/#{singular.tr('-', '_')}.rb", <<~HEREDOC)
|
78
|
+
# frozen_string_literal: true
|
79
|
+
|
80
|
+
# This model represents the '#{model}' content type in Contentful. Any linked
|
81
|
+
# entries of the '#{model}' content type will be resolved as instances of this class.
|
82
|
+
# It exposes .find, .find_by, and .find_all methods to query Contentful.
|
83
|
+
class #{const} < WCC::Contentful::Model::#{const}
|
84
|
+
# Override functionality or add utilities
|
85
|
+
#
|
86
|
+
# # Example: override equality
|
87
|
+
# def ===(other)
|
88
|
+
# ...
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# # Example: override "title" attribute to always be titlecase.
|
92
|
+
# # `@title` is populated by the gem in the initializer.
|
93
|
+
# def title
|
94
|
+
# @title_titlecased ||= @title.titlecase
|
95
|
+
# end
|
96
|
+
end
|
97
|
+
HEREDOC
|
98
|
+
|
99
|
+
view_name = const.demodulize.underscore.sub('section_', '')
|
100
|
+
FileUtils.touch("app/views/sections/_#{view_name}.html.erb")
|
101
|
+
File.write("spec/views/sections/_#{view_name}.html.erb_spec.rb", <<~HEREDOC)
|
102
|
+
# frozen_string_literal: true
|
103
|
+
|
104
|
+
require 'rails_helper'
|
105
|
+
|
106
|
+
RSpec.describe 'sections/#{view_name}' do
|
107
|
+
helper WCC::Contentful::App::SectionHelper
|
108
|
+
|
109
|
+
it 'renders successfully' do
|
110
|
+
section = contentful_create('#{model}')
|
111
|
+
|
112
|
+
render partial: 'components/section', locals: { section: section }
|
113
|
+
|
114
|
+
expect(rendered).to have_css('section.#{model}.default')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
HEREDOC
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# rubocop:enable Metrics/LineLength
|
122
|
+
|
123
|
+
task :release do
|
124
|
+
raise StandardError, 'Please run rake release only from the root folder.'
|
125
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
if (typeof window.$ == 'undefined' ) {
|
2
|
+
var $ = window.jQuery
|
3
|
+
}
|
4
|
+
|
5
|
+
$(function() {
|
6
|
+
function warningAlert(message) {
|
7
|
+
var div = $('<div>')
|
8
|
+
.addClass('alert alert-danger alert-dismissible fade show')
|
9
|
+
.text(message)
|
10
|
+
|
11
|
+
return div.append(
|
12
|
+
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
13
|
+
'<span aria-hidden="true">×</span>' +
|
14
|
+
'</button>'
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
function handleResponse($form, event, status, xhr) {
|
19
|
+
// Handle backwards compat for [rails/jquery]-ujs ajax callbacks
|
20
|
+
var json
|
21
|
+
try {
|
22
|
+
if (event.detail) {
|
23
|
+
json = JSON.parse(event.detail[2].response)
|
24
|
+
status = event.detail[1]
|
25
|
+
} else {
|
26
|
+
json = xhr.responseJSON
|
27
|
+
}
|
28
|
+
} catch(ex) {
|
29
|
+
status = 'error'
|
30
|
+
json = {}
|
31
|
+
}
|
32
|
+
|
33
|
+
if (status == 'OK' || status == 'success') {
|
34
|
+
$form.append(
|
35
|
+
$('<span>').text(json.message).delay(2000).fadeOut(2000, function() { $(this).remove() })
|
36
|
+
)
|
37
|
+
$('input:visible, textarea', $form).val('')
|
38
|
+
$('.alert', $form).remove()
|
39
|
+
if (typeof window.grecaptcha != 'undefined') {
|
40
|
+
window.grecaptcha.reset()
|
41
|
+
}
|
42
|
+
} else if (json.message) {
|
43
|
+
$form.append(warningAlert(json.message))
|
44
|
+
} else {
|
45
|
+
$form.append(warningAlert('Sorry, something went wrong.'))
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
$('[data-contact-form]').each(function(_, input) {
|
50
|
+
var $form = $(input)
|
51
|
+
|
52
|
+
$form.on('ajax:success', function(event, data, status, xhr) {
|
53
|
+
try {
|
54
|
+
handleResponse($form, event, status, xhr)
|
55
|
+
} catch(ex) {
|
56
|
+
alert('Sorry, something went wrong.')
|
57
|
+
throw ex
|
58
|
+
}
|
59
|
+
})
|
60
|
+
|
61
|
+
$form.on('ajax:error', function(event, xhr, status) {
|
62
|
+
try {
|
63
|
+
handleResponse($form, event, status, xhr)
|
64
|
+
} catch(ex) {
|
65
|
+
alert('Sorry, something went wrong.')
|
66
|
+
throw ex
|
67
|
+
}
|
68
|
+
})
|
69
|
+
})
|
70
|
+
})
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree .
|
@@ -0,0 +1,39 @@
|
|
1
|
+
.section-faq {
|
2
|
+
&__show-more-button {
|
3
|
+
text-decoration: none;
|
4
|
+
|
5
|
+
&[aria-expanded='false'] {
|
6
|
+
.section-faq__show-more-button__expanded {
|
7
|
+
display: none;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
&[aria-expanded='true'] {
|
12
|
+
.section-faq__show-more-button__collapsed {
|
13
|
+
display: none;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
&__faq-question {
|
19
|
+
cursor: pointer;
|
20
|
+
}
|
21
|
+
|
22
|
+
&__expander {
|
23
|
+
display: flex;
|
24
|
+
text-align: right;
|
25
|
+
|
26
|
+
a {
|
27
|
+
text-decoration: none;
|
28
|
+
width: 100%;
|
29
|
+
|
30
|
+
&[aria-expanded='false']::before {
|
31
|
+
content: '+';
|
32
|
+
}
|
33
|
+
|
34
|
+
&[aria-expanded='true']::before {
|
35
|
+
content: '-';
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class WCC::Contentful::App::ContactFormController < ApplicationController
|
4
|
+
include WCC::Contentful::App::PreviewPassword
|
5
|
+
|
6
|
+
def create
|
7
|
+
address =
|
8
|
+
form_model.to_address(email_object_id: params[:email_object_id])
|
9
|
+
|
10
|
+
form_model.send_email(
|
11
|
+
form_params.merge!(
|
12
|
+
{
|
13
|
+
notification_email: address,
|
14
|
+
internal_title: params[:internal_title]
|
15
|
+
}
|
16
|
+
)
|
17
|
+
)
|
18
|
+
|
19
|
+
render json: { type: 'success', message: "Thanks for reaching out. We'll be in touch soon!" }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def form_model
|
25
|
+
raise ArgumentError, 'missing form ID' unless params[:id]
|
26
|
+
|
27
|
+
@form_model ||= form_class.find(
|
28
|
+
params[:id], options: { preview: preview? }
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def form_class
|
33
|
+
WCC::Contentful::Model.resolve_constant('section-contact-form')
|
34
|
+
end
|
35
|
+
|
36
|
+
def form_params
|
37
|
+
params.slice(*form_model.fields.map(&:title))
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class WCC::Contentful::App::PagesController < ApplicationController
|
4
|
+
include WCC::Contentful::App::PreviewPassword
|
5
|
+
|
6
|
+
helper ::WCC::Contentful::App::SectionHelper
|
7
|
+
|
8
|
+
def index
|
9
|
+
@page = global_site_config&.homepage ||
|
10
|
+
page_model.find_by(slug: '/', options: { include: 3, preview: preview? })
|
11
|
+
render 'pages/show'
|
12
|
+
end
|
13
|
+
|
14
|
+
def show
|
15
|
+
slug = '/' + params[:slug]
|
16
|
+
@page = page_model.find_by(slug: slug, options: { include: 3, preview: preview? })
|
17
|
+
|
18
|
+
return render 'pages/show' if @page
|
19
|
+
|
20
|
+
redirect = redirect_model.find_by(slug: slug, options: { include: 0, preview: preview? })
|
21
|
+
raise WCC::Contentful::App::PageNotFoundError, slug unless redirect
|
22
|
+
|
23
|
+
redirect_to redirect.href
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def page_model
|
29
|
+
WCC::Contentful::Model.resolve_constant('page')
|
30
|
+
end
|
31
|
+
|
32
|
+
def redirect_model
|
33
|
+
WCC::Contentful::Model.resolve_constant('redirect')
|
34
|
+
end
|
35
|
+
|
36
|
+
def site_config_model
|
37
|
+
# They may have not installed `site-config` in the project
|
38
|
+
WCC::Contentful::Model.resolve_constant('site-config')
|
39
|
+
rescue WCC::Contentful::ContentTypeNotFoundError
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def global_site_config
|
44
|
+
return unless model = site_config_model
|
45
|
+
|
46
|
+
@global_site_config ||= model.instance(preview?)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WCC::Contentful::App::MenuHelper
|
4
|
+
def dropdown?(item)
|
5
|
+
item.respond_to?(:items)
|
6
|
+
end
|
7
|
+
|
8
|
+
def menu_button?(item)
|
9
|
+
item.is_a? WCC::Contentful::Model::MenuButton
|
10
|
+
end
|
11
|
+
|
12
|
+
def item_active?(item)
|
13
|
+
return true if item.try(:label) && item_active?(item.label)
|
14
|
+
return item.items.any? { |i| item_active?(i) } if item.respond_to?(:items)
|
15
|
+
return current_page?(item.href) if item.try(:href)
|
16
|
+
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_button(button, options = {}, &block)
|
21
|
+
html = render_button_inner_html(button, options, &block)
|
22
|
+
|
23
|
+
if button.try(:external?)
|
24
|
+
push_class('external', options)
|
25
|
+
options[:target] = :_blank
|
26
|
+
end
|
27
|
+
if button.icon.present? || button.material_icon.present? || options.dig(:icon, :fallback)
|
28
|
+
push_class('icon-only', options) unless button.text.present?
|
29
|
+
elsif button.text.present?
|
30
|
+
push_class('text-only', options)
|
31
|
+
end
|
32
|
+
|
33
|
+
push_class(button.style, options) if button.style
|
34
|
+
|
35
|
+
href = button.href
|
36
|
+
href = hash_only(href) if href.present? && local?(href)
|
37
|
+
return link_to(html, href, options) if href.present?
|
38
|
+
|
39
|
+
content_tag(:a, html, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_button_inner_html(button, options = {}, &block)
|
43
|
+
html = render_button_icon(button.icon, options.delete(:icon)) || ''.html_safe
|
44
|
+
html += render_button_material_icon(button.material_icon) + content_tag(:span, button.text)
|
45
|
+
|
46
|
+
html += capture(&block) if block_given?
|
47
|
+
html
|
48
|
+
end
|
49
|
+
|
50
|
+
def render_button_icon(icon, options = {})
|
51
|
+
fallback = options&.delete(:fallback)
|
52
|
+
return fallback&.call unless icon
|
53
|
+
|
54
|
+
options = {
|
55
|
+
alt: icon.description || icon.title,
|
56
|
+
width: icon.file.dig('details', 'image', 'width'),
|
57
|
+
height: icon.file.dig('details', 'image', 'height')
|
58
|
+
}.merge!(options || {})
|
59
|
+
image_tag(icon&.file&.url, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def render_button_material_icon(material_icon)
|
63
|
+
content_tag(:i, material_icon&.downcase, class: ['material-icons'])
|
64
|
+
end
|
65
|
+
|
66
|
+
def push_class(classes, options)
|
67
|
+
options[:class] = [*classes, *options[:class]]
|
68
|
+
end
|
69
|
+
|
70
|
+
def hash_only(href)
|
71
|
+
url = URI(href)
|
72
|
+
'#' + url.fragment if url.fragment.present?
|
73
|
+
end
|
74
|
+
|
75
|
+
# An href is local if it points to a part of the page
|
76
|
+
def local?(href)
|
77
|
+
return true if href =~ /^#/
|
78
|
+
|
79
|
+
url = URI(href)
|
80
|
+
return false unless url.fragment.present?
|
81
|
+
|
82
|
+
url.fragment = nil
|
83
|
+
current_page?(url.to_s)
|
84
|
+
end
|
85
|
+
end
|