From 6baff6504b234e209a5e1d78349dbd2589d5d7e8 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Mon, 28 Jan 2019 13:19:53 +0100 Subject: Change sorting options for starrers: name (asc/desc), most/least recent star --- app/controllers/projects/starrers_controller.rb | 7 ++---- app/finders/users_finder.rb | 5 ---- app/finders/users_star_projects_finder.rb | 31 +++++++++++++++++++++++++ app/helpers/sorting_helper.rb | 17 ++++++++++++++ app/models/user.rb | 1 - app/models/users_star_project.rb | 25 ++++++++++++++++++++ app/views/projects/starrers/_starrer.html.haml | 12 +++++----- app/views/projects/starrers/index.html.haml | 6 ++--- locale/gitlab.pot | 3 +++ 9 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 app/finders/users_star_projects_finder.rb diff --git a/app/controllers/projects/starrers_controller.rb b/app/controllers/projects/starrers_controller.rb index cb230242e6e..6ca49fceff6 100644 --- a/app/controllers/projects/starrers_controller.rb +++ b/app/controllers/projects/starrers_controller.rb @@ -10,12 +10,9 @@ class Projects::StarrersController < Projects::ApplicationController def index @sort = params[:sort].presence || sort_value_name - params[:has_starred] = @project + params[:project] = @project - @starrers = UsersFinder.new(current_user, params).execute - @starrers = @starrers.joins(:users_star_projects) - .select('"users".*, "users_star_projects"."created_at" as "starred_since"') - .where(users_star_projects: { project_id: @project.project_id }) + @starrers = UsersStarProjectsFinder.new(params).execute @starrers = @starrers.sort_by_attribute(@sort) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb index 2f3fc24b243..81ae50c0bd1 100644 --- a/app/finders/users_finder.rb +++ b/app/finders/users_finder.rb @@ -37,7 +37,6 @@ class UsersFinder users = by_2fa(users) users = by_created_at(users) users = by_custom_attributes(users) - users = by_has_starred(users) users end @@ -95,8 +94,4 @@ class UsersFinder users end end - - def by_has_starred(items) - params[:has_starred].present? ? items.has_starred(params[:has_starred]) : items - end end diff --git a/app/finders/users_star_projects_finder.rb b/app/finders/users_star_projects_finder.rb new file mode 100644 index 00000000000..66b83fa8f8e --- /dev/null +++ b/app/finders/users_star_projects_finder.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class UsersStarProjectsFinder + include CustomAttributesFilter + + attr_accessor :params + + def initialize(params = {}) + @params = params + end + + def execute + stars = UsersStarProject.all.order_id_desc + stars = by_search(stars) + stars = by_project(stars) + + stars + end + + private + + def by_search(items) + return items unless params[:search].present? + + items.search(params[:search]) + end + + def by_project(items) + params[:project].present? ? items.by_project(params[:project]) : items + end +end diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 15f35645c78..a4eb76a2359 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -167,6 +167,15 @@ module SortingHelper } end + def starrers_sort_options_hash + { + sort_value_name => sort_title_name, + sort_value_name_desc => sort_title_name_desc, + sort_value_recently_created => sort_title_recently_starred, + sort_value_oldest_created => sort_title_oldest_starred + } + end + def sortable_item(item, path, sorted_by) link_to item, path, class: sorted_by == item ? 'is-active' : '' end @@ -327,6 +336,10 @@ module SortingHelper s_('SortOptions|Oldest sign in') end + def sort_title_oldest_starred + s_('SortOptions|Oldest starred') + end + def sort_title_oldest_updated s_('SortOptions|Oldest updated') end @@ -347,6 +360,10 @@ module SortingHelper s_('SortOptions|Recent sign in') end + def sort_title_recently_starred + s_('SortOptions|Recently starred') + end + def sort_title_recently_updated s_('SortOptions|Last updated') end diff --git a/app/models/user.rb b/app/models/user.rb index f772e3f6907..4630552e02e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -282,7 +282,6 @@ class User < ApplicationRecord scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) } scope :with_emails, -> { preload(:emails) } scope :with_dashboard, -> (dashboard) { where(dashboard: dashboard) } - scope :has_starred, ->(project) { joins(:users_star_projects).where('users_star_projects.project_id': project.id) } # Limits the users to those that have TODOs, optionally in the given state. # diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb index 9be6bd2e6f3..62d44aaf955 100644 --- a/app/models/users_star_project.rb +++ b/app/models/users_star_project.rb @@ -1,10 +1,35 @@ # frozen_string_literal: true class UsersStarProject < ApplicationRecord + include Sortable + belongs_to :project, counter_cache: :star_count, touch: true belongs_to :user validates :user, presence: true validates :user_id, uniqueness: { scope: [:project_id] } validates :project, presence: true + + alias_attribute :starred_since, :created_at + + scope :order_user_name_asc, -> { joins(:user).reorder('"users"."name" ASC') } + scope :order_user_name_desc, -> { joins(:user).reorder('"users"."name" DESC') } + scope :by_project, -> (project) { where(project_id: project.id) } + + class << self + def sort_by_attribute(method) + order_method = method || 'id_desc' + + case order_method.to_s + when 'name_asc' then order_user_name_asc + when 'name_desc' then order_user_name_desc + else + order_by(order_method) + end + end + + def search(query) + joins(:user).merge(User.search(query)) + end + end end diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml index d8eee17dff4..377d62f8abd 100644 --- a/app/views/projects/starrers/_starrer.html.haml +++ b/app/views/projects/starrers/_starrer.html.haml @@ -1,19 +1,19 @@ -- user = local_assigns.fetch(:user) +- starrer = local_assigns.fetch(:starrer) .col-lg-3.col-md-4.col-sm-12 .card .card-body - = image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: '' + = image_tag avatar_icon_for_user(starrer.user, 40), class: "avatar s40", alt: '' .user-info .block-truncated - = link_to user.name, user_path(user), class: 'user js-user-link', data: { user_id: user.id } + = link_to starrer.user.name, user_path(starrer.user), class: 'user js-user-link', data: { user_id: starrer.user.id } .block-truncated - %span.cgray= user.to_reference + %span.cgray= starrer.user.to_reference - - if user == current_user + - if starrer.user == current_user %span.badge.badge-success.prepend-left-5= _("It's you") .block-truncated - = time_ago_with_tooltip(user.starred_since) + = time_ago_with_tooltip(starrer.starred_since) diff --git a/app/views/projects/starrers/index.html.haml b/app/views/projects/starrers/index.html.haml index ef1781e378c..662da94107a 100644 --- a/app/views/projects/starrers/index.html.haml +++ b/app/views/projects/starrers/index.html.haml @@ -14,16 +14,16 @@ %button.user-search-btn{ type: "submit", "aria-label" => _("Submit search") } = icon("search") .dropdown.inline.user-sort-dropdown - = dropdown_toggle(users_sort_options_hash[@sort], { toggle: 'dropdown' }) + = dropdown_toggle(starrers_sort_options_hash[@sort], { toggle: 'dropdown' }) %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable %li.dropdown-header = _("Sort by") - - users_sort_options_hash.each do |value, title| + - starrers_sort_options_hash.each do |value, title| %li = link_to filter_user_path(sort: value), class: ("is-active" if @sort == value) do = title - if @starrers.size > 0 .row.prepend-top-10 - = render partial: 'starrer', collection: @starrers, as: :user + = render partial: 'starrer', collection: @starrers, as: :starrer - else .nothing-here-block Nobody has starred this repository yet diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 7586fff2e7d..367de1c6843 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10268,6 +10268,9 @@ msgstr "" msgid "SortOptions|Oldest sign in" msgstr "" +msgid "SortOptions|Oldest starred" +msgstr "" + msgid "SortOptions|Oldest updated" msgstr "" -- cgit v1.2.1