Commit 08d938f3 authored by Scott Stern's avatar Scott Stern Committed by Olena Horal-Koretska

Add glfilteredsearch to group boards

Adding GLFilteredSearch to group issue baords
as first iteration to replace old filtered search
implementation
parent ce6ed97f
...@@ -72,14 +72,6 @@ export default () => { ...@@ -72,14 +72,6 @@ export default () => {
boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours); boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
} }
if (gon?.features?.boardsFilteredSearch) {
import('~/boards/filtered_search')
.then(({ default: initFilteredSearch }) => {
initFilteredSearch(apolloProvider);
})
.catch(() => {});
}
// eslint-disable-next-line @gitlab/no-runtime-template-compiler // eslint-disable-next-line @gitlab/no-runtime-template-compiler
issueBoardsApp = new Vue({ issueBoardsApp = new Vue({
el: $boardApp, el: $boardApp,
......
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
[data-page$='epic_boards:index'], [data-page$='epic_boards:index'],
[data-page$='epic_boards:show'] { [data-page$='epic_boards:show'] {
.filter-form { .filtered-search-wrapper {
display: none; display: none !important;
} }
} }
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
- placeholder = local_assigns[:placeholder] || _('Search or filter results...') - placeholder = local_assigns[:placeholder] || _('Search or filter results...')
- is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics - is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics
- block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : '' - block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : ''
- if board && board.to_type == "EpicBoard" - is_epic_board = board&.to_type == "EpicBoard"
- if is_epic_board
- user_can_admin_list = can?(current_user, :admin_epic_board_list, board.resource_parent) - user_can_admin_list = can?(current_user, :admin_epic_board_list, board.resource_parent)
- elsif board - elsif board
- user_can_admin_list = can?(current_user, :admin_issue_board_list, board.resource_parent) - user_can_admin_list = can?(current_user, :admin_issue_board_list, board.resource_parent)
...@@ -21,7 +22,7 @@ ...@@ -21,7 +22,7 @@
- if @can_bulk_update - if @can_bulk_update
.check-all-holder.d-none.d-sm-block.hidden .check-all-holder.d-none.d-sm-block.hidden
= check_box_tag "check-all-issues", nil, false, class: "check-all-issues left" = check_box_tag "check-all-issues", nil, false, class: "check-all-issues left"
- if Feature.enabled?(:boards_filtered_search, @group) - if Feature.enabled?(:boards_filtered_search, @group) && is_epic_board
#js-board-filtered-search #js-board-filtered-search
- else - else
.issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row .issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
......
<script>
import { mapActions } from 'vuex';
import { historyPushState } from '~/lib/utils/common_utils';
import { 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'),
},
components: { FilteredSearch },
inject: ['search'],
computed: {
initialSearch() {
return [{ type: 'filtered-search-term', value: { data: this.search } }];
},
},
methods: {
...mapActions(['performSearch']),
tokens() {
return [];
},
handleSearch(filters = []) {
const [item] = filters;
const search = item?.value?.data || '';
historyPushState(setUrlParams({ search }));
this.performSearch();
},
},
};
</script>
<template>
<filtered-search
class="gl-w-full"
namespace=""
:tokens="tokens()"
:search-input-placeholder="$options.i18n.search"
:initial-filter-value="initialSearch"
@onFilter="handleSearch"
/>
</template>
import Vue from 'vue';
import EpicFilteredSearch from 'ee_component/boards/components/epic_filtered_search.vue';
import store from '~/boards/stores';
import { queryToObject } from '~/lib/utils/url_utility';
export default () => {
const queryParams = queryToObject(window.location.search);
const el = document.getElementById('js-board-filtered-search');
if (!el) {
return null;
}
return new Vue({
el,
provide: {
search: queryParams?.search || '',
},
store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094
apolloProvider: {},
render: (createElement) => createElement(EpicFilteredSearch),
});
};
...@@ -39,6 +39,14 @@ export default () => { ...@@ -39,6 +39,14 @@ export default () => {
} }
}); });
if (gon?.features?.boardsFilteredSearch) {
import('ee/boards/epic_filtered_search')
.then(({ default: initFilteredSearch }) => {
initFilteredSearch();
})
.catch(() => {});
}
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
el: $boardApp, el: $boardApp,
......
...@@ -9,6 +9,7 @@ class Groups::EpicBoardsController < Groups::ApplicationController ...@@ -9,6 +9,7 @@ class Groups::EpicBoardsController < Groups::ApplicationController
before_action :assign_endpoint_vars before_action :assign_endpoint_vars
before_action do before_action do
push_frontend_feature_flag(:epic_boards, group, default_enabled: :yaml) push_frontend_feature_flag(:epic_boards, group, default_enabled: :yaml)
push_frontend_feature_flag(:boards_filtered_search, group)
end end
feature_category :boards feature_category :boards
......
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import EpicFilteredSearch from 'ee_component/boards/components/epic_filtered_search.vue';
import { createStore } from '~/boards/stores';
import * as commonUtils from '~/lib/utils/common_utils';
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('EpicFilteredSearch', () => {
let wrapper;
let store;
const createComponent = () => {
wrapper = shallowMount(EpicFilteredSearch, {
localVue,
provide: { search: '' },
store,
});
};
const findFilteredSearch = () => wrapper.findComponent(FilteredSearchBarRoot);
beforeEach(() => {
// this needed for actions call for performSearch
window.gon = { features: {} };
});
afterEach(() => {
wrapper.destroy();
});
describe('default', () => {
beforeEach(() => {
store = createStore();
jest.spyOn(store, 'dispatch');
createComponent();
});
it('renders FilteredSearch', () => {
expect(findFilteredSearch().exists()).toBe(true);
});
describe('when onFilter is emitted', () => {
it('calls performSearch', () => {
findFilteredSearch().vm.$emit('onFilter', [{ value: { data: '' } }]);
expect(store.dispatch).toHaveBeenCalledWith('performSearch');
});
it('calls historyPushState', () => {
jest.spyOn(commonUtils, 'historyPushState');
findFilteredSearch().vm.$emit('onFilter', [{ value: { data: 'searchQuery' } }]);
expect(commonUtils.historyPushState).toHaveBeenCalledWith(
'http://test.host/?search=searchQuery',
);
});
});
});
});
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