Skip to content

Commit

Permalink
Merge pull request #1744 from tvdeyen/sortable-resources-tables
Browse files Browse the repository at this point in the history
Sortable resources tables
  • Loading branch information
tvdeyen authored Mar 12, 2020
2 parents 3ed9508 + 8ad0674 commit ec17038
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 45 deletions.
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ gem 'mysql2', '~> 0.5.1' if ENV['DB'] == 'mysql'
gem 'pg', '~> 1.0' if ENV['DB'] == 'postgresql'

group :development, :test do
if ENV['CI']
gem 'sprockets', '< 4.0' # Sprockets 4 has serious issues with libsass on Linux machines
if ENV['GITHUB_ACTIONS']
gem 'sassc', '~> 2.1.0' # https://github.com/sass/sassc-ruby/issues/146
else
gem 'launchy'
gem 'annotate'
Expand Down
25 changes: 1 addition & 24 deletions app/assets/stylesheets/alchemy/tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,29 +57,6 @@ th {
vertical-align: top;
border-bottom: 1px solid $medium-gray;
font-weight: bold;

i {
font-style: normal;
position: absolute;
right: 2px;
top: 4px;
text-shadow: 1px 1px 1px #fff;
}

a {

&.sortable {
display: block;
margin: -4px -8px;
padding: 4px 18px 4px 8px;
text-shadow: 1px 1px 1px #fff;
}

&.sorted {
position: relative;
background: $medium-gray;
}
}
}

tr.even td {
Expand Down Expand Up @@ -141,7 +118,7 @@ td {
width: 80px;
}

&.date {
&.date, &.datetime {
width: 150px;
}

Expand Down
1 change: 1 addition & 0 deletions app/controllers/alchemy/admin/attachments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class AttachmentsController < ResourcesController

def index
@query = Attachment.ransack(search_filter_params[:q])
@query.sorts = 'name asc' if @query.sorts.empty?
@attachments = @query.result

if search_filter_params[:tagged_with].present?
Expand Down
1 change: 1 addition & 0 deletions app/controllers/alchemy/admin/languages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Admin
class LanguagesController < ResourcesController
def index
@query = Language.on_current_site.ransack(search_filter_params[:q])
@query.sorts = default_sort_order if @query.sorts.empty?
@languages = @query.result.page(params[:page] || 1).per(items_per_page)
end

Expand Down
6 changes: 6 additions & 0 deletions app/controllers/alchemy/admin/resources_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ResourcesController < Alchemy::Admin::BaseController

def index
@query = resource_handler.model.ransack(search_filter_params[:q])
@query.sorts = default_sort_order if @query.sorts.empty?
items = @query.result

if contains_relations?
Expand Down Expand Up @@ -162,6 +163,11 @@ def items_per_page_options
per_page = Alchemy::Config.get(:items_per_page)
[per_page, per_page * 2, per_page * 4]
end

def default_sort_order
name = resource_handler.attributes.detect { |attr| attr[:name] == 'name' }
name ? 'name asc' : "#{resource_handler.attributes.first[:name]} asc"
end
end
end
end
1 change: 1 addition & 0 deletions app/controllers/alchemy/admin/tags_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class TagsController < ResourcesController

def index
@query = Gutentag::Tag.ransack(search_filter_params[:q])
@query.sorts = default_sort_order if @query.sorts.empty?
@tags = @query
.result
.page(params[:page] || 1)
Expand Down
8 changes: 4 additions & 4 deletions app/views/alchemy/admin/attachments/_files_list.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
<thead>
<tr>
<th class="icon"></th>
<th class="name"><%= sort_link(@query, :name, hide_indicator: true) %></th>
<th class="file_name"><%= sort_link(@query, :file_name, hide_indicator: true) %></th>
<th class="name"><%= sort_link(@query, :name) %></th>
<th class="file_name"><%= sort_link(@query, :file_name) %></th>
<th class="file_type"><%= Alchemy::Attachment.human_attribute_name('file_mime_type') %></th>
<th class="file_size"><%= sort_link(@query, :file_size, hide_indicator: true) %></th>
<th class="date"><%= sort_link(@query, :created_at, hide_indicator: true) %></th>
<th class="file_size"><%= sort_link(@query, :file_size) %></th>
<th class="date"><%= sort_link(@query, :created_at, default_order: 'desc') %></th>
<th class="tools"></th>
</tr>
</thead>
Expand Down
6 changes: 3 additions & 3 deletions app/views/alchemy/admin/languages/_table.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<thead>
<tr>
<th>
<%= sort_link @query, :name, hide_indicator: true %>
<%= sort_link @query, :name %>
</th>
<th>
<%= sort_link @query, :language_code, hide_indicator: true %>
<%= sort_link @query, :language_code %>
</th>
<th>
<%= sort_link @query, :country_code, hide_indicator: true %>
<%= sort_link @query, :country_code %>
</th>
<th>
<%= Alchemy::Language.human_attribute_name(:code) %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/alchemy/admin/resources/_resource.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<tr class="<%= cycle('even', 'odd') %>">
<% resource_handler.attributes.each do |attribute| %>
<% resource_handler.sorted_attributes.each do |attribute| %>
<td class="<%= attribute[:type] %> <%= attribute[:name] %>">
<% if attribute[:type] == :boolean %>
<%= resource.public_send(attribute[:name]) ? render_icon(:check) : nil %>
Expand Down
4 changes: 2 additions & 2 deletions app/views/alchemy/admin/resources/_table.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<table class="list" id="<%= resource_handler.resources_name %>_list">
<thead>
<tr>
<% resource_handler.attributes.each do |attribute| %>
<% resource_handler.sorted_attributes.each do |attribute| %>
<th class="<%= attribute[:type] %> <%= attribute[:name] %>">
<%= sort_link [:resource_url_proxy, @query],
sortable_resource_header_column(attribute),
resource_handler.model.human_attribute_name(attribute[:name]),
hide_indicator: true %>
default_order: attribute[:type].to_s =~ /date|time/ ? 'desc' : 'asc' %>
</th>
<% end %>
<th class="tools"></th>
Expand Down
4 changes: 2 additions & 2 deletions app/views/alchemy/admin/tags/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
<thead>
<tr>
<th class="icon"></th>
<th class="name"><%= sort_link(@query, :name, hide_indicator: true) %></th>
<th class="name"><%= sort_link(@query, :name) %></th>
<th class="count"><%= Gutentag::Tag.human_attribute_name(:taggings_types) %></th>
<th class="count"><%= sort_link(@query, :taggings_count, hide_indicator: true) %></th>
<th class="count"><%= sort_link(@query, :taggings_count) %></th>
<th class="tools"></th>
</tr>
</thead>
Expand Down
2 changes: 1 addition & 1 deletion config/locales/alchemy.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ en:
time:
formats:
alchemy:
default: "%a, %d %b %Y %H:%M:%S %z"
default: "%m.%d.%Y %H:%M"
essence_date: "%Y-%m-%d"
page_status: "%m.%d.%Y %H:%M"
short_datetime: "%d %b %H:%M"
Expand Down
10 changes: 10 additions & 0 deletions lib/alchemy/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ class Engine < Rails::Engine
Gutentag.normaliser = ->(value) { value.to_s }
end

# Custom Ransack sort arrows
initializer 'alchemy.ransack' do
Ransack.configure do |config|
config.custom_arrows = {
up_arrow: '<i class="fa fas fa-xs fa-arrow-up"></i>',
down_arrow: '<i class="fa fas fa-xs fa-arrow-down"></i>'
}
end
end

config.after_initialize do
require_relative './userstamp'
end
Expand Down
11 changes: 9 additions & 2 deletions lib/alchemy/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ class Resource
attr_accessor :resource_relations, :model_associations
attr_reader :model

DEFAULT_SKIPPED_ATTRIBUTES = %w(id updated_at created_at creator_id updater_id)
DEFAULT_SKIPPED_ASSOCIATIONS = %w(creator updater)
DEFAULT_SKIPPED_ATTRIBUTES = %w(id created_at creator_id)
DEFAULT_SKIPPED_ASSOCIATIONS = %w(creator)
SEARCHABLE_COLUMN_TYPES = [:string, :text]

def initialize(controller_path, module_definition = nil, custom_model = nil)
Expand Down Expand Up @@ -168,6 +168,13 @@ def attributes
end.compact
end

def sorted_attributes
@_sorted_attributes ||= attributes.
sort_by { |attr| attr[:name] == 'name' ? 0 : 1 }.
sort_by! { |attr| attr[:type] == :boolean ? 1 : 0 }.
sort_by! { |attr| attr[:name] == 'updated_at' ? 1 : 0 }
end

def editable_attributes
attributes.reject { |h| restricted_attributes.map(&:to_s).include?(h[:name].to_s) }
end
Expand Down
31 changes: 28 additions & 3 deletions spec/controllers/alchemy/admin/resources_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,36 @@
end

context 'with sort parameter given' do
let(:params) { {q: {s: "name asc"}} }
let(:params) { {q: {s: "name desc"}} }

it "returns records in the right order" do
it "returns records in the defined order" do
get :index, params: params
expect(assigns(:events)).to eq([lustig, peter])
expect(assigns(:events)).to eq([peter, lustig])
end
end

context 'without sort parameter given' do
context 'if resource has name attribute' do
it "returns records sorted by name" do
get :index
expect(assigns(:events)).to eq([lustig, peter])
end
end

context 'if resource has no name attribute' do
let!(:booking1) { Booking.create!(from: 2.week.from_now) }
let!(:booking2) { Booking.create!(from: 1.weeks.from_now) }

controller(::Alchemy::Admin::ResourcesController) do
def resource_handler
@_resource_handler ||= Alchemy::Resource.new(controller_path, alchemy_module, Booking)
end
end

it "returns records sorted by first attribute" do
get :index
expect(assigns(:resources)).to eq([booking2, booking1])
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/features/admin/resources_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@

it "lists the new item" do
expect(page).to have_content "My second event"
expect(page).to have_content "03 Mar 2012"
expect(page).to have_content "03.12.2020"
end

it "shows a success message" do
Expand Down
22 changes: 22 additions & 0 deletions spec/libraries/resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,28 @@ module Alchemy
end
end

describe "#sorted_attributes" do
subject { resource.sorted_attributes }

let(:columns) do
[
double(:column, {name: 'title', type: :string}),
double(:column, {name: 'name', type: :string}),
double(:column, {name: 'updated_at', type: :datetime}),
double(:column, {name: 'public', type: :boolean})
]
end

it "sorts by name, and updated_at" do
is_expected.to eq([
{name: "name", type: :string},
{name: "title", type: :string},
{name: "public", type: :boolean},
{name: "updated_at", type: :datetime}
])
end
end

context "when alchemy_resource_relations defined as class method in the model" do
let(:resource) { Resource.new("admin/events") }

Expand Down

0 comments on commit ec17038

Please sign in to comment.