diff options
Diffstat (limited to 'app/assets/javascripts/boards')
8 files changed, 103 insertions, 35 deletions
diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index 55d13be6e5f..3874c2819a5 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -2,6 +2,9 @@ /* global Vue */ /* global BoardService */ +import FilteredSearchBoards from './filtered_search_boards'; +import eventHub from './eventhub'; + window.Vue = require('vue'); window.Vue.use(require('vue-resource')); require('./models/issue'); @@ -59,6 +62,14 @@ $(() => { }, created () { gl.boardService = new BoardService(this.endpoint, this.bulkUpdatePath, this.boardId); + + this.filterManager = new FilteredSearchBoards(Store.filter, true); + + // Listen for updateTokens event + eventHub.$on('updateTokens', this.updateTokens); + }, + beforeDestroy() { + eventHub.$off('updateTokens', this.updateTokens); }, mounted () { Store.disabled = this.disabled; @@ -77,11 +88,16 @@ $(() => { Store.addBlankState(); this.loading = false; }); - } + }, + methods: { + updateTokens() { + this.filterManager.updateTokens(); + } + }, }); gl.IssueBoardsSearch = new Vue({ - el: document.getElementById('js-boards-search'), + el: document.getElementById('js-add-list'), data: { filters: Store.state.filters }, diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js index 18324de18b3..30d3be453be 100644 --- a/app/assets/javascripts/boards/components/board.js +++ b/app/assets/javascripts/boards/components/board.js @@ -28,16 +28,16 @@ require('./board_list'); data () { return { detailIssue: Store.detail, - filters: Store.state.filters, + filter: Store.filter, }; }, watch: { - filters: { - handler () { + filter: { + handler() { this.list.page = 1; this.list.getIssues(true); }, - deep: true + deep: true, }, detailIssue: { handler () { diff --git a/app/assets/javascripts/boards/components/board_card.js b/app/assets/javascripts/boards/components/board_card.js index 795b3cf2ec0..4b72090df31 100644 --- a/app/assets/javascripts/boards/components/board_card.js +++ b/app/assets/javascripts/boards/components/board_card.js @@ -17,7 +17,8 @@ export default { :list="list" :issue="issue" :issue-link-base="issueLinkBase" - :root-path="rootPath" /> + :root-path="rootPath" + :update-filters="true" /> </li> `, components: { diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js index 22a8b971ff8..69e30cec4c5 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js +++ b/app/assets/javascripts/boards/components/issue_card_inner.js @@ -1,4 +1,6 @@ /* global Vue */ +import eventHub from '../eventhub'; + (() => { const Store = gl.issueBoards.BoardsStore; @@ -23,6 +25,11 @@ type: String, required: true, }, + updateFilters: { + type: Boolean, + required: false, + default: false, + }, }, methods: { showLabel(label) { @@ -31,29 +38,25 @@ return !this.list.label || label.id !== this.list.label.id; }, filterByLabel(label, e) { - let labelToggleText = label.title; - const labelIndex = Store.state.filters.label_name.indexOf(label.title); + if (!this.updateFilters) return; + + const filterPath = gl.issueBoards.BoardsStore.filter.path.split('&'); + const labelTitle = encodeURIComponent(label.title); + const param = `label_name[]=${labelTitle}`; + const labelIndex = filterPath.indexOf(param); $(e.currentTarget).tooltip('hide'); if (labelIndex === -1) { - Store.state.filters.label_name.push(label.title); - $('.labels-filter').prepend(`<input type="hidden" name="label_name[]" value="${label.title}" />`); + filterPath.push(param); } else { - Store.state.filters.label_name.splice(labelIndex, 1); - labelToggleText = Store.state.filters.label_name[0]; - $(`.labels-filter input[name="label_name[]"][value="${label.title}"]`).remove(); + filterPath.splice(labelIndex, 1); } - const selectedLabels = Store.state.filters.label_name; - if (selectedLabels.length === 0) { - labelToggleText = 'Label'; - } else if (selectedLabels.length > 1) { - labelToggleText = `${selectedLabels[0]} + ${selectedLabels.length - 1} more`; - } - - $('.labels-filter .dropdown-toggle-text').text(labelToggleText); + gl.issueBoards.BoardsStore.filter.path = filterPath.join('&'); Store.updateFiltersUrl(); + + eventHub.$emit('updateTokens'); }, labelStyle(label) { return { diff --git a/app/assets/javascripts/boards/eventhub.js b/app/assets/javascripts/boards/eventhub.js new file mode 100644 index 00000000000..0948c2e5352 --- /dev/null +++ b/app/assets/javascripts/boards/eventhub.js @@ -0,0 +1,3 @@ +import Vue from 'vue'; + +export default new Vue(); diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js new file mode 100644 index 00000000000..47448b02bdd --- /dev/null +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -0,0 +1,34 @@ +export default class FilteredSearchBoards extends gl.FilteredSearchManager { + constructor(store, updateUrl = false) { + super('boards'); + + this.store = store; + this.updateUrl = updateUrl; + + // Issue boards is slightly different, we handle all the requests async + // instead or reloading the page, we just re-fire the list ajax requests + this.isHandledAsync = true; + } + + updateObject(path) { + this.store.path = path.substr(1); + + if (this.updateUrl) { + gl.issueBoards.BoardsStore.updateFiltersUrl(); + } + } + + updateTokens() { + const tokens = document.querySelectorAll('.js-visual-token'); + + // Remove all the tokens as they will be replaced by the search manager + [].forEach.call(tokens, (el) => { + el.parentNode.removeChild(el); + }); + + this.loadSearchParamsFromURL(); + + // Get the placeholder back if search is empty + this.filteredSearchInput.dispatchEvent(new Event('input')); + } +} diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index f237567208c..3251ca76b26 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -10,7 +10,6 @@ class List { this.title = obj.title; this.type = obj.list_type; this.preset = ['done', 'blank'].indexOf(this.type) > -1; - this.filters = gl.issueBoards.BoardsStore.state.filters; this.page = 1; this.loading = true; this.loadingMore = false; @@ -65,12 +64,27 @@ class List { } getIssues (emptyIssues = true) { - const filters = this.filters; - const data = { page: this.page }; + const data = gl.issueBoards.BoardsStore.filter.path.split('&').reduce((data, filterParam) => { + if (filterParam === '') return data; + 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; + } - Object.keys(filters).forEach((key) => { data[key] = filters[key]; }); + return data; + }, { page: this.page }); - if (this.label) { + 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/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index 3866c6bbfc6..28ecb322df7 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -8,6 +8,9 @@ gl.issueBoards.BoardsStore = { disabled: false, + filter: { + path: '', + }, state: {}, detail: { issue: {} @@ -18,13 +21,7 @@ }, create () { this.state.lists = []; - this.state.filters = { - author_id: gl.utils.getParameterValues('author_id')[0], - assignee_id: gl.utils.getParameterValues('assignee_id')[0], - milestone_title: gl.utils.getParameterValues('milestone_title')[0], - label_name: gl.utils.getParameterValues('label_name[]'), - search: '' - }; + this.filter.path = gl.utils.getUrlParamsArray().join('&'); }, addList (listObj) { const list = new List(listObj); @@ -123,7 +120,7 @@ })[0]; }, updateFiltersUrl () { - history.pushState(null, null, `?${$.param(this.state.filters)}`); + history.pushState(null, null, `?${this.filter.path}`); } }; })(); |