Commit 22afa884 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch '8121-geo-search-bar' into 'master'

Added a search bar to `Admin > Geo > Projects`

Closes #8121

See merge request gitlab-org/gitlab-ee!8079
parents d464f52e b8289846
......@@ -21,3 +21,5 @@
- if params[:visibility_level].present?
= hidden_field_tag :visibility_level, params[:visibility_level]
= render_if_exists 'shared/projects/search_fields'
......@@ -21,6 +21,10 @@ class Admin::Geo::ProjectsController < Admin::ApplicationController
else
finder.all_projects.page(params[:page])
end
if params[:name]
@registries = @registries.with_search(params[:name])
end
end
def destroy
......
# frozen_string_literal: true
module Geo
module Fdw
class Project < ::Geo::BaseFdw
include Gitlab::SQL::Pattern
self.table_name = Gitlab::Geo::Fdw.table('projects')
class << self
# Searches for a list of projects based on the query given in `query`.
#
# On PostgreSQL this method uses "ILIKE" to perform a case-insensitive
# search.
#
# query - The search query as a String.
def search(query)
fuzzy_search(query, [:path, :name, :description])
end
end
end
end
end
# frozen_string_literal: true
class Geo::ProjectRegistry < Geo::BaseRegistry
include ::Delay
include ::EachBatch
......@@ -78,6 +80,14 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
)
end
# Search for a list of projects associated with registries,
# based on the query given in `query`.
#
# @param [String] query term that will search over :path, :name and :description
def self.with_search(query)
where(project: Geo::Fdw::Project.search(query))
end
# Must be run before fetching the repository to avoid a race condition
#
# @param [String] type must be one of the values in TYPES
......
......@@ -22,6 +22,8 @@
= nav_link(html_options: { class: active_when(params[:sync_status] == 'never') }) do
= link_to admin_geo_projects_path(sync_status: 'never') do
= s_('Geo|Never')
.nav-controls
= render(partial: 'shared/projects/search_form', autofocus: true)
- case params[:sync_status]
- when 'never'
......
- if params[:sync_status].present?
= hidden_field_tag :sync_status, params[:sync_status]
---
title: Added a search bar to `Admin > Geo > Projects`
merge_request: 8079
author:
type: changed
# frozen_string_literal: true
require 'spec_helper'
describe 'admin Geo Projects', :js, :geo do
let!(:geo_node) { create(:geo_node) }
let!(:synced_registry) { create(:geo_project_registry, :synced, :repository_verified) }
let!(:sync_pending_registry) { create(:geo_project_registry, :synced, :repository_dirty) }
let!(:sync_failed_registry) { create(:geo_project_registry, :existing_repository_sync_failed) }
let!(:never_synced_registry) { create(:geo_project_registry) }
before do
allow(Gitlab::Geo).to receive(:license_allows?).and_return(true)
sign_in(create(:admin))
end
describe 'visiting geo projects initial page' do
let(:page_url) { admin_geo_projects_path }
before do
visit(page_url)
wait_for_requests
end
it 'shows all projects in the registry' do
page.within(find('#content-body', match: :first)) do
expect(page).to have_content(synced_registry.project.full_name)
expect(page).to have_content(sync_pending_registry.project.full_name)
expect(page).to have_content(sync_failed_registry.project.full_name)
expect(page).to have_content(never_synced_registry.project.full_name)
end
end
describe 'searching for a geo project' do
it 'filters out projects with the search term' do
fill_in :name, with: synced_registry.project.name
find('#project-filter-form-field').native.send_keys(:enter)
wait_for_requests
page.within(find('#content-body', match: :first)) do
expect(page).to have_content(synced_registry.project.full_name)
expect(page).not_to have_content(sync_pending_registry.project.full_name)
expect(page).not_to have_content(sync_failed_registry.project.full_name)
expect(page).not_to have_content(never_synced_registry.project.full_name)
end
end
end
end
describe 'visiting specific tab in geo projects page' do
let(:page_url) { admin_geo_projects_path }
before do
visit(page_url)
wait_for_requests
click_link_or_button('Pending')
wait_for_requests
end
it 'shows tab specific projects' do
page.within(find('#content-body', match: :first)) do
expect(page).not_to have_content(synced_registry.project.full_name)
expect(page).to have_content(sync_pending_registry.project.full_name)
expect(page).not_to have_content(sync_failed_registry.project.full_name)
expect(page).not_to have_content(never_synced_registry.project.full_name)
end
end
describe 'searching for a geo project' do
it 'finds the project with the same name' do
fill_in :name, with: sync_pending_registry.project.name
find('#project-filter-form-field').native.send_keys(:enter)
wait_for_requests
page.within(find('#content-body', match: :first)) do
expect(page).not_to have_content(synced_registry.project.full_name)
expect(page).to have_content(sync_pending_registry.project.full_name)
expect(page).not_to have_content(sync_failed_registry.project.full_name)
expect(page).not_to have_content(never_synced_registry.project.full_name)
end
end
it 'filters out project that matches with search but shouldnt be in the tab' do
fill_in :name, with: synced_registry.project.name
find('#project-filter-form-field').native.send_keys(:enter)
wait_for_requests
page.within(find('#content-body', match: :first)) do
expect(page).not_to have_content(synced_registry.project.full_name)
expect(page).not_to have_content(sync_pending_registry.project.full_name)
expect(page).not_to have_content(sync_failed_registry.project.full_name)
expect(page).not_to have_content(never_synced_registry.project.full_name)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::Fdw::Project, :geo, type: :model do
describe '.search' do
set(:test_project) { create(:project, description: 'kitten mittens') }
set(:project) { described_class.find(test_project.id) }
it 'returns projects with a matching name' do
expect(described_class.search(project.name)).to eq([project])
end
it 'returns projects with a partially matching name' do
expect(described_class.search(project.name[0..2])).to eq([project])
end
it 'returns projects with a matching name regardless of the casing' do
expect(described_class.search(project.name.upcase)).to eq([project])
end
it 'returns projects with a matching description' do
expect(described_class.search(project.description)).to eq([project])
end
it 'returns projects with a partially matching description' do
expect(described_class.search('kitten')).to eq([project])
end
it 'returns projects with a matching description regardless of the casing' do
expect(described_class.search('KITTEN')).to eq([project])
end
it 'returns projects with a matching path' do
expect(described_class.search(project.path)).to eq([project])
end
it 'returns projects with a partially matching path' do
expect(described_class.search(project.path[0..2])).to eq([project])
end
it 'returns projects with a matching path regardless of the casing' do
expect(described_class.search(project.path.upcase)).to eq([project])
end
end
end
......@@ -3,7 +3,7 @@ require 'spec_helper'
describe Geo::ProjectRegistry do
using RSpec::Parameterized::TableSyntax
set(:project) { create(:project) }
set(:project) { create(:project, description: 'kitten mittens') }
set(:registry) { create(:geo_project_registry, project_id: project.id) }
subject { registry }
......@@ -141,6 +141,40 @@ describe Geo::ProjectRegistry do
end
end
describe '.with_search', :geo do
it 'returns project registries that refers to projects with a matching name' do
expect(described_class.with_search(project.name)).to eq([registry])
end
it 'returns project registries that refers to projects with a matching name regardless of the casing' do
expect(described_class.with_search(project.name.upcase)).to eq([registry])
end
it 'returns project registries that refers to projects with a matching description' do
expect(described_class.with_search(project.description)).to eq([registry])
end
it 'returns project registries that refers to projects with a partially matching description' do
expect(described_class.with_search('kitten')).to eq([registry])
end
it 'returns project registries that refers to projects with a matching description regardless of the casing' do
expect(described_class.with_search('KITTEN')).to eq([registry])
end
it 'returns project registries that refers to projects with a matching path' do
expect(described_class.with_search(project.path)).to eq([registry])
end
it 'returns project registries that refers to projects with a partially matching path' do
expect(described_class.with_search(project.path[0..2])).to eq([registry])
end
it 'returns project registries that refers to projects with a matching path regardless of the casing' do
expect(described_class.with_search(project.path.upcase)).to eq([registry])
end
end
describe '#repository_sync_due?' do
where(:last_synced_at, :resync, :retry_at, :expected) do
now = Time.now
......
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