diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 index 42fe0cace10..1b58fc01608 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 @@ -1,29 +1,81 @@ +/* eslint-disable no-param-reassign */ ((global) => { - const TOKEN_TYPE_STRING = 'string'; - const TOKEN_TYPE_ARRAY = 'array'; - const validTokenKeys = [{ key: 'author', type: 'string', param: 'username', - },{ + }, { key: 'assignee', type: 'string', param: 'username', - },{ + }, { key: 'milestone', type: 'string', param: 'title', - },{ + }, { key: 'label', type: 'array', param: 'name[]', - },]; + }]; + + function toggleClearSearchButton(event) { + const clearSearch = document.querySelector('.clear-search'); + + if (event.target.value) { + clearSearch.classList.remove('hidden'); + } else { + clearSearch.classList.add('hidden'); + } + } + + function loadSearchParamsFromURL() { + // We can trust that each param has one & since values containing & will be encoded + // Remove the first character of search as it is always ? + const params = window.location.search.slice(1).split('&'); + let inputValue = ''; + + params.forEach((p) => { + const split = p.split('='); + const key = decodeURIComponent(split[0]); + const value = split[1]; + + // Sanitize value since URL converts spaces into + + // Replace before decode so that we know what was originally + versus the encoded + + const sanitizedValue = value ? decodeURIComponent(value.replace(/[+]/g, ' ')) : value; + const match = validTokenKeys.find(t => key === `${t.key}_${t.param}`); + + if (match) { + const sanitizedKey = key.slice(0, key.indexOf('_')); + const valueHasSpace = sanitizedValue.indexOf(' ') !== -1; + + const preferredQuotations = '"'; + let quotationsToUse = preferredQuotations; + + if (valueHasSpace) { + // Prefer ", but use ' if required + quotationsToUse = sanitizedValue.indexOf(preferredQuotations) === -1 ? preferredQuotations : '\''; + } + + inputValue += valueHasSpace ? `${sanitizedKey}:${quotationsToUse}${sanitizedValue}${quotationsToUse}` : `${sanitizedKey}:${sanitizedValue}`; + inputValue += ' '; + } else if (!match && key === 'search') { + inputValue += sanitizedValue; + inputValue += ' '; + } + }); + + // Trim the last space value + document.querySelector('.filtered-search').value = inputValue.trim(); + + if (inputValue.trim()) { + document.querySelector('.clear-search').classList.remove('hidden'); + } + } class FilteredSearchManager { constructor() { this.bindEvents(); - this.loadSearchParamsFromURL(); + loadSearchParamsFromURL(); this.clearTokens(); } @@ -32,7 +84,7 @@ const clearSearch = document.querySelector('.clear-search'); input.addEventListener('input', this.tokenize.bind(this)); - input.addEventListener('input', this.toggleClearSearchButton); + input.addEventListener('input', toggleClearSearchButton); input.addEventListener('keydown', this.checkForEnter.bind(this)); clearSearch.addEventListener('click', this.clearSearch.bind(this)); @@ -52,64 +104,6 @@ this.searchToken = ''; } - loadSearchParamsFromURL() { - // We can trust that each param has one & since values containing & will be encoded - // Remove the first character of search as it is always ? - const params = window.location.search.slice(1).split('&'); - let inputValue = ''; - - params.forEach((p) => { - const split = p.split('='); - const key = decodeURIComponent(split[0]); - const value = split[1]; - - // Sanitize value since URL converts spaces into + - // Replace before decode so that we know what was originally + versus the encoded + - const sanitizedValue = value ? decodeURIComponent(value.replace(/[+]/g, ' ')) : value; - - const match = validTokenKeys.find((t) => { - return key === `${t.key}_${t.param}`; - }); - - if (match) { - const sanitizedKey = key.slice(0, key.indexOf('_')); - const valueHasSpace = sanitizedValue.indexOf(' ') !== -1; - - const preferredQuotations = '"'; - let quotationsToUse = preferredQuotations; - - if (valueHasSpace) { - // Prefer ", but use ' if required - quotationsToUse = sanitizedValue.indexOf(preferredQuotations) === -1 ? preferredQuotations : '\''; - } - - inputValue += valueHasSpace ? `${sanitizedKey}:${quotationsToUse}${sanitizedValue}${quotationsToUse}` : `${sanitizedKey}:${sanitizedValue}`; - inputValue += ' '; - - } else if (!match && key === 'search') { - inputValue += sanitizedValue; - inputValue += ' '; - } - }); - - // Trim the last space value - document.querySelector('.filtered-search').value = inputValue.trim(); - - if (inputValue.trim()) { - document.querySelector('.clear-search').classList.remove('hidden'); - } - } - - toggleClearSearchButton(event) { - const clearSearch = document.querySelector('.clear-search'); - - if (event.target.value) { - clearSearch.classList.remove('hidden'); - } else { - clearSearch.classList.add('hidden'); - } - } - tokenize(event) { // Re-calculate tokens this.clearTokens(); @@ -121,8 +115,9 @@ let incompleteToken = false; const addSearchTerm = function addSearchTerm(term) { - searchTerms += term + ' '; - } + // Add space for next term + searchTerms += `${term} `; + }; inputs.forEach((i) => { if (incompleteToken) { @@ -147,10 +142,7 @@ if (colonIndex !== -1) { const tokenKey = i.slice(0, colonIndex).toLowerCase(); const tokenValue = i.slice(colonIndex + 1); - - const match = validTokenKeys.find((v) => { - return v.key === tokenKey; - }); + const match = validTokenKeys.find(v => v.key === tokenKey); if (tokenValue.indexOf('"') !== -1) { lastQuotation = '"'; @@ -178,11 +170,9 @@ } printTokens() { - console.log('tokens:') - this.tokens.forEach((token) => { - console.log(token); - }) - console.log('search: ' + this.searchToken); + console.log('tokens:'); + this.tokens.forEach(token => console.log(token)); + console.log(`search: ${this.searchToken}`); } checkForEnter(event) { @@ -210,18 +200,14 @@ currentState = separatorIndex === -1 ? remaining : remaining.slice(0, separatorIndex); } - path += `&state=${currentState}` - + path += `&state=${currentState}`; this.tokens.forEach((token) => { - const param = validTokenKeys.find((t) => { - return t.key === token.key; - }).param; - + const param = validTokenKeys.find(t => t.key === token.key).param; path += `&${token.key}_${param}=${encodeURIComponent(token.value)}`; }); if (this.searchToken) { - path += '&search=' + encodeURIComponent(this.searchToken); + path += `&search=${encodeURIComponent(this.searchToken)}`; } window.location = path;