Permalink
Browse files

Added sorting to the Users view(s)

 * This was a request from Tom @ NDA
 * Generally, table sorting should be pretty easy to add to *any* table
 * It's not AJAX, yet...
  • Loading branch information...
1 parent 6d10c55 commit 87877cfaa7923acb87ec228c0eae9c2cccbc7d61 @rnhurt committed Aug 21, 2009
@@ -1,9 +1,13 @@
class Users::StudentsController < ApplicationController
before_filter :require_user
append_before_filter :authorized?
+ include SortHelper
def index
- @students = Student.search(params[:search], params[:page])
+ sort_init 'last_name'
+ sort_update
+ params[:sort_clause] = sort_clause
+ @students = Student.search(params)
respond_to do |format|
format.html
@@ -1,9 +1,13 @@
class Users::TeacherAssistantsController < ApplicationController
before_filter :require_user
append_before_filter :authorized?
+ include SortHelper
def index
- @teacher_assistants = TeacherAssistant.search(params[:search], params[:page])
+ sort_init 'last_name'
+ sort_update
+ params[:sort_clause] = sort_clause
+ @teacher_assistants = TeacherAssistant.search(params)
respond_to do |format|
format.html # index.html.erb
@@ -1,9 +1,13 @@
class Users::TeachersController < ApplicationController
before_filter :require_user
append_before_filter :authorized?
+ include SortHelper
def index
- @teachers = Teacher.search(params[:search], params[:page])
+ sort_init 'last_name'
+ sort_update
+ params[:sort_clause] = sort_clause
+ @teachers = Teacher.search(params)
respond_to do |format|
format.html
@@ -2,13 +2,13 @@
class UsersController < ApplicationController
before_filter :require_user
append_before_filter :authorized?
+ include SortHelper
def index
- @users = User.search(params[:search], params[:page])
-
- respond_to do |format|
- format.html # index.html.erb
- end
+ sort_init 'last_name'
+ sort_update
+ params[:sort_clause] = sort_clause
+ @users = User.search(params)
end
View
@@ -0,0 +1,167 @@
+# Helpers to sort tables using clickable column headers.
+#
+# Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
+# License: This source code is released under the MIT license.
+#
+# - Consecutive clicks toggle the column's sort order.
+# - Sort state is maintained by a session hash entry.
+# - Icon image identifies sort column and state.
+# - Typically used in conjunction with the Pagination module.
+#
+# Example code snippets:
+#
+# Controller:
+#
+# helper :sort
+# include SortHelper
+#
+# def list
+# sort_init 'last_name'
+# sort_update
+# @items = Contact.find(:all, :conditions => sort_clause)
+# end
+#
+# Controller with paginator:
+#
+# helper :sort
+# include SortHelper
+#
+# def list
+# sort_init 'last_name'
+# sort_update
+# @contact_pages, @items = paginate(:contacts,
+# :order_by => sort_clause,
+# :per_page => 10)
+# end
+#
+# View (table header in list.rhtml):
+#
+# <thead>
+# <tr>
+# <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
+# <%= sort_header_tag('last_name', :text => 'Name') %>
+# <%= sort_header_tag('phone') %>
+# <%= sort_header_tag('address', :width => 200) %>
+# </tr>
+# </thead>
+#
+# - The ascending and descending sort icon images are sort_asc.png and
+# sort_desc.png and reside in the application's images directory.
+# - Introduces instance variables: @sort_name, @sort_default.
+# - Introduces params :sort_key and :sort_order.
+#
+# History
+# -------
+# 2007-05-31: Version 1.0.3 (patch submitted by Chris Parker)
+# - If :title is specified, then that is set as the <th> text
+# - Add the ability to add optional :param values
+# 2006-04-04: Version 1.0.2
+# - Tidied up examples.
+# - Changed older @params and @session style to params and sessions.
+# 2006-01-19: Version 1.0.1
+# - sort_init() accepts options hash.
+# - sort_init() :icons_dir option added.
+# 2005-03-26: Version 1.0.0
+#
+module SortHelper
+ # Initializes the default sort column (default_key) with the following
+ # options:
+ #
+ # - :default_order -- the default sort order 'asc' or 'desc'. Defaults to
+ # 'asc'.
+ # - :name -- the name of the session hash entry that stores the sort state.
+ # Defaults to '<controller_name>_sort'.
+ # - :icons_dir -- directory with sort direction icons. Defaults to
+ # /images
+ #
+ def sort_init(default_key, options={})
+ options = { :default_order => 'asc',
+ :name => params[:controller] + '_sort',
+ :icons_dir => '/images',
+ }.merge(options)
+ @sort_name = options[:name]
+ @sort_default = {:key => default_key, :order => options[:default_order]}
+ @icons_dir = options[:icons_dir]
+ end
+
+ # Updates the sort state. Call this in the controller prior to calling
+ # sort_clause.
+ #
+ def sort_update()
+ if params[:sort_key]
+ sort = {:key => params[:sort_key], :order => params[:sort_order]}
+ elsif session[@sort_name]
+ sort = session[@sort_name] # Previous sort.
+ else
+ sort = @sort_default
+ end
+ session[@sort_name] = sort
+ end
+
+ # Returns an SQL sort clause corresponding to the current sort state.
+ # Use this to sort the controller's table items collection.
+ #
+ def sort_clause()
+ result = session[@sort_name][:key] + ' ' + session[@sort_name][:order]
+ result if result =~ /^[\w_]+ (asc|desc)$/i # Validate sort.
+ end
+
+ # Returns a link which sorts by the named column.
+ #
+ # - column is the name of an attribute in the sorted record collection.
+ # - The optional text explicitly specifies the displayed link text.
+ # - A sort icon image is positioned to the right of the sort link.
+ #
+ def sort_link(column, text=nil, options=nil)
+ key, order = session[@sort_name][:key], session[@sort_name][:order]
+ if key == column
+ if order.downcase == 'asc'
+ icon, order = 'sort_asc.png', 'desc'
+ else
+ icon, order = 'sort_desc.png', 'asc'
+ end
+ else
+ icon, order = nil, 'asc'
+ end
+ text = column.titleize unless text
+ params = {:params => {:sort_key => column, :sort_order => order } }
+ params = params.merge(options[:params]) if options[:params]
+ link_to(text, params) +
+ (icon ? nbsp(2) + image_tag(File.join(@icons_dir,icon)) : '')
+ end
+
+ # Returns a table header <th> tag with a sort link for the named column
+ # attribute.
+ #
+ # Options:
+ # :text The displayed link name (defaults to titleized column name).
+ # :title The tag's 'title' attribute (defaults to 'Sort by :text').
+ #
+ # Other options hash entries generate additional table header tag attributes.
+ #
+ # Example:
+ #
+ # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
+ #
+ # Renders:
+ #
+ # <th title="Sort by contact ID" width="40">
+ # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
+ # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
+ # </th>
+ #
+ def sort_header_tag(column, options = {})
+ text = options.delete(:text) || column.humanize.titleize
+ options[:title]= "Sort by #{text}" unless options[:title]
+ text = options[:title] || options.delete(:text) || column.humanize.titleize
+ content_tag('th', sort_link(column, text, options), options)
+ end
+
+ private
+
+ # Return n non-breaking spaces.
+ def nbsp(n)
+ '&nbsp;' * n
+ end
+
+end
View
@@ -22,11 +22,12 @@ class User < ActiveRecord::Base
validates_uniqueness_of :first_name, :scope => :last_name
# Search for a user using the 'will_paginate' plugin
- def self.search(search, page)
+ def self.search(params)
+ search = params[:search]
search.downcase! if search # Make sure we don't have any case sensitivity problems
- paginate :per_page => 15, :page => page,
+ paginate :per_page => 15, :page => params[:page],
:conditions => ['LOWER(first_name) like ? or LOWER(last_name) like ?', "%#{search}%", "%#{search}%"],
- :order => 'first_name',
+ :order => params[:sort_clause],
:include => :site
end
@@ -1,31 +1,33 @@
-<% user_type = users[0].class.name %>
-
<table id="users" class="master">
<thead>
<tr>
- <th>Login</th>
+ <%= sort_header_tag('login', :title => 'Login') %>
<% form_for users.class.to_s, :html => { :method => :get } do |s| %>
- <th>Name <%= text_field_tag :search,
- params[:search],
- :size => 10,
- :class => "focus search" %></th>
+ <%= sort_header_tag('first_name', :title => 'First Name') %>
+ <%= sort_header_tag('last_name', :title => 'Last Name') %>
+ <%= sort_header_tag('email', :title => 'Email Address') %>
+ <th>Campus</th>
+ <% if controller.controller_name == 'students' %>
+ <%= sort_header_tag('class_of', :title => 'Class Of') %>
+ <%= sort_header_tag('homeroom', :title => 'Homeroom') %>
<% end %>
- <th>Email Address</th>
- <th>Campus</th>
- <%= content_tag(:th, 'Class-Of') if user_type == 'Student' %>
- <%= content_tag(:th, 'Homeroom') if user_type == 'Student' %>
- <th width='1'></th>
+ <th><%= text_field_tag :search, params[:search],
+ :size => 10, :class => "focus search" %></th>
+ <% end %>
</tr>
</thead>
<tbody>
<% for u in users %>
<tr class="<%= cycle('odd', 'even') %>" onclick="location.href='<%= url_for(u)+'/edit' %>'">
<%= content_tag :td, u.login %>
- <td width='50%'><%= link_to u.full_name, url_for(u)+'/edit' %></td>
+ <td><%= link_to u.first_name, url_for(u)+'/edit' %></td>
+ <td><%= link_to u.last_name, url_for(u)+'/edit' %></td>
<%= content_tag :td, u.email %>
<%= content_tag :td, u.site.name %>
- <%= content_tag(:td, u.class_of) if user_type == 'Student' %>
- <%= content_tag(:td, u.homeroom) if user_type == 'Student' %>
+ <% if controller.controller_name == 'students' %>
+ <%= content_tag :td, u.class_of %>
+ <%= content_tag :td, u.homeroom %>
+ <% end %>
<td><%= button_to 'Delete', u, :method => :delete,
:confirm => "Are you sure you want to delete\n\n '" + u.full_name + "'?",
:class => 'btn negative' %></td>
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 87877cf

Please sign in to comment.