Add Group Milestone sorting

This commit is contained in:
George Andrinopoulos 2017-11-06 19:51:24 +02:00
parent bba020a56c
commit f4ed780ef5
7 changed files with 150 additions and 1 deletions

View file

@ -80,7 +80,8 @@ class Groups::MilestonesController < Groups::ApplicationController
milestones = MilestonesFinder.new(search_params).execute
legacy_milestones = GroupMilestone.build_collection(group, group_projects, params)
milestones + legacy_milestones
@sort = params[:sort] || 'due_date_asc'
MilestoneArray.sort(milestones + legacy_milestones, @sort)
end
def milestone

View file

@ -4,6 +4,7 @@
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls
= render 'shared/group_milestones_sort_dropdown'
- if can?(current_user, :admin_milestones, @group)
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"

View file

@ -0,0 +1,22 @@
.dropdown.inline.prepend-left-10
%button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } }
%span.light
- if @sort.present?
= milestone_sort_options_hash[@sort]
- else
= sort_title_due_date_soon
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort
%li
= link_to page_filter_path(sort: sort_value_due_date_soon, label: true) do
= sort_title_due_date_soon
= link_to page_filter_path(sort: sort_value_due_date_later, label: true) do
= sort_title_due_date_later
= link_to page_filter_path(sort: sort_value_start_date_soon, label: true) do
= sort_title_start_date_soon
= link_to page_filter_path(sort: sort_value_start_date_later, label: true) do
= sort_title_start_date_later
= link_to page_filter_path(sort: sort_value_name, label: true) do
= sort_title_name_asc
= link_to page_filter_path(sort: sort_value_name_desc, label: true) do
= sort_title_name_desc

View file

@ -0,0 +1,5 @@
---
title: Add dropdown sort to group milestones
merge_request: 15230
author: George Andrinopoulos
type: added

40
lib/milestone_array.rb Normal file
View file

@ -0,0 +1,40 @@
module MilestoneArray
class << self
def sort(array, sort_method)
case sort_method
when 'due_date_asc'
sort_asc_nulls_last(array, 'due_date')
when 'due_date_desc'
sort_desc_nulls_last(array, 'due_date')
when 'start_date_asc'
sort_asc_nulls_last(array, 'start_date')
when 'start_date_desc'
sort_desc_nulls_last(array, 'start_date')
when 'name_asc'
sort_asc(array, 'title')
when 'name_desc'
sort_desc(array, 'title')
else
array
end
end
private
def sort_asc_nulls_last(array, attribute)
array.select(&attribute.to_sym).sort_by(&attribute.to_sym) + array.reject(&attribute.to_sym)
end
def sort_desc_nulls_last(array, attribute)
array.select(&attribute.to_sym).sort_by(&attribute.to_sym).reverse + array.reject(&attribute.to_sym)
end
def sort_asc(array, attribute)
array.sort_by(&attribute.to_sym)
end
def sort_desc(array, attribute)
array.sort_by(&attribute.to_sym).reverse
end
end
end

View file

@ -0,0 +1,46 @@
require 'spec_helper'
feature 'Milestones sorting', :js do
let(:group) { create(:group) }
let!(:project) { create(:project_empty_repo, group: group) }
let!(:other_project) { create(:project_empty_repo, group: group) }
let!(:project_milestone1) { create(:milestone, project: project, title: 'v1.0', due_date: 10.days.from_now) }
let!(:other_project_milestone1) { create(:milestone, project: other_project, title: 'v1.0', due_date: 10.days.from_now) }
let!(:project_milestone2) { create(:milestone, project: project, title: 'v2.0', due_date: 5.days.from_now) }
let!(:other_project_milestone2) { create(:milestone, project: other_project, title: 'v2.0', due_date: 5.days.from_now) }
let(:user) { create(:group_member, :master, user: create(:user), group: group ).user }
before do
sign_in(user)
end
scenario 'visit group milestones and sort by due_date_asc' do
visit group_milestones_path(group)
expect(page).to have_button('Due soon')
# assert default sorting
within '.milestones' do
expect(page.all('ul.content-list > li').first.text).to include('v2.0')
expect(page.all('ul.content-list > li').last.text).to include('v1.0')
end
click_button 'Due soon'
sort_options = find('ul.dropdown-menu-sort li').all('a').collect(&:text)
expect(sort_options[0]).to eq('Due soon')
expect(sort_options[1]).to eq('Due later')
expect(sort_options[2]).to eq('Start soon')
expect(sort_options[3]).to eq('Start later')
click_link 'Due later'
expect(page).to have_button('Due later')
within '.milestones' do
expect(page.all('ul.content-list > li').first.text).to include('v1.0')
expect(page.all('ul.content-list > li').last.text).to include('v2.0')
end
end
end

View file

@ -0,0 +1,34 @@
require 'spec_helper'
describe MilestoneArray do
let(:object1) { instance_double("BirdMilestone", due_date: Time.now, start_date: Time.now - 15.days, title: 'v2.0') }
let(:object2) { instance_double("CatMilestone", due_date: Time.now - 1.day, start_date: nil, title: 'v1.0') }
let(:object3) { instance_double("DogMilestone", due_date: nil, start_date: Time.now - 30.days, title: 'v3.0') }
let(:array) { [object1, object3, object2] }
describe '#sort' do
it 'reorders array with due date in ascending order with nulls last' do
expect(described_class.sort(array, 'due_date_asc')).to eq([object2, object1, object3])
end
it 'reorders array with due date in desc order with nulls last' do
expect(described_class.sort(array, 'due_date_desc')).to eq([object1, object2, object3])
end
it 'reorders array with start date in ascending order with nulls last' do
expect(described_class.sort(array, 'start_date_asc')).to eq([object3, object1, object2])
end
it 'reorders array with start date in descending order with nulls last' do
expect(described_class.sort(array, 'start_date_desc')).to eq([object1, object3, object2])
end
it 'reorders array with title in ascending order' do
expect(described_class.sort(array, 'name_asc')).to eq([object2, object1, object3])
end
it 'reorders array with title in descending order' do
expect(described_class.sort(array, 'name_desc')).to eq([object3, object1, object2])
end
end
end