summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--app/controllers/projects/tags_controller.rb6
-rw-r--r--app/models/repository.rb19
-rw-r--r--app/views/projects/tags/index.html.haml15
-rw-r--r--spec/models/repository_spec.rb41
5 files changed, 78 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG
index b12ba9f31b1..030bb61703a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -93,6 +93,7 @@ v 8.9.0 (unreleased)
- Show categorised search queries in the search autocomplete
- RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented
- Improve issuables APIs performance when accessing notes !4471
+ - Add sorting dropdown to tags page !4423
- External links now open in a new tab
- Prevent default actions of disabled buttons and links
- Markdown editor now correctly resets the input value on edit cancellation !4175
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 46b242aa5ff..6dc495247c8 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -6,8 +6,10 @@ class Projects::TagsController < Projects::ApplicationController
before_action :authorize_admin_project!, only: [:destroy]
def index
- sorted = VersionSorter.rsort(@repository.tag_names)
- @tags = Kaminari.paginate_array(sorted).page(params[:page])
+ @sort = params[:sort] || 'name'
+ @tags = @repository.tags_sorted_by(@sort)
+ @tags = Kaminari.paginate_array(@tags).page(params[:page])
+
@releases = project.releases.where(tag: @tags)
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 65d1bad511d..bbd7682d8e7 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -598,6 +598,21 @@ class Repository
end
end
+ def tags_sorted_by(value)
+ case value
+ when 'name'
+ # Would be better to use `sort_by` but `version_sorter` only exposes
+ # `sort` and `rsort`
+ VersionSorter.rsort(tag_names).map { |tag_name| find_tag(tag_name) }
+ when 'updated_desc'
+ tags_sorted_by_committed_date.reverse
+ when 'updated_asc'
+ tags_sorted_by_committed_date
+ else
+ tags
+ end
+ end
+
def contributors
commits = self.commits(nil, limit: 2000, offset: 0, skip_merges: true)
@@ -995,4 +1010,8 @@ class Repository
def file_on_head(regex)
tree(:head).blobs.find { |file| file.name =~ regex }
end
+
+ def tags_sorted_by_committed_date
+ tags.sort_by { |tag| commit(tag.target).committed_date }
+ end
end
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 2779084fe38..4ca1f58ac5c 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -11,12 +11,23 @@
.nav-controls
= link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do
New tag
+ .dropdown.inline
+ %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} }
+ %span.light= @sort.humanize
+ %b.caret
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li
+ = link_to namespace_project_tags_path(sort: nil) do
+ Name
+ = link_to namespace_project_tags_path(sort: sort_value_recently_updated) do
+ = sort_title_recently_updated
+ = link_to namespace_project_tags_path(sort: sort_value_oldest_updated) do
+ = sort_title_oldest_updated
.tags
- unless @tags.empty?
%ul.content-list
- - @tags.each do |tag|
- = render 'tag', tag: @repository.find_tag(tag)
+ = render partial: 'tag', collection: @tags
= paginate @tags, theme: 'gitlab'
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 8c2347992f1..d8350000bf6 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -31,6 +31,47 @@ describe Repository, models: true do
it { is_expected.not_to include('v1.0.0') }
end
+ describe 'tags_sorted_by' do
+ context 'name' do
+ subject { repository.tags_sorted_by('name').map(&:name) }
+
+ it { is_expected.to eq(['v1.1.0', 'v1.0.0']) }
+ end
+
+ context 'updated' do
+ let(:tag_a) { repository.find_tag('v1.0.0') }
+ let(:tag_b) { repository.find_tag('v1.1.0') }
+
+ context 'desc' do
+ subject { repository.tags_sorted_by('updated_desc').map(&:name) }
+
+ before do
+ double_first = double(committed_date: Time.now)
+ double_last = double(committed_date: Time.now - 1.second)
+
+ allow(repository).to receive(:commit).with(tag_a.target).and_return(double_first)
+ allow(repository).to receive(:commit).with(tag_b.target).and_return(double_last)
+ end
+
+ it { is_expected.to eq(['v1.0.0', 'v1.1.0']) }
+ end
+
+ context 'asc' do
+ subject { repository.tags_sorted_by('updated_asc').map(&:name) }
+
+ before do
+ double_first = double(committed_date: Time.now - 1.second)
+ double_last = double(committed_date: Time.now)
+
+ allow(repository).to receive(:commit).with(tag_a.target).and_return(double_last)
+ allow(repository).to receive(:commit).with(tag_b.target).and_return(double_first)
+ end
+
+ it { is_expected.to eq(['v1.1.0', 'v1.0.0']) }
+ end
+ end
+ end
+
describe :last_commit_for_path do
subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }