GitLab wurde erfolgreich aktualisiert. Dank regelmäßiger Updates bleibt das THM GitLab sicher und Sie profitieren von den neuesten Funktionen. Danke für Ihre Geduld.

Commit 101fddfa authored by Sean McGivern's avatar Sean McGivern

Allow sorting by due date and label priority

parent 6619772f
......@@ -16,7 +16,8 @@ def sort_options_hash
sort_value_oldest_signin => sort_title_oldest_signin,
sort_value_downvotes => sort_title_downvotes,
sort_value_upvotes => sort_title_upvotes,
sort_value_priority => sort_title_priority
sort_value_priority => sort_title_priority,
sort_value_label_priority => sort_title_label_priority
......@@ -50,6 +51,10 @@ def member_sort_options_hash
def sort_title_priority
def sort_title_label_priority
'Label priority'
......@@ -161,6 +166,10 @@ def sort_value_priority
def sort_value_label_priority
def sort_value_oldest_updated
......@@ -144,7 +144,8 @@ def sort(method, excluded_labels: [])
when 'milestone_due_desc' then order_milestone_due_desc
when 'downvotes_desc' then order_downvotes_desc
when 'upvotes_desc' then order_upvotes_desc
when 'priority' then order_labels_priority(excluded_labels: excluded_labels)
when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels)
when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels)
when 'position_asc' then order_position_asc
......@@ -154,7 +155,28 @@ def sort(method, excluded_labels: [])
sorted.order(id: :desc)
def order_labels_priority(excluded_labels: [])
def order_due_date_and_labels_priority(excluded_labels: [])
# The order_ methods also modify the query in other ways:
# - For milestones, we add a JOIN.
# - For label priority, we change the SELECT, and add a GROUP BY.#
# After doing those, we need to reorder to the order we want. The existing
# ORDER BYs won't work because:
# 1. We need milestone due date first.
# 2. We can't ORDER BY a column that isn't in the GROUP BY and doesn't
# have an aggregate function applied, so we do a useless MIN() instead.
milestones_due_date = 'MIN(milestones.due_date)'
order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date]).
reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
def order_labels_priority(excluded_labels: [], extra_select_columns: [])
params = {
target_type: name,
target_column: "#{table_name}.id",
......@@ -164,7 +186,12 @@ def order_labels_priority(excluded_labels: [])
highest_priority = highest_label_priority(params).to_sql
select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
select_columns = [
"(#{highest_priority}) AS highest_priority"
] + extra_select_columns
select(select_columns.join(', ')).
reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
......@@ -48,8 +48,14 @@ class Todo < ActiveRecord::Base
after_save :keep_around_commit
class << self
# Priority sorting isn't displayed in the dropdown, because we don't show
# milestones, but still show something if the user has a URL with that
# selected.
def sort(method)
method == "priority" ? order_by_labels_priority : order_by(method)
case method.to_s
when 'priority', 'label_priority' then order_by_labels_priority
else order_by(method)
# Order by priority depending on which issue/merge request the Todo belongs to
......@@ -57,8 +57,8 @@
= icon('chevron-down')
= link_to todos_filter_path(sort: sort_value_priority) do
= sort_title_priority
= link_to todos_filter_path(sort: sort_value_label_priority) do
= sort_title_label_priority
= link_to todos_filter_path(sort: sort_value_recently_created) do
= sort_title_recently_created
= link_to todos_filter_path(sort: sort_value_oldest_created) do
......@@ -10,6 +10,8 @@
= link_to page_filter_path(sort: sort_value_priority, label: true) do
= sort_title_priority
= link_to page_filter_path(sort: sort_value_label_priority, label: true) do
= sort_title_label_priority
= link_to page_filter_path(sort: sort_value_recently_created, label: true) do
= sort_title_recently_created
= link_to page_filter_path(sort: sort_value_oldest_created, label: true) do
......@@ -5,7 +5,7 @@
%h4 Labels can be applied to issues and merge requests to categorize them.
%p You can also star label to make it a priority label.
%p You can also star a label to make it a priority label.
- if can?(current_user, :admin_label, @project)
= link_to 'New label', new_namespace_project_label_path(@project.namespace, @project), class: 'btn btn-new', title: 'New label', id: 'new_label_link'
= link_to 'Generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post, class: 'btn btn-success btn-inverted', title: 'Generate a default set of labels', id: 'generate_labels_link'
title: Allow sorting by due date and priority
......@@ -65,7 +65,7 @@ issues and merge requests assigned to each label.
Prioritized labels are like any other label, but sorted by priority. This allows
you to sort issues and merge requests by priority.
you to sort issues and merge requests by label priority.
To prioritize labels, navigate to your project's **Issues > Labels** and click
on the star icon next to them to put them in the priority list. Click on the
......@@ -77,9 +77,13 @@ having their priority set to null.
![Prioritize labels](img/labels_prioritize.png)
Now that you have labels prioritized, you can use the 'Priority' filter in the
issues or merge requests tracker. Those with the highest priority label, will
appear on top.
Now that you have labels prioritized, you can use the 'Priority' and 'Label
priority' filters in the issues or merge requests tracker.
The 'Label priority' filter puts issues with the highest priority label on top.
The 'Priority' filter sorts issues by their soonest milestone due date, then by
label priority.
![Filter labels by priority](img/labels_filter_by_priority.png)
......@@ -156,4 +160,3 @@ mouse over the label in the issue tracker or wherever else the label is
![Label tooltips](img/labels_description_tooltip.png)
......@@ -29,7 +29,7 @@
issue_1.labels << label_5
login_as user
visit namespace_project_issues_path(project.namespace, project, sort: 'priority')
visit namespace_project_issues_path(project.namespace, project, sort: 'label_priority')
# Ensure we are indicating that issues are sorted by priority
expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
......@@ -68,7 +68,7 @@
issue_6.labels << label_5 # 8 - No priority
login_as user
visit namespace_project_issues_path(project.namespace, project, sort: 'priority')
visit namespace_project_issues_path(project.namespace, project, sort: 'label_priority')
expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
......@@ -344,6 +344,46 @@
describe '.order_due_date_and_labels_priority' do
let(:project) { create(:empty_project) }
def create_issue(milestone, labels)
create(:labeled_issue, milestone: milestone, labels: labels, project: project)
it 'sorts issues in order of milestone due date, then label priority' do
first_priority = create(:label, project: project, priority: 1)
second_priority = create(:label, project: project, priority: 2)
no_priority = create(:label, project: project)
first_milestone = create(:milestone, project: project, due_date:
second_milestone = create(:milestone, project: project, due_date: + 1.month)
third_milestone = create(:milestone, project: project)
# The issues here are ordered by label priority, to ensure that we don't
# accidentally just sort by creation date.
second_milestone_first_priority = create_issue(second_milestone, [first_priority, second_priority, no_priority])
third_milestone_first_priority = create_issue(third_milestone, [first_priority, second_priority, no_priority])
first_milestone_second_priority = create_issue(first_milestone, [second_priority, no_priority])
second_milestone_second_priority = create_issue(second_milestone, [second_priority, no_priority])
no_milestone_second_priority = create_issue(nil, [second_priority, no_priority])
first_milestone_no_priority = create_issue(first_milestone, [no_priority])
second_milestone_no_labels = create_issue(second_milestone, [])
third_milestone_no_priority = create_issue(third_milestone, [no_priority])
result = Issue.order_due_date_and_labels_priority
expect(result).to eq([first_milestone_second_priority,
describe '.order_labels_priority' do
let(:label_1) { create(:label, title: 'label_1', project: issue.project, priority: 1) }
let(:label_2) { create(:label, title: 'label_2', project: issue.project, priority: 2) }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment