Commit cae08033 authored by Annabel Dunstone Gray's avatar Annabel Dunstone Gray

Merge branch '31902-namespace-recent-searches-to-project' into 'master'

Scope recent searches to project

Closes #31902

See merge request !11142
parents fd210c20 cae2274f
...@@ -16,10 +16,14 @@ class FilteredSearchManager { ...@@ -16,10 +16,14 @@ class FilteredSearchManager {
this.recentSearchesStore = new RecentSearchesStore({ this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(), isLocalStorageAvailable: RecentSearchesService.isAvailable(),
}); });
let recentSearchesKey = 'issue-recent-searches'; const searchHistoryDropdownElement = document.querySelector('.js-filtered-search-history-dropdown');
const projectPath = searchHistoryDropdownElement ?
searchHistoryDropdownElement.dataset.projectFullPath : 'project';
let recentSearchesPagePrefix = 'issue-recent-searches';
if (page === 'merge_requests') { if (page === 'merge_requests') {
recentSearchesKey = 'merge-request-recent-searches'; recentSearchesPagePrefix = 'merge-request-recent-searches';
} }
const recentSearchesKey = `${projectPath}-${recentSearchesPagePrefix}`;
this.recentSearchesService = new RecentSearchesService(recentSearchesKey); this.recentSearchesService = new RecentSearchesService(recentSearchesKey);
// Fetch recent searches from localStorage // Fetch recent searches from localStorage
...@@ -47,7 +51,7 @@ class FilteredSearchManager { ...@@ -47,7 +51,7 @@ class FilteredSearchManager {
this.recentSearchesRoot = new RecentSearchesRoot( this.recentSearchesRoot = new RecentSearchesRoot(
this.recentSearchesStore, this.recentSearchesStore,
this.recentSearchesService, this.recentSearchesService,
document.querySelector('.js-filtered-search-history-dropdown'), searchHistoryDropdownElement,
); );
this.recentSearchesRoot.init(); this.recentSearchesRoot.init();
......
...@@ -3,6 +3,7 @@ import _ from 'underscore'; ...@@ -3,6 +3,7 @@ import _ from 'underscore';
class RecentSearchesStore { class RecentSearchesStore {
constructor(initialState = {}) { constructor(initialState = {}) {
this.state = Object.assign({ this.state = Object.assign({
isLocalStorageAvailable: true,
recentSearches: [], recentSearches: [],
}, initialState); }, initialState);
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
dropdown_class: "filtered-search-history-dropdown", dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content", content_class: "filtered-search-history-dropdown-content",
title: "Recent searches" }) do title: "Recent searches" }) do
.js-filtered-search-history-dropdown .js-filtered-search-history-dropdown{ data: { project_full_path: @project.full_path } }
.filtered-search-box-input-container .filtered-search-box-input-container
.scroll-container .scroll-container
%ul.tokens-container.list-unstyled %ul.tokens-container.list-unstyled
......
---
title: Scope issue/merge request recent searches to project
merge_request:
author:
...@@ -3,17 +3,17 @@ require 'spec_helper' ...@@ -3,17 +3,17 @@ require 'spec_helper'
describe 'Recent searches', js: true, feature: true do describe 'Recent searches', js: true, feature: true do
include FilteredSearchHelpers include FilteredSearchHelpers
let!(:group) { create(:group) } let(:project_1) { create(:empty_project, :public) }
let!(:project) { create(:project, group: group) } let(:project_2) { create(:empty_project, :public) }
let!(:user) { create(:user) } let(:project_1_local_storage_key) { "#{project_1.full_path}-issue-recent-searches" }
before do before do
Capybara.ignore_hidden_elements = false Capybara.ignore_hidden_elements = false
project.add_master(user) create(:issue, project: project_1)
group.add_developer(user) create(:issue, project: project_2)
create(:issue, project: project)
login_as(user)
# Visit any fast-loading page so we can clear local storage without a DOM exception
visit '/404'
remove_recent_searches remove_recent_searches
end end
...@@ -22,7 +22,7 @@ describe 'Recent searches', js: true, feature: true do ...@@ -22,7 +22,7 @@ describe 'Recent searches', js: true, feature: true do
end end
it 'searching adds to recent searches' do it 'searching adds to recent searches' do
visit namespace_project_issues_path(project.namespace, project) visit namespace_project_issues_path(project_1.namespace, project_1)
input_filtered_search('foo', submit: true) input_filtered_search('foo', submit: true)
input_filtered_search('bar', submit: true) input_filtered_search('bar', submit: true)
...@@ -35,8 +35,8 @@ describe 'Recent searches', js: true, feature: true do ...@@ -35,8 +35,8 @@ describe 'Recent searches', js: true, feature: true do
end end
it 'visiting URL with search params adds to recent searches' do it 'visiting URL with search params adds to recent searches' do
visit namespace_project_issues_path(project.namespace, project, label_name: 'foo', search: 'bar') visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'foo', search: 'bar')
visit namespace_project_issues_path(project.namespace, project, label_name: 'qux', search: 'garply') visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'qux', search: 'garply')
items = all('.filtered-search-history-dropdown-item', visible: false) items = all('.filtered-search-history-dropdown-item', visible: false)
...@@ -46,9 +46,9 @@ describe 'Recent searches', js: true, feature: true do ...@@ -46,9 +46,9 @@ describe 'Recent searches', js: true, feature: true do
end end
it 'saved recent searches are restored last on the list' do it 'saved recent searches are restored last on the list' do
set_recent_searches('["saved1", "saved2"]') set_recent_searches(project_1_local_storage_key, '["saved1", "saved2"]')
visit namespace_project_issues_path(project.namespace, project, search: 'foo') visit namespace_project_issues_path(project_1.namespace, project_1, search: 'foo')
items = all('.filtered-search-history-dropdown-item', visible: false) items = all('.filtered-search-history-dropdown-item', visible: false)
...@@ -58,9 +58,27 @@ describe 'Recent searches', js: true, feature: true do ...@@ -58,9 +58,27 @@ describe 'Recent searches', js: true, feature: true do
expect(items[2].text).to eq('saved2') expect(items[2].text).to eq('saved2')
end end
it 'searches are scoped to projects' do
visit namespace_project_issues_path(project_1.namespace, project_1)
input_filtered_search('foo', submit: true)
input_filtered_search('bar', submit: true)
visit namespace_project_issues_path(project_2.namespace, project_2)
input_filtered_search('more', submit: true)
input_filtered_search('things', submit: true)
items = all('.filtered-search-history-dropdown-item', visible: false)
expect(items.count).to eq(2)
expect(items[0].text).to eq('things')
expect(items[1].text).to eq('more')
end
it 'clicking item fills search input' do it 'clicking item fills search input' do
set_recent_searches('["foo", "bar"]') set_recent_searches(project_1_local_storage_key, '["foo", "bar"]')
visit namespace_project_issues_path(project.namespace, project) visit namespace_project_issues_path(project_1.namespace, project_1)
all('.filtered-search-history-dropdown-item', visible: false)[0].trigger('click') all('.filtered-search-history-dropdown-item', visible: false)[0].trigger('click')
wait_for_filtered_search('foo') wait_for_filtered_search('foo')
...@@ -69,8 +87,8 @@ describe 'Recent searches', js: true, feature: true do ...@@ -69,8 +87,8 @@ describe 'Recent searches', js: true, feature: true do
end end
it 'clear recent searches button, clears recent searches' do it 'clear recent searches button, clears recent searches' do
set_recent_searches('["foo"]') set_recent_searches(project_1_local_storage_key, '["foo"]')
visit namespace_project_issues_path(project.namespace, project) visit namespace_project_issues_path(project_1.namespace, project_1)
items_before = all('.filtered-search-history-dropdown-item', visible: false) items_before = all('.filtered-search-history-dropdown-item', visible: false)
...@@ -83,8 +101,8 @@ describe 'Recent searches', js: true, feature: true do ...@@ -83,8 +101,8 @@ describe 'Recent searches', js: true, feature: true do
end end
it 'shows flash error when failed to parse saved history' do it 'shows flash error when failed to parse saved history' do
set_recent_searches('fail') set_recent_searches(project_1_local_storage_key, 'fail')
visit namespace_project_issues_path(project.namespace, project) visit namespace_project_issues_path(project_1.namespace, project_1)
expect(find('.flash-alert')).to have_text('An error occured while parsing recent searches') expect(find('.flash-alert')).to have_text('An error occured while parsing recent searches')
end end
......
...@@ -73,11 +73,11 @@ module FilteredSearchHelpers ...@@ -73,11 +73,11 @@ module FilteredSearchHelpers
end end
def remove_recent_searches def remove_recent_searches
execute_script('window.localStorage.removeItem(\'issue-recent-searches\');') execute_script('window.localStorage.clear();')
end end
def set_recent_searches(input) def set_recent_searches(key, input)
execute_script("window.localStorage.setItem('issue-recent-searches', '#{input}');") execute_script("window.localStorage.setItem('#{key}', '#{input}');")
end end
def wait_for_filtered_search(text) def wait_for_filtered_search(text)
......
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