Add Group Milestone sorting
This commit is contained in:
parent
bba020a56c
commit
f4ed780ef5
7 changed files with 150 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
22
app/views/shared/_group_milestones_sort_dropdown.html.haml
Normal file
22
app/views/shared/_group_milestones_sort_dropdown.html.haml
Normal 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
|
5
changelogs/unreleased/39720-group-milestone-sorting.yml
Normal file
5
changelogs/unreleased/39720-group-milestone-sorting.yml
Normal 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
40
lib/milestone_array.rb
Normal 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
|
46
spec/features/groups/milestones_sorting_spec.rb
Normal file
46
spec/features/groups/milestones_sorting_spec.rb
Normal 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
|
34
spec/lib/milestone_array_spec.rb
Normal file
34
spec/lib/milestone_array_spec.rb
Normal 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
|
Loading…
Reference in a new issue