diff --git a/app/assets/javascripts/boards/components/board_app.vue b/app/assets/javascripts/boards/components/board_app.vue index 4683f47e60af19414098db1baaabf29211b0eec9..fcbba7b521a75737a8a4674b9af760d61768292f 100644 --- a/app/assets/javascripts/boards/components/board_app.vue +++ b/app/assets/javascripts/boards/components/board_app.vue @@ -141,6 +141,7 @@ export default { :board-id="boardId" :add-column-form-visible="addColumnFormVisible" :is-swimlanes-on="isSwimlanesOn" + :filters="filterParams" @switchBoard="switchBoard" @setFilters="setFilters" @setAddColumnFormVisibility="addColumnFormVisible = $event" @@ -157,6 +158,7 @@ export default { :list-query-variables="listQueryVariables" @setActiveList="setActiveId" @setAddColumnFormVisibility="addColumnFormVisible = $event" + @setFilters="setFilters" /> <board-settings-sidebar v-if="activeList" diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index 82633a28b338d39d94f7039a39083b7120cdffcb..1adff98ec56f05b42ffd689c7eaa537a6ce9fe54 100644 --- a/app/assets/javascripts/boards/components/board_card.vue +++ b/app/assets/javascripts/boards/components/board_card.vue @@ -164,6 +164,7 @@ export default { :update-filters="true" :index="index" :show-work-item-type-icon="showWorkItemTypeIcon" + @setFilters="$emit('setFilters', $event)" > <slot></slot> </board-card-inner> diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue index 6ca46893aff40a051d7620055a04a858dd5fcf6b..37cf825a90f48c739fa2a87038083befda8ccbe1 100644 --- a/app/assets/javascripts/boards/components/board_card_inner.vue +++ b/app/assets/javascripts/boards/components/board_card_inner.vue @@ -9,15 +9,14 @@ import { } from '@gitlab/ui'; import { sortBy } from 'lodash'; import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner'; -import { isScopedLabel } from '~/lib/utils/common_utils'; -import { updateHistory } from '~/lib/utils/url_utility'; +import { isScopedLabel, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import { updateHistory, queryToObject } from '~/lib/utils/url_utility'; import { sprintf, __, n__ } from '~/locale'; import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue'; import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue'; import { ListType } from '../constants'; -import eventHub from '../eventhub'; import { setError } from '../graphql/cache_updates'; import IssueDueDate from './issue_due_date.vue'; import IssueTimeEstimate from './issue_time_estimate.vue'; @@ -221,7 +220,10 @@ export default { updateHistory({ url: `${filterPath}${filter}`, }); - eventHub.$emit('updateTokens'); + + const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true }); + const filters = convertObjectPropsToCamelCase(rawFilterParams, {}); + this.$emit('setFilters', filters); } }, showScopedLabel(label) { diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue index 8d25c1cb8c2897bf859efefbc89a429244cd8a4a..844a4e51a07d2f91fcb2ea44f8903a662f78c0ed 100644 --- a/app/assets/javascripts/boards/components/board_column.vue +++ b/app/assets/javascripts/boards/components/board_column.vue @@ -28,6 +28,11 @@ export default { default: () => [], }, }, + data() { + return { + showNewForm: false, + }; + }, computed: { highlighted() { return this.highlightedLists.includes(this.list.id); @@ -48,6 +53,11 @@ export default { immediate: true, }, }, + methods: { + toggleNewForm() { + this.showNewForm = !this.showNewForm; + }, + }, }; </script> @@ -70,9 +80,18 @@ export default { :list="list" :filter-params="filters" :board-id="boardId" + @toggleNewForm="toggleNewForm" @setActiveList="$emit('setActiveList', $event)" /> - <board-list ref="board-list" :board-id="boardId" :list="list" :filter-params="filters" /> + <board-list + ref="board-list" + :board-id="boardId" + :list="list" + :filter-params="filters" + :show-new-form="showNewForm" + @toggleNewForm="toggleNewForm" + @setFilters="$emit('setFilters', $event)" + /> </div> </div> </template> diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue index dbdfe314ae0b7f9574e5536ba39a88ab56c94d34..6ab6e416baac53c2b3cc7647be6ccbee6e01212e 100644 --- a/app/assets/javascripts/boards/components/board_content.vue +++ b/app/assets/javascripts/boards/components/board_content.vue @@ -214,6 +214,7 @@ export default { :data-draggable-item-type="$options.draggableItemTypes.list" :class="{ 'gl-display-none! gl-sm-display-inline-block!': addColumnFormVisible }" @setActiveList="$emit('setActiveList', $event)" + @setFilters="$emit('setFilters', $event)" /> <transition name="slide" @after-enter="afterFormEnters"> @@ -238,6 +239,7 @@ export default { :highlighted-lists="highlightedLists" @setActiveList="$emit('setActiveList', $event)" @move-list="updateListPosition" + @setFilters="$emit('setFilters', $event)" > <board-add-new-column v-if="addColumnFormVisible" diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue index faaef226c21d58de1170122a25339aac87655c37..d510e7a9c294ee87817247fbd7e2415aec3cbbe5 100644 --- a/app/assets/javascripts/boards/components/board_filtered_search.vue +++ b/app/assets/javascripts/boards/components/board_filtered_search.vue @@ -22,7 +22,6 @@ import { } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import { AssigneeFilterType, GroupByParamType } from 'ee_else_ce/boards/constants'; -import eventHub from '../eventhub'; export default { i18n: { @@ -45,6 +44,10 @@ export default { type: Object, default: () => ({}), }, + filters: { + type: Object, + required: true, + }, }, data() { return { @@ -340,16 +343,21 @@ export default { ); }, }, + watch: { + filters: { + handler(updatedFilters) { + this.filterParams = { ...this.filterParams, ...updatedFilters }; + this.filteredSearchKey += 1; + }, + immediate: true, + }, + }, created() { - eventHub.$on('updateTokens', this.updateTokens); if (!isEmpty(this.eeFilters)) { this.filterParams = this.eeFilters; this.$emit('setFilters', this.formattedFilterParams); } }, - beforeDestroy() { - eventHub.$off('updateTokens', this.updateTokens); - }, methods: { formattedFilterParams() { const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true }); diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index df7f9cce5b362912af2d40d8a9dd843f2616b783..ee5bbe50a455265be956905f6932d998fe94701d 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -13,7 +13,6 @@ import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_posi import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { DEFAULT_BOARD_LIST_ITEMS_SIZE, - toggleFormEventPrefix, DraggableItemTypes, listIssuablesQueries, ListType, @@ -26,7 +25,6 @@ import { setError, } from '../graphql/cache_updates'; import { shouldCloneCard, moveItemVariables } from '../boards_util'; -import eventHub from '../eventhub'; import BoardCard from './board_card.vue'; import BoardNewIssue from './board_new_issue.vue'; import BoardCutLine from './board_cut_line.vue'; @@ -72,12 +70,15 @@ export default { type: Object, required: true, }, + showNewForm: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { showCount: false, - showIssueForm: false, - showEpicForm: false, currentList: null, isLoadingMore: false, toListId: null, @@ -191,9 +192,6 @@ export default { wipLimit: this.list.maxIssueCount, }); }, - toggleFormEventPrefix() { - return this.isEpicBoard ? toggleFormEventPrefix.epic : toggleFormEventPrefix.issue; - }, boardItemsSizeExceedsMax() { return this.list.maxIssueCount > 0 && this.listItemsCount > this.list.maxIssueCount; }, @@ -204,10 +202,10 @@ export default { return this.$apollo.queries.currentList.loading && !this.isLoadingMore; }, epicCreateFormVisible() { - return this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showEpicForm; + return this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showNewForm; }, issueCreateFormVisible() { - return !this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showIssueForm; + return !this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showNewForm; }, listRef() { // When list is draggable, the reference to the list needs to be accessed differently @@ -258,19 +256,6 @@ export default { this.showCount = this.scrollHeight() > Math.ceil(this.listHeight()); }); }, - 'list.id': { - handler(id, oldVal) { - if (id) { - eventHub.$on(`${this.toggleFormEventPrefix}${this.list.id}`, this.toggleForm); - - eventHub.$off(`${this.toggleFormEventPrefix}${oldVal}`, this.toggleForm); - } - }, - immediate: true, - }, - }, - beforeDestroy() { - eventHub.$off(`${this.toggleFormEventPrefix}${this.list.id}`, this.toggleForm); }, methods: { listHeight() { @@ -290,13 +275,6 @@ export default { }); this.isLoadingMore = false; }, - toggleForm() { - if (this.isEpicBoard) { - this.showEpicForm = !this.showEpicForm; - } else { - this.showIssueForm = !this.showIssueForm; - } - }, isObservableItem(index) { // observe every 6 item of 10 to achieve smooth loading state return index !== 0 && index % 6 === 0; @@ -572,7 +550,7 @@ export default { } }, async addListItem(input) { - this.toggleForm(); + this.$emit('toggleNewForm'); this.addItemToListInProgress = true; let issuable; try { @@ -655,12 +633,14 @@ export default { v-if="issueCreateFormVisible" :list="list" :board-id="boardId" + @toggleNewForm="$emit('toggleNewForm')" @addNewIssue="addListItem" /> <board-new-epic v-if="epicCreateFormVisible" :list="list" :board-id="boardId" + @toggleNewForm="$emit('toggleNewForm')" @addNewEpic="addListItem" /> <component @@ -690,6 +670,7 @@ export default { :item="item" :data-draggable-item-type="$options.draggableItemTypes.card" :show-work-item-type-icon="!isEpicBoard" + @setFilters="$emit('setFilters', $event)" > <board-card-move-to-position v-if="showMoveToPosition" @@ -715,6 +696,7 @@ export default { :item="item" :data-draggable-item-type="$options.draggableItemTypes.card" :show-work-item-type-icon="!isEpicBoard" + @setFilters="$emit('setFilters', $event)" > <board-card-move-to-position v-if="showMoveToPosition" diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index 3d5d7650c728e069c4f8b36b015f27768f0e2c25..8a8f149dc6a2ac60147aef8c66fd3ebdfcca90fd 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -21,12 +21,10 @@ import setActiveBoardItemMutation from 'ee_else_ce/boards/graphql/client/set_act import AccessorUtilities from '~/lib/utils/accessor'; import { ListType, - toggleFormEventPrefix, updateListQueries, toggleCollapsedMutations, listsDeferredQuery, } from 'ee_else_ce/boards/constants'; -import eventHub from '../eventhub'; import { setError } from '../graphql/cache_updates'; import ItemCount from './item_count.vue'; @@ -244,19 +242,16 @@ export default { showScopedLabels(label) { return this.scopedLabelsAvailable && isScopedLabel(label); }, - showNewIssueForm() { + showNewForm() { if (this.isSwimlanesHeader) { this.$emit('openUnassignedLane'); this.$nextTick(() => { - eventHub.$emit(`${toggleFormEventPrefix.issue}${this.list.id}`); + this.$emit('toggleNewForm'); }); } else { - eventHub.$emit(`${toggleFormEventPrefix.issue}${this.list.id}`); + this.$emit('toggleNewForm'); } }, - showNewEpicForm() { - eventHub.$emit(`${toggleFormEventPrefix.epic}${this.list.id}`); - }, toggleExpanded() { const collapsed = !this.list.collapsed; this.updateLocalCollapsedStatus(collapsed); @@ -497,7 +492,7 @@ export default { size="small" icon="plus" data-testid="new-issue-btn" - @click="showNewIssueForm" + @click="showNewForm" /> <gl-button @@ -508,7 +503,7 @@ export default { size="small" icon="plus" data-testid="new-epic-btn" - @click="showNewEpicForm" + @click="showNewForm" /> <gl-button diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue index ea22bb08f2a958110d43e300e79e891f0ee0b3de..6c21ea4293625ece94f5624dafed2a674ec0754a 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.vue +++ b/app/assets/javascripts/boards/components/board_new_issue.vue @@ -3,8 +3,6 @@ import { s__ } from '~/locale'; import { getMilestone, formatIssueInput, getBoardQuery } from 'ee_else_ce/boards/boards_util'; import BoardNewIssueMixin from 'ee_else_ce/boards/mixins/board_new_issue'; -import { toggleFormEventPrefix } from '../constants'; -import eventHub from '../eventhub'; import { setError } from '../graphql/cache_updates'; import BoardNewItem from './board_new_item.vue'; @@ -64,9 +62,6 @@ export default { }, }, computed: { - formEventPrefix() { - return toggleFormEventPrefix.issue; - }, disableSubmit() { return this.isGroupBoard ? !this.selectedProject.name : false; }, @@ -107,7 +102,7 @@ export default { this.$emit('addNewIssue', input); }, cancel() { - eventHub.$emit(`${this.formEventPrefix}${this.list.id}`); + this.$emit('toggleNewForm'); }, }, }; @@ -116,7 +111,6 @@ export default { <template> <board-new-item :list="list" - :form-event-prefix="formEventPrefix" :submit-button-title="__('Create issue')" :disable-submit="disableSubmit" @form-submit="submit" diff --git a/app/assets/javascripts/boards/components/board_new_item.vue b/app/assets/javascripts/boards/components/board_new_item.vue index a4e1b8ef273fd731483026737a653706a800abea..946d791b5944be30d5dcbb746df53e60b42618d6 100644 --- a/app/assets/javascripts/boards/components/board_new_item.vue +++ b/app/assets/javascripts/boards/components/board_new_item.vue @@ -16,10 +16,6 @@ export default { type: Object, required: true, }, - formEventPrefix: { - type: String, - required: true, - }, disableSubmit: { type: Boolean, required: false, diff --git a/app/assets/javascripts/boards/components/board_top_bar.vue b/app/assets/javascripts/boards/components/board_top_bar.vue index 820c1fc1dd1c4542f10358fcca08db7a19ba7acb..bc13622ce4ba6532e289153ca95c81806a915e87 100644 --- a/app/assets/javascripts/boards/components/board_top_bar.vue +++ b/app/assets/javascripts/boards/components/board_top_bar.vue @@ -45,6 +45,10 @@ export default { type: Boolean, required: true, }, + filters: { + type: Object, + required: true, + }, }, data() { return { @@ -104,11 +108,13 @@ export default { v-if="isIssueBoard" :board="board" :is-swimlanes-on="isSwimlanesOn" + :filters="filters" @setFilters="$emit('setFilters', $event)" /> <epic-board-filtered-search v-else :board="board" + :filters="filters" @setFilters="$emit('setFilters', $event)" /> </div> diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue index c28415de62008cae39c07579e9cc6114e9dab65b..2e2d04996eeaedfd14036d46acbc9a55d805e67e 100644 --- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue +++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue @@ -57,6 +57,10 @@ export default { required: false, default: false, }, + filters: { + type: Object, + required: true, + }, }, computed: { tokensCE() { @@ -210,6 +214,7 @@ export default { :tokens="tokens" :board="board" :is-swimlanes-on="isSwimlanesOn" + :filters="filters" @setFilters="$emit('setFilters', $event)" /> </template> diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js index a3983f11c8657ae459a402c78cc555f61a76cb48..84564560fe332124e828ee3f2c7cb061236697f1 100644 --- a/app/assets/javascripts/boards/constants.js +++ b/app/assets/javascripts/boards/constants.js @@ -46,11 +46,6 @@ export const formType = { edit: 'edit', }; -export const toggleFormEventPrefix = { - epic: 'toggle-epic-form-', - issue: 'toggle-issue-form-', -}; - export const INCIDENT = 'INCIDENT'; export const flashAnimationDuration = 2000; diff --git a/ee/app/assets/javascripts/boards/components/board_new_epic.vue b/ee/app/assets/javascripts/boards/components/board_new_epic.vue index 9f3e0d75bc6f5bb95b8fc82a36c7b1cf6b36c875..ac9b096f5d5d5c005e9e0641663799ef604f1b66 100644 --- a/ee/app/assets/javascripts/boards/components/board_new_epic.vue +++ b/ee/app/assets/javascripts/boards/components/board_new_epic.vue @@ -1,8 +1,6 @@ <script> import { s__ } from '~/locale'; import BoardNewItem from '~/boards/components/board_new_item.vue'; -import { toggleFormEventPrefix } from '~/boards/constants'; -import eventHub from '~/boards/eventhub'; import { setError } from '~/boards/graphql/cache_updates'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import epicBoardQuery from '../graphql/epic_board.query.graphql'; @@ -58,12 +56,6 @@ export default { }, }, computed: { - formEventPrefix() { - return toggleFormEventPrefix.epic; - }, - formEvent() { - return `${this.formEventPrefix}${this.list.id}`; - }, groupPath() { return this.selectedGroup?.fullPath ?? this.fullPath; }, @@ -91,7 +83,7 @@ export default { }); }, cancel() { - eventHub.$emit(this.formEvent); + this.$emit('toggleNewForm'); }, }, }; @@ -100,7 +92,6 @@ export default { <template> <board-new-item :list="list" - :form-event-prefix="formEventPrefix" :submit-button-title="__('Create epic')" @form-submit="submit" @form-cancel="cancel" diff --git a/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue b/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue index 41c0999058a7b58f5549021423f0ac292507bc37..74bdabcf93d7f1a5d3fcebae88635e6abed48ab2 100644 --- a/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue +++ b/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue @@ -24,6 +24,10 @@ export default { required: false, default: () => {}, }, + filters: { + type: Object, + required: true, + }, }, computed: { tokens() { @@ -80,6 +84,7 @@ export default { data-testid="epic-filtered-search" :tokens="tokens" :board="board" + :filters="filters" @setFilters="$emit('setFilters', $event)" /> </template> diff --git a/ee/app/assets/javascripts/boards/components/epic_lane.vue b/ee/app/assets/javascripts/boards/components/epic_lane.vue index 7ce23d990a4f0767b69215e1322322ca92ff7aa1..173947fd126e741dfb64ef3d7272a59878cf5d54 100644 --- a/ee/app/assets/javascripts/boards/components/epic_lane.vue +++ b/ee/app/assets/javascripts/boards/components/epic_lane.vue @@ -226,6 +226,7 @@ export default { :can-admin-epic="canAdminEpic" :lists="lists" :total-issues-count="totalIssuesCountByListId[list.id]" + @setFilters="$emit('setFilters', $event)" /> </div> </div> diff --git a/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue b/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue index 7b2f006746831bcbcdd07236c5f45a8cc85e7da2..b9826f24eb9fae3d4abb3506104e827c54d5411f 100644 --- a/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue +++ b/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue @@ -69,6 +69,7 @@ export default { hasMoreUnassignedIssuables: {}, isLoadingMoreIssues: false, totalIssuesCountByListId: {}, + showNewForm: [], }; }, apollo: { @@ -209,6 +210,13 @@ export default { setTotalIssuesCount(listId, count) { this.totalIssuesCountByListId[listId] = count; }, + toggleNewForm(listId) { + if (this.showNewForm.includes(listId)) { + this.showNewForm.splice(this.showNewForm.indexOf(listId), 1); + } else { + this.showNewForm = [...this.showNewForm, listId]; + } + }, }, }; </script> @@ -246,6 +254,7 @@ export default { :filter-params="filters" :is-swimlanes-header="true" :board-id="boardId" + @toggleNewForm="toggleNewForm(list.id)" @setActiveList="$emit('setActiveList', $event)" @openUnassignedLane="openUnassignedLane" @setTotalIssuesCount="setTotalIssuesCount" @@ -259,10 +268,22 @@ export default { :remain="bufferSize" :bench="bufferSize" :scrollelement="$refs.scrollableContainer" - :item="$options.EpicLane" - :itemcount="epics.length" - :itemprops="getEpicLaneProps" - /> + > + <epic-lane + v-for="epic in epics" + :key="epic.id" + :epic="epic" + :lists="lists" + :disabled="disabled" + :can-admin-list="canAdminList" + :board-id="boardId" + :filter-params="filters" + :highlighted-lists="highlightedLists" + :can-admin-epic="canAdminEpic" + :total-issues-count-by-list-id="totalIssuesCountByListId" + @setFilters="$emit('setFilters', $event)" + /> + </virtual-list> <div v-if="hasMoreEpicsToLoad" class="swimlanes-button gl-pb-3 gl-pl-3 gl-sticky gl-left-0"> <gl-button category="tertiary" @@ -321,8 +342,11 @@ export default { :can-admin-epic="canAdminEpic" :lists="lists" :total-issues-count="totalIssuesCountByListId[list.id]" + :show-new-form="showNewForm.indexOf(list.id) > -1" + @toggleNewForm="toggleNewForm(list.id)" @updatePageInfo="updatePageInfo" @issuesLoaded="isLoadingMoreIssues = false" + @setFilters="$emit('setFilters', $event)" /> </div> </div> diff --git a/ee/app/assets/javascripts/boards/components/issues_lane_list.vue b/ee/app/assets/javascripts/boards/components/issues_lane_list.vue index 53b0448ce5cd1683ea635bf97dd942e9f93ffda4..ac77ab8bfecf3b173b799abbbcf773f842a8b4eb 100644 --- a/ee/app/assets/javascripts/boards/components/issues_lane_list.vue +++ b/ee/app/assets/javascripts/boards/components/issues_lane_list.vue @@ -4,7 +4,6 @@ import Draggable from 'vuedraggable'; import { __, s__ } from '~/locale'; import BoardCard from '~/boards/components/board_card.vue'; import BoardNewIssue from '~/boards/components/board_new_issue.vue'; -import eventHub from '~/boards/eventhub'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { STATUS_CLOSED } from '~/issues/constants'; import { @@ -82,10 +81,14 @@ export default { required: false, default: 0, }, + showNewForm: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { - showIssueForm: false, toListId: null, }; }, @@ -183,7 +186,7 @@ export default { return this.list.maxIssueCount > 0 && this.totalIssuesCount > this.list.maxIssueCount; }, showNewIssue() { - return this.list.type !== STATUS_CLOSED && this.showIssueForm && this.isUnassignedIssuesLane; + return this.list.type !== STATUS_CLOSED && this.showNewForm && this.isUnassignedIssuesLane; }, }, watch: { @@ -203,19 +206,7 @@ export default { } }, }, - created() { - eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm); - }, - beforeDestroy() { - eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm); - }, methods: { - toggleForm() { - this.showIssueForm = !this.showIssueForm; - if (this.showIssueForm && this.isUnassignedIssuesLane) { - this.$el.scrollIntoView(false); - } - }, handleDragOnStart() { document.body.classList.add('is-dragging'); }, @@ -391,7 +382,7 @@ export default { }); }, async addListItem(input) { - this.toggleForm(); + this.$emit('toggleNewForm'); try { await this.$apollo.mutate({ mutation: listIssuablesQueries.issue.createMutation, @@ -448,6 +439,7 @@ export default { v-if="showNewIssue" :list="list" :board-id="boardId" + @toggleNewForm="$emit('toggleNewForm')" @addNewIssue="addListItem" /> <component @@ -472,6 +464,7 @@ export default { :list="list" :item="issue" :can-admin="canAdminEpic" + @setFilters="$emit('setFilters', $event)" /> </template> <gl-loading-icon diff --git a/ee/spec/frontend/boards/components/board_filtered_search_spec.js b/ee/spec/frontend/boards/components/board_filtered_search_spec.js index 2bc1118397d73938fd1c8a436a0eb9897d364d6f..4add3b67a3f69bc8e6d246c51fcef9f26561c57f 100644 --- a/ee/spec/frontend/boards/components/board_filtered_search_spec.js +++ b/ee/spec/frontend/boards/components/board_filtered_search_spec.js @@ -17,6 +17,7 @@ describe('ee/BoardFilteredSearch', () => { propsData: { tokens: [], board: {}, + filters: {}, }, provide: { boardBaseUrl: 'root', diff --git a/ee/spec/frontend/boards/components/board_list_header_spec.js b/ee/spec/frontend/boards/components/board_list_header_spec.js index 8e2a219916a4625c2b1d4ff9996c0665604b66a1..adfc10f40eaadc7605080fa5b590c6dd75c33029 100644 --- a/ee/spec/frontend/boards/components/board_list_header_spec.js +++ b/ee/spec/frontend/boards/components/board_list_header_spec.js @@ -12,7 +12,6 @@ import { mockLabelList, } from 'jest/boards/mock_data'; import { ListType } from '~/boards/constants'; -import boardsEventHub from '~/boards/eventhub'; import * as cacheUpdates from '~/boards/graphql/cache_updates'; import listQuery from 'ee/boards/graphql/board_lists_deferred.query.graphql'; import epicListQuery from 'ee/boards/graphql/epic_board_lists_deferred.query.graphql'; @@ -129,7 +128,6 @@ describe('Board List Header Component', () => { describe('New epic button', () => { beforeEach(() => { - jest.spyOn(boardsEventHub, '$emit'); createComponent({ isEpicBoard: true, issuableType: 'epic' }); }); @@ -155,13 +153,12 @@ describe('Board List Header Component', () => { expect(findButtonGroup().exists()).toBe(false); }); - it('emits `toggle-epic-form` event on Sidebar eventHub when clicked', () => { - expect(boardsEventHub.$emit).not.toHaveBeenCalled(); + it('emits `toggleNewForm` event when clicked', () => { + expect(wrapper.emitted('toggleNewForm')).toBeUndefined(); findNewEpicButton().trigger('click'); - expect(boardsEventHub.$emit).toHaveBeenCalledWith(`toggle-epic-form-${mockList.id}`); - expect(boardsEventHub.$emit).toHaveBeenCalledTimes(1); + expect(wrapper.emitted('toggleNewForm')).toHaveLength(1); }); }); diff --git a/ee/spec/frontend/boards/components/board_list_spec.js b/ee/spec/frontend/boards/components/board_list_spec.js index 99216a5168963a93cd78fdeccf0bc71f17a8aeab..dfc506c29b36e453c84f9c14cd02f7c0115a77a9 100644 --- a/ee/spec/frontend/boards/components/board_list_spec.js +++ b/ee/spec/frontend/boards/components/board_list_spec.js @@ -11,7 +11,6 @@ import listIssuesQuery from '~/boards/graphql/lists_issues.query.graphql'; import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql'; import * as cacheUpdates from '~/boards/graphql/cache_updates'; import { TYPE_EPIC, TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; -import eventHub from '~/boards/eventhub'; import issueMoveListMutation from 'ee/boards/graphql/issue_move_list.mutation.graphql'; import epicMoveListMutation from 'ee/boards/graphql/epic_move_list.mutation.graphql'; import epicCreateMutation from 'ee/boards/graphql/epic_create.mutation.graphql'; @@ -100,6 +99,7 @@ describe('BoardList Component', () => { isGroupBoard: true, isEpicBoard, }, + componentProps: { showNewForm: true }, stubs: { BoardNewIssue, BoardNewEpic, @@ -108,9 +108,6 @@ describe('BoardList Component', () => { await waitForPromises(); - eventHub.$emit(`toggle-${issuableType}-form-${mockList.id}`); - - await nextTick(); expect(wrapper.findComponent(formComponent).exists()).toBe(true); expect(wrapper.findComponent(notRenderedFormComponent).exists()).toBe(false); }, @@ -395,6 +392,7 @@ describe('BoardList Component', () => { listProps: { id: listId, }, + componentProps: { showNewForm: true }, provide: { boardType: WORKSPACE_GROUP, issuableType, @@ -412,8 +410,6 @@ describe('BoardList Component', () => { await waitForPromises(); - eventHub.$emit(`toggle-${issuableType}-form-${listId}`); - await nextTick(); expect(wrapper.findComponent(component).exists()).toBe(true); wrapper.findComponent(component).vm.$emit(event, { title: 'Foo' }); @@ -435,6 +431,7 @@ describe('BoardList Component', () => { listProps: { id: listId, }, + componentProps: { showNewForm: true }, provide: { boardType: WORKSPACE_GROUP, issuableType, @@ -457,8 +454,6 @@ describe('BoardList Component', () => { await waitForPromises(); - eventHub.$emit(`toggle-${issuableType}-form-${listId}`); - await nextTick(); expect(wrapper.findComponent(component).exists()).toBe(true); wrapper.findComponent(component).vm.$emit(event, { title: 'Foo' }); diff --git a/ee/spec/frontend/boards/components/board_new_epic_spec.js b/ee/spec/frontend/boards/components/board_new_epic_spec.js index 73584fb9f04008d540ca81e13244c42761833a44..1cfdf0b118cea4070fdd442fcdbb5de8cd895c88 100644 --- a/ee/spec/frontend/boards/components/board_new_epic_spec.js +++ b/ee/spec/frontend/boards/components/board_new_epic_spec.js @@ -10,7 +10,6 @@ import epicBoardQuery from 'ee/boards/graphql/epic_board.query.graphql'; import { mockList } from 'jest/boards/mock_data'; import BoardNewItem from '~/boards/components/board_new_item.vue'; -import eventHub from '~/boards/eventhub'; import { mockEpicBoardResponse } from '../mock_data'; @@ -66,7 +65,6 @@ describe('Epic boards new epic form', () => { expect(boardNewItem.exists()).toBe(true); expect(boardNewItem.props()).toEqual({ list: mockList, - formEventPrefix: 'toggle-epic-form-', submitButtonTitle: 'Create epic', disableSubmit: false, }); @@ -79,11 +77,10 @@ describe('Epic boards new epic form', () => { expect(groupSelect.exists()).toBe(true); }); - it('emits event `toggle-epic-form` with current list Id suffix on eventHub when `board-new-item` emits form-cancel event', async () => { - jest.spyOn(eventHub, '$emit').mockImplementation(); + it('emits event `toggleNewForm` when `board-new-item` emits form-cancel event', async () => { findBoardNewItem().vm.$emit('form-cancel'); await nextTick(); - expect(eventHub.$emit).toHaveBeenCalledWith(`toggle-epic-form-${mockList.id}`); + expect(wrapper.emitted('toggleNewForm')).toHaveLength(1); }); }); diff --git a/ee/spec/frontend/boards/components/board_top_bar_spec.js b/ee/spec/frontend/boards/components/board_top_bar_spec.js index c15b0e9f081031e545f54624d88e41aa097d3de0..4820012b6f71b883daa8ba796f2c25c279b9d2d7 100644 --- a/ee/spec/frontend/boards/components/board_top_bar_spec.js +++ b/ee/spec/frontend/boards/components/board_top_bar_spec.js @@ -44,6 +44,7 @@ describe('BoardTopBar', () => { boardId: 'gid://gitlab/Board/1', isSwimlanesOn: false, addColumnFormVisible: false, + filters: {}, }, provide: { swimlanesFeatureAvailable: false, diff --git a/ee/spec/frontend/boards/components/epics_swimlanes_spec.js b/ee/spec/frontend/boards/components/epics_swimlanes_spec.js index 4ab81e6c77394246e884684b08fce2fc79e03823..aa433d915b009fa20d7baea3612aa1306c58fa0d 100644 --- a/ee/spec/frontend/boards/components/epics_swimlanes_spec.js +++ b/ee/spec/frontend/boards/components/epics_swimlanes_spec.js @@ -136,15 +136,16 @@ describe('EpicsSwimlanes', () => { expect(virtualList.props()).toMatchObject({ remain: bufferSize, bench: bufferSize, - item: EpicLane, size: EPIC_LANE_BASE_HEIGHT, - itemcount: mockEpics.length, - itemprops: expect.any(Function), }); expect(virtualList.props().scrollelement).toBe(scrollableContainer); }); + it('renders epic lanes', () => { + expect(wrapper.findAllComponents(EpicLane)).toHaveLength(mockEpics.length); + }); + it('does not display load more epics button if there are no more epics', () => { expect(findLoadMoreEpicsButton().exists()).toBe(false); }); diff --git a/ee/spec/frontend/boards/components/issues_lane_list_spec.js b/ee/spec/frontend/boards/components/issues_lane_list_spec.js index 63fc9bfe4b0f56bb65a6b7eabded58f590919f97..606841c932b106d74749625e2df3e6ca341117ff 100644 --- a/ee/spec/frontend/boards/components/issues_lane_list_spec.js +++ b/ee/spec/frontend/boards/components/issues_lane_list_spec.js @@ -7,7 +7,6 @@ import waitForPromises from 'helpers/wait_for_promises'; import { DraggableItemTypes } from 'ee_else_ce/boards/constants'; import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql'; import IssuesLaneList from 'ee/boards/components/issues_lane_list.vue'; -import eventHub from '~/boards/eventhub'; import BoardCard from '~/boards/components/board_card.vue'; import BoardNewIssue from '~/boards/components/board_new_issue.vue'; import { ListType } from '~/boards/constants'; @@ -49,6 +48,7 @@ describe('IssuesLaneList', () => { canAdminEpic = false, highlightedLists = [], totalIssuesCount = 2, + showNewForm = false, listsIssuesQueryHandler = listIssuesQueryHandlerSuccess, moveIssueMutationHandler = moveIssueMutationHandlerSuccess, createIssueMutationHandler = createIssueMutationHandlerSuccess, @@ -118,6 +118,7 @@ describe('IssuesLaneList', () => { lists: mockLists, highlightedLists, totalIssuesCount, + showNewForm, }, provide: { fullPath: 'gitlab-org', @@ -329,12 +330,11 @@ describe('IssuesLaneList', () => { }, isUnassignedIssuesLane: true, canAdminEpic: true, + showNewForm: true, }); await waitForPromises(); - eventHub.$emit(`toggle-issue-form-${mockList.id}`); - await nextTick(); expect(findNewIssueForm().exists()).toBe(true); findNewIssueForm().vm.$emit('addNewIssue', { title: 'Foo' }); @@ -350,13 +350,12 @@ describe('IssuesLaneList', () => { }, isUnassignedIssuesLane: true, canAdminEpic: true, + showNewForm: true, createIssueMutationHandler: queryHandlerFailure, }); await waitForPromises(); - eventHub.$emit(`toggle-issue-form-${mockList.id}`); - await nextTick(); expect(findNewIssueForm().exists()).toBe(true); findNewIssueForm().vm.$emit('addNewIssue', { title: 'Foo' }); diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js index 8f2752b6bd840b36f498c5e0721ba3bb4d30eabd..162544e19bbe06397b83cb1828d128e5e38d027c 100644 --- a/spec/frontend/boards/board_card_inner_spec.js +++ b/spec/frontend/boards/board_card_inner_spec.js @@ -10,7 +10,6 @@ import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/i import BoardCardInner from '~/boards/components/board_card_inner.vue'; import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql'; import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue'; -import eventHub from '~/boards/eventhub'; import { TYPE_ISSUE } from '~/issues/constants'; import { updateHistory } from '~/lib/utils/url_utility'; import { mockLabelList, mockIssue, mockIssueFullPath, mockIssueDirectNamespace } from './mock_data'; @@ -436,9 +435,8 @@ describe('Board card component', () => { expect(updateHistory).toHaveBeenCalledTimes(1); }); - it('emits updateTokens event', () => { - expect(eventHub.$emit).toHaveBeenCalledTimes(1); - expect(eventHub.$emit).toHaveBeenCalledWith('updateTokens'); + it('emits setFilters event', () => { + expect(wrapper.emitted('setFilters').length).toBe(1); }); }); @@ -452,8 +450,8 @@ describe('Board card component', () => { expect(updateHistory).not.toHaveBeenCalled(); }); - it('does not emit updateTokens event', () => { - expect(eventHub.$emit).not.toHaveBeenCalled(); + it('does not emit setFilters event', () => { + expect(wrapper.emitted('setFilters')).toBeUndefined(); }); }); }); diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js index a43d94e9b2d920b2b0b070e03b8683e5cfd8469f..40c6857194356a0bc4289119dbc08e63935247aa 100644 --- a/spec/frontend/boards/board_list_spec.js +++ b/spec/frontend/boards/board_list_spec.js @@ -8,11 +8,10 @@ import createComponent from 'jest/boards/board_list_helper'; import { ESC_KEY_CODE } from '~/lib/utils/keycodes'; import BoardCard from '~/boards/components/board_card.vue'; import BoardCutLine from '~/boards/components/board_cut_line.vue'; -import eventHub from '~/boards/eventhub'; import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue'; import listIssuesQuery from '~/boards/graphql/lists_issues.query.graphql'; -import { mockIssues, mockList, mockIssuesMore, mockGroupIssuesResponse } from './mock_data'; +import { mockIssues, mockIssuesMore, mockGroupIssuesResponse } from './mock_data'; describe('Board list component', () => { let wrapper; @@ -75,8 +74,10 @@ describe('Board list component', () => { expect(wrapper.find('.board-card').attributes('data-item-id')).toBe('gid://gitlab/Issue/436'); }); - it('shows new issue form after eventhub event', async () => { - eventHub.$emit(`toggle-issue-form-${mockList.id}`); + it('shows new issue form when showNewForm prop is true', async () => { + wrapper = createComponent({ + componentProps: { showNewForm: true }, + }); await nextTick(); expect(wrapper.find('.board-new-issue-form').exists()).toBe(true); @@ -87,12 +88,10 @@ describe('Board list component', () => { listProps: { listType: ListType.closed, }, + componentProps: { showNewForm: true }, }); await waitForPromises(); - eventHub.$emit(`toggle-issue-form-${mockList.id}`); - - await nextTick(); expect(wrapper.find('.board-new-issue-form').exists()).toBe(false); }); diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js index 5e96b508f37a3d66cd965f853533554a7fed6cd1..dbc9b42380b97b78b5cf096275ad58a529be8129 100644 --- a/spec/frontend/boards/components/board_filtered_search_spec.js +++ b/spec/frontend/boards/components/board_filtered_search_spec.js @@ -65,6 +65,7 @@ describe('BoardFilteredSearch', () => { propsData: { ...props, tokens, + filters: {}, }, }); }; diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js index dad0d148449320ab8520268d8c60a910938807c4..0c764537a246a766eda2d81e27f876558b921c28 100644 --- a/spec/frontend/boards/components/board_new_issue_spec.js +++ b/spec/frontend/boards/components/board_new_issue_spec.js @@ -5,7 +5,6 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import BoardNewIssue from '~/boards/components/board_new_issue.vue'; import BoardNewItem from '~/boards/components/board_new_item.vue'; import ProjectSelect from '~/boards/components/project_select.vue'; -import eventHub from '~/boards/eventhub'; import groupBoardQuery from '~/boards/graphql/group_board.query.graphql'; import projectBoardQuery from '~/boards/graphql/project_board.query.graphql'; import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; @@ -96,18 +95,16 @@ describe('Issue boards new issue form', () => { expect(boardNewItem.exists()).toBe(true); expect(boardNewItem.props()).toEqual({ list: mockList, - formEventPrefix: 'toggle-issue-form-', submitButtonTitle: 'Create issue', disableSubmit: false, }); }); - it('emits event `toggle-issue-form` with current list Id suffix on eventHub when `board-new-item` emits form-cancel event', async () => { - jest.spyOn(eventHub, '$emit').mockImplementation(); + it('emits event `toggleNewForm` when `board-new-item` emits form-cancel event', async () => { findBoardNewItem().vm.$emit('form-cancel'); await nextTick(); - expect(eventHub.$emit).toHaveBeenCalledWith(`toggle-issue-form-${mockList.id}`); + expect(wrapper.emitted('toggleNewForm')).toHaveLength(1); }); describe('when in group issue board', () => { diff --git a/spec/frontend/boards/components/board_new_item_spec.js b/spec/frontend/boards/components/board_new_item_spec.js index 23acba3595adf504d98c53f01dbed22743f49326..00537cdf5a06223eb27085e09729a413744a685e 100644 --- a/spec/frontend/boards/components/board_new_item_spec.js +++ b/spec/frontend/boards/components/board_new_item_spec.js @@ -8,14 +8,12 @@ import { mockList } from '../mock_data'; const createComponent = ({ list = mockList, - formEventPrefix = 'toggle-issue-form-', disabledSubmit = false, submitButtonTitle = 'Create item', } = {}) => mountExtended(BoardNewItem, { propsData: { list, - formEventPrefix, disabledSubmit, submitButtonTitle, }, diff --git a/spec/frontend/boards/components/board_top_bar_spec.js b/spec/frontend/boards/components/board_top_bar_spec.js index 332f6548502bfa3759bb659ab7bc16d81374ce35..c759f0b3430b51281de0402a462a2052760fe16a 100644 --- a/spec/frontend/boards/components/board_top_bar_spec.js +++ b/spec/frontend/boards/components/board_top_bar_spec.js @@ -45,6 +45,7 @@ describe('BoardTopBar', () => { boardId: 'gid://gitlab/Board/1', isSwimlanesOn: false, addColumnFormVisible: false, + filters: {}, }, provide: { swimlanesFeatureAvailable: false,