Add dropdown sort to project milestones
This commit is contained in:
parent
902ea5c85b
commit
e118d48df9
8 changed files with 130 additions and 5 deletions
|
@ -13,11 +13,14 @@ class Projects::MilestonesController < Projects::ApplicationController
|
||||||
def index
|
def index
|
||||||
@milestones =
|
@milestones =
|
||||||
case params[:state]
|
case params[:state]
|
||||||
when 'all' then @project.milestones.reorder(due_date: :desc, title: :asc)
|
when 'all' then @project.milestones
|
||||||
when 'closed' then @project.milestones.closed.reorder(due_date: :desc, title: :asc)
|
when 'closed' then @project.milestones.closed
|
||||||
else @project.milestones.active.reorder(due_date: :asc, title: :asc)
|
else @project.milestones.active
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@sort = params[:sort] || 'due_date_asc'
|
||||||
|
@milestones = @milestones.sort(@sort)
|
||||||
|
|
||||||
@milestones = @milestones.includes(:project)
|
@milestones = @milestones.includes(:project)
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
|
|
|
@ -2,6 +2,7 @@ module SortingHelper
|
||||||
def sort_options_hash
|
def sort_options_hash
|
||||||
{
|
{
|
||||||
sort_value_name => sort_title_name,
|
sort_value_name => sort_title_name,
|
||||||
|
sort_value_name_desc => sort_title_name_desc,
|
||||||
sort_value_recently_updated => sort_title_recently_updated,
|
sort_value_recently_updated => sort_title_recently_updated,
|
||||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||||
sort_value_recently_created => sort_title_recently_created,
|
sort_value_recently_created => sort_title_recently_created,
|
||||||
|
@ -50,6 +51,17 @@ module SortingHelper
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def milestone_sort_options_hash
|
||||||
|
{
|
||||||
|
sort_value_name => sort_title_name_asc,
|
||||||
|
sort_value_name_desc => sort_title_name_desc,
|
||||||
|
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||||
|
sort_value_due_date_later => sort_title_due_date_later,
|
||||||
|
sort_value_start_date_soon => sort_title_start_date_soon,
|
||||||
|
sort_value_start_date_later => sort_title_start_date_later,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def sort_title_priority
|
def sort_title_priority
|
||||||
'Priority'
|
'Priority'
|
||||||
end
|
end
|
||||||
|
@ -90,6 +102,14 @@ module SortingHelper
|
||||||
'Due later'
|
'Due later'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sort_title_start_date_soon
|
||||||
|
'Start soon'
|
||||||
|
end
|
||||||
|
|
||||||
|
def sort_title_start_date_later
|
||||||
|
'Start later'
|
||||||
|
end
|
||||||
|
|
||||||
def sort_title_name
|
def sort_title_name
|
||||||
'Name'
|
'Name'
|
||||||
end
|
end
|
||||||
|
@ -202,6 +222,14 @@ module SortingHelper
|
||||||
'due_date_desc'
|
'due_date_desc'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sort_value_start_date_soon
|
||||||
|
'start_date_asc'
|
||||||
|
end
|
||||||
|
|
||||||
|
def sort_value_start_date_later
|
||||||
|
'start_date_desc'
|
||||||
|
end
|
||||||
|
|
||||||
def sort_value_name
|
def sort_value_name
|
||||||
'name_asc'
|
'name_asc'
|
||||||
end
|
end
|
||||||
|
|
|
@ -107,6 +107,21 @@ class Milestone < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.sort(method)
|
||||||
|
case method.to_s
|
||||||
|
when 'due_date_asc'
|
||||||
|
reorder(Gitlab::Database.nulls_last_order('due_date', 'ASC'))
|
||||||
|
when 'due_date_desc'
|
||||||
|
reorder(Gitlab::Database.nulls_last_order('due_date', 'DESC'))
|
||||||
|
when 'start_date_asc'
|
||||||
|
reorder(Gitlab::Database.nulls_last_order('start_date', 'ASC'))
|
||||||
|
when 'start_date_desc'
|
||||||
|
reorder(Gitlab::Database.nulls_last_order('start_date', 'DESC'))
|
||||||
|
else
|
||||||
|
order_by(method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns the String necessary to reference this Milestone in Markdown
|
# Returns the String necessary to reference this Milestone in Markdown
|
||||||
#
|
#
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones)
|
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones)
|
||||||
|
|
||||||
.nav-controls
|
.nav-controls
|
||||||
|
= render 'shared/milestones_sort_dropdown'
|
||||||
- if can?(current_user, :admin_milestone, @project)
|
- if can?(current_user, :admin_milestone, @project)
|
||||||
= link_to new_namespace_project_milestone_path(@project.namespace, @project), class: 'btn btn-new', title: 'New Milestone' do
|
= link_to new_namespace_project_milestone_path(@project.namespace, @project), class: 'btn btn-new', title: 'New Milestone' do
|
||||||
New Milestone
|
New Milestone
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
Open
|
Open
|
||||||
%span.badge= counts[:opened]
|
%span.badge= counts[:opened]
|
||||||
%li{ class: milestone_class_for_state(params[:state], 'closed') }>
|
%li{ class: milestone_class_for_state(params[:state], 'closed') }>
|
||||||
= link_to milestones_filter_path(state: 'closed') do
|
= link_to milestones_filter_path(state: 'closed', sort: 'due_date_desc') do
|
||||||
Closed
|
Closed
|
||||||
%span.badge= counts[:closed]
|
%span.badge= counts[:closed]
|
||||||
%li{ class: milestone_class_for_state(params[:state], 'all') }>
|
%li{ class: milestone_class_for_state(params[:state], 'all') }>
|
||||||
= link_to milestones_filter_path(state: 'all') do
|
= link_to milestones_filter_path(state: 'all', sort: 'due_date_desc') do
|
||||||
All
|
All
|
||||||
%span.badge= counts[:all]
|
%span.badge= counts[:all]
|
||||||
|
|
22
app/views/shared/_milestones_sort_dropdown.html.haml
Normal file
22
app/views/shared/_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
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add dropdown sort to project milestones
|
||||||
|
merge_request:
|
||||||
|
author: George Andrinopoulos
|
52
spec/features/projects/milestones/milestones_sorting_spec.rb
Normal file
52
spec/features/projects/milestones/milestones_sorting_spec.rb
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
feature 'Milestones sorting', :feature, :js do
|
||||||
|
include SortingHelper
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:project) { create(:empty_project, name: 'test', namespace: user.namespace) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
# Milestones
|
||||||
|
create(:milestone,
|
||||||
|
due_date: 10.days.from_now,
|
||||||
|
created_at: 2.hours.ago,
|
||||||
|
title: "aaa", project: project)
|
||||||
|
create(:milestone,
|
||||||
|
due_date: 11.days.from_now,
|
||||||
|
created_at: 1.hour.ago,
|
||||||
|
title: "bbb", project: project)
|
||||||
|
login_as(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'visit project milestones and sort by due_date_asc' do
|
||||||
|
visit namespace_project_milestones_path(project.namespace, project)
|
||||||
|
|
||||||
|
expect(page).to have_button('Due soon')
|
||||||
|
|
||||||
|
# assert default sorting
|
||||||
|
within '.milestones' do
|
||||||
|
expect(page.all('ul.content-list > li').first.text).to include('aaa')
|
||||||
|
expect(page.all('ul.content-list > li').last.text).to include('bbb')
|
||||||
|
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')
|
||||||
|
expect(sort_options[4]).to eq('Name, ascending')
|
||||||
|
expect(sort_options[5]).to eq('Name, descending')
|
||||||
|
|
||||||
|
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('bbb')
|
||||||
|
expect(page.all('ul.content-list > li').last.text).to include('aaa')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue