Commit 86a3dee2 authored by Clement Ho's avatar Clement Ho

Prevent visual token dropdown from opening the wrong filter dropdown

parent bd1d7781
...@@ -80,11 +80,18 @@ ...@@ -80,11 +80,18 @@
} }
// Determines the full search query (visual tokens + input) // Determines the full search query (visual tokens + input)
static getSearchQuery() { static getSearchQuery(untilInput = false) {
const tokensContainer = document.querySelector('.tokens-container'); const tokens = [].slice.call(document.querySelectorAll('.tokens-container li'));
const values = []; const values = [];
[].forEach.call(tokensContainer.querySelectorAll('.js-visual-token'), (token) => { if (untilInput) {
const inputIndex = _.findIndex(tokens, t => t.classList.contains('input-token'));
// Add one to include input-token to the tokens array
tokens.splice(inputIndex + 1);
}
tokens.forEach((token) => {
if (token.classList.contains('js-visual-token')) {
const name = token.querySelector('.name'); const name = token.querySelector('.name');
const value = token.querySelector('.value'); const value = token.querySelector('.value');
const symbol = value && value.dataset.symbol ? value.dataset.symbol : ''; const symbol = value && value.dataset.symbol ? value.dataset.symbol : '';
...@@ -99,10 +106,21 @@ ...@@ -99,10 +106,21 @@
} else { } else {
values.push(name.innerText); values.push(name.innerText);
} }
}); } else if (token.classList.contains('input-token')) {
const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const input = document.querySelector('.filtered-search'); const input = document.querySelector('.filtered-search');
values.push(input && input.value); const inputValue = input && input.value;
if (isLastVisualTokenValid) {
values.push(inputValue);
} else {
const previous = values.pop();
values.push(`${previous}${inputValue}`);
}
}
});
return values.join(' '); return values.join(' ');
} }
......
...@@ -139,7 +139,7 @@ ...@@ -139,7 +139,7 @@
} }
setDropdown() { setDropdown() {
const query = gl.DropdownUtils.getSearchQuery(); const query = gl.DropdownUtils.getSearchQuery(true);
const { lastToken, searchToken } = this.tokenizer.processTokens(query); const { lastToken, searchToken } = this.tokenizer.processTokens(query);
if (this.currentDropdown) { if (this.currentDropdown) {
......
...@@ -363,12 +363,15 @@ ...@@ -363,12 +363,15 @@
tokenChange() { tokenChange() {
const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown]; const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown];
if (dropdown) {
const currentDropdownRef = dropdown.reference; const currentDropdownRef = dropdown.reference;
this.setDropdownWrapper(); this.setDropdownWrapper();
currentDropdownRef.dispatchInputEvent(); currentDropdownRef.dispatchInputEvent();
} }
} }
}
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchManager = FilteredSearchManager; gl.FilteredSearchManager = FilteredSearchManager;
......
...@@ -242,6 +242,23 @@ describe 'Visual tokens', js: true, feature: true do ...@@ -242,6 +242,23 @@ describe 'Visual tokens', js: true, feature: true do
end end
end end
describe 'editing a search term while editing another filter token' do
before do
input_filtered_search('author assignee:', submit: false)
first('.tokens-container .filtered-search-term').double_click
end
it 'opens hint dropdown' do
expect(page).to have_css('#js-dropdown-hint', visible: true)
end
it 'opens author dropdown' do
find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: 'author').click
expect(page).to have_css('#js-dropdown-author', visible: true)
end
end
describe 'add new token after editing existing token' do describe 'add new token after editing existing token' do
before do before do
input_filtered_search('author:@root assignee:none', submit: false) input_filtered_search('author:@root assignee:none', submit: false)
...@@ -319,4 +336,17 @@ describe 'Visual tokens', js: true, feature: true do ...@@ -319,4 +336,17 @@ describe 'Visual tokens', js: true, feature: true do
expect(token.find('.name').text).to eq('Author') expect(token.find('.name').text).to eq('Author')
end end
end end
describe 'search using incomplete visual tokens' do
before do
input_filtered_search('author:@root assignee:none', extra_space: false)
end
it 'tokenizes the search term to complete visual token' do
expect_tokens([
{ name: 'author', value: '@root' },
{ name: 'assignee', value: 'none' }
])
end
end
end end
...@@ -4,9 +4,14 @@ module FilteredSearchHelpers ...@@ -4,9 +4,14 @@ module FilteredSearchHelpers
end end
# Enables input to be set (similar to copy and paste) # Enables input to be set (similar to copy and paste)
def input_filtered_search(search_term, submit: true) def input_filtered_search(search_term, submit: true, extra_space: true)
search = search_term
if extra_space
# Add an extra space to engage visual tokens # Add an extra space to engage visual tokens
filtered_search.set("#{search_term} ") search = "#{search_term} "
end
filtered_search.set(search)
if submit if submit
filtered_search.send_keys(:enter) filtered_search.send_keys(:enter)
......
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