Commit c349bb15 authored by Clement Ho's avatar Clement Ho

Refactor addWordToInput

parent 8f77b317
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
(() => { (() => {
class DropdownHint extends gl.FilteredSearchDropdown { class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) { constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input); super(droplab, dropdown, input, filter);
this.config = { this.config = {
droplabFilter: { droplabFilter: {
template: 'hint', template: 'hint',
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
const tag = selected.querySelector('.js-filter-tag').innerText.trim(); const tag = selected.querySelector('.js-filter-tag').innerText.trim();
if (tag.length) { if (tag.length) {
gl.FilteredSearchDropdownManager.addWordToInput(token); gl.FilteredSearchDropdownManager.addWordToInput(token.replace(':', ''));
} }
this.dismissDropdown(); this.dismissDropdown();
this.dispatchInputEvent(); this.dispatchInputEvent();
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
(() => { (() => {
class DropdownNonUser extends gl.FilteredSearchDropdown { class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, endpoint, symbol) { constructor(droplab, dropdown, input, filter, endpoint, symbol) {
super(droplab, dropdown, input); super(droplab, dropdown, input, filter);
this.symbol = symbol; this.symbol = symbol;
this.config = { this.config = {
droplabAjax: { droplabAjax: {
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
(() => { (() => {
class DropdownUser extends gl.FilteredSearchDropdown { class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) { constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input); super(droplab, dropdown, input, filter);
this.config = { this.config = {
droplabAjaxFilter: { droplabAjaxFilter: {
endpoint: '/autocomplete/users.json', endpoint: '/autocomplete/users.json',
......
...@@ -58,11 +58,11 @@ ...@@ -58,11 +58,11 @@
return updatedItem; return updatedItem;
} }
static setDataValueIfSelected(selected) { static setDataValueIfSelected(filter, selected) {
const dataValue = selected.getAttribute('data-value'); const dataValue = selected.getAttribute('data-value');
if (dataValue) { if (dataValue) {
gl.FilteredSearchDropdownManager.addWordToInput(dataValue); gl.FilteredSearchDropdownManager.addWordToInput(filter, dataValue);
} }
// Return boolean based on whether it was set // Return boolean based on whether it was set
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger'; const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown { class FilteredSearchDropdown {
constructor(droplab, dropdown, input) { constructor(droplab, dropdown, input, filter) {
this.droplab = droplab; this.droplab = droplab;
this.hookId = input.getAttribute('data-id'); this.hookId = input.getAttribute('data-id');
this.input = input; this.input = input;
this.filter = filter;
this.dropdown = dropdown; this.dropdown = dropdown;
this.loadingTemplate = `<div class="filter-dropdown-loading"> this.loadingTemplate = `<div class="filter-dropdown-loading">
<i class="fa fa-spinner fa-spin"></i> <i class="fa fa-spinner fa-spin"></i>
...@@ -30,11 +31,11 @@ ...@@ -30,11 +31,11 @@
const { selected } = e.detail; const { selected } = e.detail;
if (selected.tagName === 'LI' && selected.innerHTML) { if (selected.tagName === 'LI' && selected.innerHTML) {
const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(selected); const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(this.filter, selected);
if (!dataValueSet) { if (!dataValueSet) {
const value = getValueFunction(selected); const value = getValueFunction(selected);
gl.FilteredSearchDropdownManager.addWordToInput(value); gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value);
} }
this.dismissDropdown(); this.dismissDropdown();
......
...@@ -55,31 +55,30 @@ ...@@ -55,31 +55,30 @@
}; };
} }
static addWordToInput(word, addSpace = false) { static addWordToInput(tokenName, tokenValue = '') {
const input = document.querySelector('.filtered-search'); const input = document.querySelector('.filtered-search');
input.value = input.value.trim(); const word = `${tokenName}:${tokenValue}`;
const value = input.value; const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(input.value);
const hasExistingValue = value.length !== 0;
const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(value);
const lastSearchToken = searchToken.split(' ').last(); const lastSearchToken = searchToken.split(' ').last();
const lastInputCharacter = input.value[input.value.length - 1];
const lastInputTrimmedCharacter = input.value.trim()[input.value.trim().length - 1];
// Find out what part of the token value the user has typed // Remove the typed tokenName
// and remove it from input before appending the selected token value if (word.indexOf(lastSearchToken) === 0 && searchToken !== '') {
if (lastToken !== searchToken) { // Remove spaces after the colon
const lastTokenString = `${lastToken.symbol}${lastToken.value}`; if (lastInputCharacter === ' ' && lastInputTrimmedCharacter === ':') {
input.value = input.value.trim();
// Spaces inside the token means that the token value will be escaped by quotes }
const hasQuotes = lastTokenString.indexOf(' ') !== -1;
// Add 2 length to account for the length of the front and back quotes input.value = input.value.slice(0, -1 * lastSearchToken.length);
const lengthToRemove = hasQuotes ? lastTokenString.length + 2 : lastTokenString.length; } else if (lastInputCharacter !== ' ') {
input.value = value.slice(0, -1 * (lengthToRemove)); // Remove the existing tokenValue
} else if (searchToken !== '' && word.indexOf(lastSearchToken) !== -1) { const lastTokenString = `${lastToken.key}:${lastToken.symbol}${lastToken.value}`;
input.value = value.slice(0, -1 * lastSearchToken.length); input.value = input.value.slice(0, -1 * lastTokenString.length);
} }
input.value += hasExistingValue && addSpace ? ` ${word}` : word; input.value += word;
} }
updateCurrentDropdownOffset() { updateCurrentDropdownOffset() {
...@@ -106,7 +105,7 @@ ...@@ -106,7 +105,7 @@
if (!mappingKey.reference) { if (!mappingKey.reference) {
const dl = this.droplab; const dl = this.droplab;
const defaultArguments = [null, dl, element, this.filteredSearchInput]; const defaultArguments = [null, dl, element, this.filteredSearchInput, key];
const glArguments = defaultArguments.concat(mappingKey.extraArguments || []); const glArguments = defaultArguments.concat(mappingKey.extraArguments || []);
// Passing glArguments to `new gl[glClass](<arguments>)` // Passing glArguments to `new gl[glClass](<arguments>)`
......
//= require extensions/array
//= require filtered_search/filtered_search_tokenizer //= require filtered_search/filtered_search_tokenizer
//= require filtered_search/filtered_search_dropdown_manager //= require filtered_search/filtered_search_dropdown_manager
...@@ -8,6 +9,10 @@ ...@@ -8,6 +9,10 @@
return document.querySelector('.filtered-search').value; return document.querySelector('.filtered-search').value;
} }
function setInputValue(value) {
document.querySelector('.filtered-search').value = value;
}
beforeEach(() => { beforeEach(() => {
const input = document.createElement('input'); const input = document.createElement('input');
input.classList.add('filtered-search'); input.classList.add('filtered-search');
...@@ -19,47 +24,33 @@ ...@@ -19,47 +24,33 @@
}); });
describe('input has no existing value', () => { describe('input has no existing value', () => {
it('should add word', () => { it('should add just tokenName', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord'); gl.FilteredSearchDropdownManager.addWordToInput('milestone');
expect(getInputValue()).toBe('firstWord'); expect(getInputValue()).toBe('milestone:');
}); });
it('should not add space before first word', () => { it('should add tokenName and tokenValue', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord', true); gl.FilteredSearchDropdownManager.addWordToInput('label', 'none');
expect(getInputValue()).toBe('firstWord'); expect(getInputValue()).toBe('label:none');
}); });
it('should not add space before second word by default', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord');
expect(getInputValue()).toBe('firstWord');
gl.FilteredSearchDropdownManager.addWordToInput('secondWord');
expect(getInputValue()).toBe('firstWordsecondWord');
}); });
it('should add space before new word when addSpace is passed', () => { describe('input has existing value', () => {
expect(getInputValue()).toBe(''); it('should be able to just add tokenName', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord'); setInputValue('a');
expect(getInputValue()).toBe('firstWord'); gl.FilteredSearchDropdownManager.addWordToInput('author');
gl.FilteredSearchDropdownManager.addWordToInput('secondWord', true); expect(getInputValue()).toBe('author:');
expect(getInputValue()).toBe('firstWord secondWord');
}); });
});
describe('input has exsting value', () => {
it('should only add the remaining characters of the word', () => {
const lastToken = {
key: 'author',
value: 'roo',
};
document.querySelector('.filtered-search').value = `${lastToken.key}:${lastToken.value}`; it('should replace tokenValue', () => {
gl.FilteredSearchDropdownManager.addWordToInput('root'); setInputValue('author:roo');
expect(getInputValue()).toBe('author:root'); gl.FilteredSearchDropdownManager.addWordToInput('author', '@root');
expect(getInputValue()).toBe('author:@root');
}); });
it('should only add the remaining characters of the word (contains space)', () => { it('should add tokenValues containing spaces', () => {
document.querySelector('.filtered-search').value = 'label:~"test'; setInputValue('label:~"test');
gl.FilteredSearchDropdownManager.addWordToInput('~\'"test me"\''); gl.FilteredSearchDropdownManager.addWordToInput('label', '~\'"test me"\'');
expect(getInputValue()).toBe('label:~\'"test me"\''); expect(getInputValue()).toBe('label:~\'"test me"\'');
}); });
}); });
......
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