Commit 89b30999 authored by Alexis Reigel's avatar Alexis Reigel

use filtered search bar for admin runners

parent d4387d88
import FilteredSearchTokenKeys from './filtered_search_token_keys';
const tokenKeys = [{
key: 'status',
type: 'string',
param: 'status',
symbol: '',
icon: 'signal',
tag: 'status',
}];
const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys);
export default AdminRunnersFilteredSearchTokenKeys;
......@@ -7,6 +7,7 @@ import DropdownHint from './dropdown_hint';
import DropdownEmoji from './dropdown_emoji';
import DropdownNonUser from './dropdown_non_user';
import DropdownUser from './dropdown_user';
import NullDropdown from './null_dropdown';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
export default class FilteredSearchDropdownManager {
......@@ -90,6 +91,11 @@ export default class FilteredSearchDropdownManager {
gl: DropdownEmoji,
element: this.container.querySelector('#js-dropdown-my-reaction'),
},
status: {
reference: null,
gl: NullDropdown,
element: this.container.querySelector('#js-dropdown-admin-runner-status'),
},
};
supportedTokens.forEach((type) => {
......
import FilteredSearchDropdown from './filtered_search_dropdown';
export default class NullDropdown extends FilteredSearchDropdown {
renderContent(forceShowList = false) {
this.droplab.changeHookList(this.hookId, this.dropdown, [], this.config);
super.renderContent(forceShowList);
}
}
import initFilteredSearch from '~/pages/search/init_filtered_search';
import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ADMIN_RUNNERS,
filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
});
});
......@@ -3,4 +3,5 @@
export const FILTERED_SEARCH = {
MERGE_REQUESTS: 'merge_requests',
ISSUES: 'issues',
ADMIN_RUNNERS: 'admin/runners',
};
......@@ -26,8 +26,9 @@ class Admin::RunnersFinder < UnionFinder
end
def filter_by_status!
if @params[:status].present? && Ci::Runner::AVAILABLE_STATUSES.include?(@params[:status])
@runners = @runners.public_send(@params[:status]) # rubocop:disable GitlabSecurity/PublicSend
status = @params[:status_status]
if status.present? && Ci::Runner::AVAILABLE_STATUSES.include?(status)
@runners = @runners.public_send(status) # rubocop:disable GitlabSecurity/PublicSend
end
end
......
- active_status = params[:status].presence
- toggle_text = 'Status'
- if active_status
= hidden_field_tag :status, params[:status]
- toggle_text = params[:status].titleize
= dropdown_tag(toggle_text, options: { wrapper_class: 'dropdown-menu-selectable', title: 'Statuses' }) do
%ul
%li= link_to 'Any Status', admin_runners_path(safe_params.slice(:search)), class: ('is-active' unless active_status)
%li.divider
- Ci::Runner::AVAILABLE_STATUSES.each do |status|
%li= link_to status.titleize, admin_runners_path(safe_params.slice(:search).merge(status: status)), class: ('is-active' if active_status == status)
......@@ -41,18 +41,50 @@
= render partial: 'ci/runner/how_to_setup_shared_runner',
locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token }
.append-bottom-20.clearfix
= form_tag admin_runners_path, id: 'runners-search', method: :get do
.float-left
.form-inline
.form-group
= search_field_tag :search, params[:search], class: 'form-control input-short', placeholder: 'Runner description or token', spellcheck: false
= submit_tag 'Search', class: 'btn'
.float-left.prepend-left-10
= render 'statuses'
.float-right.light
.row-content-block.second-block
= form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
.filtered-search-wrapper
.filtered-search-box
= dropdown_tag(custom_icon('icon_history'),
options: { wrapper_class: "filtered-search-history-dropdown-wrapper",
toggle_class: "filtered-search-history-dropdown-toggle-button",
dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content",
title: "Recent searches" }) do
.js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
.filtered-search-box-input-container.droplab-dropdown
.scroll-container
%ul.tokens-container.list-unstyled
%li.input-token
%input.form-control.filtered-search{ { id: 'filtered-search-runners', placeholder: 'Search or filter results...' } }
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { action: 'submit' } }
= button_tag class: %w[btn btn-link] do
= icon('search')
%span
Press Enter or click to search
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
= button_tag class: %w[btn btn-link] do
-# Encapsulate static class name `{{icon}}` inside #{} to bypass
-# haml lint's ClassAttributeWithStaticValue
%i.fa{ class: "#{'{{icon}}'}" }
%span.js-filter-hint
{{hint}}
%span.js-filter-tag.dropdown-light-content
{{tag}}
#js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_STATUSES.each do |status|
%li.filter-dropdown-item{ data: { value: status } }
= button_tag class: %w[btn btn-link] do
= status.titleize
= button_tag class: %w[clear-search hidden] do
= icon('times')
.clearfix
.float-right.light
.prepend-top-10
Runners currently online: #{@active_runners_cnt}
%br
......
require 'spec_helper'
describe "Admin Runners" do
describe "Admin Runners", :js do
include StubENV
include FilteredSearchHelpers
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
......@@ -30,26 +31,20 @@ describe "Admin Runners" do
end
it 'shows correct runner when description matches' do
within '#runners-search' do
fill_in 'search', with: 'runner-foo'
click_button 'Search'
end
input_filtered_search_keys('runner-foo')
expect(page).to have_content("runner-foo")
expect(page).not_to have_content("runner-bar")
end
it 'shows no runner when description does not match' do
within '#runners-search' do
fill_in 'search', with: 'runner-baz'
click_button 'Search'
end
input_filtered_search_keys('runner-baz')
expect(page).to have_text 'No runners found'
end
end
describe 'filter by status', :js do
describe 'filter by status' do
it 'shows correct runner when status matches' do
FactoryBot.create :ci_runner, description: 'runner-active', active: true
FactoryBot.create :ci_runner, description: 'runner-paused', active: false
......@@ -59,8 +54,7 @@ describe "Admin Runners" do
expect(page).to have_content 'runner-active'
expect(page).to have_content 'runner-paused'
click_button 'Status'
click_link 'Active'
input_filtered_search_keys('status:active')
expect(page).to have_content 'runner-active'
expect(page).not_to have_content 'runner-paused'
end
......@@ -71,8 +65,7 @@ describe "Admin Runners" do
visit admin_runners_path
click_button 'Status'
click_link 'Offline'
input_filtered_search_keys('status:offline')
expect(page).not_to have_content 'runner-active'
expect(page).not_to have_content 'runner-paused'
......@@ -81,48 +74,22 @@ describe "Admin Runners" do
end
end
describe 'filter by status and enter search term', :js do
before do
FactoryBot.create :ci_runner, description: 'runner-a-1', active: true
FactoryBot.create :ci_runner, description: 'runner-a-2', active: false
FactoryBot.create :ci_runner, description: 'runner-b-1', active: true
visit admin_runners_path
end
it 'shows correct runner when status is selected first and then search term is entered' do
click_button 'Status'
click_link 'Active'
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
it 'shows correct runner when status is selected and search term is entered' do
FactoryBot.create :ci_runner, description: 'runner-a-1', active: true
FactoryBot.create :ci_runner, description: 'runner-a-2', active: false
FactoryBot.create :ci_runner, description: 'runner-b-1', active: true
within '#runners-search' do
fill_in 'search', with: 'runner-a'
click_button 'Search'
end
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
end
it 'shows correct runner when search term is entered first and then status is selected' do
within '#runners-search' do
fill_in 'search', with: 'runner-a'
click_button 'Search'
end
visit admin_runners_path
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-a-2'
expect(page).not_to have_content 'runner-b-1'
input_filtered_search_keys('status:active')
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
click_button 'Status'
click_link 'Active'
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
end
input_filtered_search_keys('status:active runner-a')
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
end
end
......
......@@ -23,7 +23,7 @@ describe Admin::RunnersFinder do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:paused).and_call_original
described_class.new(params: { status: 'paused' }).execute
described_class.new(params: { status_status: 'paused' }).execute
end
end
......
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