Skip to content

Adding new navigation menu items

Jessie Keck edited this page Nov 15, 2019 · 2 revisions

Spotlight's exhibit menu (About, Browse, Curated Features, etc.) is extendable for downstream applications to add their own custom menu items/pages for their exhibits. There is some setup required to provide the a new menu item.

Define a type for the menu item

The menu item will need to have a type that will be used in various places around the app to distinguish it from the other menu items. This type should not be about, browse, or curated_features as these are the types that Spotlight provides for you. For the purposes of this guide, we'll give our navigation/menu item the type blorgh.

Create a partial for the blorgh menu item

The partial must be in the app/views/shared directory and have the menu item type + "_navbar". In our example we would create the file app/views/shared/_blorgh_navbar.html.erb.

The partial should contain a list item (<li>) and a link (<a>) to the location we want to send the user. As of this writing the list item should have the class nav-item and the link should have the class nav-link to be styled appropriately. The label and whether the menu item should be displayed or not is managed in the database and available to our menu item in the navigation variable.

<% if navigation.display? %>
  <li class="nav-item">
    <%= link_to(navigation.label_or_default, 'path_we_will_send_user', class: 'nav-link') %>
  </li>
<% end %>

Add i18n keys

The user facing label is backed by an i18n key to allow the menu item to be translated properly by exhibit admin/curators. We should add the default user facing label for the menu item to your locale file under the spotlight.main_navigation key.

en:
  spotlight:
    main_navigation:
      blorgh: 'BLORGH!'

Add a Controller and Route

Depending on where our menu item is sending the user, we'll most likely want to add a new controller and route for our page. Whatever mechanism we choose to do this, there are a couple of considerations we'll want to make in our code.

The Blorgh route

Our route should be nested within the exhibits route for consistency with other pages (and so we can properly authorize that a user can see our page, explained below).

# in config/routes.rb
resources :exhibits, only: [], path: '/' do
  resource :blorgh, only: :show
end

Now that we have a route we can update the _blorgh_navbar.html.erb partial to use the named route (exhibit_blorgh_path) that was just created.

The BlorghController

Our controller should sub-class Spotlight::ApplicationController in order to get access to a lot of helpful things for building our page (such as current_exhibit context, etc).

We should authorize that the user can access something in order to view the page (most likely a model that we would add for our controller). At the very least we should authorize that the user has read access to the exhibit itself so that the page isn't visible when the exhibit unpublished.

class BlorghController < Spotlight::ApplicationController
  before_action do
    authorize!(:read, current_exhibit)
  end

  def show; end
end

Adding the Menu Item to exhibits

Spotlight provides a way to have our menu item created automatically for an exhibit when it is created. If we want all exhibits, on creation, to get our menu item by default, we can add our item to the exhibit_main_navigation engine configuration.

# In config/initializers/spotlight_initializer.rb
Spotlight::Engine.config.exhibit_main_navigation = [:curated_features, :browse, :about, :blorgh]

In the case where we want to add our menu item to existing exhibits, we'll need to add something to a file like db/seeds.rb or just run a command like below ensuring that our blorgh type is the nav_type attribute of the MainNavigation object.

Spotlight::Exhibit.find_each do |exhibit|
  Spotlight::MainNavigation.find_or_create_by(exhibit_id: exhibit.id, nav_type: 'blorgh')
end