Commit 43238a40 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'archived-projects-only' into 'master'

Add an option to list only archived projects

Closes #35994

See merge request !13492
parents 1957099b 55f4ddad
...@@ -3,9 +3,9 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -3,9 +3,9 @@ class Admin::ProjectsController < Admin::ApplicationController
before_action :group, only: [:show, :transfer] before_action :group, only: [:show, :transfer]
def index def index
finder = Admin::ProjectsFinder.new(params: params, current_user: current_user) params[:sort] ||= 'latest_activity_desc'
@projects = finder.execute @sort = params[:sort]
@sort = finder.sort @projects = Admin::ProjectsFinder.new(params: params, current_user: current_user).execute
respond_to do |format| respond_to do |format|
format.html format.html
......
class Admin::ProjectsFinder class Admin::ProjectsFinder
attr_reader :sort, :namespace_id, :visibility_level, :with_push, attr_reader :params, :current_user
:abandoned, :last_repository_check_failed, :archived,
:personal, :name, :page, :current_user
def initialize(params:, current_user:) def initialize(params:, current_user:)
@params = params
@current_user = current_user @current_user = current_user
@sort = params.fetch(:sort) { 'latest_activity_desc' }
@namespace_id = params[:namespace_id]
@visibility_level = params[:visibility_level]
@with_push = params[:with_push]
@abandoned = params[:abandoned]
@last_repository_check_failed = params[:last_repository_check_failed]
@archived = params[:archived]
@personal = params[:personal]
@name = params[:name]
@page = params[:page]
end end
def execute def execute
items = Project.without_deleted.with_statistics items = Project.without_deleted.with_statistics
items = items.in_namespace(namespace_id) if namespace_id.present? items = by_namespace_id(items)
items = items.where(visibility_level: visibility_level) if visibility_level.present? items = by_visibilty_level(items)
items = items.with_push if with_push.present? items = by_with_push(items)
items = items.abandoned if abandoned.present? items = by_abandoned(items)
items = items.where(last_repository_check_failed: true) if last_repository_check_failed.present? items = by_last_repository_check_failed(items)
items = items.non_archived unless archived.present? items = by_archived(items)
items = items.personal(current_user) if personal.present? items = by_personal(items)
items = items.search(name) if name.present? items = by_name(items)
items = items.sort(sort) items = sort(items)
items.includes(:namespace).order("namespaces.path, projects.name ASC").page(page) items.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page])
end
private
def by_namespace_id(items)
params[:namespace_id].present? ? items.in_namespace(params[:namespace_id]) : items
end
def by_visibilty_level(items)
params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items
end
def by_with_push(items)
params[:with_push].present? ? items.with_push : items
end
def by_abandoned(items)
params[:abandoned].present? ? items.abandoned : items
end
def by_last_repository_check_failed(items)
params[:last_repository_check_failed].present? ? items.where(last_repository_check_failed: true) : items
end
def by_archived(items)
if params[:archived] == 'only'
items.archived
elsif params[:archived].blank?
items.non_archived
else
items
end
end
def by_personal(items)
params[:personal].present? ? items.personal(current_user) : items
end
def by_name(items)
params[:name].present? ? items.search(params[:name]) : items
end
def sort(items)
sort = params.fetch(:sort) { 'latest_activity_desc' }
items.sort(sort)
end end
end end
...@@ -125,9 +125,18 @@ class ProjectsFinder < UnionFinder ...@@ -125,9 +125,18 @@ class ProjectsFinder < UnionFinder
end end
def by_archived(projects) def by_archived(projects)
# Back-compatibility with the places where `params[:archived]` can be set explicitly to `false` if params[:non_archived]
params[:non_archived] = !Gitlab::Utils.to_boolean(params[:archived]) if params.key?(:archived) projects.non_archived
elsif params.key?(:archived) # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false`
params[:non_archived] ? projects.non_archived : projects if params[:archived] == 'only'
projects.archived
elsif Gitlab::Utils.to_boolean(params[:archived])
projects
else
projects.non_archived
end
else
projects
end
end end
end end
...@@ -247,6 +247,7 @@ class Project < ActiveRecord::Base ...@@ -247,6 +247,7 @@ class Project < ActiveRecord::Base
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) } scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) } scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) }
scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) } scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
scope :archived, -> { where(archived: true) }
scope :non_archived, -> { where(archived: false) } scope :non_archived, -> { where(archived: false) }
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) }
......
...@@ -15,8 +15,11 @@ ...@@ -15,8 +15,11 @@
= link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do = link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do
Hide archived projects Hide archived projects
%li %li
= link_to filter_projects_path(archived: true), class: ("is-active" if params[:archived].present?) do = link_to filter_projects_path(archived: true), class: ("is-active" if Gitlab::Utils.to_boolean(params[:archived])) do
Show archived projects Show archived projects
%li
= link_to filter_projects_path(archived: 'only'), class: ("is-active" if params[:archived] == 'only') do
Show archived projects only
- if current_user - if current_user
%li.divider %li.divider
%li %li
......
---
title: Add an option to list only archived projects
merge_request: 13492
author: Mehdi Lahmam (@mehlah)
type: added
...@@ -36,6 +36,14 @@ describe "Admin::Projects" do ...@@ -36,6 +36,14 @@ describe "Admin::Projects" do
expect(page).to have_content(archived_project.name) expect(page).to have_content(archived_project.name)
expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived') expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived')
end end
it 'renders only archived projects', js: true do
find(:css, '#sort-projects-dropdown').click
click_link 'Show archived projects only'
expect(page).to have_content(archived_project.name)
expect(page).not_to have_content(project.name)
end
end end
describe "GET /admin/projects/:namespace_id/:id" do describe "GET /admin/projects/:namespace_id/:id" do
......
...@@ -26,6 +26,13 @@ RSpec.describe 'Dashboard Archived Project' do ...@@ -26,6 +26,13 @@ RSpec.describe 'Dashboard Archived Project' do
expect(page).to have_link(archived_project.name) expect(page).to have_link(archived_project.name)
end end
it 'renders only archived projects' do
click_link 'Show archived projects only'
expect(page).to have_content(archived_project.name)
expect(page).not_to have_content(project.name)
end
it 'searchs archived projects', :js do it 'searchs archived projects', :js do
click_button 'Last updated' click_button 'Last updated'
click_link 'Show archived projects' click_link 'Show archived projects'
......
...@@ -118,6 +118,12 @@ describe Admin::ProjectsFinder do ...@@ -118,6 +118,12 @@ describe Admin::ProjectsFinder do
it { is_expected.to match_array([archived_project, shared_project, public_project, internal_project, private_project]) } it { is_expected.to match_array([archived_project, shared_project, public_project, internal_project, private_project]) }
end end
context 'archived=only' do
let(:params) { { archived: 'only' } }
it { is_expected.to eq([archived_project]) }
end
end end
context 'filter by personal' do context 'filter by personal' do
......
...@@ -123,6 +123,12 @@ describe ProjectsFinder do ...@@ -123,6 +123,12 @@ describe ProjectsFinder do
it { is_expected.to match_array([public_project, internal_project, archived_project]) } it { is_expected.to match_array([public_project, internal_project, archived_project]) }
end end
describe 'filter by archived only' do
let(:params) { { archived: 'only' } }
it { is_expected.to eq([archived_project]) }
end
describe 'filter by archived for backward compatibility' do describe 'filter by archived for backward compatibility' do
let(:params) { { archived: false } } let(:params) { { archived: false } }
......
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