content_block_tools 1.0.2 → 1.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.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/content_block_tools.scss +1 -0
  3. data/lib/content_block_tools/components/base_component.rb +15 -0
  4. data/lib/content_block_tools/components/contact_component.html.erb +18 -0
  5. data/lib/content_block_tools/components/contact_component.rb +31 -0
  6. data/lib/content_block_tools/components/contacts/address_component.html.erb +5 -0
  7. data/lib/content_block_tools/components/contacts/address_component.rb +44 -0
  8. data/lib/content_block_tools/components/contacts/contact_link_component.html.erb +12 -0
  9. data/lib/content_block_tools/components/contacts/contact_link_component.rb +21 -0
  10. data/lib/content_block_tools/components/contacts/email_address_component.html.erb +12 -0
  11. data/lib/content_block_tools/components/contacts/email_address_component.rb +30 -0
  12. data/lib/content_block_tools/components/contacts/telephone_component.html.erb +32 -0
  13. data/lib/content_block_tools/components/contacts/telephone_component.rb +53 -0
  14. data/lib/content_block_tools/content_block.rb +85 -12
  15. data/lib/content_block_tools/presenters/field_presenters/contact/{email_address_presenter.rb → email_presenter.rb} +1 -1
  16. data/lib/content_block_tools/version.rb +1 -1
  17. data/lib/content_block_tools.rb +14 -11
  18. metadata +41 -11
  19. data/lib/content_block_tools/presenters/base_presenter.rb +0 -138
  20. data/lib/content_block_tools/presenters/block_presenters/base_presenter.rb +0 -21
  21. data/lib/content_block_tools/presenters/block_presenters/contact/address_presenter.rb +0 -42
  22. data/lib/content_block_tools/presenters/block_presenters/contact/block_level_contact_item.rb +0 -34
  23. data/lib/content_block_tools/presenters/block_presenters/contact/contact_link_presenter.rb +0 -41
  24. data/lib/content_block_tools/presenters/block_presenters/contact/email_address_presenter.rb +0 -50
  25. data/lib/content_block_tools/presenters/block_presenters/contact/telephone_presenter.rb +0 -83
  26. data/lib/content_block_tools/presenters/contact_presenter.rb +0 -40
  27. data/lib/content_block_tools/presenters/pension_presenter.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12237d984dd481c7d46d14b86cde8ecbafa25f3a5fb5880004ffebcda3a128e9
4
- data.tar.gz: 32b6a8c2b1102950408b6bb18f4ddf5681a0a8455db0de599cec49335cf096d6
3
+ metadata.gz: d6e2e8e76c7ac69f15bcb193069f82be59acdd78b7291812cbff6f896e6c8c87
4
+ data.tar.gz: f46aa1f1fac9b526a45811b367db042c4d9f48b29c9f629fb708cdf0693ad299
5
5
  SHA512:
6
- metadata.gz: 5fddff7d9d2964c7e0c46e05b98eb71b2d033a885f918663455d856aaaa5b3ec38ab4dd9fd9d9f396debcc739b65c97e462a31a40c78da3d81f02bd9dda4fa4b
7
- data.tar.gz: 24a69d66c20764ef4328500b7bf6736a20a12e0e745340f30981dc457ab009fa968591893f9504ec3d0961f9f9ff7bd44a542ef64fa3a6854a9e83e16e19091f
6
+ metadata.gz: 62173df5e11a6023a91f7f2c39378098c89293ae6f5db96aa2289aca1f9cdbc030d5ed932b2d8fba1dc914d8514e3e87cb240c2377f034968b5ccfe47c515675
7
+ data.tar.gz: fb9389766399957affb5c8c45640bd4324f26c383057ec3e458fbf2719b6dfe7eca81c7006294b041b1ca5fc65e51280ace5b632a1de513149061f2dc753563a
@@ -1,3 +1,4 @@
1
+ @import "govuk/core/links";
1
2
  @import "govuk/core/lists";
2
3
  @import "govuk/core/typography";
3
4
 
@@ -0,0 +1,15 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ class BaseComponent < ViewComponent::Base
4
+ def render
5
+ render_in(view_context)
6
+ end
7
+
8
+ private
9
+
10
+ def view_context
11
+ ActionView::Base.new(ActionView::LookupContext.new([]), {}, nil)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ <div class="vcard">
2
+ <p class="fn org content-block__title"><%= content_block.title %></p>
3
+
4
+ <% if block_type.present? && content_block.details[:description] %>
5
+ <%= render_govspeak(content_block.details[:description]) %>
6
+ <% end %>
7
+
8
+ <% if block_type.nil? %>
9
+ <% BLOCK_TYPES.each do |block_type| %>
10
+ <% content_by_block_type[block_type].each do |item| %>
11
+ <p class="content-block__subtitle"><%= item[:title] %></p>
12
+ <%= component_for_block_type(block_type).new(item:).render.html_safe %>
13
+ <% end %>
14
+ <% end %>
15
+ <% else %>
16
+ <%= component_for_block_type(block_type).new(item: item_to_render).render.html_safe %>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,31 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ class ContactComponent < ContentBlockTools::Components::BaseComponent
4
+ BLOCK_TYPES = %i[addresses email_addresses telephones contact_links].freeze
5
+
6
+ def initialize(content_block:, block_type: nil, block_name: nil)
7
+ @content_block = content_block
8
+ @block_type = block_type
9
+ @block_name = block_name
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :content_block, :block_type, :block_name
15
+
16
+ def component_for_block_type(block_type)
17
+ "ContentBlockTools::Components::Contacts::#{block_type.to_s.singularize.camelize}Component".constantize
18
+ end
19
+
20
+ def content_by_block_type
21
+ @content_by_block_type ||= content_block.details.keys.map { |key|
22
+ [key, content_block.details[key]&.values]
23
+ }.to_h
24
+ end
25
+
26
+ def item_to_render
27
+ content_block.details.dig(block_type, block_name)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ <p class="adr content-block__body">
2
+ <%= lines.map { |field, value| address_line(field, value) }.join(",<br />").html_safe %>
3
+ </p>
4
+
5
+ <%= render_govspeak(item[:description]) if item[:description].present? %>
@@ -0,0 +1,44 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ module Contacts
4
+ class AddressComponent < ContentBlockTools::Components::BaseComponent
5
+ include ContentBlockTools::Govspeak
6
+
7
+ def initialize(item:)
8
+ @item = item
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :item
14
+
15
+ def lines
16
+ address_parts.map { |attribute|
17
+ next if item[attribute].blank?
18
+
19
+ [attribute, item[attribute]]
20
+ }.compact.to_h
21
+ end
22
+
23
+ def address_parts
24
+ %i[recipient street_address town_or_city state_or_county postal_code country]
25
+ end
26
+
27
+ def address_line(field, value)
28
+ content_tag(:span, value, { class: class_for_field_name(field) })
29
+ end
30
+
31
+ def class_for_field_name(field_name)
32
+ {
33
+ recipient: "organization-name",
34
+ street_address: "street-address",
35
+ town_or_city: "locality",
36
+ state_or_county: "region",
37
+ postal_code: "postal-code",
38
+ country: "country-name",
39
+ }[field_name]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ <ul class="content-block__list">
2
+ <li>
3
+ <a href="<%= item[:url] %>" class="url content-block__link">
4
+ <%= link_text %>
5
+ </a>
6
+ </li>
7
+ <% if item[:description] %>
8
+ <li>
9
+ <%= render_govspeak(item[:description]) %>
10
+ </li>
11
+ <% end %>
12
+ </ul>
@@ -0,0 +1,21 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ module Contacts
4
+ class ContactLinkComponent < ContentBlockTools::Components::BaseComponent
5
+ include ContentBlockTools::Govspeak
6
+
7
+ def initialize(item:)
8
+ @item = item
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :item
14
+
15
+ def link_text
16
+ item[:label] || item[:url]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ <ul class="content-block__list">
2
+ <li>
3
+ <a href="<%= "mailto:#{item[:email_address]}#{query_params}" %>" class="email content-block__link">
4
+ <%= link_text %>
5
+ </a>
6
+ </li>
7
+ <% if item[:description] %>
8
+ <li>
9
+ <%= render_govspeak(item[:description]) %>
10
+ </li>
11
+ <% end %>
12
+ </ul>
@@ -0,0 +1,30 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ module Contacts
4
+ class EmailAddressComponent < ContentBlockTools::Components::BaseComponent
5
+ include ContentBlockTools::Govspeak
6
+
7
+ def initialize(item:)
8
+ @item = item
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :item
14
+
15
+ def query_params
16
+ params = {
17
+ subject: item[:subject],
18
+ body: item[:body],
19
+ }.compact.map { |k, v| "#{k}=#{v}" }.join("&")
20
+
21
+ "?#{params}" if params.present?
22
+ end
23
+
24
+ def link_text
25
+ item[:label] || item[:email_address]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ <% if item[:description] %>
2
+ <%= render_govspeak(item[:description], root_class: "content-block__body") %>
3
+ <% end %>
4
+
5
+ <ul class="content-block__list">
6
+ <% item[:telephone_numbers].each do |number| %>
7
+ <li>
8
+ <span><%= number[:label] %>: </span>
9
+ <span class="tel"><%= number[:telephone_number] %></span>
10
+ </li>
11
+ <% end %>
12
+ </ul>
13
+
14
+ <% if show_video_relay_service? %>
15
+ <%= render_govspeak(video_relay_service_content) %>
16
+ <% end %>
17
+
18
+ <% if show_bsl_guidance? %>
19
+ <%= render_govspeak(bsl_guidance[:value], root_class: "content-block__body") %>
20
+ <% end %>
21
+
22
+ <% if show_opening_hours? %>
23
+ <%= render_govspeak(opening_hours[:opening_hours], root_class: "content-block__body") %>
24
+ <% end %>
25
+
26
+ <% if show_call_charges? %>
27
+ <p class="content-block__body">
28
+ <a href="<%= call_charges[:call_charges_info_url] %>" class="content-block__link">
29
+ <%= call_charges[:label] %>
30
+ </a>
31
+ </p>
32
+ <% end %>
@@ -0,0 +1,53 @@
1
+ module ContentBlockTools
2
+ module Components
3
+ module Contacts
4
+ class TelephoneComponent < ContentBlockTools::Components::BaseComponent
5
+ include ContentBlockTools::Govspeak
6
+
7
+ def initialize(item:)
8
+ @item = item
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :item
14
+
15
+ def video_relay_service
16
+ @video_relay_service ||= item[:video_relay_service] || {}
17
+ end
18
+
19
+ def show_video_relay_service?
20
+ video_relay_service[:show].present?
21
+ end
22
+
23
+ def video_relay_service_content
24
+ "#{video_relay_service[:prefix]} #{video_relay_service[:telephone_number]}"
25
+ end
26
+
27
+ def bsl_guidance
28
+ @bsl_guidance ||= item[:bsl_guidance] || {}
29
+ end
30
+
31
+ def show_bsl_guidance?
32
+ bsl_guidance[:show].present?
33
+ end
34
+
35
+ def opening_hours
36
+ @opening_hours ||= item[:opening_hours] || {}
37
+ end
38
+
39
+ def show_opening_hours?
40
+ opening_hours[:show_opening_hours].present?
41
+ end
42
+
43
+ def call_charges
44
+ @call_charges ||= item[:call_charges] || {}
45
+ end
46
+
47
+ def show_call_charges?
48
+ call_charges[:show_call_charges_info_url].present?
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,6 +1,4 @@
1
1
  module ContentBlockTools
2
- ContentBlock = Data.define(:content_id, :title, :document_type, :details, :embed_code)
3
-
4
2
  # Defines a Content Block
5
3
  #
6
4
  # @api public
@@ -40,25 +38,100 @@ module ContentBlockTools
40
38
  # content_block_reference.embed_code #=> "{{embed:content_block_pension:2b92cade-549c-4449-9796-e7a3957f3a86}}"
41
39
  # content_block_reference.embed_code #=> "{{embed:content_block_contact:2b92cade-549c-4449-9796-e7a3957f3a86/field_name}}"
42
40
  # @return [String]
43
- class ContentBlock < Data
44
- # A lookup of presenters for particular content block types
45
- CONTENT_PRESENTERS = {
46
- "content_block_contact" => ContentBlockTools::Presenters::ContactPresenter,
47
- "content_block_pension" => ContentBlockTools::Presenters::PensionPresenter,
48
- }.freeze
41
+ class ContentBlock
42
+ include ActionView::Helpers::TagHelper
43
+
44
+ CONTENT_BLOCK_PREFIX = "content_block_".freeze
45
+
46
+ attr_reader :content_id, :title, :embed_code
47
+
48
+ def initialize(content_id:, title:, document_type:, details:, embed_code:)
49
+ @content_id = content_id
50
+ @title = title
51
+ @document_type = document_type
52
+ @details = details
53
+ @embed_code = embed_code
54
+ end
49
55
 
50
56
  # Calls the appropriate presenter class to return a HTML representation of a content
51
57
  # block. Defaults to {Presenters::BasePresenter}
52
58
  #
53
59
  # @return [string] A HTML representation of the content block
54
60
  def render
55
- CONTENT_PRESENTERS
56
- .fetch(document_type, Presenters::BasePresenter)
57
- .new(self).render
61
+ content_tag(
62
+ base_tag,
63
+ content,
64
+ class: %W[content-block content-block--#{document_type}],
65
+ data: {
66
+ content_block: "",
67
+ document_type: document_type,
68
+ content_id: content_id,
69
+ embed_code: embed_code,
70
+ },
71
+ )
58
72
  end
59
73
 
60
74
  def details
61
- to_h[:details].deep_symbolize_keys
75
+ @details.deep_symbolize_keys
76
+ end
77
+
78
+ def document_type
79
+ @document_type.delete_prefix(CONTENT_BLOCK_PREFIX)
80
+ end
81
+
82
+ private
83
+
84
+ def base_tag
85
+ rendering_block? ? :div : :span
86
+ end
87
+
88
+ def content
89
+ field_names.present? ? field_or_block_content : component.new(content_block: self).render
90
+ rescue NameError
91
+ title
92
+ end
93
+
94
+ def field_or_block_content
95
+ content = details.dig(*field_names)
96
+ case content
97
+ when String
98
+ field_presenter(field_names.last).new(content).render
99
+ when Hash
100
+ component.new(content_block: self, block_type: field_names.first, block_name: field_names.last).render
101
+ else
102
+ ContentBlockTools.logger.warn("Content not found for content block #{content_id} and fields #{field_names}")
103
+ embed_code
104
+ end
105
+ end
106
+
107
+ def rendering_block?
108
+ !field_names.present? || details.dig(*field_names).is_a?(Hash)
109
+ end
110
+
111
+ def component
112
+ "ContentBlockTools::Components::#{document_type.camelize}Component".constantize
113
+ end
114
+
115
+ def field_presenter(field)
116
+ "ContentBlockTools::Presenters::FieldPresenters::#{document_type.camelize}::#{field.to_s.camelize}Presenter".constantize
117
+ rescue NameError
118
+ ContentBlockTools::Presenters::FieldPresenters::BasePresenter
119
+ end
120
+
121
+ def field_names
122
+ @field_names ||= begin
123
+ embed_code_match = ContentBlockReference::EMBED_REGEX.match(embed_code)
124
+ if embed_code_match.present?
125
+ all_fields = embed_code_match[4]&.reverse&.chomp("/")&.reverse
126
+ all_fields&.split("/")&.map do |item|
127
+ is_number?(item) ? item.to_i : item.to_sym
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ def is_number?(item)
134
+ Float(item, exception: false)
62
135
  end
63
136
  end
64
137
  end
@@ -2,7 +2,7 @@ module ContentBlockTools
2
2
  module Presenters
3
3
  module FieldPresenters
4
4
  module Contact
5
- class EmailAddressPresenter < BasePresenter
5
+ class EmailPresenter < BasePresenter
6
6
  def render
7
7
  content_tag(:a, field, class: "govuk-link", href: "mailto:#{field}")
8
8
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ContentBlockTools
4
- VERSION = "1.0.2"
4
+ VERSION = "1.1.0"
5
5
  end
@@ -1,23 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "action_view"
4
+ require "rails"
4
5
  require "uri"
5
6
  require "govspeak"
7
+ require "view_component/base"
6
8
 
7
9
  require "content_block_tools/helpers/govspeak"
8
10
 
9
- require "content_block_tools/presenters/field_presenters/base_presenter"
10
- require "content_block_tools/presenters/field_presenters/contact/email_address_presenter"
11
-
12
- require "content_block_tools/presenters/block_presenters/base_presenter"
13
- require "content_block_tools/presenters/block_presenters/contact/address_presenter"
14
- require "content_block_tools/presenters/block_presenters/contact/contact_link_presenter"
15
- require "content_block_tools/presenters/block_presenters/contact/email_address_presenter"
16
- require "content_block_tools/presenters/block_presenters/contact/telephone_presenter"
11
+ require "content_block_tools/components/base_component"
12
+ require "content_block_tools/components/contact_component"
13
+ require "content_block_tools/components/contacts/address_component"
14
+ require "content_block_tools/components/contacts/contact_link_component"
15
+ require "content_block_tools/components/contacts/email_address_component"
16
+ require "content_block_tools/components/contacts/telephone_component"
17
17
 
18
- require "content_block_tools/presenters/base_presenter"
19
- require "content_block_tools/presenters/contact_presenter"
20
- require "content_block_tools/presenters/pension_presenter"
18
+ require "content_block_tools/presenters/field_presenters/base_presenter"
19
+ require "content_block_tools/presenters/field_presenters/contact/email_presenter"
21
20
 
22
21
  require "content_block_tools/content_block"
23
22
  require "content_block_tools/content_block_reference"
@@ -30,6 +29,10 @@ module ContentBlockTools
30
29
  class Error < StandardError; end
31
30
  module Presenters; end
32
31
 
32
+ module Components
33
+ module Contacts; end
34
+ end
35
+
33
36
  class << self
34
37
  attr_writer :logger
35
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: content_block_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
@@ -93,6 +93,34 @@ dependencies:
93
93
  - - '='
94
94
  - !ruby/object:Gem::Version
95
95
  version: 10.6.1
96
+ - !ruby/object:Gem::Dependency
97
+ name: rails
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: view_component
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '='
115
+ - !ruby/object:Gem::Version
116
+ version: 4.0.1
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '='
122
+ - !ruby/object:Gem::Version
123
+ version: 4.0.1
96
124
  email:
97
125
  - govuk-dev@digital.cabinet-office.gov.uk
98
126
  executables: []
@@ -103,21 +131,23 @@ files:
103
131
  - app/assets/stylesheets/blocks/_contact.scss
104
132
  - app/assets/stylesheets/content_block_tools.scss
105
133
  - lib/content_block_tools.rb
134
+ - lib/content_block_tools/components/base_component.rb
135
+ - lib/content_block_tools/components/contact_component.html.erb
136
+ - lib/content_block_tools/components/contact_component.rb
137
+ - lib/content_block_tools/components/contacts/address_component.html.erb
138
+ - lib/content_block_tools/components/contacts/address_component.rb
139
+ - lib/content_block_tools/components/contacts/contact_link_component.html.erb
140
+ - lib/content_block_tools/components/contacts/contact_link_component.rb
141
+ - lib/content_block_tools/components/contacts/email_address_component.html.erb
142
+ - lib/content_block_tools/components/contacts/email_address_component.rb
143
+ - lib/content_block_tools/components/contacts/telephone_component.html.erb
144
+ - lib/content_block_tools/components/contacts/telephone_component.rb
106
145
  - lib/content_block_tools/content_block.rb
107
146
  - lib/content_block_tools/content_block_reference.rb
108
147
  - lib/content_block_tools/engine.rb
109
148
  - lib/content_block_tools/helpers/govspeak.rb
110
- - lib/content_block_tools/presenters/base_presenter.rb
111
- - lib/content_block_tools/presenters/block_presenters/base_presenter.rb
112
- - lib/content_block_tools/presenters/block_presenters/contact/address_presenter.rb
113
- - lib/content_block_tools/presenters/block_presenters/contact/block_level_contact_item.rb
114
- - lib/content_block_tools/presenters/block_presenters/contact/contact_link_presenter.rb
115
- - lib/content_block_tools/presenters/block_presenters/contact/email_address_presenter.rb
116
- - lib/content_block_tools/presenters/block_presenters/contact/telephone_presenter.rb
117
- - lib/content_block_tools/presenters/contact_presenter.rb
118
149
  - lib/content_block_tools/presenters/field_presenters/base_presenter.rb
119
- - lib/content_block_tools/presenters/field_presenters/contact/email_address_presenter.rb
120
- - lib/content_block_tools/presenters/pension_presenter.rb
150
+ - lib/content_block_tools/presenters/field_presenters/contact/email_presenter.rb
121
151
  - lib/content_block_tools/version.rb
122
152
  - node_modules/govuk-frontend/README.md
123
153
  - node_modules/govuk-frontend/dist/govuk-prototype-kit/functions.js
@@ -1,138 +0,0 @@
1
- module ContentBlockTools
2
- module Presenters
3
- class BasePresenter
4
- include ActionView::Context
5
- include ActionView::Helpers::TagHelper
6
-
7
- # The default HTML tag to wrap the presented response in - can be overridden in a subclass
8
- BASE_TAG_TYPE = :span
9
-
10
- # A lookup of presenters for particular fields - can be overridden in a subclass
11
- FIELD_PRESENTERS = {}.freeze
12
-
13
- # A lookup of presenters for particular blocks - can be overridden in a subclass
14
- BLOCK_PRESENTERS = {}.freeze
15
-
16
- def self.has_embedded_objects(*object_types)
17
- @embedded_objects = object_types
18
-
19
- object_types.each do |object_type|
20
- define_method(object_type) do
21
- embedded_objects_of_type(object_type)
22
- end
23
- end
24
- end
25
-
26
- # Returns a new presenter object
27
- #
28
- # @param [{ContentBlockTools::ContentBlock}] content_block A content block object
29
- #
30
- # @return [{ContentBlockTools::Presenters::BasePresenter}]
31
- def initialize(content_block)
32
- @content_block = content_block
33
- end
34
-
35
- # Returns a HTML representation of the content block wrapped in a base tag with
36
- # a class and data attributes
37
- # Calls the {#content} method, which can be overridden in a subclass
38
- #
39
- # @return [string] A HTML representation of the content block
40
- def render
41
- content_tag(
42
- base_tag,
43
- content,
44
- class: %W[content-block content-block--#{document_type}],
45
- data: {
46
- content_block: "",
47
- document_type: document_type,
48
- content_id: content_block.content_id,
49
- embed_code: content_block.embed_code,
50
- },
51
- )
52
- end
53
-
54
- private
55
-
56
- attr_reader :content_block
57
-
58
- # The default representation of the content block - this can be overridden in a subclass
59
- # by overriding the content, default_content or content_for_fields methods
60
- #
61
- # @return [string] A representation of the content block to be wrapped in the base_tag in
62
- # {#content}
63
- def content
64
- ContentBlockTools.logger.info("Getting content for content block #{content_block.content_id}")
65
- field_names.present? ? content_for_field_names : default_content
66
- end
67
-
68
- def default_content
69
- content_block.title
70
- end
71
-
72
- def content_for_field_names
73
- if field_or_block_content.blank?
74
- ContentBlockTools.logger.warn("Content not found for content block #{content_block.content_id} and fields #{field_names}")
75
- return content_block.embed_code
76
- end
77
-
78
- field_or_block_presenter.new(field_or_block_content, rendering_context: :field_names, content_block:).render
79
- end
80
-
81
- def field_names
82
- @field_names ||= begin
83
- embed_code_match = ContentBlockReference::EMBED_REGEX.match(content_block.embed_code)
84
- if embed_code_match.present?
85
- all_fields = embed_code_match[4]&.reverse&.chomp("/")&.reverse
86
- all_fields&.split("/")&.map do |item|
87
- is_number?(item) ? item.to_i : item.to_sym
88
- end
89
- end
90
- end
91
- end
92
-
93
- def is_number?(item)
94
- Float(item, exception: false)
95
- end
96
-
97
- def field_or_block_content
98
- @field_or_block_content ||= field_names.any? ? content_block.details.deep_symbolize_keys.dig(*field_names) : nil
99
- end
100
-
101
- def rendering_block?
102
- field_or_block_content.is_a?(Hash)
103
- end
104
-
105
- def field_or_block_presenter
106
- @field_or_block_presenter ||= if rendering_block?
107
- block_presenter || ContentBlockTools::Presenters::BlockPresenters::BasePresenter
108
- else
109
- field_presenter || ContentBlockTools::Presenters::FieldPresenters::BasePresenter
110
- end
111
- end
112
-
113
- def field_presenter
114
- @field_presenter ||= field_names ? self.class::FIELD_PRESENTERS[field_names.last] : nil
115
- end
116
-
117
- def block_presenter
118
- @block_presenter ||= field_names ? self.class::BLOCK_PRESENTERS[field_names.first] : nil
119
- end
120
-
121
- def base_tag
122
- field_names ? field_or_block_presenter::BASE_TAG_TYPE : self.class::BASE_TAG_TYPE
123
- end
124
-
125
- def embedded_objects_of_type(type)
126
- content_block.details.fetch(type, {}).values
127
- end
128
-
129
- def embedded_objects
130
- self.class.instance_variable_get("@embedded_objects")
131
- end
132
-
133
- def document_type
134
- content_block.document_type.delete_prefix("content_block_")
135
- end
136
- end
137
- end
138
- end
@@ -1,21 +0,0 @@
1
- module ContentBlockTools
2
- module Presenters
3
- module BlockPresenters
4
- class BasePresenter
5
- include ActionView::Context
6
- include ActionView::Helpers::TextHelper
7
- include ContentBlockTools::Govspeak
8
-
9
- BASE_TAG_TYPE = :span
10
-
11
- attr_reader :item
12
-
13
- def initialize(item, **_args)
14
- @item = item
15
- end
16
-
17
- def render; end
18
- end
19
- end
20
- end
21
- end
@@ -1,42 +0,0 @@
1
- require_relative "./block_level_contact_item"
2
-
3
- module ContentBlockTools
4
- module Presenters
5
- module BlockPresenters
6
- module Contact
7
- class AddressPresenter < ContentBlockTools::Presenters::BlockPresenters::BasePresenter
8
- include ContentBlockTools::Presenters::BlockPresenters::Contact::BlockLevelContactItem
9
-
10
- def render
11
- wrapper do
12
- output = []
13
-
14
- output << content_tag(:p, class: "adr content-block__body") do
15
- %i[recipient street_address town_or_city state_or_county postal_code country].map { |field|
16
- next if item[field].blank?
17
-
18
- content_tag(:span, item[field], { class: class_for_field_name(field) })
19
- }.compact_blank.join(",<br/>").html_safe
20
- end
21
-
22
- output << render_govspeak(item[:description]) if item[:description].present?
23
-
24
- output.join.html_safe
25
- end
26
- end
27
-
28
- def class_for_field_name(field_name)
29
- {
30
- recipient: "organization-name",
31
- street_address: "street-address",
32
- town_or_city: "locality",
33
- state_or_county: "region",
34
- postal_code: "postal-code",
35
- country: "country-name",
36
- }[field_name]
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,34 +0,0 @@
1
- module ContentBlockTools
2
- module Presenters
3
- module BlockPresenters
4
- module Contact
5
- module BlockLevelContactItem
6
- BASE_TAG_TYPE = :div
7
-
8
- def initialize(item, content_block:, rendering_context: :block, **_args)
9
- @item = item
10
- @content_block = content_block
11
- @rendering_context = rendering_context
12
- end
13
-
14
- def wrapper(&block)
15
- content_tag(:div) do
16
- concat title
17
- concat yield block
18
- end
19
- end
20
-
21
- def title
22
- if @rendering_context == :field_names
23
- content_tag(:p,
24
- @content_block.title,
25
- class: "content-block__title")
26
- else
27
- content_tag(:p, item[:title], class: "content-block__subtitle")
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,41 +0,0 @@
1
- require_relative "./block_level_contact_item"
2
-
3
- module ContentBlockTools
4
- module Presenters
5
- module BlockPresenters
6
- module Contact
7
- class ContactLinkPresenter < ContentBlockTools::Presenters::BlockPresenters::BasePresenter
8
- include ContentBlockTools::Presenters::BlockPresenters::Contact::BlockLevelContactItem
9
-
10
- def render
11
- wrapper do
12
- content_tag(:ul, class: "content-block__list") do
13
- concat link
14
- concat description if item[:description]
15
- end
16
- end
17
- end
18
-
19
- def link
20
- content_tag(:li) do
21
- content_tag(:a,
22
- link_text,
23
- class: "url content-block__link",
24
- href: item[:url])
25
- end
26
- end
27
-
28
- def link_text
29
- item[:label] || item[:url]
30
- end
31
-
32
- def description
33
- content_tag(:li) do
34
- render_govspeak(item[:description])
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,50 +0,0 @@
1
- require_relative "./block_level_contact_item"
2
-
3
- module ContentBlockTools
4
- module Presenters
5
- module BlockPresenters
6
- module Contact
7
- class EmailAddressPresenter < ContentBlockTools::Presenters::BlockPresenters::BasePresenter
8
- include ContentBlockTools::Presenters::BlockPresenters::Contact::BlockLevelContactItem
9
-
10
- def render
11
- wrapper do
12
- content_tag(:ul, class: "content-block__list") do
13
- concat email
14
- concat description if item[:description].present?
15
- end
16
- end
17
- end
18
-
19
- def email
20
- content_tag(:li) do
21
- concat content_tag(:a,
22
- link_text,
23
- class: "email content-block__link",
24
- href: "mailto:#{item[:email_address]}#{query_params}")
25
- end
26
- end
27
-
28
- def query_params
29
- params = {
30
- subject: item[:subject],
31
- body: item[:body],
32
- }.compact.map { |k, v| "#{k}=#{v}" }.join("&")
33
-
34
- "?#{params}" if params.present?
35
- end
36
-
37
- def link_text
38
- item[:label] || item[:email_address]
39
- end
40
-
41
- def description
42
- content_tag(:li) do
43
- render_govspeak(item[:description])
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,83 +0,0 @@
1
- require_relative "./block_level_contact_item"
2
-
3
- module ContentBlockTools
4
- module Presenters
5
- module BlockPresenters
6
- module Contact
7
- class TelephonePresenter < ContentBlockTools::Presenters::BlockPresenters::BasePresenter
8
- include ContentBlockTools::Presenters::BlockPresenters::Contact::BlockLevelContactItem
9
-
10
- def render
11
- wrapper do
12
- content_tag(:div) do
13
- concat description if item[:description].present?
14
- concat number_list
15
- concat video_relay_service
16
- concat bsl_details
17
- concat opening_hours
18
- concat call_charges_link
19
- end
20
- end
21
- end
22
-
23
- def description
24
- render_govspeak(item[:description], root_class: "content-block__body")
25
- end
26
-
27
- def number_list
28
- content_tag(:ul, class: "content-block__list") do
29
- item[:telephone_numbers].each do |number|
30
- concat number_list_item(number)
31
- end
32
- end
33
- end
34
-
35
- def number_list_item(number)
36
- content_tag(:li) do
37
- concat content_tag(:span, "#{number[:label]}: ")
38
- concat content_tag(:span, number[:telephone_number], { class: "tel" })
39
- end
40
- end
41
-
42
- def video_relay_service
43
- video_relay_service = item[:video_relay_service] || {}
44
-
45
- if video_relay_service[:show]
46
- content = "#{video_relay_service[:prefix]} #{video_relay_service[:telephone_number]}"
47
- render_govspeak(content, root_class: "content-block__body")
48
- end
49
- end
50
-
51
- def bsl_details
52
- bsl_guidance = item[:bsl_guidance] || {}
53
-
54
- render_govspeak(bsl_guidance[:value], root_class: "content-block__body") if bsl_guidance[:show]
55
- end
56
-
57
- def opening_hours
58
- opening_hours = item[:opening_hours] || {}
59
-
60
- render_govspeak(opening_hours[:opening_hours], root_class: "content-block__body") if opening_hours[:show_opening_hours]
61
- end
62
-
63
- def opening_hours_list_item(item)
64
- content_tag(:li, "#{item[:day_from]} to #{item[:day_to]}, #{item[:time_from]} to #{item[:time_to]}")
65
- end
66
-
67
- def call_charges_link
68
- call_charges = item[:call_charges] || {}
69
-
70
- if call_charges[:show_call_charges_info_url]
71
- content_tag(:p) do
72
- concat content_tag(:a,
73
- call_charges[:label],
74
- class: "content-block__link",
75
- href: call_charges[:call_charges_info_url])
76
- end
77
- end
78
- end
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,40 +0,0 @@
1
- module ContentBlockTools
2
- module Presenters
3
- class ContactPresenter < BasePresenter
4
- include ActionView::Helpers::TextHelper
5
- include ContentBlockTools::Govspeak
6
-
7
- BASE_TAG_TYPE = :div
8
-
9
- FIELD_PRESENTERS = {
10
- email_address: ContentBlockTools::Presenters::FieldPresenters::Contact::EmailAddressPresenter,
11
- }.freeze
12
-
13
- BLOCK_PRESENTERS = {
14
- addresses: ContentBlockTools::Presenters::BlockPresenters::Contact::AddressPresenter,
15
- telephones: ContentBlockTools::Presenters::BlockPresenters::Contact::TelephonePresenter,
16
- email_addresses: ContentBlockTools::Presenters::BlockPresenters::Contact::EmailAddressPresenter,
17
- contact_links: ContentBlockTools::Presenters::BlockPresenters::Contact::ContactLinkPresenter,
18
- }.freeze
19
-
20
- has_embedded_objects :addresses, :email_addresses, :telephones, :contact_links
21
-
22
- private
23
-
24
- def default_content
25
- content_tag(:div, class: "vcard") do
26
- concat content_tag(:p, content_block.title, class: "fn org content-block__title")
27
- concat render_govspeak(content_block.details[:description]) if content_block.details[:description]
28
- embedded_objects.each do |object|
29
- items = send(object)
30
- concat(items.map { |item| presenter_for_object_type(object).new(item, content_block:).render }.join.html_safe)
31
- end
32
- end
33
- end
34
-
35
- def presenter_for_object_type(type)
36
- "ContentBlockTools::Presenters::BlockPresenters::Contact::#{type.to_s.singularize.underscore.camelize}Presenter".constantize
37
- end
38
- end
39
- end
40
- end
@@ -1,11 +0,0 @@
1
- module ContentBlockTools
2
- module Presenters
3
- class PensionPresenter < BasePresenter
4
- private
5
-
6
- def default_content
7
- content_block.title
8
- end
9
- end
10
- end
11
- end