Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/boards/components')
-rw-r--r--app/assets/javascripts/boards/components/board_app.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue43
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue12
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue30
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue11
-rw-r--r--app/assets/javascripts/boards/components/board_top_bar.vue3
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue272
-rw-r--r--app/assets/javascripts/boards/components/config_toggle.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue12
-rw-r--r--app/assets/javascripts/boards/components/toggle_focus.vue2
13 files changed, 188 insertions, 209 deletions
diff --git a/app/assets/javascripts/boards/components/board_app.vue b/app/assets/javascripts/boards/components/board_app.vue
index 1cfa35ffd91..4d915ff341a 100644
--- a/app/assets/javascripts/boards/components/board_app.vue
+++ b/app/assets/javascripts/boards/components/board_app.vue
@@ -1,6 +1,7 @@
<script>
// eslint-disable-next-line no-restricted-imports
import { mapGetters } from 'vuex';
+import { omit } from 'lodash';
import { refreshCurrentPage, queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import BoardContent from '~/boards/components/board_content.vue';
@@ -115,9 +116,8 @@ export default {
return this.activeListId ? this.boardListsApollo[this.activeListId] : undefined;
},
formattedFilterParams() {
- if (this.filterParams.groupBy) delete this.filterParams.groupBy;
return filterVariables({
- filters: this.filterParams,
+ filters: omit(this.filterParams, 'groupBy'),
issuableType: this.issuableType,
filterInfo: FiltersInfo,
filterFields: FilterFields,
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 05865dc7305..fd45d2d31c3 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -2,6 +2,9 @@
// eslint-disable-next-line no-restricted-imports
import { mapActions, mapState } from 'vuex';
import Tracking from '~/tracking';
+import setSelectedBoardItemsMutation from '~/boards/graphql/client/set_selected_board_items.mutation.graphql';
+import unsetSelectedBoardItemsMutation from '~/boards/graphql/client/unset_selected_board_items.mutation.graphql';
+import selectedBoardItemsQuery from '~/boards/graphql/client/selected_board_items.query.graphql';
import setActiveBoardItemMutation from 'ee_else_ce/boards/graphql/client/set_active_board_item.mutation.graphql';
import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql';
import BoardCardInner from './board_card_inner.vue';
@@ -52,9 +55,12 @@ export default {
return !this.isApolloBoard;
},
},
+ selectedBoardItems: {
+ query: selectedBoardItemsQuery,
+ },
},
computed: {
- ...mapState(['selectedBoardItems', 'activeId']),
+ ...mapState(['activeId']),
activeItemId() {
return this.isApolloBoard ? this.activeBoardItem?.id : this.activeId;
},
@@ -62,10 +68,7 @@ export default {
return this.item.id === this.activeItemId;
},
multiSelectVisible() {
- return (
- !this.activeItemId &&
- this.selectedBoardItems.findIndex((boardItem) => boardItem.id === this.item.id) > -1
- );
+ return !this.activeItemId && this.selectedBoardItems?.includes(this.item.id);
},
isDisabled() {
return this.disabled || !this.item.id || this.item.isLoading || !this.canAdmin;
@@ -93,7 +96,7 @@ export default {
},
},
methods: {
- ...mapActions(['toggleBoardItemMultiSelection', 'toggleBoardItem']),
+ ...mapActions(['toggleBoardItem']),
toggleIssue(e) {
// Don't do anything if this happened on a no trigger element
if (e.target.closest('.js-no-trigger')) return;
@@ -110,7 +113,10 @@ export default {
this.track('click_card', { label: 'right_sidebar' });
}
},
- toggleItem() {
+ async toggleItem() {
+ await this.$apollo.mutate({
+ mutation: unsetSelectedBoardItemsMutation,
+ });
this.$apollo.mutate({
mutation: setActiveBoardItemMutation,
variables: {
@@ -119,13 +125,32 @@ export default {
},
});
},
+ async toggleBoardItemMultiSelection(item) {
+ if (this.activeItemId) {
+ await this.$apollo.mutate({
+ mutation: setSelectedBoardItemsMutation,
+ variables: {
+ itemId: this.activeItemId,
+ },
+ });
+ await this.$apollo.mutate({
+ mutation: setActiveBoardItemMutation,
+ variables: { boardItem: null },
+ });
+ }
+ this.$apollo.mutate({
+ mutation: setSelectedBoardItemsMutation,
+ variables: {
+ itemId: item.id,
+ },
+ });
+ },
},
};
</script>
<template>
<li
- data-qa-selector="board_card"
:class="[
{
'multi-select gl-bg-blue-50 gl-border-blue-200': multiSelectVisible,
@@ -141,7 +166,7 @@ export default {
:data-item-iid="item.iid"
:data-item-path="item.referencePath"
:style="cardStyle"
- data-testid="board_card"
+ data-testid="board-card"
class="board-card gl-p-5 gl-rounded-base gl-line-height-normal gl-relative gl-mb-3"
@click="toggleIssue($event)"
>
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index c441a718dd8..c10ff2e08da 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -9,11 +9,12 @@ import {
} from '@gitlab/ui';
import { sortBy } from 'lodash';
// eslint-disable-next-line no-restricted-imports
-import { mapActions, mapState } from 'vuex';
+import { mapActions } from 'vuex';
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 { sprintf, __, n__ } from '~/locale';
+import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
@@ -86,8 +87,13 @@ export default {
maxCounter: 99,
};
},
+ apollo: {
+ isShowingLabels: {
+ query: isShowingLabelsQuery,
+ update: (data) => data.isShowingLabels,
+ },
+ },
computed: {
- ...mapState(['isShowingLabels']),
isLoading() {
return this.item.isLoading || this.item.iid === '-1';
},
@@ -252,7 +258,7 @@ export default {
v-if="item.hidden"
v-gl-tooltip
name="spam"
- :title="__('This issue is hidden because its author has been banned')"
+ :title="__('This issue is hidden because its author has been banned.')"
class="gl-mr-2 hidden-icon gl-text-orange-500 gl-cursor-help"
data-testid="hidden-icon"
/>
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index bcd7db8dcb4..67a4c5eba45 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -93,7 +93,7 @@ export default {
}"
:data-list-id="list.id"
class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal is-expandable"
- data-qa-selector="board_list"
+ data-testid="board-list"
>
<div
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-gray-50"
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index 3c2659b00c9..554f3bfa416 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -219,7 +219,7 @@ export default {
<template>
<div
v-cloak
- data-qa-selector="boards_list"
+ data-testid="boards-list"
class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-min-h-0"
>
<gl-alert v-if="errorToDisplay" variant="danger" :dismissible="true" @dismiss="dismissError">
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index d12478b42d8..a3d55ac8306 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -1,13 +1,15 @@
<script>
import { GlModal, GlAlert } from '@gitlab/ui';
// eslint-disable-next-line no-restricted-imports
-import { mapActions, mapState } from 'vuex';
+import { mapActions } from 'vuex';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { visitUrl, updateHistory, getParameterByName } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import eventHub from '~/boards/eventhub';
import { formType } from '../constants';
+import { setError } from '../graphql/cache_updates';
+import errorQuery from '../graphql/client/error.query.graphql';
import createBoardMutation from '../graphql/board_create.mutation.graphql';
import destroyBoardMutation from '../graphql/board_destroy.mutation.graphql';
import updateBoardMutation from '../graphql/board_update.mutation.graphql';
@@ -93,8 +95,13 @@ export default {
isLoading: false,
};
},
+ apollo: {
+ error: {
+ query: errorQuery,
+ update: (data) => data.boardsAppError,
+ },
+ },
computed: {
- ...mapState(['error']),
isNewForm() {
return this.currentPage === formType.new;
},
@@ -133,7 +140,7 @@ export default {
variant: this.buttonKind,
disabled: this.submitDisabled,
loading: this.isLoading,
- 'data-qa-selector': 'save_changes_button',
+ 'data-testid': 'save-changes-button',
},
};
},
@@ -177,7 +184,8 @@ export default {
}
},
methods: {
- ...mapActions(['setError', 'unsetError', 'setBoard']),
+ ...mapActions(['setBoard']),
+ setError,
isFocusMode() {
return Boolean(document.querySelector('.content-wrapper > .js-focus-mode-board.is-focused'));
},
@@ -211,8 +219,8 @@ export default {
try {
await this.deleteBoard();
visitUrl(this.boardBaseUrl);
- } catch {
- this.setError({ message: this.$options.i18n.deleteErrorMessage });
+ } catch (error) {
+ setError({ error, message: this.$options.i18n.deleteErrorMessage });
} finally {
this.isLoading = false;
}
@@ -236,8 +244,8 @@ export default {
: '';
updateHistory({ url: `${this.boardBaseUrl}/${getIdFromGraphQLId(board.id)}${param}` });
}
- } catch {
- this.setError({ message: this.$options.i18n.saveErrorMessage });
+ } catch (error) {
+ setError({ error, message: this.$options.i18n.saveErrorMessage });
} finally {
this.isLoading = false;
}
@@ -295,11 +303,11 @@ export default {
@hide.prevent
>
<gl-alert
- v-if="!isApolloBoard && error"
+ v-if="error"
class="gl-mb-3"
variant="danger"
:dismissible="true"
- @dismiss="unsetError"
+ @dismiss="() => setError({ message: null, captureError: false })"
>
{{ error }}
</gl-alert>
@@ -316,7 +324,7 @@ export default {
ref="name"
v-model="board.name"
class="form-control"
- data-qa-selector="board_name_field"
+ data-testid="board-name-field"
type="text"
:placeholder="$options.i18n.titleFieldPlaceholder"
@keyup.enter="submit"
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 1bb7e88122a..2693a6bb5ea 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -653,7 +653,7 @@ export default {
<div
v-show="!list.collapsed"
class="board-list-component gl-relative gl-h-full gl-display-flex gl-flex-direction-column gl-min-h-0"
- data-qa-selector="board_list_cards_area"
+ data-testid="board-list-cards-area"
>
<div
v-if="loading"
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 42c30dc8245..0235edd69ac 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -201,8 +201,8 @@ export default {
})
);
},
- totalWeight() {
- return this.boardList?.totalWeight;
+ totalIssueWeight() {
+ return this.boardList?.totalIssueWeight;
},
canShowTotalWeight() {
return this.weightFeatureAvailable && !this.isLoading;
@@ -365,7 +365,6 @@ export default {
}"
:style="headerStyle"
class="board-header gl-relative"
- data-qa-selector="board_list_header"
data-testid="board-list-header"
>
<h3
@@ -473,8 +472,8 @@ export default {
<div v-else>• {{ itemsTooltipLabel }}</div>
<div v-if="weightFeatureAvailable && !isLoading">
- <gl-sprintf :message="__('%{totalWeight} total weight')">
- <template #totalWeight>{{ totalWeight }}</template>
+ <gl-sprintf :message="__('%{totalIssueWeight} total weight')">
+ <template #totalIssueWeight>{{ totalIssueWeight }}</template>
</gl-sprintf>
</div>
</gl-tooltip>
@@ -507,7 +506,7 @@ export default {
<gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
<span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3" data-testid="weight">
<gl-icon class="gl-mr-2" name="weight" :size="14" />
- {{ totalWeight }}
+ {{ totalIssueWeight }}
</span>
</template>
<!-- EE end -->
diff --git a/app/assets/javascripts/boards/components/board_top_bar.vue b/app/assets/javascripts/boards/components/board_top_bar.vue
index 7fd1a934381..31664c28831 100644
--- a/app/assets/javascripts/boards/components/board_top_bar.vue
+++ b/app/assets/javascripts/boards/components/board_top_bar.vue
@@ -4,6 +4,7 @@ import { s__ } from '~/locale';
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
import IssueBoardFilteredSearch from 'ee_else_ce/boards/components/issue_board_filtered_search.vue';
import { getBoardQuery } from 'ee_else_ce/boards/boards_util';
+import ToggleLabels from '~/vue_shared/components/toggle_labels.vue';
import { setError } from '../graphql/cache_updates';
import ConfigToggle from './config_toggle.vue';
import NewBoardButton from './new_board_button.vue';
@@ -17,7 +18,7 @@ export default {
ConfigToggle,
NewBoardButton,
ToggleFocus,
- ToggleLabels: () => import('ee_component/boards/components/toggle_labels.vue'),
+ ToggleLabels,
ToggleEpicsSwimlanes: () => import('ee_component/boards/components/toggle_epics_swimlanes.vue'),
EpicBoardFilteredSearch: () =>
import('ee_component/boards/components/epic_filtered_search.vue'),
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index cc6fde92f9b..cd2a4a02b2e 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -1,15 +1,7 @@
<script>
-import {
- GlLoadingIcon,
- GlSearchBoxByType,
- GlDropdown,
- GlDropdownDivider,
- GlDropdownSectionHeader,
- GlDropdownItem,
- GlModalDirective,
-} from '@gitlab/ui';
+import { GlButton, GlCollapsibleListbox, GlModalDirective } from '@gitlab/ui';
import { produce } from 'immer';
-import { throttle } from 'lodash';
+import { differenceBy, debounce } from 'lodash';
// eslint-disable-next-line no-restricted-imports
import { mapActions, mapState } from 'vuex';
@@ -18,7 +10,8 @@ import BoardForm from 'ee_else_ce/boards/components/board_form.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isMetaKey } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import { s__, __ } from '~/locale';
import eventHub from '../eventhub';
import groupBoardsQuery from '../graphql/group_boards.query.graphql';
@@ -34,15 +27,16 @@ export default {
name: 'BoardsSelector',
i18n: {
fetchBoardsError: s__('Boards|An error occurred while fetching boards. Please try again.'),
+ headerText: s__('IssueBoards|Switch board'),
+ noResultsText: s__('IssueBoards|No matching boards found'),
+ hiddenBoardsText: s__(
+ 'IssueBoards|Some of your boards are hidden, add a license to see them again.',
+ ),
},
components: {
BoardForm,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlDropdown,
- GlDropdownDivider,
- GlDropdownSectionHeader,
- GlDropdownItem,
+ GlButton,
+ GlCollapsibleListbox,
},
directives: {
GlModalDirective,
@@ -60,11 +54,6 @@ export default {
'isApolloBoard',
],
props: {
- throttleDuration: {
- type: Number,
- default: 200,
- required: false,
- },
boardApollo: {
type: Object,
required: false,
@@ -78,13 +67,10 @@ export default {
},
data() {
return {
- hasScrollFade: false,
- scrollFadeInitialized: false,
boards: [],
recentBoards: [],
loadingBoards: false,
loadingRecentBoards: false,
- throttledSetScrollFade: throttle(this.setScrollFade, this.throttleDuration),
contentClientHeight: 0,
maxPosition: 0,
filterTerm: '',
@@ -97,6 +83,12 @@ export default {
boardToUse() {
return this.isApolloBoard ? this.boardApollo : this.board;
},
+ boardToUseName() {
+ return this.boardToUse?.name || s__('IssueBoards|Select board');
+ },
+ boardToUseId() {
+ return getIdFromGraphQLId(this.boardToUse.id) || '';
+ },
isBoardToUseLoading() {
return this.isApolloBoard ? this.isCurrentBoardLoading : this.isBoardLoading;
},
@@ -112,6 +104,26 @@ export default {
loading() {
return this.loadingRecentBoards || this.loadingBoards;
},
+ listBoxItems() {
+ const mapItems = ({ id, name }) => ({ text: name, value: id });
+
+ if (this.showRecentSection) {
+ const notRecent = differenceBy(this.filteredBoards, this.recentBoards, 'id');
+
+ return [
+ {
+ text: __('Recent'),
+ options: this.recentBoards.map(mapItems),
+ },
+ {
+ text: __('All'),
+ options: notRecent.map(mapItems),
+ },
+ ];
+ }
+
+ return this.filteredBoards.map(mapItems);
+ },
filteredBoards() {
return this.boards.filter((board) =>
board.name.toLowerCase().includes(this.filterTerm.toLowerCase()),
@@ -126,34 +138,25 @@ export default {
showDropdown() {
return this.showCreate || this.hasMissingBoards;
},
- scrollFadeClass() {
- return {
- 'fade-out': !this.hasScrollFade,
- };
- },
showRecentSection() {
return (
- this.recentBoards.length &&
+ this.recentBoards.length > 0 &&
this.boards.length > MIN_BOARDS_TO_VIEW_RECENT &&
!this.filterTerm.length
);
},
},
watch: {
- filteredBoards() {
- this.scrollFadeInitialized = false;
- this.$nextTick(this.setScrollFade);
- },
- recentBoards() {
- this.scrollFadeInitialized = false;
- this.$nextTick(this.setScrollFade);
- },
boardToUse(newBoard) {
document.title = newBoard.name;
},
},
created() {
eventHub.$on('showBoardModal', this.showPage);
+ this.handleSearch = debounce(this.setFilterTerm, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
+ destroyed() {
+ this.handleSearch.cancel();
},
beforeDestroy() {
eventHub.$off('showBoardModal', this.showPage);
@@ -248,34 +251,6 @@ export default {
this.$emit('switchBoard', board.id);
},
- isScrolledUp() {
- const { content } = this.$refs;
-
- if (!content) {
- return false;
- }
-
- const currentPosition = this.contentClientHeight + content.scrollTop;
-
- return currentPosition < this.maxPosition;
- },
- initScrollFade() {
- const { content } = this.$refs;
-
- if (!content) {
- return;
- }
-
- this.scrollFadeInitialized = true;
-
- this.contentClientHeight = content.clientHeight;
- this.maxPosition = content.scrollHeight;
- },
- setScrollFade() {
- if (!this.scrollFadeInitialized) this.initScrollFade();
-
- this.hasScrollFade = this.isScrolledUp();
- },
fetchCurrentBoard(boardId) {
this.fetchBoard({
fullPath: this.fullPath,
@@ -283,17 +258,24 @@ export default {
boardType: this.boardType,
});
},
- async switchBoard(boardId, e) {
+ setFilterTerm(value) {
+ this.filterTerm = value;
+ },
+ async switchBoardKeyEvent(boardId, e) {
if (isMetaKey(e)) {
+ e.stopPropagation();
window.open(`${this.boardBaseUrl}/${boardId}`, '_blank');
- } else if (this.isApolloBoard) {
+ }
+ },
+ switchBoardGroup(value) {
+ if (this.isApolloBoard) {
// Epic board ID is supported in EE version of this file
- this.$emit('switchBoard', this.fullBoardId(boardId));
- updateHistory({ url: `${this.boardBaseUrl}/${boardId}` });
+ this.$emit('switchBoard', this.fullBoardId(value));
+ updateHistory({ url: `${this.boardBaseUrl}/${value}` });
} else {
this.unsetActiveId();
- this.fetchCurrentBoard(boardId);
- updateHistory({ url: `${this.boardBaseUrl}/${boardId}` });
+ this.fetchCurrentBoard(value);
+ updateHistory({ url: `${this.boardBaseUrl}/${value}` });
}
},
},
@@ -303,105 +285,65 @@ export default {
<template>
<div class="boards-switcher gl-mr-3" data-testid="boards-selector">
<span class="boards-selector-wrapper">
- <gl-dropdown
+ <gl-collapsible-listbox
v-if="showDropdown"
+ block
data-testid="boards-dropdown"
- data-qa-selector="boards_dropdown"
- toggle-class="dropdown-menu-toggle"
- menu-class="flex-column dropdown-extended-height"
+ searchable
+ :searching="loading"
+ toggle-class="gl-min-w-20"
+ :header-text="$options.i18n.headerText"
+ :no-results-text="$options.i18n.noResultsText"
:loading="isBoardToUseLoading"
- :text="boardToUse.name"
- @show="loadBoards"
+ :items="listBoxItems"
+ :toggle-text="boardToUseName"
+ :selected="boardToUseId"
+ @search="handleSearch"
+ @select="switchBoardGroup"
+ @shown="loadBoards"
>
- <p class="gl-dropdown-header-top" @mousedown.prevent>
- {{ s__('IssueBoards|Switch board') }}
- </p>
- <gl-search-box-by-type ref="searchBox" v-model="filterTerm" class="m-2" />
-
- <div
- v-if="!loading"
- ref="content"
- data-qa-selector="boards_dropdown_content"
- class="dropdown-content flex-fill"
- @scroll.passive="throttledSetScrollFade"
- >
- <gl-dropdown-item
- v-show="filteredBoards.length === 0"
- class="gl-pointer-events-none text-secondary"
- >
- {{ s__('IssueBoards|No matching boards found') }}
- </gl-dropdown-item>
-
- <gl-dropdown-section-header v-if="showRecentSection">
- {{ __('Recent') }}
- </gl-dropdown-section-header>
-
- <template v-if="showRecentSection">
- <gl-dropdown-item
- v-for="recentBoard in recentBoards"
- :key="`recent-${recentBoard.id}`"
- data-testid="dropdown-item"
- @click.prevent="switchBoard(recentBoard.id, $event)"
- >
- {{ recentBoard.name }}
- </gl-dropdown-item>
- </template>
-
- <gl-dropdown-divider v-if="showRecentSection" />
-
- <gl-dropdown-section-header v-if="showRecentSection">
- {{ __('All') }}
- </gl-dropdown-section-header>
-
- <gl-dropdown-item
- v-for="otherBoard in filteredBoards"
- :key="otherBoard.id"
- data-testid="dropdown-item"
- @click.prevent="switchBoard(otherBoard.id, $event)"
- >
- {{ otherBoard.name }}
- </gl-dropdown-item>
-
- <gl-dropdown-item v-if="hasMissingBoards" class="no-pointer-events">
+ <template #list-item="{ item }">
+ <div data-testid="dropdown-item-recent" @click="switchBoardKeyEvent(item.value, $event)">
+ {{ item.text }}
+ </div>
+ </template>
+
+ <template #footer>
+ <div v-if="hasMissingBoards" class="gl-border-t gl-font-sm gl-px-4 gl-pt-4 gl-pb-3">
{{
s__('IssueBoards|Some of your boards are hidden, add a license to see them again.')
}}
- </gl-dropdown-item>
- </div>
-
- <div
- v-show="filteredBoards.length > 0"
- class="dropdown-content-faded-mask"
- :class="scrollFadeClass"
- ></div>
-
- <gl-loading-icon v-if="loading" size="sm" />
-
- <div v-if="canAdminBoard">
- <gl-dropdown-divider />
-
- <gl-dropdown-item
- v-if="showCreate"
- v-gl-modal-directive="'board-config-modal'"
- data-qa-selector="create_new_board_button"
- data-track-action="click_button"
- data-track-label="create_new_board"
- data-track-property="dropdown"
- @click.prevent="showPage('new')"
- >
- {{ s__('IssueBoards|Create new board') }}
- </gl-dropdown-item>
-
- <gl-dropdown-item
- v-if="showDelete"
- v-gl-modal-directive="'board-config-modal'"
- class="text-danger"
- @click.prevent="showPage('delete')"
- >
- {{ s__('IssueBoards|Delete board') }}
- </gl-dropdown-item>
- </div>
- </gl-dropdown>
+ </div>
+ <div v-if="canAdminBoard" class="gl-border-t gl-py-2 gl-px-2">
+ <gl-button
+ v-if="showCreate"
+ v-gl-modal-directive="'board-config-modal'"
+ block
+ class="gl-justify-content-start!"
+ category="tertiary"
+ data-testid="create-new-board-button"
+ data-track-action="click_button"
+ data-track-label="create_new_board"
+ data-track-property="dropdown"
+ @click="showPage('new')"
+ >
+ {{ s__('IssueBoards|Create new board') }}
+ </gl-button>
+
+ <gl-button
+ v-if="showDelete"
+ v-gl-modal-directive="'board-config-modal'"
+ block
+ category="tertiary"
+ variant="danger"
+ class="gl-mt-0! gl-justify-content-start!"
+ @click="showPage('delete')"
+ >
+ {{ s__('IssueBoards|Delete board') }}
+ </gl-button>
+ </div>
+ </template>
+ </gl-collapsible-listbox>
<board-form
v-if="currentPage"
diff --git a/app/assets/javascripts/boards/components/config_toggle.vue b/app/assets/javascripts/boards/components/config_toggle.vue
index bc896932ffc..69e6cc870d2 100644
--- a/app/assets/javascripts/boards/components/config_toggle.vue
+++ b/app/assets/javascripts/boards/components/config_toggle.vue
@@ -49,7 +49,7 @@ export default {
v-gl-tooltip
:title="tooltipTitle"
:class="{ 'dot-highlight': hasScope || boardHasScope }"
- data-qa-selector="boards_config_button"
+ data-testid="boards-config-button"
@click.prevent="showPage"
>
{{ buttonText }}
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 a7b3f5536a4..c28415de620 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -62,11 +62,7 @@ export default {
tokensCE() {
const { issue, incident } = this.$options.i18n;
const { types } = this.$options;
- const { fetchUsers, fetchLabels } = issueBoardFilters(
- this.$apollo,
- this.fullPath,
- this.isGroupBoard,
- );
+ const { fetchLabels } = issueBoardFilters(this.$apollo, this.fullPath, this.isGroupBoard);
const tokens = [
{
@@ -77,7 +73,8 @@ export default {
token: UserToken,
dataType: 'user',
unique: true,
- fetchUsers,
+ isProject: !this.isGroupBoard,
+ fullPath: this.fullPath,
preloadedUsers: this.preloadedUsers(),
},
{
@@ -89,7 +86,8 @@ export default {
token: UserToken,
dataType: 'user',
unique: true,
- fetchUsers,
+ isProject: !this.isGroupBoard,
+ fullPath: this.fullPath,
preloadedUsers: this.preloadedUsers(),
},
{
diff --git a/app/assets/javascripts/boards/components/toggle_focus.vue b/app/assets/javascripts/boards/components/toggle_focus.vue
index 990a6fa63d4..a886abf9e61 100644
--- a/app/assets/javascripts/boards/components/toggle_focus.vue
+++ b/app/assets/javascripts/boards/components/toggle_focus.vue
@@ -38,7 +38,7 @@ export default {
v-gl-tooltip
category="tertiary"
:icon="isFullscreen ? 'minimize' : 'maximize'"
- data-qa-selector="focus_mode_button"
+ data-testid="focus-mode-button"
:title="$options.i18n.toggleFocusMode"
:aria-label="$options.i18n.toggleFocusMode"
@click="toggleFocusMode"