wcc-contentful-app 0.4.0.pre.rc → 1.0.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +2 -2
- data/Guardfile +1 -1
- data/README.md +11 -0
- data/Rakefile +121 -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/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 +15 -15
- metadata +164 -103
- 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: cfa9d4f23576789c57eec32e281809dbe73ecacd6b5c5bf77a2e1f2901735a66
|
4
|
+
data.tar.gz: 76e260820f5b44b8191205464ee3aa653764b1b4a78f69669f2eef13240d2573
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f9090104d47faf28821061231614f975fb4f5365ec8b38bef38f94fb90c40ddcddcb25a59973ac1bd1dcc27c864958ed9cf4bbcc8fe9f39812cd976421e214c
|
7
|
+
data.tar.gz: 4def3fae3ac934d36c238d166bf1cf524ead5c6a640b9cf8f2929c22987a7d962c2bbfc2b45a70e7061494a1f9110728747af4ad7f287a9cb93df4025160e028
|
data/.rspec
CHANGED
data/Guardfile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
./../wcc-contentful/Guardfile
|
data/README.md
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/wcc-contentful-app.svg)](https://rubygems.org/gems/wcc-contentful-app)
|
2
|
+
[![Build Status](https://travis-ci.org/watermarkchurch/wcc-contentful.svg?branch=master)](https://travis-ci.org/watermarkchurch/wcc-contentful)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/github/watermarkchurch/wcc-contentful/badge.svg?branch=master)](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,121 @@
|
|
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
|
@@ -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
|