diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | app/controllers/projects/tags_controller.rb | 6 | ||||
-rw-r--r-- | app/models/repository.rb | 19 | ||||
-rw-r--r-- | app/views/projects/tags/index.html.haml | 15 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 41 |
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 } |