As a project manager in a fintech specialized development company (hi CapSens), I’ve seen loads and loads of web platforms’ back-offices.
These administration interfaces are very common and similar especially for the indexes (list of ressources) : a big paginated table of 50 lines, a sidebar that contains the filter and a title. Always the same interface. This article explores ways to enhance these simple interface designs.
Being in a Ruby on Rails company, this article will be showing bits of Ruby code and focused on ActiveAdmin design but it can be applied to any other Admin index.
Here is a a basic ActiveAdmin index. For the example, I came up with a Customer model and an index displaying the fields shown on the right. The view is default from AA’s generator so we also have a bunch of useless filters stacked in a sidebar on the right. Already seen this, right ?
The code of this project can be found on this Github repository. You’ll find a git branch representing each phase of this article (here “1_base_admin”).
Now that we are set up, let’s move on and explore ways to enhance our admin index.
Theme up your Admin
There are several open-source themes available for ActiveAdmin. Amongst all the quick wins I’ll show you in this article, this one might be the biggest.
First of all, we need to pick the theme we’d like in order to customize our admin’s interface. This wiki references a list of AA’s themes. When choosing your theme, you’ll want it to be functionnal, you have enough bugs to deal with, don’t wan’t to add up new ones thanks to your theming, right ? A good indicator is to ensure that there are not too much opened issues and that the theme is still kept up to date (check the last commit on the master branch). Last but not least, if your project already contains numerous AA pages, you should go for a light theming in order to avoid breaking changes that you might miss.
Amongst all the available themes of this wiki, my favorite one is Artic Admin but for the reasons I gave you above, we’ll go for a lighter theming: ActiveMaterial. To implement it, just follow the doc on the Github’s page, you should be good to go in a minute (it only requires 3 lines of code to add).
The AA’s interface changed and now look different. With a bit of configuration we can easily customize it more. The theme is made in SASS (SCSS) so we can look up for variables and modify the default configuration.
Customizing the theming
If we take a look at the color variables available we can see there are 14 of them. For this, add up a new file app/assets/stylesheets/active_admin/variables/_colors.scss and require it in active_admin.scss file before the other files like this.
// Customization
@import ‘active_admin/variables/variables’;
@import ‘active_admin/variables/fonts’;
// Libraries
@import “active_admin/mixins”;
@import “active_material”;
An example of admin.scss code
Now let’s go in our new _variables.scss file and tweak the theme a bit! First we need to define our color palette. ActiveMaterial being a material design template, I used a material color palette generator for this. There are plenty of them available on the web, but I particularly like Material.io.
Once you are done defining your template, you just have to report the value in our _variable.scss file by re-assigning the value of existing SASS variables:
$am-theme-primary: #42a5f5;
// A darker primary theme color for contrast when overlaying
// important items containers that are already treated
// with primary color.
$am-theme-primary-700: #0077c2;
// Used for primary action button and components
$am-theme-accent: #673ab7;
// The background color of the document.
$am-theme-backdrop: #eeeeee;
// Background color of “paper” elements such as cards.
$am-theme-paper: #F5F5F6;
// Color used to separate elements such as table's lines
$am-theme-divider: darken($am-theme-backdrop, 2.5%);
Here is my _variable.scss file to match the color palette above.
Here is my _variable.scss file to match the color palette above. You can find the code here.
Of course, there are other options for further customization: fonts, elevations, sizes, breakpoints. To do that, just repeat the same process than for the color.
Filter sidebar toggle
Now that we added some colors, we can see that our filters sidebar is taking 20% of the screen. It’s a bit much for a feature that you won’t use all the time, isn’t it? Let’s find a way to make it appear only when needed.
By finding a solution for this matter, I stepped upon this article from Emanuele Tozzato that shows a simple way to sort it out. With a little bit of Jquery and Css, he allows to toggle in and out the filters sidebar thanks to an action item.
We’ll just push a little bit further his approach because I’m not a big fan of adding an action item. These should be used for admins CRUD actions. So I just tweaked the code a little bit to move the toggle filters button on the top right of the indexes’ table.
If you’re interested, you can find the code here.
Stripping up the table
Sometimes, it can be complexe for an administrator to distinguish elements from one lines to another. One solution is to strip the table. To do this, I just need to create a new scss component :
// app/assets/active_admin/components/_tables.scss
$table-striping-color: $am-theme-paper;
.index_content table {
tr.odd {
background: $table-striping-color;
}
tr.even {
background: lighten($table-striping-color, 10%);
}
}
How to colour every other row in a table in SAS
For the striping color, I used the value of our $am-theme-paper (the background color of components such as cards or tables) and I just darkened the even columns. Easy right ? You can find the full code here.
Decorate your datas
Sometimes you may find columns in your indexes that don’t have any interest in being separated. For instance the first name and the last name or each part of an address. Then you can quickly merge them into a new column “name” or “full address”.
Moreover, when showing an amount, you may want to add the currency and number formatting to ease the reading.
You can use a decorator like Draper for this. This avoid to overload the admin logic.
__# app/decorators/customer_decorator.rb__
class CustomerDecorator < Draper::Decorator
delegate_all
def name
“#{firstname&.capitalize} #{lastname&.upcase}”
end
def membership_amount_in_dollars
h.number_to_currency(membership_amount, locale: :en)
end
end
An example of a decorator for a client
Then for each decorate column used, don’t forget to specify how the sorting should behave like this:
# app/admin/customers.rb
ActiveAdmin.register Customer do
decorate_with CustomerDecorator
index do
selectable_column
column :id
column :name, sortable: :lastname
column :email
column :phone_number
column :city
column :language
column :membership_amount_in_dollars, sortable: :membership_amount
column :state
column :created_at
column :updated_at
actions
end
end
Example of an AA index for a client
Enhance the state display
The ressources displayed in an admin index often comes with a state. In our customers’ index, it’s a basic sales’ pipeline. Indeed, a customer is first in the “new” state before being contacted, then it might enter in the negociating phase and finally he becomes signed. He might change later to the terminated phase (when he cancels the contract).
Status Labels
Of course, we could just add up a bit of color using the very simple status_tag
feature of ActiveAdmin.
First of all, we add the status_tag logic in our AA customers’ index view :
# app/admin/customers.rb
ActiveAdmin.register Customer do
decorate_with CustomerDecorator
index do
# [... others columns]
column :state do |customer|
status_tag customer.state
end
# [... others columns]
end
end
Then we can use a SASS’map to customize the status_tag background color :
// app/assets/stylesheets/active_admin/components/_status_tags.scss
$customers_states_colors: (
new: #BBC6C3,
contacted: #70C0C6,
negociating: #9DEA4F,
signed: #329932,
terminated: #FF320E
);
.status_tag {
@each $state, $color in $customers_states_colors {
&.#{$state} {
background: $color;
}
}
}
Convert labels to progress
The results is more visual but on the other hand our customers’ states are linear which means that for each customers, its first state will be new and at last he will go into the terminated phase.
Note that I used an enum for this because these states didn’t need any transitions or guards but you can achieve the same result with a state machine like AASM or Statesman.
One way to graphically represent this linearity is to display the state in a progress bar. Whenever it’s empty means that the customer is in the new state and full means that the customer is either signed or terminated. We will also reuse the color schemes defined before to make it more visual.
First, let’s add a method in our customer decorator that will return the completion state in percent for our progress bar :
class CustomerDecorator < Draper::Decorator
delegate_all
# [ other decorator logic here ... ]
def state_completition_in_percent
customer_state_index = Customer.state.values.index(state).to_f + 1
return 100 if state == :terminated
total_states_count_without_terminated_state = Customer.state.values.length - 1
completion = customer_state_index / total_states_count_without_terminated_state
(completion * 100).round(0)
end
end
Then we will render an .html.erb partial in our customer.state column :
ActiveAdmin.register Customer do
decorate_with CustomerDecorator
index do
[ other columns logic here ... ]
column :state do |customer|
render partial: 'admin/customers/material_progress_bar', locals: { customer: customer }
end
actions
end
end
Now we can create our material_progress_bar partial :
<div class="progress-wrapper <%= customer.state %>">
<span class="state"><%= customer.state %></span>
<div class="progress">
<div class="bar" style="width: <%= customer.state_completition_in_percent %>%"></div>
</div>
</div>
At last, a little bit of styling (don’t forget to require it in your application.scss file) :
@import 'active_admin/variables/colors';
$customers_states_colors: (
new: #BBC6C3,
contacted: #70C0C6,
negociating: #9DEA4F,
signed: #329932,
terminated: #FF320E
);
$progress-bar-bg: #acece6;
$state-text-color: #707675;
$progress-bar-border-color: $state-text-color;
.progress-wrapper {
.progress {
position: relative;
height: 10px;
display: block;
width: 100%;
min-width: 100px;
background-color: $progress-bar-bg;
border-radius: 2px;
background-clip: padding-box;
margin: 0.15rem 0 1rem 0;
overflow: hidden;
.bar {
position: absolute;
top: 0;
bottom: 0;
transition: width 1s expandWidth;
}
}
@each $state, $color in $customers_states_colors {
&.#{$state} {
color: $state-text-color;
.progress {
border: 0.5px solid $progress-bar-border-color;
background-color: transparent;
.bar {
background: $color;
}
}
}
}
}
view raw