diff options
-rw-r--r-- | app/assets/javascripts/boards/components/modal/index.vue | 14 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/list.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/boards/utils/query_data.js | 21 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/common_utils.js | 47 | ||||
-rw-r--r-- | spec/javascripts/boards/mock_data.js | 2 | ||||
-rw-r--r-- | spec/javascripts/boards/utils/query_data_spec.js | 27 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/common_utils_spec.js | 40 |
7 files changed, 80 insertions, 78 deletions
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue index 33e72a6782e..7b33a7573e7 100644 --- a/app/assets/javascripts/boards/components/modal/index.vue +++ b/app/assets/javascripts/boards/components/modal/index.vue @@ -1,6 +1,6 @@ <script> /* global ListIssue */ - import queryData from '~/boards/utils/query_data'; + import { urlParamsToObject } from '~/lib/utils/common_utils'; import loadingIcon from '~/vue_shared/components/loading_icon.vue'; import ModalHeader from './header.vue'; import ModalList from './list.vue'; @@ -109,13 +109,11 @@ loadIssues(clearIssues = false) { if (!this.showAddIssuesModal) return false; - return gl.boardService - .getBacklog( - queryData(this.filter.path, { - page: this.page, - per: this.perPage, - }), - ) + return gl.boardService.getBacklog({ + ...urlParamsToObject(this.filter.path), + page: this.page, + per: this.perPage, + }) .then(res => res.data) .then(data => { if (clearIssues) { diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index 050cbd8db48..42f25bda3af 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -3,7 +3,7 @@ import ListLabel from '~/vue_shared/models/label'; import ListAssignee from '~/vue_shared/models/assignee'; -import queryData from '../utils/query_data'; +import { urlParamsToObject } from '~/lib/utils/common_utils'; const PER_PAGE = 20; @@ -114,7 +114,10 @@ class List { } getIssues(emptyIssues = true) { - const data = queryData(gl.issueBoards.BoardsStore.filter.path, { page: this.page }); + const data = { + ...urlParamsToObject(gl.issueBoards.BoardsStore.filter.path), + page: this.page, + }; if (this.label && data.label_name) { data.label_name = data.label_name.filter(label => label !== this.label.title); diff --git a/app/assets/javascripts/boards/utils/query_data.js b/app/assets/javascripts/boards/utils/query_data.js deleted file mode 100644 index 65315979df7..00000000000 --- a/app/assets/javascripts/boards/utils/query_data.js +++ /dev/null @@ -1,21 +0,0 @@ -export default (path, extraData) => path.split('&').reduce((dataParam, filterParam) => { - if (filterParam === '') return dataParam; - - const data = dataParam; - const paramSplit = filterParam.split('='); - const paramKeyNormalized = paramSplit[0].replace('[]', ''); - const isArray = paramSplit[0].indexOf('[]'); - const value = decodeURIComponent(paramSplit[1].replace(/\+/g, ' ')); - - if (isArray !== -1) { - if (!data[paramKeyNormalized]) { - data[paramKeyNormalized] = []; - } - - data[paramKeyNormalized].push(value); - } else { - data[paramKeyNormalized] = value; - } - - return data; -}, extraData); diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 2f3dd6f6cbc..9124d189a44 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -131,16 +131,43 @@ export const parseUrlPathname = url => { return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : `/${parsedUrl.pathname}`; }; -// We can trust that each param has one & since values containing & will be encoded -// Remove the first character of search as it is always ? -export const getUrlParamsArray = () => - window.location.search - .slice(1) - .split('&') - .map(param => { - const split = param.split('='); - return [decodeURI(split[0]), split[1]].join('='); - }); +const splitPath = (path = '') => path + .replace(/^\?/, '') + .split('&'); + +export const urlParamsToArray = (path = '') => splitPath(path) + .filter(param => param.length > 0) + .map(param => { + const split = param.split('='); + return [decodeURI(split[0]), split[1]].join('='); + }); + +export const getUrlParamsArray = () => urlParamsToArray(window.location.search); + +export const urlParamsToObject = (path = '') => splitPath(path) + .reduce((dataParam, filterParam) => { + if (filterParam === '') { + return dataParam; + } + + const data = dataParam; + let [key, value] = filterParam.split('='); + const isArray = key.includes('[]'); + key = key.replace('[]', ''); + value = decodeURIComponent(value.replace(/\+/g, ' ')); + + if (isArray) { + if (!data[key]) { + data[key] = []; + } + + data[key].push(value); + } else { + data[key] = value; + } + + return data; + }, {}); export const isMetaKey = e => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey; diff --git a/spec/javascripts/boards/mock_data.js b/spec/javascripts/boards/mock_data.js index 81f1a97112f..f380ef450db 100644 --- a/spec/javascripts/boards/mock_data.js +++ b/spec/javascripts/boards/mock_data.js @@ -27,7 +27,7 @@ export const listObjDuplicate = { export const BoardsMockData = { GET: { - '/test/-/boards/1/lists/300/issues?id=300&page=1&=': { + '/test/-/boards/1/lists/300/issues?id=300&page=1': { issues: [ { title: 'Testing', diff --git a/spec/javascripts/boards/utils/query_data_spec.js b/spec/javascripts/boards/utils/query_data_spec.js deleted file mode 100644 index 922215ffc1d..00000000000 --- a/spec/javascripts/boards/utils/query_data_spec.js +++ /dev/null @@ -1,27 +0,0 @@ -import queryData from '~/boards/utils/query_data'; - -describe('queryData', () => { - it('parses path for label with trailing +', () => { - expect( - queryData('label_name[]=label%2B', {}), - ).toEqual({ - label_name: ['label+'], - }); - }); - - it('parses path for milestone with trailing +', () => { - expect( - queryData('milestone_title=A%2B', {}), - ).toEqual({ - milestone_title: 'A+', - }); - }); - - it('parses path for search terms with spaces', () => { - expect( - queryData('search=two+words', {}), - ).toEqual({ - search: 'two words', - }); - }); -}); diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 71b26a315af..5a3fc84aae0 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -29,24 +29,46 @@ describe('common_utils', () => { }); }); - describe('getUrlParamsArray', () => { - it('should return params array', () => { - expect(commonUtils.getUrlParamsArray() instanceof Array).toBe(true); + describe('urlParamsToArray', () => { + it('returns empty array for empty querystring', () => { + expect(commonUtils.urlParamsToArray('')).toEqual([]); + }); + + it('should decode params', () => { + expect( + commonUtils.urlParamsToArray('?label_name%5B%5D=test')[0], + ).toBe('label_name[]=test'); }); it('should remove the question mark from the search params', () => { - const paramsArray = commonUtils.getUrlParamsArray(); + const paramsArray = commonUtils.urlParamsToArray('?test=thing'); expect(paramsArray[0][0] !== '?').toBe(true); }); + }); - it('should decode params', () => { - window.history.pushState('', '', '?label_name%5B%5D=test'); + describe('urlParamsToObject', () => { + it('parses path for label with trailing +', () => { + expect( + commonUtils.urlParamsToObject('label_name[]=label%2B', {}), + ).toEqual({ + label_name: ['label+'], + }); + }); + it('parses path for milestone with trailing +', () => { expect( - commonUtils.getUrlParamsArray()[0], - ).toBe('label_name[]=test'); + commonUtils.urlParamsToObject('milestone_title=A%2B', {}), + ).toEqual({ + milestone_title: 'A+', + }); + }); - window.history.pushState('', '', '?'); + it('parses path for search terms with spaces', () => { + expect( + commonUtils.urlParamsToObject('search=two+words', {}), + ).toEqual({ + search: 'two words', + }); }); }); |