Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Landing pages backend scaffold #4247

Merged
merged 17 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions app/controllers/landing_page_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class LandingPageController < ContentItemsController
private

# SCAFFOLDING: can be removed when basic content items are available
# from content-store
def request_content_item(_base_path)
GdsApi.content_store.content_item(request.path).to_h
rescue StandardError
fake_data
end

# SCAFFOLDING: can be removed when basic content items are available
# from content-store
def fake_data
{
"base_path" => request.path,
"title" => "Landing Page",
"description" => "A landing page example",
"locale" => "en",
"document_type" => "landing_page",
"schema_name" => "landing_page",
"publishing_app" => "whitehall",
"rendering_app" => "frontend",
"update_type" => "major",
"details" => {},
"routes" => [
{
"type" => "exact",
"path" => request.path,
},
],
}
end
end
45 changes: 45 additions & 0 deletions app/helpers/block_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module BlockHelper
def tab_items_to_component_format(tab_items)
tab_items.map do |ti|
{
id: ti["id"],
label: ti["label"],
content: sanitize("<p class=\"govuk-body-m\">#{ti['content']}</p>"),
}
end
end

def column_class_for_equal_columns(number_of_columns)
case number_of_columns
when 1
"govuk-grid-column"
when 2
"govuk-grid-column-one-half"
when 3
"govuk-grid-column-one-third"
else
"govuk-grid-column-one-quarter"
end
end

def column_class_for_assymetric_columns(number_of_columns, column_size)
case number_of_columns
when 3
case column_size
when 1
"govuk-grid-column-one-third"
when 2
"govuk-grid-column-two-thirds"
end
when 4
case column_size
when 1
"govuk-grid-column-one-quarter"
when 2
"govuk-grid-column-two-quarters"
when 3
"govuk-grid-column-three-quarters"
end
end
end
end
11 changes: 11 additions & 0 deletions app/models/block/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Block
class Base
attr_reader :id, :type, :data

def initialize(block_hash)
@data = block_hash
@id = data["id"]
@type = data["type"]
end
end
end
5 changes: 5 additions & 0 deletions app/models/block/columns_layout.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Block
class ColumnsLayout < Block::LayoutBase
alias_method :columns, :blocks
end
end
11 changes: 11 additions & 0 deletions app/models/block/layout_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Block
class LayoutBase < Block::Base
attr_reader :blocks

def initialize(block_hash)
super(block_hash)

@blocks = data["blocks"].map { |subblock_hash| BlockFactory.build(subblock_hash) }
end
end
end
26 changes: 26 additions & 0 deletions app/models/block/two_column_layout.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Block
class TwoColumnLayout < Block::LayoutBase
attr_reader :left, :right, :theme
alias_method :columns, :blocks

def initialize(block_hash)
super(block_hash)

@left = columns[0]
@right = columns[1]
@theme = data["theme"]
end

def left_column_size
theme == "two_thirds_one_third" ? 2 : 1
end

def right_column_size
theme == "one_third_two_thirds" ? 2 : 1
end

def total_columns
left_column_size + right_column_size
end
end
end
12 changes: 12 additions & 0 deletions app/models/block_factory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class BlockFactory
def self.build(block_hash)
block_class(block_hash["type"]).new(block_hash)
end

def self.block_class(type)
klass = "Block::#{type.camelize}".constantize
klass.ancestors.include?(Block::Base) ? klass : Block::Base
rescue StandardError
Block::Base
end
end
7 changes: 5 additions & 2 deletions app/models/content_item_factory.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
class ContentItemFactory
def self.build(content_hash)
content_item_class(content_hash).new(content_hash)
content_item_class(content_hash["document_type"]).new(content_hash)
end

def self.content_item_class(_content_hash)
def self.content_item_class(document_type)
klass = document_type.camelize.constantize
klass.superclass == ContentItem ? klass : ContentItem
rescue StandardError
ContentItem
end
end
27 changes: 27 additions & 0 deletions app/models/landing_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class LandingPage < ContentItem
attr_reader :blocks

ADDITIONAL_CONTENT_PATH = "lib/data/landing_page_content_items".freeze

def initialize(content_store_response)
if content_store_response.dig("details", "blocks")
super(content_store_response)
else
super(content_store_response.deep_merge(load_additional_content(content_store_response["base_path"])))
end

@blocks = (@content_store_response.dig("details", "blocks") || []).map { |block_hash| BlockFactory.build(block_hash) }
end

private

# SCAFFOLDING: can be removed (and reference above) when full content items
# including block details are available from content-store
def load_additional_content(base_path)
file_slug = base_path.split("/").last.gsub("-", "_")
filename = Rails.root.join("#{ADDITIONAL_CONTENT_PATH}/#{file_slug}.yaml")
return { "details" => {} } unless File.exist?(filename)

{ "details" => YAML.load(File.read(filename)) }
end
end
4 changes: 4 additions & 0 deletions app/views/landing_page/blocks/_big_number.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<%= render "govuk_publishing_components/components/big_number", {
number: block.data["number"],
label: block.data["label"],
} %>
5 changes: 5 additions & 0 deletions app/views/landing_page/blocks/_columns_layout.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="govuk-grid-row">
<% block.columns.each do |column| %>
<div class="<%= column_class_for_equal_columns(block.columns.count) %>"><%= render "landing_page/blocks/#{column.type}", block: column %></div>
<% end %>
</div>
4 changes: 4 additions & 0 deletions app/views/landing_page/blocks/_govspeak.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<%= render "govuk_publishing_components/components/govspeak", {
} do %>
<%= block.data["content"].html_safe %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/landing_page/blocks/_tabs.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= render "govuk_publishing_components/components/tabs", {
tabs: tab_items_to_component_format(block.data["tab_items"]),
} %>
8 changes: 8 additions & 0 deletions app/views/landing_page/blocks/_two_column_layout.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="govuk-grid-row">
<div class="<%= column_class_for_assymetric_columns(block.total_columns, block.left_column_size) %>">
<%= render "landing_page/blocks/#{block.left.type}", block: block.left %>
</div>
<div class="<%= column_class_for_assymetric_columns(block.total_columns, block.right_column_size) %>">
<%= render "landing_page/blocks/#{block.right.type}", block: block.right %>
</div>
</div>
9 changes: 9 additions & 0 deletions app/views/landing_page/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

<div class="landing-page">
<% @content_item.blocks.each do |block| %>
<%= render "landing_page/blocks/#{block.type}", block: %>
<% end %>
<% if @content_item.blocks.empty? %>
Warning: No blocks specified for this page
<% end %>
</div>
9 changes: 9 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

get "/foreign-travel-advice", to: "travel_advice#index", as: :travel_advice

scope "/landing-page" do
get "/", to: "landing_page#show"
get "/*any", to: "landing_page#show"
end

# Accounts
get "/sign-in", to: "help#sign_in"
get "/sign-in/redirect", to: "sessions#create"
Expand Down Expand Up @@ -59,6 +64,10 @@
get "/find-licences/:slug/:authority_slug", to: "licence_transaction#authority", as: "licence_transaction_authority"
get "/find-licences/:slug/:authority_slug/:interaction", to: "licence_transaction#authority_interaction", as: "licence_transaction_authority_interaction"

constraints FormatRoutingConstraint.new("landing_page") do
get ":slug", to: "landing_page#show"
end

# Simple Smart Answer pages
constraints FormatRoutingConstraint.new("simple_smart_answer") do
get ":slug/y(/*responses)" => "simple_smart_answers#flow", :as => :smart_answer_flow
Expand Down
43 changes: 43 additions & 0 deletions lib/data/landing_page_content_items/landing_page.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
blocks:
- type: govspeak
content: |
<h2>Here's a heading</h2>
<p>Here's some content!</p>
<p>Here's some more content</p>
<ul>
<li>What?</li>
<li>When?</li>
</ul>
<a href="/landing-page/sub-page-1">Visit sub-page 1</a>
- type: tabs
id: landing-pages-item-selector
tab_items:
- id: tab-1
label: Item 1
content: Here's the content for item one
- id: tab-2
label: Item 2
content: Here's the content for item two
- type: govspeak
content: <p>Here's some more content!</p>
- type: two_column_layout
theme: two_thirds_one_third
blocks:
- type: govspeak
content: <p>Left content!</p>
- type: govspeak
content: <p>Right content!</p>
- type: govspeak
content: <h2>Statistics</h2>
- type: columns_layout
blocks:
- type: big_number
number: £75m
label: amount of money that looks big
- type: big_number
number: 100%
label: increase in the number of big_number components added to the columns at this point
- type: big_number
number: £43
label: Cost of a cup of coffee in Covent Garden

5 changes: 5 additions & 0 deletions lib/data/landing_page_content_items/sub_page_1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blocks:
- type: govspeak
content: |
<h2>Sub Page 1</h2>
<a href="/landing-page">Back to main landing page</a>
43 changes: 43 additions & 0 deletions spec/fixtures/landing_page.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
blocks:
- type: govspeak
content: |
<h2>Here's a heading</h2>
<p>Here's some content!</p>
<p>Here's some more content</p>
<ul>
<li>What?</li>
<li>When?</li>
</ul>
<a href="/landing-page/sub-page-1">Visit sub-page 1</a>
- type: tabs
id: landing-pages-item-selector
tab_items:
- id: tab-1
label: Item 1
content: Here's the content for item one
- id: tab-2
label: Item 2
content: Here's the content for item two
- type: govspeak
content: <p>Here's some more content!</p>
- type: two_column_layout
theme: two_thirds_one_third
blocks:
- type: govspeak
content: <p>Left content!</p>
- type: govspeak
content: <p>Right content!</p>
- type: govspeak
content: <h2>Statistics</h2>
- type: columns_layout
blocks:
- type: big_number
number: £75m
label: amount of money that looks big
- type: big_number
number: 100%
label: increase in the number of big_number components added to the columns at this point
- type: big_number
number: £43
label: Cost of a cup of coffee in Covent Garden

Loading