diff options
Diffstat (limited to 'app/assets/javascripts/boards/components/board_filtered_search.vue')
-rw-r--r-- | app/assets/javascripts/boards/components/board_filtered_search.vue | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue new file mode 100644 index 00000000000..e564af0c353 --- /dev/null +++ b/app/assets/javascripts/boards/components/board_filtered_search.vue @@ -0,0 +1,154 @@ +<script> +import { pickBy } from 'lodash'; +import { mapActions } from 'vuex'; +import { updateHistory, setUrlParams } from '~/lib/utils/url_utility'; +import { __ } from '~/locale'; +import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; + +export default { + i18n: { + search: __('Search'), + label: __('Label'), + author: __('Author'), + }, + components: { FilteredSearch }, + inject: ['initialFilterParams'], + props: { + tokens: { + type: Array, + required: true, + }, + }, + data() { + return { + filterParams: this.initialFilterParams, + }; + }, + computed: { + urlParams() { + const { authorUsername, labelName, search } = this.filterParams; + let notParams = {}; + + if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) { + notParams = pickBy( + { + 'not[label_name][]': this.filterParams.not.labelName, + 'not[author_username]': this.filterParams.not.authorUsername, + }, + undefined, + ); + } + + return { + ...notParams, + author_username: authorUsername, + 'label_name[]': labelName, + search, + }; + }, + }, + methods: { + ...mapActions(['performSearch']), + handleFilter(filters) { + this.filterParams = this.getFilterParams(filters); + + updateHistory({ + url: setUrlParams(this.urlParams, window.location.href, true, false, true), + title: document.title, + replace: true, + }); + + this.performSearch(); + }, + getFilteredSearchValue() { + const { authorUsername, labelName, search } = this.filterParams; + const filteredSearchValue = []; + + if (authorUsername) { + filteredSearchValue.push({ + type: 'author_username', + value: { data: authorUsername, operator: '=' }, + }); + } + + if (labelName?.length) { + filteredSearchValue.push( + ...labelName.map((label) => ({ + type: 'label_name', + value: { data: label, operator: '=' }, + })), + ); + } + + if (this.filterParams['not[authorUsername]']) { + filteredSearchValue.push({ + type: 'author_username', + value: { data: this.filterParams['not[authorUsername]'], operator: '!=' }, + }); + } + + if (this.filterParams['not[labelName]']) { + filteredSearchValue.push( + ...this.filterParams['not[labelName]'].map((label) => ({ + type: 'label_name', + value: { data: label, operator: '!=' }, + })), + ); + } + + if (search) { + filteredSearchValue.push(search); + } + + return filteredSearchValue; + }, + getFilterParams(filters = []) { + const notFilters = filters.filter((item) => item.value.operator === '!='); + const equalsFilters = filters.filter((item) => item.value.operator === '='); + + return { ...this.generateParams(equalsFilters), not: { ...this.generateParams(notFilters) } }; + }, + generateParams(filters = []) { + const filterParams = {}; + const labels = []; + const plainText = []; + + filters.forEach((filter) => { + switch (filter.type) { + case 'author_username': + filterParams.authorUsername = filter.value.data; + break; + case 'label_name': + labels.push(filter.value.data); + break; + case 'filtered-search-term': + if (filter.value.data) plainText.push(filter.value.data); + break; + default: + break; + } + }); + + if (labels.length) { + filterParams.labelName = labels; + } + + if (plainText.length) { + filterParams.search = plainText.join(' '); + } + return filterParams; + }, + }, +}; +</script> + +<template> + <filtered-search + class="gl-w-full" + namespace="" + :tokens="tokens" + :search-input-placeholder="$options.i18n.search" + :initial-filter-value="getFilteredSearchValue()" + @onFilter="handleFilter" + /> +</template> |