37 Signals have done a brilliant job making great GUIs and I often want to have a similar nice interface for internal projects, so here is a simple admin layout generator to give you a GUI in that style. I haven’t copied the markup or code in any way from 37 Signals, but the look is obviously inspired by them.
This generator is now Rails 3 only and gem-based. If you want to use the Rails 2 version you should do the following to install the Rails 2 branch in the older way:
git clone git://github.com/andyjeffries/andy_admin.git ~/.rails/generators/andy_admin
cd ~/.rails/generators/andy_admin
git checkout -b rails2 origin/rails2
Assuming you’re using Rails 3, you simply need to install the gem on your system:
gem install andy_admin
and then add it to your Gemfile in your application:
gem "andy_admin"
To add this admin layout to your application is easy:
rails generate andy_admin "My Site Name" 232
This will create the admin and login layouts, all javascript/css files and copy in any necessary images and using a hue of 232 degrees (with the saturation and lightness values automatically calculated).
The login layout (login.html.erb) is really a layout and view in one, the first step will need to be extracting the form within the layout in to a view and making the yield call uncommented. Then you can use it for a login form. It will look something like this:
Saving text in flash[:error], flash[:notice] or flash[:warning] will give it the appropriate display in the templates (either login or the main admin template)
You should try to set the instance variable @page_title within your controller as the section of the site you’re using, or maybe any section heading. This is displayed in the main title tag and in the header bar.
If you declare an instance variable of @current_user_name (and optionally one of @last_login_time) these values will be displayed in the top right of the header bar.
The navigation tabs are simply declared as ul#navigation and ul#subnavigation within the div#header element. If they have a class of active they will be displayed as seamless to the page (to show the current tab). For example:
<ul id='navigation'>
<li class='active'><a href='#'>Type 1</a></li>
<li><a href='#'>Type 2</a></li>
<li><a href='#'>Type 3</a></li>
</ul>
<ul id='subnavigation'>
<li><a href='#'>Type 3</a></li>
<li><a href='#'>Type 3</a></li>
</ul>
However, the generation of these items is handled by a builder method in config/initializers/andy_admin_menu.rb and looks like this:
ANDY_ADMIN_MENU = AndyAdmin::Menu.build do
main :test1, "Test 1", '/'
main :test2, "Test 2", '#'
main :test3, "Test 3", "/"
sub :test4, "Test 4 S"
sub :logout, "Logout"
end
The AndyAdmin::Menu class is capable of iterating over it’s elements and displaying the active tab (when passed the symbol of the current tab as @current_section_id) as such.
The main content area is simply the main part of the Rails view. You can display the heading for the page in an h1 tag. If there are actions to take (New links, etc) you can put them in a span within the h1.
For example:
<h1>
Overview
<span><a href='#'>Add new</a> | <a href='#'>Search</a></span>
</h1>
If you’re listing items, the easiest way is to follow 37 Signal’s example and break them out by date using div.date_breakout, for example:
<div class='date_breakout'>Friday, 12 July 2009</div>
This is easily done with the date_breakout helper provided with the generator:
date_breakout(item.created_at)
Then each item is in a div.item. An optional div.summary is available for sending less important information to the right:
<div class='item'>
<div class='summary'>
Edited by <strong>Andy J.</strong>
</div>
<a href='#'>Test item</a>
</div>
To use the sidebar, simply define content for :sidebar and use h2 tags for the headings. For example:
<% content_for :sidebar do %>
<h2>Should we delete it?</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p><a href='#'>I understand - delete</a></p>
<% end %>
If you prefer you can wrap each item in a div.card which will style it similar to the main body content – white background, drop shadow – but slightly lower to the page.
Once you’ve created your main content area and sidebars, they should looks something like this…
The general markup structure is to use h2 for field labels. If there is an error you can immediately follow it with a span.error to display the error message continued on the same line.
Then there can be an optional div.description for any helpful hints/descriptive text.
Finally there should be the actual input(s) within a div.input. The div.input can contain labels which are displayed inline (for checkboxes, for example).
For example:
<h2>Your name</h2>
<span class='error'>can't be blank</span>
<div class='description'>
Your name appears at the top of each invoice
</div>
<div class='input'>
<input type='text'>
</div>
The actions buttons should be within a div.actions at the bottom of the form and can be normal links, links with a class of awesome (Yes, it uses ‘Awesome Buttons’) or buttons.
For example:
<div class='actions'>
<button class='awesome green' type='submit'>Save</button>
<a href='#foo' class='awesome red'>Delete</a>
or <a href='#'>Cancel</a>
</div>
If you prefer to use Rails’ built in form generation (and let’s be honest, who doesn’t) there is a custom Form Builder available to generate compliant forms very easily:
<% form_for @website, :builder => AndyAdmin::FormBuilder, :url => '/' do |f| %>
<%= f.text_field :name, :description => "Use the site's full name" %>
<%= f.text_area :content, :title => "Rich content" %>
<%= f.date_select :launched_at %>
<%= f.check_box :live, :label => "Yes, I want the site to be live" %>
<%= f.submit "Update", :colour => "blue" %> or
<%= f.cancel "Cancel", "/" %>
<% end %>
The title is the h2 tag used to title the input, the description is the hint text that appears above the input and the label is used after checkboxes. It automatically handles displaying of errors.
It will look something like this:
As another little nicety, if you give a link a class of ‘link_to_site’ it will appear as a block element with a grey background/border. This is sometimes useful when providing a link to view the item in the context of the main site:
<%= link_to "➤ View this news item on the main site", news_path(@news_item), :class => "link_to_site" %>