diff --git a/app/controllers/landing_page_controller.rb b/app/controllers/landing_page_controller.rb new file mode 100644 index 0000000000..5f87dcd46c --- /dev/null +++ b/app/controllers/landing_page_controller.rb @@ -0,0 +1,32 @@ +class LandingPageController < ContentItemsController + # 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) + 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 diff --git a/app/helpers/block_helper.rb b/app/helpers/block_helper.rb new file mode 100644 index 0000000000..766a2786fb --- /dev/null +++ b/app/helpers/block_helper.rb @@ -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("

#{ti['content']}

"), + } + 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 diff --git a/app/models/block/base.rb b/app/models/block/base.rb new file mode 100644 index 0000000000..8e3da59c4a --- /dev/null +++ b/app/models/block/base.rb @@ -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 diff --git a/app/models/block/columns_layout.rb b/app/models/block/columns_layout.rb new file mode 100644 index 0000000000..023b02b6e9 --- /dev/null +++ b/app/models/block/columns_layout.rb @@ -0,0 +1,5 @@ +module Block + class ColumnsLayout < Block::LayoutBase + alias_method :columns, :blocks + end +end diff --git a/app/models/block/layout_base.rb b/app/models/block/layout_base.rb new file mode 100644 index 0000000000..a55c329e87 --- /dev/null +++ b/app/models/block/layout_base.rb @@ -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 diff --git a/app/models/block/two_column_layout.rb b/app/models/block/two_column_layout.rb new file mode 100644 index 0000000000..4158318e16 --- /dev/null +++ b/app/models/block/two_column_layout.rb @@ -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 diff --git a/app/models/block_factory.rb b/app/models/block_factory.rb new file mode 100644 index 0000000000..6ffe84723a --- /dev/null +++ b/app/models/block_factory.rb @@ -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 diff --git a/app/models/content_item_factory.rb b/app/models/content_item_factory.rb index 9b4bde458a..3d7c9e058e 100644 --- a/app/models/content_item_factory.rb +++ b/app/models/content_item_factory.rb @@ -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 diff --git a/app/models/landing_page.rb b/app/models/landing_page.rb new file mode 100644 index 0000000000..d951b76df5 --- /dev/null +++ b/app/models/landing_page.rb @@ -0,0 +1,25 @@ +class LandingPage < ContentItem + attr_reader :blocks + + 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("lib/data/landing_page_content_items/#{file_slug}.yaml") + return { "details" => {} } unless File.exist?(filename) + + { "details" => YAML.load(File.read(filename)) } + end +end diff --git a/app/views/landing_page/blocks/_big_number.html.erb b/app/views/landing_page/blocks/_big_number.html.erb new file mode 100644 index 0000000000..77636587a8 --- /dev/null +++ b/app/views/landing_page/blocks/_big_number.html.erb @@ -0,0 +1,4 @@ +<%= render "govuk_publishing_components/components/big_number", { + number: block.data["number"], + label: block.data["label"], +} %> \ No newline at end of file diff --git a/app/views/landing_page/blocks/_columns_layout.html.erb b/app/views/landing_page/blocks/_columns_layout.html.erb new file mode 100644 index 0000000000..b443ac1829 --- /dev/null +++ b/app/views/landing_page/blocks/_columns_layout.html.erb @@ -0,0 +1,5 @@ +
+ <% block.columns.each do |column| %> +
<%= render "landing_page/blocks/#{column.type}", block: column %>
+ <% end %> +
\ No newline at end of file diff --git a/app/views/landing_page/blocks/_govspeak.html.erb b/app/views/landing_page/blocks/_govspeak.html.erb new file mode 100644 index 0000000000..511180e548 --- /dev/null +++ b/app/views/landing_page/blocks/_govspeak.html.erb @@ -0,0 +1,4 @@ +<%= render "govuk_publishing_components/components/govspeak", { +} do %> + <%= block.data["content"].html_safe %> +<% end %> diff --git a/app/views/landing_page/blocks/_tabs.html.erb b/app/views/landing_page/blocks/_tabs.html.erb new file mode 100644 index 0000000000..93aa5887fe --- /dev/null +++ b/app/views/landing_page/blocks/_tabs.html.erb @@ -0,0 +1,3 @@ +<%= render "govuk_publishing_components/components/tabs", { + tabs: tab_items_to_component_format(block.data["tab_items"]), +} %> \ No newline at end of file diff --git a/app/views/landing_page/blocks/_two_column_layout.html.erb b/app/views/landing_page/blocks/_two_column_layout.html.erb new file mode 100644 index 0000000000..10df858856 --- /dev/null +++ b/app/views/landing_page/blocks/_two_column_layout.html.erb @@ -0,0 +1,8 @@ +
+
+ <%= render "landing_page/blocks/#{block.left.type}", block: block.left %> +
+
+ <%= render "landing_page/blocks/#{block.right.type}", block: block.right %> +
+
diff --git a/app/views/landing_page/show.html.erb b/app/views/landing_page/show.html.erb new file mode 100644 index 0000000000..09856c50c8 --- /dev/null +++ b/app/views/landing_page/show.html.erb @@ -0,0 +1,9 @@ + +
+ <% @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 %> +
diff --git a/config/routes.rb b/config/routes.rb index f13c08aea9..28e01dc555 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,6 +29,15 @@ 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 + + constraints FormatRoutingConstraint.new("landing_page") do + get ":slug", to: "landing_page#show" + end + # Accounts get "/sign-in", to: "help#sign_in" get "/sign-in/redirect", to: "sessions#create" diff --git a/lib/data/landing_page_content_items/landing_page.yaml b/lib/data/landing_page_content_items/landing_page.yaml new file mode 100644 index 0000000000..161d8cfef4 --- /dev/null +++ b/lib/data/landing_page_content_items/landing_page.yaml @@ -0,0 +1,43 @@ +blocks: +- type: govspeak + content: | +

Here's a heading

+

Here's some content!

+

Here's some more content

+ + Visit sub-page 1 +- 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:

Here's some more content!

+- type: two_column_layout + theme: two_thirds_one_third + blocks: + - type: govspeak + content:

Left content!

+ - type: govspeak + content:

Right content!

+- type: govspeak + content:

Statistics

+- 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 + diff --git a/lib/data/landing_page_content_items/sub_page_1.yaml b/lib/data/landing_page_content_items/sub_page_1.yaml new file mode 100644 index 0000000000..221e5ca96b --- /dev/null +++ b/lib/data/landing_page_content_items/sub_page_1.yaml @@ -0,0 +1,5 @@ +blocks: +- type: govspeak + content: | +

Sub Page 1

+ Back to main landing page \ No newline at end of file