diff options
author | Jacopo <beschi.jacopo@gmail.com> | 2017-03-03 11:35:04 +0100 |
---|---|---|
committer | Jacopo <beschi.jacopo@gmail.com> | 2017-04-06 07:11:37 +0200 |
commit | b996a82ff44e3bcad5e5fb70cabbfa808d06cf62 (patch) | |
tree | d5a39a4a0e1b8d26eb9d6c47d817b2a0ff6ba6ce /app | |
parent | 280531a762e4922761b79403934c549203e5b45f (diff) | |
download | gitlab-ce-b996a82ff44e3bcad5e5fb70cabbfa808d06cf62.tar.gz |
ProjectsFinder should handle more options
Extended ProjectFinder in order to handle the following options:
- current_user - which user use
- project_ids_relation: int[] - project ids to use
- params:
- trending: boolean
- non_public: boolean
- starred: boolean
- sort: string
- visibility_level: int
- tags: string[]
- personal: boolean
- search: string
- non_archived: boolean
GroupProjectsFinder now inherits from ProjectsFinder.
Changed the code in order to use the new available options.
Diffstat (limited to 'app')
20 files changed, 200 insertions, 99 deletions
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index daecfc832bf..a1975c0e341 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -3,6 +3,7 @@ class Admin::ProjectsController < Admin::ApplicationController before_action :group, only: [:show, :transfer] def index + params[:sort] ||= 'latest_activity_desc' @projects = Project.with_statistics @projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? diff --git a/app/controllers/concerns/filter_projects.rb b/app/controllers/concerns/filter_projects.rb deleted file mode 100644 index 6014112256a..00000000000 --- a/app/controllers/concerns/filter_projects.rb +++ /dev/null @@ -1,17 +0,0 @@ -# == FilterProjects -# -# Controller concern to handle projects filtering -# * by name -# * by archived state -# -module FilterProjects - extend ActiveSupport::Concern - - def filter_projects(projects) - projects = projects.search(params[:name]) if params[:name].present? - projects = projects.non_archived if params[:archived].blank? - projects = projects.personal(current_user) if params[:personal].present? && current_user - - projects - end -end diff --git a/app/controllers/concerns/params_backward_compatibility.rb b/app/controllers/concerns/params_backward_compatibility.rb new file mode 100644 index 00000000000..b0e3d9c7b34 --- /dev/null +++ b/app/controllers/concerns/params_backward_compatibility.rb @@ -0,0 +1,7 @@ +module ParamsBackwardCompatibility + private + + def set_non_archived_param + params[:non_archived] = params[:archived].blank? + end +end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index be00d765f73..5a1efcab1a3 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -1,10 +1,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController - include FilterProjects + include ParamsBackwardCompatibility + + before_action :set_non_archived_param + before_action :default_sorting def index - @projects = load_projects(current_user.authorized_projects) - @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.page(params[:page]) + @projects = load_projects(params.merge(non_public: true)).page(params[:page]) respond_to do |format| format.html { @last_push = current_user.recent_push } @@ -21,10 +22,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def starred - @projects = load_projects(current_user.viewable_starred_projects) - @projects = @projects.includes(:forked_from_project, :tags) - @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.page(params[:page]) + @projects = load_projects(params.merge(starred: true)). + includes(:forked_from_project, :tags).page(params[:page]) @last_push = current_user.recent_push @groups = [] @@ -41,14 +40,18 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController private - def load_projects(base_scope) - projects = base_scope.sorted_by_activity.includes(:route, namespace: :route) + def default_sorting + params[:sort] ||= 'latest_activity_desc' + @sort = params[:sort] + end - filter_projects(projects) + def load_projects(finder_params) + ProjectsFinder.new(params: finder_params, current_user: current_user). + execute.includes(:route, namespace: :route) end def load_events - @events = Event.in_projects(load_projects(current_user.authorized_projects)) + @events = Event.in_projects(load_projects(params.merge(non_public: true))) @events = event_filter.apply_filter(@events).with_associations @events = @events.limit(20).offset(params[:offset] || 0) end diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 6167f9bd335..8f1870759e4 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -1,14 +1,12 @@ class Explore::ProjectsController < Explore::ApplicationController - include FilterProjects + include ParamsBackwardCompatibility + + before_action :set_non_archived_param def index - @projects = load_projects - @tags = @projects.tags_on(:tags) - @projects = @projects.tagged_with(params[:tag]) if params[:tag].present? - @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? - @projects = filter_projects(@projects) - @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.includes(:namespace).page(params[:page]) + params[:sort] ||= 'latest_activity_desc' + @sort = params[:sort] + @projects = load_projects.page(params[:page]) respond_to do |format| format.html @@ -21,10 +19,9 @@ class Explore::ProjectsController < Explore::ApplicationController end def trending - @projects = load_projects(Project.trending) - @projects = filter_projects(@projects) - @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.page(params[:page]) + params[:trending] = true + @sort = params[:sort] + @projects = load_projects.page(params[:page]) respond_to do |format| format.html @@ -37,10 +34,7 @@ class Explore::ProjectsController < Explore::ApplicationController end def starred - @projects = load_projects - @projects = filter_projects(@projects) - @projects = @projects.reorder('star_count DESC') - @projects = @projects.page(params[:page]) + @projects = load_projects.reorder('star_count DESC').page(params[:page]) respond_to do |format| format.html @@ -52,10 +46,10 @@ class Explore::ProjectsController < Explore::ApplicationController end end - protected + private - def load_projects(base_scope = nil) - base_scope ||= ProjectsFinder.new.execute(current_user) - base_scope.includes(:route, namespace: :route) + def load_projects + ProjectsFinder.new(current_user: current_user, params: params). + execute.includes(:route, namespace: :route) end end diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 8b69c18d689..29ffaeb19c1 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -27,7 +27,7 @@ class Groups::ApplicationController < ApplicationController end def group_projects - @projects ||= GroupProjectsFinder.new(group).execute(current_user) + @projects ||= GroupProjectsFinder.new(group: group, current_user: current_user).execute end def authorize_admin_group! diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 05f9ee1ee90..78c9f1f7004 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,7 +1,7 @@ class GroupsController < Groups::ApplicationController - include FilterProjects include IssuesAction include MergeRequestsAction + include ParamsBackwardCompatibility respond_to :html @@ -105,15 +105,16 @@ class GroupsController < Groups::ApplicationController protected def setup_projects + set_non_archived_param + params[:sort] ||= 'latest_activity_desc' + @sort = params[:sort] + options = {} options[:only_owned] = true if params[:shared] == '0' options[:only_shared] = true if params[:shared] == '1' - @projects = GroupProjectsFinder.new(group, options).execute(current_user) + @projects = GroupProjectsFinder.new(params: params, group: group, options: options, current_user: current_user).execute @projects = @projects.includes(:namespace) - @projects = @projects.sorted_by_activity - @projects = filter_projects(@projects) - @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.page(params[:page]) if params[:name].blank? end diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index ba46e2528e6..1eb3800e49d 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -9,7 +9,7 @@ class Projects::ForksController < Projects::ApplicationController def index base_query = project.forks.includes(:creator) - @forks = base_query.merge(ProjectsFinder.new.execute(current_user)) + @forks = base_query.merge(ProjectsFinder.new(current_user: current_user).execute) @total_forks_count = base_query.size @private_forks_count = @total_forks_count - @forks.size @public_forks_count = @total_forks_count - @private_forks_count diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2683614d2e8..a452bbba422 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -140,6 +140,6 @@ class UsersController < ApplicationController end def projects_for_current_user - ProjectsFinder.new.execute(current_user) + ProjectsFinder.new(current_user: current_user).execute end end diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb index 3b9a421b118..f043c38c6f9 100644 --- a/app/finders/group_projects_finder.rb +++ b/app/finders/group_projects_finder.rb @@ -1,42 +1,63 @@ -class GroupProjectsFinder < UnionFinder - def initialize(group, options = {}) +# GroupProjectsFinder +# +# Used to filter Projects by set of params +# +# Arguments: +# current_user - which user use +# project_ids_relation: int[] - project ids to use +# group +# options: +# only_owned: boolean +# only_shared: boolean +# params: +# sort: string +# visibility_level: int +# tags: string[] +# personal: boolean +# search: string +# non_archived: boolean +# +class GroupProjectsFinder < ProjectsFinder + attr_reader :group, :options + + def initialize(group:, params: {}, options: {}, current_user: nil, project_ids_relation: nil) + super(params: params, current_user: current_user, project_ids_relation: project_ids_relation) @group = group @options = options end - def execute(current_user = nil) - segments = group_projects(current_user) - find_union(segments, Project) - end - private - def group_projects(current_user) - only_owned = @options.fetch(:only_owned, false) - only_shared = @options.fetch(:only_shared, false) + def init_collection + only_owned = options.fetch(:only_owned, false) + only_shared = options.fetch(:only_shared, false) projects = [] if current_user - if @group.users.include?(current_user) - projects << @group.projects unless only_shared - projects << @group.shared_projects unless only_owned + if group.users.include?(current_user) + projects << group.projects unless only_shared + projects << group.shared_projects unless only_owned else unless only_shared - projects << @group.projects.visible_to_user(current_user) - projects << @group.projects.public_to_user(current_user) + projects << group.projects.visible_to_user(current_user) + projects << group.projects.public_to_user(current_user) end unless only_owned - projects << @group.shared_projects.visible_to_user(current_user) - projects << @group.shared_projects.public_to_user(current_user) + projects << group.shared_projects.visible_to_user(current_user) + projects << group.shared_projects.public_to_user(current_user) end end else - projects << @group.projects.public_only unless only_shared - projects << @group.shared_projects.public_only unless only_owned + projects << group.projects.public_only unless only_shared + projects << group.shared_projects.public_only unless only_owned end projects end + + def union(items) + find_union(items, Project) + end end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index f7ebb1807d7..4cc42b88a2a 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -116,9 +116,9 @@ class IssuableFinder if current_user && params[:authorized_only].presence && !current_user_related? current_user.authorized_projects elsif group - GroupProjectsFinder.new(group).execute(current_user) + GroupProjectsFinder.new(group: group, current_user: current_user).execute else - projects_finder.execute(current_user, item_project_ids(items)) + ProjectsFinder.new(current_user: current_user, project_ids_relation: item_project_ids(items)).execute end @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) @@ -405,8 +405,4 @@ class IssuableFinder def current_user_related? params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me' end - - def projects_finder - @projects_finder ||= ProjectsFinder.new - end end diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb index e52083f86e4..042d792dada 100644 --- a/app/finders/labels_finder.rb +++ b/app/finders/labels_finder.rb @@ -83,7 +83,7 @@ class LabelsFinder < UnionFinder def projects return @projects if defined?(@projects) - @projects = skip_authorization ? Project.all : ProjectsFinder.new.execute(current_user) + @projects = skip_authorization ? Project.all : ProjectsFinder.new(current_user: current_user).execute @projects = @projects.in_namespace(params[:group_id]) if group? @projects = @projects.where(id: params[:project_ids]) if projects? @projects = @projects.reorder(nil) diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index 18ec45f300d..f6d8226bf3f 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -1,19 +1,93 @@ +# ProjectsFinder +# +# Used to filter Projects by set of params +# +# Arguments: +# current_user - which user use +# project_ids_relation: int[] - project ids to use +# params: +# trending: boolean +# non_public: boolean +# starred: boolean +# sort: string +# visibility_level: int +# tags: string[] +# personal: boolean +# search: string +# non_archived: boolean +# class ProjectsFinder < UnionFinder - def execute(current_user = nil, project_ids_relation = nil) - segments = all_projects(current_user) - segments.map! { |s| s.where(id: project_ids_relation) } if project_ids_relation + attr_accessor :params + attr_reader :current_user, :project_ids_relation - find_union(segments, Project).with_route + def initialize(params: {}, current_user: nil, project_ids_relation: nil) + @params = params + @current_user = current_user + @project_ids_relation = project_ids_relation + end + + def execute + items = init_collection + items = by_ids(items) + items = union(items) + items = by_personal(items) + items = by_visibilty_level(items) + items = by_tags(items) + items = by_search(items) + items = by_archived(items) + sort(items) end private - def all_projects(current_user) + def init_collection projects = [] - projects << current_user.authorized_projects if current_user - projects << Project.unscoped.public_to_user(current_user) + if params[:trending].present? + projects << Project.trending + elsif params[:starred].present? && current_user + projects << current_user.viewable_starred_projects + else + projects << current_user.authorized_projects if current_user + projects << Project.unscoped.public_to_user(current_user) unless params[:non_public].present? + end projects end + + def by_ids(items) + project_ids_relation ? items.map { |item| item.where(id: project_ids_relation) } : items + end + + def union(items) + find_union(items, Project).with_route + end + + def by_personal(items) + (params[:personal].present? && current_user) ? items.personal(current_user) : items + end + + def by_visibilty_level(items) + params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items + end + + def by_tags(items) + params[:tag].present? ? items.tagged_with(params[:tag]) : items + end + + def by_search(items) + params[:search] ||= params[:name] + params[:search].present? ? items.search(params[:search]) : items + end + + def sort(items) + params[:sort].present? ? items.sort(params[:sort]) : items + end + + def by_archived(projects) + # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false` + params[:non_archived] = !Gitlab::Utils.to_boolean(params[:archived]) if params.key?(:archived) + + params[:non_archived] ? projects.non_archived : projects + end end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index b7f091f334d..dc13386184e 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -95,7 +95,7 @@ class TodosFinder def projects(items) item_project_ids = items.reorder(nil).select(:project_id) - ProjectsFinder.new.execute(current_user, item_project_ids) + ProjectsFinder.new(current_user: current_user, project_ids_relation: item_project_ids).execute end def type? diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 5c89cbea3fc..3a5d1b97c36 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -25,8 +25,8 @@ module SortingHelper def projects_sort_options_hash options = { sort_value_name => sort_title_name, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_latest_activity => sort_title_latest_activity, + sort_value_oldest_activity => sort_title_oldest_activity, sort_value_recently_created => sort_title_recently_created, sort_value_oldest_created => sort_title_oldest_created } @@ -78,6 +78,14 @@ module SortingHelper 'Last updated' end + def sort_title_oldest_activity + 'Oldest updated' + end + + def sort_title_latest_activity + 'Last updated' + end + def sort_title_oldest_created 'Oldest created' end @@ -198,6 +206,14 @@ module SortingHelper 'updated_desc' end + def sort_value_oldest_activity + 'latest_activity_asc' + end + + def sort_value_latest_activity + 'latest_activity_desc' + end + def sort_value_oldest_created 'created_asc' end diff --git a/app/models/project.rb b/app/models/project.rb index 12fd0668ff8..1f95d00baf8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -349,10 +349,15 @@ class Project < ActiveRecord::Base end def sort(method) - if method == 'storage_size_desc' + case method.to_s + when 'storage_size_desc' # storage_size is a joined column so we need to # pass a string to avoid AR adding the table name reorder('project_statistics.storage_size DESC, projects.id DESC') + when 'latest_activity_desc' + reorder(last_activity_at: :desc) + when 'latest_activity_asc' + reorder(last_activity_at: :asc) else order_by(method) end diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 4cc21696eb6..cb58c115d54 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -12,7 +12,7 @@ class GroupPolicy < BasePolicy can_read ||= globally_viewable can_read ||= member can_read ||= @user.admin? - can_read ||= GroupProjectsFinder.new(@subject).execute(@user).any? + can_read ||= GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any? can! :read_group if can_read # Only group masters and group owners can create new projects @@ -41,6 +41,6 @@ class GroupPolicy < BasePolicy return true if @subject.internal? && !@user.external? return true if @subject.users.include?(@user) - GroupProjectsFinder.new(@subject).execute(@user).any? + GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any? end end diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb index c1549df5ac6..8409b592b72 100644 --- a/app/services/search/global_service.rb +++ b/app/services/search/global_service.rb @@ -8,7 +8,7 @@ module Search def execute group = Group.find_by(id: params[:group_id]) if params[:group_id].present? - projects = ProjectsFinder.new.execute(current_user) + projects = ProjectsFinder.new(current_user: current_user).execute if group projects = projects.inside_path(group.full_path) diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml index 1bbd4602ecf..8843d4e7c84 100644 --- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml @@ -1,4 +1,4 @@ -- publicish_project_count = ProjectsFinder.new.execute(current_user).count +- publicish_project_count = ProjectsFinder.new(current_user: current_user).execute.count .blank-state.blank-state-welcome %h2.blank-state-welcome-title Welcome to GitLab diff --git a/app/views/shared/projects/_dropdown.html.haml b/app/views/shared/projects/_dropdown.html.haml index 2d25b8aad62..8939aeb6c3a 100644 --- a/app/views/shared/projects/_dropdown.html.haml +++ b/app/views/shared/projects/_dropdown.html.haml @@ -1,4 +1,4 @@ -- @sort ||= sort_value_recently_updated +- @sort ||= sort_value_latest_activity .dropdown - toggle_text = projects_sort_options_hash[@sort] = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { id: 'sort-projects-dropdown' }) |