Commit 12a5a651 authored by James Fargher's avatar James Fargher

Merge branch 'sort-issues-by-label-prio' into 'master'

Sorting issues by label priority in graphQL

See merge request gitlab-org/gitlab!27936
parents 607269c0 fbb309d2
...@@ -52,7 +52,7 @@ module Resolvers ...@@ -52,7 +52,7 @@ module Resolvers
type Types::IssueType, null: true type Types::IssueType, null: true
NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc].freeze NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc label_priority_asc label_priority_desc].freeze
def resolve(**args) def resolve(**args)
# The project could have been loaded in batch by `BatchLoader`. # The project could have been loaded in batch by `BatchLoader`.
......
...@@ -7,5 +7,7 @@ module Types ...@@ -7,5 +7,7 @@ module Types
value 'PRIORITY_ASC', 'Priority by ascending order', value: :priority_asc value 'PRIORITY_ASC', 'Priority by ascending order', value: :priority_asc
value 'PRIORITY_DESC', 'Priority by descending order', value: :priority_desc value 'PRIORITY_DESC', 'Priority by descending order', value: :priority_desc
value 'LABEL_PRIORITY_ASC', 'Label priority by ascending order', value: :label_priority_asc
value 'LABEL_PRIORITY_DESC', 'Label priority by descending order', value: :label_priority_desc
end end
end end
...@@ -5,9 +5,9 @@ module Types ...@@ -5,9 +5,9 @@ module Types
graphql_name 'IssueSort' graphql_name 'IssueSort'
description 'Values for sorting issues' description 'Values for sorting issues'
value 'DUE_DATE_ASC', 'Due date by ascending order', value: 'due_date_asc' value 'DUE_DATE_ASC', 'Due date by ascending order', value: :due_date_asc
value 'DUE_DATE_DESC', 'Due date by descending order', value: 'due_date_desc' value 'DUE_DATE_DESC', 'Due date by descending order', value: :due_date_desc
value 'RELATIVE_POSITION_ASC', 'Relative position by ascending order', value: 'relative_position_asc' value 'RELATIVE_POSITION_ASC', 'Relative position by ascending order', value: :relative_position_asc
end end
end end
......
---
title: Add sorting issues by label priority to graphQL endpoint
merge_request: 27936
author:
type: added
...@@ -4593,6 +4593,16 @@ enum IssueSort { ...@@ -4593,6 +4593,16 @@ enum IssueSort {
""" """
DUE_DATE_DESC DUE_DATE_DESC
"""
Label priority by ascending order
"""
LABEL_PRIORITY_ASC
"""
Label priority by descending order
"""
LABEL_PRIORITY_DESC
""" """
Priority by ascending order Priority by ascending order
""" """
......
...@@ -13027,6 +13027,18 @@ ...@@ -13027,6 +13027,18 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "LABEL_PRIORITY_ASC",
"description": "Label priority by ascending order",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "LABEL_PRIORITY_DESC",
"description": "Label priority by descending order",
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "DUE_DATE_ASC", "name": "DUE_DATE_ASC",
"description": "Due date by ascending order", "description": "Due date by ascending order",
......
...@@ -126,7 +126,6 @@ describe Resolvers::IssuesResolver do ...@@ -126,7 +126,6 @@ describe Resolvers::IssuesResolver do
context 'when sorting by due date' do context 'when sorting by due date' do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:due_issue1) { create(:issue, project: project, due_date: 3.days.from_now) } let_it_be(:due_issue1) { create(:issue, project: project, due_date: 3.days.from_now) }
let_it_be(:due_issue2) { create(:issue, project: project, due_date: nil) } let_it_be(:due_issue2) { create(:issue, project: project, due_date: nil) }
let_it_be(:due_issue3) { create(:issue, project: project, due_date: 2.days.ago) } let_it_be(:due_issue3) { create(:issue, project: project, due_date: 2.days.ago) }
...@@ -143,7 +142,6 @@ describe Resolvers::IssuesResolver do ...@@ -143,7 +142,6 @@ describe Resolvers::IssuesResolver do
context 'when sorting by relative position' do context 'when sorting by relative position' do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:relative_issue1) { create(:issue, project: project, relative_position: 2000) } let_it_be(:relative_issue1) { create(:issue, project: project, relative_position: 2000) }
let_it_be(:relative_issue2) { create(:issue, project: project, relative_position: nil) } let_it_be(:relative_issue2) { create(:issue, project: project, relative_position: nil) }
let_it_be(:relative_issue3) { create(:issue, project: project, relative_position: 1000) } let_it_be(:relative_issue3) { create(:issue, project: project, relative_position: 1000) }
...@@ -156,22 +154,40 @@ describe Resolvers::IssuesResolver do ...@@ -156,22 +154,40 @@ describe Resolvers::IssuesResolver do
context 'when sorting by priority' do context 'when sorting by priority' do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) } let_it_be(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) }
let_it_be(:late_milestone) { create(:milestone, project: project, due_date: 30.days.from_now) } let_it_be(:late_milestone) { create(:milestone, project: project, due_date: 30.days.from_now) }
let_it_be(:label_1) { create(:label, project: project, priority: 1) } let_it_be(:priority_label1) { create(:label, project: project, priority: 1) }
let_it_be(:label_2) { create(:label, project: project, priority: 5) } let_it_be(:priority_label2) { create(:label, project: project, priority: 5) }
let_it_be(:issue1) { create(:issue, project: project, labels: [label_1], milestone: late_milestone) } let_it_be(:priority_issue1) { create(:issue, project: project, labels: [priority_label1], milestone: late_milestone) }
let_it_be(:issue2) { create(:issue, project: project, labels: [label_2]) } let_it_be(:priority_issue2) { create(:issue, project: project, labels: [priority_label2]) }
let_it_be(:issue3) { create(:issue, project: project, milestone: early_milestone) } let_it_be(:priority_issue3) { create(:issue, project: project, milestone: early_milestone) }
let_it_be(:issue4) { create(:issue, project: project) } let_it_be(:priority_issue4) { create(:issue, project: project) }
it 'sorts issues ascending' do
expect(resolve_issues(sort: :priority_asc).items).to eq([priority_issue3, priority_issue1, priority_issue2, priority_issue4])
end
it 'sorts issues descending' do
expect(resolve_issues(sort: :priority_desc).items).to eq([priority_issue1, priority_issue3, priority_issue2, priority_issue4])
end
end
context 'when sorting by label priority' do
let_it_be(:project) { create(:project) }
let_it_be(:label1) { create(:label, project: project, priority: 1) }
let_it_be(:label2) { create(:label, project: project, priority: 5) }
let_it_be(:label3) { create(:label, project: project, priority: 10) }
let_it_be(:label_issue1) { create(:issue, project: project, labels: [label1]) }
let_it_be(:label_issue2) { create(:issue, project: project, labels: [label2]) }
let_it_be(:label_issue3) { create(:issue, project: project, labels: [label1, label3]) }
let_it_be(:label_issue4) { create(:issue, project: project) }
it 'sorts issues ascending' do it 'sorts issues ascending' do
expect(resolve_issues(sort: :priority_asc).items).to eq([issue3, issue1, issue2, issue4]) expect(resolve_issues(sort: :label_priority_asc).items).to eq([label_issue3, label_issue1, label_issue2, label_issue4])
end end
it 'sorts issues descending' do it 'sorts issues descending' do
expect(resolve_issues(sort: :priority_desc).items).to eq([issue1, issue3, issue2, issue4]) expect(resolve_issues(sort: :label_priority_desc).items).to eq([label_issue2, label_issue3, label_issue1, label_issue4])
end end
end end
end end
......
...@@ -8,6 +8,8 @@ describe GitlabSchema.types['IssueSort'] do ...@@ -8,6 +8,8 @@ describe GitlabSchema.types['IssueSort'] do
it_behaves_like 'common sort values' it_behaves_like 'common sort values'
it 'exposes all the existing issue sort values' do it 'exposes all the existing issue sort values' do
expect(described_class.values.keys).to include(*%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC]) expect(described_class.values.keys).to include(
*%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC LABEL_PRIORITY_ASC LABEL_PRIORITY_DESC]
)
end end
end end
...@@ -252,12 +252,12 @@ describe 'getting an issue list for a project' do ...@@ -252,12 +252,12 @@ describe 'getting an issue list for a project' do
let_it_be(:early_milestone) { create(:milestone, project: sort_project, due_date: 10.days.from_now) } let_it_be(:early_milestone) { create(:milestone, project: sort_project, due_date: 10.days.from_now) }
let_it_be(:late_milestone) { create(:milestone, project: sort_project, due_date: 30.days.from_now) } let_it_be(:late_milestone) { create(:milestone, project: sort_project, due_date: 30.days.from_now) }
let_it_be(:label_1) { create(:label, project: sort_project, priority: 1) } let_it_be(:priority_label1) { create(:label, project: sort_project, priority: 1) }
let_it_be(:label_2) { create(:label, project: sort_project, priority: 5) } let_it_be(:priority_label2) { create(:label, project: sort_project, priority: 5) }
let_it_be(:issue1) { create(:issue, project: sort_project, labels: [label_1], milestone: late_milestone) } let_it_be(:priority_issue1) { create(:issue, project: sort_project, labels: [priority_label1], milestone: late_milestone) }
let_it_be(:issue2) { create(:issue, project: sort_project, labels: [label_2]) } let_it_be(:priority_issue2) { create(:issue, project: sort_project, labels: [priority_label2]) }
let_it_be(:issue3) { create(:issue, project: sort_project, milestone: early_milestone) } let_it_be(:priority_issue3) { create(:issue, project: sort_project, milestone: early_milestone) }
let_it_be(:issue4) { create(:issue, project: sort_project) } let_it_be(:priority_issue4) { create(:issue, project: sort_project) }
let_it_be(:params) { 'sort: PRIORITY_ASC' } let_it_be(:params) { 'sort: PRIORITY_ASC' }
...@@ -277,20 +277,20 @@ describe 'getting an issue list for a project' do ...@@ -277,20 +277,20 @@ describe 'getting an issue list for a project' do
context 'when ascending' do context 'when ascending' do
it 'sorts issues' do it 'sorts issues' do
expect(grab_iids).to eq([issue3.iid, issue1.iid, issue2.iid, issue4.iid]) expect(grab_iids).to eq([priority_issue3.iid, priority_issue1.iid, priority_issue2.iid, priority_issue4.iid])
end end
context 'when paginating' do context 'when paginating' do
let(:params) { 'sort: PRIORITY_ASC, first: 2' } let(:params) { 'sort: PRIORITY_ASC, first: 2' }
it 'sorts issues' do it 'sorts issues' do
expect(grab_iids).to eq([issue3.iid, issue1.iid]) expect(grab_iids).to eq([priority_issue3.iid, priority_issue1.iid])
cursored_query = query("sort: PRIORITY_ASC, after: \"#{end_cursor}\"") cursored_query = query("sort: PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user) post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges'] response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([issue2.iid, issue4.iid]) expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end end
end end
end end
...@@ -299,20 +299,90 @@ describe 'getting an issue list for a project' do ...@@ -299,20 +299,90 @@ describe 'getting an issue list for a project' do
let(:params) { 'sort: PRIORITY_DESC' } let(:params) { 'sort: PRIORITY_DESC' }
it 'sorts issues' do it 'sorts issues' do
expect(grab_iids).to eq([issue1.iid, issue3.iid, issue2.iid, issue4.iid]) expect(grab_iids).to eq([priority_issue1.iid, priority_issue3.iid, priority_issue2.iid, priority_issue4.iid])
end end
context 'when paginating' do context 'when paginating' do
let(:params) { 'sort: PRIORITY_DESC, first: 2' } let(:params) { 'sort: PRIORITY_DESC, first: 2' }
it 'sorts issues' do it 'sorts issues' do
expect(grab_iids).to eq([issue1.iid, issue3.iid]) expect(grab_iids).to eq([priority_issue1.iid, priority_issue3.iid])
cursored_query = query("sort: PRIORITY_DESC, after: \"#{end_cursor}\"") cursored_query = query("sort: PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user) post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges'] response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([issue2.iid, issue4.iid]) expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
end
end
end
context 'when sorting by label priority' do
let_it_be(:sort_project) { create(:project, :public) }
let_it_be(:label1) { create(:label, project: sort_project, priority: 1) }
let_it_be(:label2) { create(:label, project: sort_project, priority: 5) }
let_it_be(:label3) { create(:label, project: sort_project, priority: 10) }
let_it_be(:label_issue1) { create(:issue, project: sort_project, labels: [label1]) }
let_it_be(:label_issue2) { create(:issue, project: sort_project, labels: [label2]) }
let_it_be(:label_issue3) { create(:issue, project: sort_project, labels: [label1, label3]) }
let_it_be(:label_issue4) { create(:issue, project: sort_project) }
let_it_be(:params) { 'sort: LABEL_PRIORITY_ASC' }
def query(issue_params = params)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
"issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq [label_issue3.iid, label_issue1.iid, label_issue2.iid, label_issue4.iid]
end
context 'when paginating' do
let(:params) { 'sort: LABEL_PRIORITY_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue3.iid, label_issue1.iid]
cursored_query = query("sort: LABEL_PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq [label_issue2.iid, label_issue4.iid]
end
end
end
context 'when descending' do
let(:params) { 'sort: LABEL_PRIORITY_DESC' }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue2.iid, label_issue3.iid, label_issue1.iid, label_issue4.iid]
end
context 'when paginating' do
let(:params) { 'sort: LABEL_PRIORITY_DESC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq [label_issue2.iid, label_issue3.iid]
cursored_query = query("sort: LABEL_PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq [label_issue1.iid, label_issue4.iid]
end end
end end
end end
......
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