Commit 9d73357a authored by Dmitry Gruzd's avatar Dmitry Gruzd Committed by Peter Leitzen

Add sort by last updated to Issue/MR sort options

This change adds the ability to sort search results by Last Updated
parent 6009b61a
......@@ -122,15 +122,24 @@ module SearchHelper
end
def search_sort_options
options = []
options << {
title: _('Created date'),
sortable: true,
sortParam: {
asc: 'created_asc',
desc: 'created_desc'
[
{
title: _('Created date'),
sortable: true,
sortParam: {
asc: 'created_asc',
desc: 'created_desc'
}
},
{
title: _('Last updated'),
sortable: true,
sortParam: {
asc: 'updated_asc',
desc: 'updated_desc'
}
}
}
]
end
private
......
---
title: 'Search: Add Sort by Last Updated to Issue/MR'
merge_request: 53589
author:
type: changed
......@@ -186,6 +186,18 @@ module Elastic
order: 'desc'
}
})
when :updated_at_asc
query_hash.merge(sort: {
updated_at: {
order: 'asc'
}
})
when :updated_at_desc
query_hash.merge(sort: {
updated_at: {
order: 'desc'
}
})
else
query_hash
end
......
......@@ -266,6 +266,15 @@ RSpec.describe SearchHelper do
}
}
mock_updated_sort = {
title: _('Last updated'),
sortable: true,
sortParam: {
asc: 'updated_asc',
desc: 'updated_desc'
}
}
before do
allow(self).to receive(:current_user).and_return(user)
end
......@@ -276,13 +285,13 @@ RSpec.describe SearchHelper do
end
it 'returns the correct data' do
expect(search_sort_options).to eq([mock_relevant_sort, mock_created_sort])
expect(search_sort_options).to eq([mock_relevant_sort, mock_created_sort, mock_updated_sort])
end
end
context 'with basic search enabled' do
it 'returns the correct data' do
expect(search_sort_options).to eq([mock_created_sort])
expect(search_sort_options).to eq([mock_created_sort, mock_updated_sort])
end
end
end
......
......@@ -300,13 +300,17 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
end
context 'ordering' do
let(:query) { 'sorted' }
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let(:results_created) { described_class.new(user, 'sorted', [project.id], sort: sort) }
let(:results) { described_class.new(user, query, [project.id], sort: sort) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
let(:results_updated) { described_class.new(user, 'updated', [project.id], sort: sort) }
before do
ensure_elasticsearch_index!
......@@ -687,19 +691,24 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
end
context 'ordering' do
let(:query) { 'sorted' }
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let(:results) { described_class.new(user, query, [project.id], sort: sort) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted'
include_examples 'search results sorted' do
let(:results_created) { described_class.new(user, 'sorted', [project.id], sort: sort) }
let(:results_updated) { described_class.new(user, 'updated', [project.id], sort: sort) }
end
end
end
......
......@@ -144,18 +144,24 @@ RSpec.describe Search::GlobalService do
end
end
context 'sort by created_at' do
context 'ordering' do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
......@@ -214,18 +220,24 @@ RSpec.describe Search::GlobalService do
context 'merge_request' do
let(:scope) { 'merge_requests' }
context 'sort by created_at' do
context 'sorting' do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
end
......
......@@ -241,18 +241,24 @@ RSpec.describe Search::GroupService, :elastic do
context 'issues' do
let(:scope) { 'issues' }
context 'sort by created_at' do
context 'sorting' do
let!(:project) { create(:project, :public, group: group) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
......@@ -260,18 +266,24 @@ RSpec.describe Search::GroupService, :elastic do
context 'merge requests' do
let(:scope) { 'merge_requests' }
context 'sort by created_at' do
context 'sorting' do
let!(:project) { create(:project, :public, group: group) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
......
......@@ -183,18 +183,24 @@ RSpec.describe Search::ProjectService do
context 'issues' do
let(:scope) { 'issues' }
context 'sort by created_at', :elastic do
context 'sorting', :elastic do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(project, nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(project, nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(project, nil, search: 'updated', sort: sort).execute }
end
end
end
......@@ -202,18 +208,24 @@ RSpec.describe Search::ProjectService do
context 'merge requests' do
let(:scope) { 'merge_requests' }
context 'sort by created_at', :elastic do
context 'sorting', :elastic do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
before do
ensure_elasticsearch_index!
end
include_examples 'search results sorted' do
let(:results) { described_class.new(project, nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(project, nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(project, nil, search: 'updated', sort: sort).execute }
end
end
end
......
......@@ -11,6 +11,10 @@ module Gitlab
:created_at_asc
when %w[created_at desc], [nil, 'created_desc']
:created_at_desc
when %w[updated_at asc], [nil, 'updated_asc']
:updated_at_asc
when %w[updated_at desc], [nil, 'updated_desc']
:updated_at_desc
else
:unknown
end
......
......@@ -136,6 +136,10 @@ module Gitlab
scope.reorder('created_at ASC')
when :created_at_desc
scope.reorder('created_at DESC')
when :updated_at_asc
scope.reorder('updated_at ASC')
when :updated_at_desc
scope.reorder('updated_at DESC')
else
scope.reorder('created_at DESC')
end
......
......@@ -557,21 +557,31 @@ RSpec.describe SearchHelper do
describe '#search_sort_options' do
let(:user) { create(:user) }
mock_created_sort = {
title: _('Created date'),
sortable: true,
sortParam: {
asc: 'created_asc',
desc: 'created_desc'
mock_created_sort = [
{
title: _('Created date'),
sortable: true,
sortParam: {
asc: 'created_asc',
desc: 'created_desc'
}
},
{
title: _('Last updated'),
sortable: true,
sortParam: {
asc: 'updated_asc',
desc: 'updated_desc'
}
}
}
]
before do
allow(self).to receive(:current_user).and_return(user)
end
it 'returns the correct data' do
expect(search_sort_options).to eq([mock_created_sort])
expect(search_sort_options).to eq(mock_created_sort)
end
end
......
......@@ -178,12 +178,18 @@ RSpec.describe Gitlab::SearchResults do
end
context 'ordering' do
let(:query) { 'sorted' }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
include_examples 'search results sorted'
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results_created) { described_class.new(user, 'sorted', Project.order(:id), sort: sort, filters: filters) }
let(:results_updated) { described_class.new(user, 'updated', Project.order(:id), sort: sort, filters: filters) }
end
end
end
......@@ -214,12 +220,18 @@ RSpec.describe Gitlab::SearchResults do
end
context 'ordering' do
let(:query) { 'sorted' }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
include_examples 'search results sorted'
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results_created) { described_class.new(user, 'sorted', Project.order(:id), sort: sort, filters: filters) }
let(:results_updated) { described_class.new(user, 'updated', Project.order(:id), sort: sort, filters: filters) }
end
end
end
......
......@@ -56,14 +56,20 @@ RSpec.describe Search::GlobalService do
context 'issues' do
let(:scope) { 'issues' }
context 'sort by created_at' do
context 'sorting' do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
end
......@@ -71,14 +77,20 @@ RSpec.describe Search::GlobalService do
context 'merge_request' do
let(:scope) { 'merge_requests' }
context 'sort by created_at' do
context 'sorting' do
let!(:project) { create(:project, :public) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
end
......
......@@ -44,15 +44,21 @@ RSpec.describe Search::GroupService do
context 'issues' do
let(:scope) { 'issues' }
context 'sort by created_at' do
context 'sorting' do
let!(:group) { create(:group) }
let!(:project) { create(:project, :public, group: group) }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
......@@ -60,15 +66,21 @@ RSpec.describe Search::GroupService do
context 'merge requests' do
let(:scope) { 'merge_requests' }
context 'sort by created_at' do
context 'sorting' do
let!(:group) { create(:group) }
let!(:project) { create(:project, :public, group: group) }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
include_examples 'search results sorted' do
let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
......
# frozen_string_literal: true
RSpec.shared_examples 'search results sorted' do
context 'sort: newest' do
context 'sort: created_desc' do
let(:sort) { 'created_desc' }
it 'sorts results by created_at' do
expect(results.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
expect(results_created.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
end
end
context 'sort: oldest' do
context 'sort: created_asc' do
let(:sort) { 'created_asc' }
it 'sorts results by created_at' do
expect(results.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
expect(results_created.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
end
end
context 'sort: updated_desc' do
let(:sort) { 'updated_desc' }
it 'sorts results by updated_desc' do
expect(results_updated.objects(scope).map(&:id)).to eq([new_updated.id, old_updated.id, very_old_updated.id])
end
end
context 'sort: updated_asc' do
let(:sort) { 'updated_asc' }
it 'sorts results by updated_asc' do
expect(results_updated.objects(scope).map(&:id)).to eq([very_old_updated.id, old_updated.id, new_updated.id])
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