Fix sorting by label priorities

parent 99e928f1
...@@ -146,7 +146,8 @@ module Issuable ...@@ -146,7 +146,8 @@ module Issuable
def order_labels_priority(excluded_labels: []) def order_labels_priority(excluded_labels: [])
condition_field = "#{table_name}.id" condition_field = "#{table_name}.id"
highest_priority = highest_label_priority(name, condition_field, excluded_labels: excluded_labels).to_sql project_field = "#{table_name}.project_id"
highest_priority = highest_label_priority(name, project_field, condition_field, excluded_labels: excluded_labels).to_sql
select("#{table_name}.*, (#{highest_priority}) AS highest_priority"). select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
group(arel_table[:id]). group(arel_table[:id]).
......
...@@ -38,10 +38,12 @@ module Sortable ...@@ -38,10 +38,12 @@ module Sortable
private private
def highest_label_priority(object_types, condition_field, excluded_labels: []) def highest_label_priority(object_types, project_field, condition_field, excluded_labels: [])
query = Label.select(Label.arel_table[:priority].minimum). query = Label.select(LabelPriority.arel_table[:priority].minimum).
left_join_priorities.
joins(:label_links). joins(:label_links).
where(label_links: { target_type: object_types }). where(label_links: { target_type: object_types }).
where("label_priorities.project_id = #{project_field}").
where("label_links.target_id = #{condition_field}"). where("label_links.target_id = #{condition_field}").
reorder(nil) reorder(nil)
......
...@@ -42,6 +42,17 @@ class Label < ActiveRecord::Base ...@@ -42,6 +42,17 @@ class Label < ActiveRecord::Base
where.not(id: prioritized(project).select(:id)) where.not(id: prioritized(project).select(:id))
end end
def self.left_join_priorities
labels = Label.arel_table
priorities = LabelPriority.arel_table
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin).
on(labels[:id].eq(priorities[:label_id])).
join_sources
joins(label_priorities)
end
alias_attribute :name, :title alias_attribute :name, :title
def self.reference_prefix def self.reference_prefix
......
...@@ -52,7 +52,7 @@ class Todo < ActiveRecord::Base ...@@ -52,7 +52,7 @@ class Todo < ActiveRecord::Base
# Todos with highest priority first then oldest todos # Todos with highest priority first then oldest todos
# Need to order by created_at last because of differences on Mysql and Postgres when joining by type "Merge_request/Issue" # Need to order by created_at last because of differences on Mysql and Postgres when joining by type "Merge_request/Issue"
def order_by_labels_priority def order_by_labels_priority
highest_priority = highest_label_priority(["Issue", "MergeRequest"], "todos.target_id").to_sql highest_priority = highest_label_priority(["Issue", "MergeRequest"], "todos.project_id", "todos.target_id").to_sql
select("#{table_name}.*, (#{highest_priority}) AS highest_priority"). select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')). order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')).
......
...@@ -15,21 +15,28 @@ describe Projects::LabelsController do ...@@ -15,21 +15,28 @@ describe Projects::LabelsController do
let!(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') } let!(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') }
let!(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') } let!(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') }
let!(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') } let!(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') }
let!(:label_4) { create(:label, project: project, priority: nil, title: 'Label 4') } let!(:label_4) { create(:label, project: project, title: 'Label 4') }
let!(:label_5) { create(:label, project: project, priority: nil, title: 'Label 5') } let!(:label_5) { create(:label, project: project, title: 'Label 5') }
let!(:group_label_1) { create(:group_label, group: group, priority: 3, title: 'Group Label 1') } let!(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1') }
let!(:group_label_2) { create(:group_label, group: group, priority: 1, title: 'Group Label 2') } let!(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') }
let!(:group_label_3) { create(:group_label, group: group, priority: nil, title: 'Group Label 3') } let!(:group_label_3) { create(:group_label, group: group, title: 'Group Label 3') }
let!(:group_label_4) { create(:group_label, group: group, priority: nil, title: 'Group Label 4') } let!(:group_label_4) { create(:group_label, group: group, title: 'Group Label 4') }
before do
create(:label_priority, project: project, label: group_label_1, priority: 3)
create(:label_priority, project: project, label: group_label_2, priority: 1)
end
context '@prioritized_labels' do context '@prioritized_labels' do
before do before do
list_labels list_labels
end end
it 'contains only prioritized labels' do it 'does not include labels without priority' do
expect(assigns(:prioritized_labels)).to all(have_attributes(priority: a_value > 0)) list_labels
expect(assigns(:prioritized_labels)).not_to include(group_label_3, group_label_4, label_4, label_5)
end end
it 'is sorted by priority, then label title' do it 'is sorted by priority, then label title' do
...@@ -38,16 +45,16 @@ describe Projects::LabelsController do ...@@ -38,16 +45,16 @@ describe Projects::LabelsController do
end end
context '@labels' do context '@labels' do
it 'contains only unprioritized labels' do it 'is sorted by label title' do
list_labels list_labels
expect(assigns(:labels)).to all(have_attributes(priority: nil)) expect(assigns(:labels)).to eq [group_label_3, group_label_4, label_4, label_5]
end end
it 'is sorted by label title' do it 'does not include labels with priority' do
list_labels list_labels
expect(assigns(:labels)).to eq [group_label_3, group_label_4, label_4, label_5] expect(assigns(:labels)).not_to include(group_label_2, label_1, label_3, group_label_1, label_2)
end end
it 'does not include group labels when project does not belong to a group' do it 'does not include group labels when project does not belong to a group' do
......
...@@ -3,6 +3,16 @@ FactoryGirl.define do ...@@ -3,6 +3,16 @@ FactoryGirl.define do
sequence(:title) { |n| "label#{n}" } sequence(:title) { |n| "label#{n}" }
color "#990000" color "#990000"
project project
transient do
priority nil
end
after(:create) do |label, evaluator|
if evaluator.priority
label.priorities.create(project: label.project, priority: evaluator.priority)
end
end
end end
factory :group_label, class: GroupLabel do factory :group_label, class: GroupLabel do
......
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