Commit cec733fe authored by Andrew Smith's avatar Andrew Smith

Allow sorting by title in REST/GraphQL API

Changelog: added
EE: true
parent 204f9332
......@@ -64,7 +64,7 @@ GET /groups/:id/epics?state=opened
| `author_id` | integer | no | Return epics created by the given user `id` |
| `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used |
| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Available in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) and later |
| `order_by` | string | no | Return epics ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `order_by` | string | no | Return epics ordered by `created_at`, `updated_at`, or `title` fields. Default is `created_at` |
| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search epics against their `title` and `description` |
| `state` | string | no | Search epics against their `state`, possible filters: `opened`, `closed` and `all`, default: `all` |
......
......@@ -14232,6 +14232,8 @@ Roadmap sort values.
| <a id="epicsortend_date_desc"></a>`END_DATE_DESC` | Sort by end date in descending order. |
| <a id="epicsortstart_date_asc"></a>`START_DATE_ASC` | Sort by start date in ascending order. |
| <a id="epicsortstart_date_desc"></a>`START_DATE_DESC` | Sort by start date in descending order. |
| <a id="epicsorttitle_asc"></a>`TITLE_ASC` | Sort by title in ascending order. |
| <a id="epicsorttitle_desc"></a>`TITLE_DESC` | Sort by title in descending order. |
| <a id="epicsortend_date_asc"></a>`end_date_asc` **{warning-solid}** | **Deprecated** in 13.11. Use END_DATE_ASC. |
| <a id="epicsortend_date_desc"></a>`end_date_desc` **{warning-solid}** | **Deprecated** in 13.11. Use END_DATE_DESC. |
| <a id="epicsortstart_date_asc"></a>`start_date_asc` **{warning-solid}** | **Deprecated** in 13.11. Use START_DATE_ASC. |
......
......@@ -16,5 +16,7 @@ module Types
value 'START_DATE_ASC', 'Sort by start date in ascending order.', value: :start_date_asc
value 'END_DATE_DESC', 'Sort by end date in descending order.', value: :end_date_desc
value 'END_DATE_ASC', 'Sort by end date in ascending order.', value: :end_date_asc
value 'TITLE_DESC', 'Sort by title in descending order.', value: :title_desc
value 'TITLE_ASC', 'Sort by title in ascending order.', value: :title_asc
end
end
......@@ -112,6 +112,14 @@ module EE
reorder(keyset_order)
end
scope :order_title_asc, -> do
reorder(title: :asc)
end
scope :order_title_desc, -> do
reorder(title: :desc)
end
scope :order_closed_date_desc, -> { reorder(closed_at: :desc) }
scope :order_relative_position, -> do
......@@ -179,6 +187,8 @@ module EE
when 'start_date_desc' then order_start_date_desc
when 'end_date_asc' then order_end_date_asc
when 'end_date_desc' then order_end_date_desc
when 'title_asc' then order_title_asc
when 'title_desc' then order_title_desc
else
super
end
......@@ -256,6 +266,8 @@ module EE
when 'end_date_asc' then order_end_date_asc
when 'end_date_desc' then order_end_date_desc
when 'relative_position' then order_relative_position
when 'title_asc' then order_title_asc
when 'title_desc' then order_title_desc
else
super
end
......@@ -268,7 +280,9 @@ module EE
'start_date_asc' => -> { order_start_date_asc },
'start_date_desc' => -> { order_start_date_desc },
'end_date_asc' => -> { order_end_date_asc },
'end_date_desc' => -> { order_end_date_desc }
'end_date_desc' => -> { order_end_date_desc },
'title_asc' => -> { order_title_asc },
'title_desc' => -> { order_title_desc }
}
)
end
......
......@@ -22,8 +22,8 @@ module API
success EE::API::Entities::Epic
end
params do
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
desc: 'Return epics ordered by `created_at` or `updated_at` fields.'
optional :order_by, type: String, values: %w[created_at updated_at title], default: 'created_at',
desc: 'Return epics ordered by `created_at`, `updated_at` or `title` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return epics sorted in `asc` or `desc` order.'
optional :search, type: String, desc: 'Search epics for text present in the title or description'
......
......@@ -180,29 +180,42 @@ RSpec.describe Resolvers::EpicsResolver do
let!(:epic1) { create(:epic, group: group, title: 'first created', description: 'description', start_date: 10.days.ago, end_date: 10.days.from_now) }
let!(:epic2) { create(:epic, group: group, title: 'second created', description: 'text 1', start_date: 20.days.ago, end_date: 20.days.from_now) }
let!(:epic3) { create(:epic, group: group, title: 'third', description: 'text 2', start_date: 30.days.ago, end_date: 30.days.from_now) }
let!(:epic4) { create(:epic, group: group, title: 'forth created', description: 'four', start_date: 40.days.ago, end_date: 40.days.from_now) }
it 'orders epics by start date in descending order' do
epics = resolve_epics(sort: 'start_date_desc')
expect(epics).to eq([epic1, epic2, epic3])
expect(epics).to eq([epic1, epic2, epic3, epic4])
end
it 'orders epics by start date in ascending order' do
epics = resolve_epics(sort: 'start_date_asc')
expect(epics).to eq([epic3, epic2, epic1])
expect(epics).to eq([epic4, epic3, epic2, epic1])
end
it 'orders epics by end date in descending order' do
epics = resolve_epics(sort: 'end_date_desc')
expect(epics).to eq([epic3, epic2, epic1])
expect(epics).to eq([epic4, epic3, epic2, epic1])
end
it 'orders epics by end date in ascending order' do
epics = resolve_epics(sort: 'end_date_asc')
expect(epics).to eq([epic1, epic2, epic3])
expect(epics).to eq([epic1, epic2, epic3, epic4])
end
it 'orders epics by title in descending order' do
epics = resolve_epics(sort: 'title_desc')
expect(epics).to eq([epic3, epic2, epic4, epic1])
end
it 'orders epics by title in ascending order' do
epics = resolve_epics(sort: 'title_asc')
expect(epics).to eq([epic1, epic4, epic2, epic3])
end
end
......
......@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['EpicSort'] do
it { expect(described_class.graphql_name).to eq('EpicSort') }
it 'exposes all the existing epic sort orders' do
expect(described_class.values.keys).to include(*%w[start_date_desc start_date_asc end_date_desc end_date_asc])
expect(described_class.values.keys).to include(*%w[start_date_desc start_date_asc end_date_desc end_date_asc START_DATE_DESC START_DATE_ASC END_DATE_DESC END_DATE_ASC TITLE_DESC TITLE_ASC])
end
end
......@@ -87,6 +87,24 @@ RSpec.describe Epic do
end
end
describe 'title sort scopes' do
let_it_be(:epic1) { create(:epic, title: 'foo') }
let_it_be(:epic2) { create(:epic, title: 'bar') }
let_it_be(:epic3) { create(:epic, title: 'baz') }
describe '.order_title_asc' do
it 'returns epics ordered by title, ascending' do
expect(described_class.order_title_asc).to eq([epic2, epic3, epic1, confidential_epic, public_epic])
end
describe '.order_title_desc' do
it 'returns epics ordered by title, decending' do
expect(described_class.order_title_desc).to eq([public_epic, confidential_epic, epic1, epic3, epic2])
end
end
end
end
describe '.in_milestone' do
let_it_be(:milestone) { create(:milestone, project: project) }
......@@ -182,10 +200,10 @@ RSpec.describe Epic do
end
describe 'ordering' do
let!(:epic1) { create(:epic, start_date: 7.days.ago, end_date: 3.days.ago, updated_at: 3.days.ago, created_at: 7.days.ago, relative_position: 3) }
let!(:epic2) { create(:epic, start_date: 3.days.ago, updated_at: 10.days.ago, created_at: 12.days.ago, relative_position: 1) }
let!(:epic3) { create(:epic, end_date: 5.days.ago, updated_at: 5.days.ago, created_at: 6.days.ago, relative_position: 2) }
let!(:epic4) { create(:epic, relative_position: 4) }
let!(:epic1) { create(:epic, start_date: 7.days.ago, end_date: 3.days.ago, updated_at: 3.days.ago, created_at: 7.days.ago, relative_position: 3, title: 'foo') }
let!(:epic2) { create(:epic, start_date: 3.days.ago, updated_at: 10.days.ago, created_at: 12.days.ago, relative_position: 1, title: 'bar') }
let!(:epic3) { create(:epic, end_date: 5.days.ago, updated_at: 5.days.ago, created_at: 6.days.ago, relative_position: 2, title: 'baz') }
let!(:epic4) { create(:epic, relative_position: 4, title: 'world') }
def epics(order_by)
described_class.order_by(order_by)
......@@ -230,6 +248,14 @@ RSpec.describe Epic do
it 'orders by relative_position ASC' do
expect(epics(:relative_position)).to eq([epic2, epic3, epic1, epic4])
end
it 'orders by title ASC' do
expect(epics(:title_asc)).to eq([epic2, epic3, epic1, epic4])
end
it 'orders by title DESC' do
expect(epics(:title_desc)).to eq([epic4, epic1, epic3, epic2])
end
end
describe '#valid_parent?' do
......
......@@ -160,6 +160,7 @@ RSpec.describe API::Epics do
let!(:epic) do
create(:epic,
group: group,
title: 'baz',
state: :closed,
created_at: 3.days.ago,
updated_at: 2.days.ago)
......@@ -269,6 +270,18 @@ RSpec.describe API::Epics do
expect_paginated_array_response([epic2.id, epic.id])
end
it 'sorts by title descending when requested' do
get api(url), params: { order_by: :title }
expect_paginated_array_response([epic2.id, epic.id])
end
it 'sorts by title ascending when requested' do
get api(url), params: { order_by: :title, sort: :asc }
expect_paginated_array_response([epic.id, epic2.id])
end
it 'returns an array of labeled epics' do
get api(url), params: { labels: label.title }
......
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