Skip to content
Jonathan Rochkind edited this page Mar 16, 2015 · 41 revisions

There are a variety of ways to customize Umlaut look-and-feel and behavior in your local app.

In general, you should find the smallest, cleanest, most "surgical" way of specifying a desired customization. The less code you write, the less code you over-ride (or copy-and-paste or duplicate) from Umlaut, the better. This will make it more likely you'll be able to upgrade to future versions of Umlaut without problems, and it will minimize the amount of code you have to maintain locally in a local 'fork' of some part of umlaut's functionality.

You should never edit code in Umlaut gem source for purely local use, there should always be a way to customize Umlaut behavior in your local app using the standard distro un-modified gem. If there's not, we should fix/refactor Umlaut so there is. The only reason to edit Umlaut gem code is to write something to contribute back to Umlaut as a bug fix or new feature. Or to just generally experiment and see how Umlaut works. But we recommend running an app based on a locally modified version of Umlaut -- unless you really want to create a local fork.

Here are some ways Umlaut can be customized by your local app.

Configuration

Umlaut's configuration generally lives in ./config/umlaut_services.yml (for service plugins) and ./app/controller/umlaut_controller.rb for other configuration key/values. See Installation 'configuration' section for an overview, or look in those files in your local app, generated there by umlaut installer.

Customize CSS

A large amount of look and feel changes can actually be done purely with custom CSS, over-riding Umlaut's styles.

For instance, here's how to change the colors of the Umlaut header ( example works with Umlaut 3.1+ and later )

We will make use of the Rails 3.1 asset pipeline, which assembles our CSS. Assuming you have an ./app/assets/application.css with the line *= require_tree . in it.

Create a file in your local ./app/assets/stylesheets, any name you want but ending in css.erb, say umlaut_override.css.erb, containing:

      .umlaut .header {
        background-color: #002d73; /* hopkins blue */
        color: #DDD; /* slightly off white to be less bright */
      }

You could also turn off Umlaut stock CSS entirely by removing the require umlaut line from your local ./app/assets/stylesheets/application.css, but then you'd have to provide a lot of CSS yourself to have Umlaut elements display usably.

For more information on the Rails Asset Pipeline, please see the Rails Guide.

Notes

  • Umlaut's CSS (included require umlaut) automatically includes Bootstrap too -- Umlaut's CSS is based on bootstrap. The exact version of bootstrap can be controlled locally by what version of the bootstrap-sass gem you are using, updated with bundler or specified in your Gemfile -- subject to any restrictions expressed by the Umlaut gem.
  • jrochkind has found that sometimes, in development mode, he needs to delete his browser's cache in order to refresh changes in assets, not sure why, it's not supposed to work this way, an idiosyncracy of the rails asset pipeline.
  • When running a rails app in production mode, you'll have to precompile your assets, and re-precompile them when there are changes. See the Rails Guide.

Customize CSS with SASS variables (Umlaut 3.1+ only)

Umlaut's CSS is written in Sass, compiled with the standard Rails asset pipeline. Umlaut also includes bootstrap in Sass via the bootstrap-sass ruby gem.

Rather than trying to over-ride styles already defined by Umlaut/Bootstrap in pure CSS, it can be more efficient and maintainable to actually redefine Sass variables in your local app.

To do that, you need to switch your app's asset pipeline to be importing Umlaut's styles via Sass @import. First, remove the //= require 'umlaut' from your application.css, and instead create a file in your local app ./app/assets/stylesheets/umlaut_local.scss, and add a line @import 'umlaut'; to it.

  • You probably already have a require_tree . in your application.css, which says to include all the files in your app/assets/stylesheets, including this new one you just added.
  • You've switched from a require to the Sass-specific @import so you can hook into the Sass compilation to define Sass variables used by Umlaut's styles, and/or use Sass rules defined by Umlaut's styles.
  • You can call the new file you create anything you want, but do not call it umlaut.scss, or it'll conflict with umlaut's own style assets.

Now in your new umlaut_local.scss, you can define variables from Umlaut's sass or Bootstrap's sass, before the import, or use the rules defined by Umlaut after the import.

// Over-ride Bootstrap variables
$linkColor: 	blue;

// Over-ride umlaut variables, eg
$umlautBorderColor:                         #ebb211;
$umlautBackgroundColor:                     #fffdea;
$umlautAltBackgroundColor:	            #fcf1d4;
$umlautHighlightedBackgroundColor:	    white;
$umlautHighlightedSectionBorderColor:       #dedede;
$umlautAvailableColor:                      #00CC33;
$umlautUnavailableColor:                    red;

@import 'umlaut';

// Here, you could define your own styles using Umlaut or Bootstrap Sass
// variables, or using Sass `@include` or `@import` of mixins or styles
// defined by Umlaut or Bootstrap.

You might also want to actually redefine or alter mixins or classes defined by Umlaut or Bootstrap -- sorry, we're not actually sure the best practices for doing that, but please feel free to experiment and let us know, including requesting any changes to how Umlaut does things that might make things easier.

Custom header and footer templates (Umlaut 3.1+)

To customize the header and footer more fully than through CSS alone, you can provide local custom Rails template partials for the header and footer sections.

Umlaut provides header and footer in ./app/views/umlaut/_header.html.erb and _footer.html.erb.

You can provide your own local overrides of these partials, just add a file in your local app at ./app/views/umlaut/_header.html.erb or _footer.html.erb. You might want to copy the original Umlaut source to start with, to see some Umlaut utility functions that may be useful to you.

Note The header and footer are used on 'resolve' menu pages, as well as search pages and other Umlaut pages. Any logic involving resolve-specific data or instance variables needs to be guarded by conditionals that recognize the iVars may not be there.

Local Rails layout

A Rails 'layout' is a wrapper template providing standard HTML wrapper markup, headers, footers, etc. By default, Umlaut pages use a built-in Umlaut layout inside Umlaut gem source at ./app/views/layouts/umlaut.html.erb.

If you need more customization than you can get from CSS alone (custom navbar, removing or altering layout of permalink url, etc), you can provide your own local layout file instead. NOTE If localizing the header and footer template is sufficient, that is recommended over localizing the entire layout; localizing the layout may create larger forwards compatibility problems with future Umlaut upgrades.

Your default Rails app already includes a helper at ./app/views/layouts/application.html.erb, you can start there, but you'll want to include a few things from the standard umlaut helper (see source) to get full functionality:

  • Include render_umlaut_head_content in section to get some automatic umlaut functionality like OpenSearch auto-discovery links.
  • Wrap the yield in a div with classes "umlaut container" for umlaut stock CSS to apply properly.
  • Optionally include permalink as demonstrated in stock umlaut layout.
  • Optionally set a header and html <title> using umlaut logic as demonstrated in the umlaut stock layout.
  • Include a 'footer' div to make current CSS apply correctly; footer div can optionally include some standard umlaut functionality, such as a 'credits' line and some debugging links, as demonstrated in the stock umlaut layout.

To use a local layout, in your local ./app/controllers/umlaut_controller.rb, set:

layout "application"

Or any other named local layout.

Note that the default layout includes some debugging links in footer already, triggered by inclusion in your UmlautController config of:

  • test_resolve_base ("[T]" link to configured test resolver for current page)
  • sfx.sfx_base_url ("[S]" link to native SFX results for current page)

Display Section configuration

The Umlaut resolve response is formed of individual sections. These sections are used for placing content on the HTML page, and are also used for returning content from Umlaut's APIs and the JQuery Content Utility.

Configuration of these sections is done declaratively, as an array of configuration Hashes, stored in the umlaut_config resolve_sections key.

Each hash can configure what area of the screen (main, sidebar, etc) the section shows up in, as well as custom partials used to render the section, custom rules for when to show the section on the screen, custom rules for whether to show the 'updating' spinner, etc. The order of sections in the array determines the order they will appear on the screen. Each hash has a :div_id value, which is used as the unique identifier for the section.

You can customize the order of sections, or other section details, by editing the resolve_sections array and it's contents in your local ./app/controller/umlaut_controller.rb, along with other Umlaut configuration.

For instance, to move the 'search_inside' section from the sidebar to the main area, before the 'fulltext' section (Umlaut 4.1+):

# ./app/controllers/umlaut_controller.rb
class UmlautController < ApplicationController 
   # ....

   umlaut_config.configure do
      #....
      search_inside = resolve_sections.remove_section("search_inside")
      resolve_sections.insert_section(search_inside, :before => "fulltext")
   end
end

The remove_section and insert_section methods are available on the resolve_sections array for adding (Umlaut 4.1+), removing, and re-ordering sections. insert_section can take an :after argument instead of :before as well.

  • It may be helpful to look at the default list of resolve_sections that you may want to modify. You can find it in Umlaut source code for UmlautConfigurable (Should we add a rake task that prints it out? Probably).

  • Section headings and prompts are supplied via Rails i18n. You can change, add, and remove them by defining just those keys you want to change in a local ./config/locales/en.yml (or other language) file. See list of defaults in Umlaut source. (They can also be supplied as the section_heading and section_prompt keys in the resolve_sections config, which might be useful for dynamically changing them in a resolve_sections_filter as described below)

  • You can add whole new sections (advanced topic, probably only needed if you are writing custom service plugins).

  • Change over configuration regarding visibility logic and others. For complete documentation of options available, see generated docs for SectionRenderer

Per-request resolve section configuration

There is support beginning in Umlaut 4.1 for applying changes to the resolve_sections configuration on a per-request basis. For an example, you might want to re-order the sections only for book-like requests.

You do this by supplying a ruby lambda/proc to the resolve_sections_filter configuration.

# ./app/controllers/umlaut_controller.rb
class UmlautController < ApplicationController
    # ...

    umlaut_config.configure do 
      #...
      add_resolve_sections_filter! Proc.new { |request, sections|
        # re-order resolve sections to put copies_in_library below document_delivery,
        # only for book-type requests

        if MetadataHelper.title_is_serial?(request.referent)
          holding = sections.remove_section("holding")
          sections.insert_section(holding, :after => 'document_delivery') if holding
        end
      }

You have to use Proc.new to define your block of custom logic, rather than lambda or proc, because of some current idiosyncracies in the configuration setup, sorry.

Customize section highlighting

Umlaut highlights a particular section as recommended on the resolve page: For instance, the fulltext section, when fulltext is available.

You can customize which section(s) receive highlight styling for a given request by passing a logic block in Umlaut configuration.

add_section_highlights_filter! Proc.new { |request, highlighted_section_list| }
  # The first arg is the Umlaut Request object, the second is an
  # array of section ID's desigated as highlighted by Umlaut's default
  # configuration. You can _mutate_ that array, with add/delete/replace
  # methods, to change what sections get highlighted, based on
  # the characteristics of the current request
end

Due to some unfortunate technical idiosyncracies, we recommend creating the proc object with Proc.new and curly braces, as above.

Custom static pages

Some use cases will involve displaying custom static pages on the resolve page (for example a link to a help page). It is very easy to configure Umlaut to do this, through modifications to UmlautConfigurable. In the resolve_sections part of UmlautConfigurable, add another add_resolve_sections block. Here you can specify a partial that will be rendered. If you change visibility to true, it will be displayed no matter what. html_area specifies where in the view it should be rendered. You will then need to create or override the partial within the resolve folder in your app, with your own code. See the SectionRenderer documentation for a full description of the options available.

  add_resolve_sections! do
    div_id "help"
    html_area :sidebar
    bg_update false
    partial "help"
    show_heading false
    show_spinner false
    visibility true
  end

Write custom local service plugin

Writing a custom local service plugin should be pretty much the same process as writing an official Umlaut distro service plugin, the source will just live in your local app instead of in shared Umlaut distro codebase. Unless you have a local service whose functionality is really quite unique to your environment, consider contributing it back to Umlaut.

See Writing a service plugin