Headers, Footers, and a Sidebar Extension

Preparation

We'd like to have a header and a footer on all pages, independently of their origin. Also, headers and footers should be made editable with Scrivito. For the header, a logo is sufficient at this time; the footer, however, should be able to accommodate any desired content. Beyond that, we'd like to add some content to the sidebar of Solidus' products overview page.

But first, let's create a Homepage model to be able to differentiate the homepage from other pages:

rails g scrivito:page Homepage

Analogously to what we applied to the Page view, remove the navigation from app/views/homepage/index.html.erb because the navigation is already rendered in the Solidus context. For this, remove the first <div>...</div> block from the view. Afterwards, the file should look like this:

<%= scrivito_tag :h1, @obj, :title %>
<%= scrivito_tag :div, @obj, :body %>

To make the root object a Homepage, open the Rails console and change the object class (_obj_class) of Obj.root to “Homepage”:

ws = Scrivito::Workspace.create(title: 'Adapting Homepage')
Scrivito::Workspace.current = ws
Obj.root.update(_obj_class: 'Homepage')

# In your browser, select the "Adapting Homepage" working copy
# and check the homepage (/). Then:

ws.publish

Now, add attributes for the header logo, the footer, and the additional sidebar content to the Homepage model at app/models/homepage.rb. We'll use a reference attribute named logo, a widgetlist named footer, and another widgetlist named products_sidebar. The model file should now contain the following:

class Homepage < Obj
  attribute :title, :string
  attribute :body, :widgetlist
  attribute :child_order, :referencelist

  # global content
  attribute :logo, :reference
  attribute :footer, :widgetlist
  attribute :products_sidebar, :widgetlist
end

Rendering the header logo

To replace the Solidus logo, first create a corresponding Deface rule:

# app/overrides/spree/shared/header_logo.rb

Deface::Override.new(virtual_path:     "spree/shared/_header",
                     replace_contents: "#logo",
                     name:             "scrivito_header_logo",
                     partial:          "shared/scrivito_header_logo")

Then create the partial that renders the image. We utilize Scrivito's image transformation capability to limit the image dimensions to 150 x 50 pixels:

<!-- app/views/shared/_scrivito_header_logo.html.erb -->

<%= link_to scrivito_path(Obj.root) do %>
  <%= scrivito_image_tag Obj.root, :logo, {}, transform: { width: 150, height: 50 } %>
<% end %>

If you visit your local site at localhost:3000, you can upload an image by clicking the logo in Edit mode. This opens Scrivito's Content Browser.

Rendering the footer

The Solidus footer can be replaced analogously to the header. So, first create the Deface rule:

# app/overrides/spree/shared/footer.rb

Deface::Override.new(virtual_path:     "spree/shared/_footer",
                     replace_contents: "#footer",
                     name:             "scrivito_footer",
                     partial:          "shared/scrivito_footer")

Then create the partial that renders the footer:

<!-- app/views/shared/_scrivito_footer.html.erb -->

<footer class="scrivito_content" data-hook>
  <%= scrivito_tag(:div, Obj.root, :footer) %>
</footer>

Since the footer attribute is a widgetlist, you can freely compose its contents in Edit mode. You might, for example, add a “Text Widget” to it and enter “Powered by Solidus and Scrivito”.

Adding content to the sidebar

On the products overview page, there should be a box an editor can fill with content. The method we use to achieve this is the same as for the header and the footer. So, first create a corresponding Deface rule to extend the sidebar Solidus provides:

# app/overrides/spree/products/sidebar.rb:

Deface::Override.new(virtual_path:  "spree/products/index",
                     insert_bottom: "div[data-hook='homepage_sidebar_navigation']",
                     name:          "scrivito_products_sidebar",
                     partial:       "shared/scrivito_products_sidebar")

Next, create the partial to be rendered on the sidebar.

<!-- app/views/shared/_scrivito_products_sidebar.html.erb -->

<%= scrivito_tag(:div, Obj.root, :products_sidebar) %>

If you visit your site now, you can add content underneath the sidebar navigation by adding, for example, a “Text Widget” and entering “Free shipping on all orders over $50”.