Make columns of user and ordergroup lists sortable

This commit implements the sort functionality for the user lists (by name, email, last_activity) and ordergroup lists (by name).
It is a first attempt addressing issue #560.
This commit is contained in:
Harald Reingruber 2022-05-27 17:06:25 +02:00 committed by GitHub
parent 8f94403ccf
commit 0a6345c60b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 278 additions and 25 deletions

View file

@ -2,7 +2,7 @@ class Admin::OrdergroupsController < Admin::BaseController
inherit_resources
def index
@ordergroups = Ordergroup.undeleted.order('name ASC')
@ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
if request.format.csv?
send_data OrdergroupsCsv.new(@ordergroups).to_csv, filename: 'ordergroups.csv', type: 'text/csv'

View file

@ -3,6 +3,8 @@ class Admin::UsersController < Admin::BaseController
def index
@users = params[:show_deleted] ? User.deleted : User.undeleted
@users = @users.sort_by_param(params["sort"])
@users = @users.includes(:mail_delivery_status)
if request.format.csv?
@ -12,7 +14,7 @@ class Admin::UsersController < Admin::BaseController
# if somebody uses the search field:
@users = @users.natural_search(params[:user_name]) unless params[:user_name].blank?
@users = @users.natural_order.page(params[:page]).per(@per_page)
@users = @users.page(params[:page]).per(@per_page)
end
def destroy

View file

@ -1,6 +1,6 @@
class Foodcoop::OrdergroupsController < ApplicationController
def index
@ordergroups = Ordergroup.undeleted.order('name')
@ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
unless params[:name].blank? # Search by name
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%")

View file

@ -1,6 +1,6 @@
class Foodcoop::UsersController < ApplicationController
def index
@users = User.undeleted.natural_order
@users = User.undeleted.sort_by_param(params["sort"])
# if somebody uses the search field:
@users = @users.natural_search(params[:user_name]) unless params[:user_name].blank?

View file

@ -148,6 +148,29 @@ class Ordergroup < Group
financial_transactions.last.try(:created_on) || created_on
end
def self.sort_by_param(param)
param ||= "name"
sort_param_map = {
"name" => "name",
"name_reverse" => "name DESC",
"members_count" => "count(users.id)",
"members_count_reverse" => "count(users.id) DESC",
"last_user_activity" => "max(users.last_activity)",
"last_user_activity_reverse" => "max(users.last_activity) DESC",
"last_order" => "max(orders.starts)",
"last_order_reverse" => "max(orders.starts) DESC"
}
result = self
result = result.left_joins(:users).group("groups.id") if param.starts_with?("members_count", "last_user_activity")
result = result.left_joins(:orders).group("groups.id") if param.starts_with?("last_order")
# Never pass user input data to Arel.sql() because of SQL Injection vulnerabilities.
# This case here is okay, as param is mapped to the actual order string.
result.order(Arel.sql(sort_param_map[param]))
end
private
# Make sure, that a user can only be in one ordergroup

View file

@ -250,4 +250,27 @@ class User < ApplicationRecord
# this should not be part of the model anyway
{ :id => id, :name => "#{display} (#{ordergroup.try(:name)})" }
end
def self.sort_by_param(param)
param ||= "name"
sort_param_map = {
"nick" => "nick",
"nick_reverse" => "nick DESC",
"name" => "first_name, last_name",
"name_reverse" => "first_name DESC, last_name DESC",
"email" => "users.email",
"email_reverse" => "users.email DESC",
"phone" => "phone",
"phone_reverse" => "phone DESC",
"last_activity" => "last_activity",
"last_activity_reverse" => "last_activity DESC",
"ordergroup" => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name",
"ordergroup_reverse" => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name DESC"
}
# Never pass user input data to Arel.sql() because of SQL Injection vulnerabilities.
# This case here is okay, as param is mapped to the actual order string.
self.eager_load(:groups).order(Arel.sql(sort_param_map[param])) # eager_load is like left_join but without duplicates
end
end

View file

@ -4,10 +4,11 @@
%table.table.table-striped
%thead
%tr
%th= heading_helper Ordergroup, :name
%th= heading_helper Ordergroup, :user_tokens
%th= sort_link_helper heading_helper(Ordergroup, :name), "name"
%th= sort_link_helper heading_helper(Ordergroup, :user_tokens), "members_count"
%th= heading_helper Ordergroup, :contact_address
%th= heading_helper Ordergroup, :last_user_activity
%th= sort_link_helper heading_helper(Ordergroup, :last_user_activity), "last_user_activity"
%th= sort_link_helper heading_helper(Ordergroup, :last_order), "last_order"
%th= t 'ui.actions'
%tbody
- for ordergroup in @ordergroups
@ -17,6 +18,7 @@
%abbr{title: ordergroup_members_title(ordergroup)}= ordergroup.users.size
%td= link_to_gmaps ordergroup.contact_address
%td= format_date ordergroup.last_user_activity
%td= format_date ordergroup.last_order.try(:starts)
%td
= link_to t('ui.edit'), edit_admin_ordergroup_path(ordergroup), class: 'btn btn-mini'
= link_to t('ui.delete'), [:admin, ordergroup], :data => {:confirm => t('ui.confirm_delete', name: ordergroup.name)},

View file

@ -5,11 +5,11 @@
%thead
%tr
- if FoodsoftConfig[:use_nick]
%th= heading_helper User, :nick
%th= heading_helper User, :name
%th= heading_helper User, :email
%th= sort_link_helper heading_helper(User, :nick), "nick"
%th= sort_link_helper heading_helper(User, :name), "name"
%th= sort_link_helper heading_helper(User, :email), "email"
%th= t 'admin.access_to'
%th= heading_helper User, :last_activity
%th= sort_link_helper heading_helper(User, :last_activity), "last_activity"
%th(colspan="2")= t 'ui.actions'
%tbody
- for user in @users

View file

@ -5,11 +5,11 @@
%table.table.table-striped
%thead
%tr
%th= heading_helper Ordergroup, :name
%th= sort_link_helper heading_helper(Ordergroup, :name), "name"
%th= heading_helper Ordergroup, :user_tokens
%th= heading_helper Ordergroup, :break
%th= heading_helper Ordergroup, :last_user_activity
%th= heading_helper Ordergroup, :last_order
%th= sort_link_helper heading_helper(Ordergroup, :last_user_activity), "last_user_activity"
%th= sort_link_helper heading_helper(Ordergroup, :last_order), "last_order"
%tbody
- for ordergroup in @ordergroups

View file

@ -5,11 +5,11 @@
%thead
%tr
- if FoodsoftConfig[:use_nick]
%th= heading_helper User, :nick
%th= heading_helper User, :name
%th= heading_helper User, :email
%th= heading_helper User, :phone
%th= heading_helper User, :ordergroup
%th= sort_link_helper heading_helper(User, :nick), "nick"
%th= sort_link_helper heading_helper(User, :name), "name"
%th= sort_link_helper heading_helper(User, :email), "email"
%th= sort_link_helper heading_helper(User, :phone), "phone"
%th= sort_link_helper heading_helper(User, :ordergroup), "ordergroup"
%th= heading_helper User, :workgroup, count: 3
%tbody
- for user in @users