summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/components
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-20 13:49:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-20 13:49:51 +0000
commit71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e (patch)
tree6a2d93ef3fb2d353bb7739e4b57e6541f51cdd71 /app/assets/javascripts/boards/components
parenta7253423e3403b8c08f8a161e5937e1488f5f407 (diff)
downloadgitlab-ce-71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e.tar.gz
Add latest changes from gitlab-org/gitlab@15-9-stable-eev15.9.0-rc42
Diffstat (limited to 'app/assets/javascripts/boards/components')
-rw-r--r--app/assets/javascripts/boards/components/board_app.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_card_move_to_position.vue48
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue20
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue3
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue1
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue109
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_top_bar.vue44
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue38
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue4
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue2
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue9
15 files changed, 257 insertions, 83 deletions
diff --git a/app/assets/javascripts/boards/components/board_app.vue b/app/assets/javascripts/boards/components/board_app.vue
index 970e3509d20..d41fc1e9300 100644
--- a/app/assets/javascripts/boards/components/board_app.vue
+++ b/app/assets/javascripts/boards/components/board_app.vue
@@ -11,7 +11,12 @@ export default {
BoardSettingsSidebar,
BoardTopBar,
},
- inject: ['fullBoardId'],
+ inject: ['initialBoardId'],
+ data() {
+ return {
+ boardId: this.initialBoardId,
+ };
+ },
computed: {
...mapGetters(['isSidebarOpen']),
},
@@ -21,13 +26,18 @@ export default {
destroyed() {
window.removeEventListener('popstate', refreshCurrentPage);
},
+ methods: {
+ switchBoard(id) {
+ this.boardId = id;
+ },
+ },
};
</script>
<template>
<div class="boards-app gl-relative" :class="{ 'is-compact': isSidebarOpen }">
- <board-top-bar />
- <board-content :board-id="fullBoardId" />
+ <board-top-bar :board-id="boardId" @switchBoard="switchBoard" />
+ <board-content :board-id="boardId" />
<board-settings-sidebar />
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 0c64cbad5b1..3071c1f334e 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -9,7 +9,7 @@ export default {
BoardCardInner,
},
mixins: [Tracking.mixin()],
- inject: ['disabled'],
+ inject: ['disabled', 'isApolloBoard'],
props: {
list: {
type: Object,
@@ -63,6 +63,15 @@ export default {
colorClass() {
return this.isColorful ? 'gl-pl-4 gl-border-l-solid gl-border-4' : '';
},
+ formattedItem() {
+ return this.isApolloBoard
+ ? {
+ ...this.item,
+ assignees: this.item.assignees?.nodes || [],
+ labels: this.item.labels?.nodes || [],
+ }
+ : this.item;
+ },
},
methods: {
...mapActions(['toggleBoardItemMultiSelection', 'toggleBoardItem']),
@@ -106,7 +115,7 @@ export default {
>
<board-card-inner
:list="list"
- :item="item"
+ :item="formattedItem"
:update-filters="true"
:index="index"
:show-work-item-type-icon="showWorkItemTypeIcon"
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 77df111afc1..88f51c71e06 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -214,7 +214,9 @@ export default {
<template>
<div>
<div class="gl-display-flex" dir="auto">
- <h4 class="board-card-title gl-mb-0 gl-mt-0 gl-mr-3 gl-font-base gl-overflow-break-word">
+ <h4
+ class="board-card-title gl-min-w-0 gl-mb-0 gl-mt-0 gl-mr-3 gl-font-base gl-overflow-break-word"
+ >
<issuable-blocked-icon
v-if="item.blocked"
:item="item"
diff --git a/app/assets/javascripts/boards/components/board_card_move_to_position.vue b/app/assets/javascripts/boards/components/board_card_move_to_position.vue
index 706b453e868..f58f7838576 100644
--- a/app/assets/javascripts/boards/components/board_card_move_to_position.vue
+++ b/app/assets/javascripts/boards/components/board_card_move_to_position.vue
@@ -1,19 +1,17 @@
<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlDisclosureDropdown } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import { s__ } from '~/locale';
-
import Tracking from '~/tracking';
+import {
+ BOARD_CARD_MOVE_TO_POSITIONS_OPTIONS,
+ BOARD_CARD_MOVE_TO_POSITIONS_START_OPTION,
+} from '../constants';
export default {
- i18n: {
- moveToStartText: s__('Boards|Move to start of list'),
- moveToEndText: s__('Boards|Move to end of list'),
- },
+ BOARD_CARD_MOVE_TO_POSITIONS_OPTIONS,
name: 'BoardCardMoveToPosition',
components: {
- GlDropdown,
- GlDropdownItem,
+ GlDisclosureDropdown,
},
mixins: [Tracking.mixin()],
props: {
@@ -96,30 +94,30 @@ export default {
allItemsLoadedInList: !this.listHasNextPage,
});
},
+ selectMoveAction({ text }) {
+ if (text === BOARD_CARD_MOVE_TO_POSITIONS_START_OPTION) {
+ this.moveToStart();
+ } else {
+ this.moveToEnd();
+ }
+ },
},
};
</script>
<template>
- <gl-dropdown
+ <gl-disclosure-dropdown
ref="dropdown"
:key="itemIdentifier"
- icon="ellipsis_v"
- :text="s__('Boards|Move card')"
- :text-sr-only="true"
- class="move-to-position gl-display-block gl-mb-2 gl-ml-2 gl-mt-n3 gl-mr-n3"
+ class="move-to-position gl-display-block gl-mb-2 gl-ml-auto gl-mt-n3 gl-mr-n3 js-no-trigger"
category="tertiary"
+ :items="$options.BOARD_CARD_MOVE_TO_POSITIONS_OPTIONS"
+ icon="ellipsis_v"
:tabindex="index"
+ :toggle-text="s__('Boards|Move card')"
+ :text-sr-only="true"
no-caret
- @keydown.esc.native="$emit('hide')"
- >
- <div>
- <gl-dropdown-item @click.stop="moveToStart">
- {{ $options.i18n.moveToStartText }}
- </gl-dropdown-item>
- <gl-dropdown-item @click.stop="moveToEnd">
- {{ $options.i18n.moveToEndText }}
- </gl-dropdown-item>
- </div>
- </gl-dropdown>
+ data-testid="board-move-to-position"
+ @action="selectMoveAction"
+ />
</template>
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index b728b8dd22a..708e1539c6e 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -9,17 +9,17 @@ export default {
BoardListHeader,
BoardList,
},
- inject: {
- boardId: {
- default: '',
- },
- },
+ inject: ['isApolloBoard'],
props: {
list: {
type: Object,
default: () => ({}),
required: false,
},
+ boardId: {
+ type: String,
+ required: true,
+ },
},
computed: {
...mapState(['filterParams', 'highlightedLists']),
@@ -28,7 +28,7 @@ export default {
return this.highlightedLists.includes(this.list.id);
},
listItems() {
- return this.getBoardItemsByList(this.list.id);
+ return this.isApolloBoard ? [] : this.getBoardItemsByList(this.list.id);
},
isListDraggable() {
return isListDraggable(this.list);
@@ -84,7 +84,13 @@ export default {
:class="{ 'board-column-highlighted': highlighted }"
>
<board-list-header :list="list" />
- <board-list ref="board-list" :board-items="listItems" :list="list" />
+ <board-list
+ ref="board-list"
+ :board-id="boardId"
+ :board-items="listItems"
+ :list="list"
+ :filter-params="filterParams"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index 92f79e61f14..8a37719eae8 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -116,6 +116,8 @@ export default {
value: this.boardListsToUse,
delay: 100,
delayOnTouchOnly: true,
+ filter: 'input',
+ preventOnFilter: false,
};
return this.canDragColumns ? options : {};
@@ -172,6 +174,7 @@ export default {
v-for="(list, index) in boardListsToUse"
:key="index"
ref="board"
+ :board-id="boardId"
:list="list"
:data-draggable-item-type="$options.draggableItemTypes.list"
:class="{ 'gl-xs-display-none!': addColumnFormVisible }"
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index e6d1e558c37..6227f185eda 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -6,12 +6,13 @@ import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdow
import { __, sprintf } from '~/locale';
import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
-import { BoardType, ISSUABLE, INCIDENT, issuableTypes } from '~/boards/constants';
+import { BoardType, ISSUABLE, INCIDENT } from '~/boards/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_ISSUE } from '~/issues/constants';
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
-import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue';
+import SidebarSeverityWidget from '~/sidebar/components/severity/sidebar_severity_widget.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import SidebarLabelsWidget from '~/sidebar/components/labels/labels_select_widget/labels_select_root.vue';
@@ -30,7 +31,7 @@ export default {
SidebarSubscriptionsWidget,
SidebarDropdownWidget,
SidebarTodoWidget,
- SidebarSeverity,
+ SidebarSeverityWidget,
MountingPortal,
SidebarHealthStatusWidget: () =>
import('ee_component/sidebar/components/health_status/sidebar_health_status_widget.vue'),
@@ -66,7 +67,7 @@ export default {
default: false,
},
issuableType: {
- default: issuableTypes.issue,
+ default: TYPE_ISSUE,
},
isGroupBoard: {
default: false,
@@ -174,7 +175,7 @@ export default {
/>
</template>
<template #default>
- <board-sidebar-title />
+ <board-sidebar-title data-testid="sidebar-title" />
<sidebar-assignees-widget
:iid="activeBoardItem.iid"
:full-path="fullPath"
@@ -237,7 +238,7 @@ export default {
>
{{ __('None') }}
</sidebar-labels-widget>
- <sidebar-severity
+ <sidebar-severity-widget
v-if="isIncidentSidebar"
:iid="activeBoardItem.iid"
:project-path="fullPath"
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index ce86a4d3123..1bc5d910561 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -327,7 +327,6 @@ export default {
if (Array.isArray(value)) {
return value.map((valueItem) => encodeURIComponent(valueItem));
}
-
return encodeURIComponent(value);
}
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 060a708a22f..6f2b35f5191 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -8,7 +8,13 @@ import { sortableStart, sortableEnd } from '~/sortable/utils';
import Tracking from '~/tracking';
import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
-import { toggleFormEventPrefix, DraggableItemTypes } from '../constants';
+import {
+ DEFAULT_BOARD_LIST_ITEMS_SIZE,
+ toggleFormEventPrefix,
+ DraggableItemTypes,
+ listIssuablesQueries,
+ ListType,
+} from 'ee_else_ce/boards/constants';
import eventHub from '../eventhub';
import BoardCard from './board_card.vue';
import BoardNewIssue from './board_new_issue.vue';
@@ -31,12 +37,24 @@ export default {
BoardCardMoveToPosition,
},
mixins: [Tracking.mixin()],
- inject: ['isEpicBoard', 'disabled'],
+ inject: [
+ 'isEpicBoard',
+ 'isGroupBoard',
+ 'disabled',
+ 'fullPath',
+ 'boardType',
+ 'issuableType',
+ 'isApolloBoard',
+ ],
props: {
list: {
type: Object,
required: true,
},
+ boardId: {
+ type: String,
+ required: true,
+ },
boardItems: {
type: Array,
required: true,
@@ -48,6 +66,8 @@ export default {
showCount: false,
showIssueForm: false,
showEpicForm: false,
+ currentList: null,
+ isLoadingMore: false,
};
},
apollo: {
@@ -66,15 +86,50 @@ export default {
return this.isEpicBoard;
},
},
+ currentList: {
+ query() {
+ return listIssuablesQueries[this.issuableType].query;
+ },
+ variables() {
+ return {
+ id: this.list.id,
+ ...this.listQueryVariables,
+ };
+ },
+ skip() {
+ return !this.isApolloBoard || this.list.collapsed;
+ },
+ update(data) {
+ return data[this.boardType].board.lists.nodes[0];
+ },
+ context: {
+ isSingleRequest: true,
+ },
+ },
},
computed: {
...mapState(['pageInfoByListId', 'listsFlags', 'filterParams', 'isUpdateIssueOrderInProgress']),
+ boardListItems() {
+ return this.isApolloBoard
+ ? this.currentList?.[`${this.issuableType}s`].nodes || []
+ : this.boardItems;
+ },
+ listQueryVariables() {
+ return {
+ fullPath: this.fullPath,
+ boardId: this.boardId,
+ filters: this.filterParams,
+ isGroup: this.isGroupBoard,
+ isProject: !this.isGroupBoard,
+ first: DEFAULT_BOARD_LIST_ITEMS_SIZE,
+ };
+ },
listItemsCount() {
return this.isEpicBoard ? this.list.epicsCount : this.boardList?.issuesCount;
},
paginatedIssueText() {
return sprintf(__('Showing %{pageSize} of %{total} %{issuableType}'), {
- pageSize: this.boardItems.length,
+ pageSize: this.boardListItems.length,
total: this.listItemsCount,
issuableType: this.isEpicBoard ? 'epics' : 'issues',
});
@@ -86,13 +141,17 @@ export default {
return this.list.maxIssueCount > 0 && this.listItemsCount > this.list.maxIssueCount;
},
hasNextPage() {
- return this.pageInfoByListId[this.list.id]?.hasNextPage;
+ return this.isApolloBoard
+ ? this.currentList?.[`${this.issuableType}s`].pageInfo?.hasNextPage
+ : this.pageInfoByListId[this.list.id]?.hasNextPage;
},
loading() {
- return this.listsFlags[this.list.id]?.isLoading;
+ return this.isApolloBoard
+ ? this.$apollo.queries.currentList.loading && !this.isLoadingMore
+ : this.listsFlags[this.list.id]?.isLoading;
},
loadingMore() {
- return this.listsFlags[this.list.id]?.isLoadingMore;
+ return this.isApolloBoard ? this.isLoadingMore : this.listsFlags[this.list.id]?.isLoadingMore;
},
epicCreateFormVisible() {
return this.isEpicBoard && this.list.listType !== 'closed' && this.showEpicForm;
@@ -105,7 +164,7 @@ export default {
return this.canMoveIssue ? this.$refs.list.$el : this.$refs.list;
},
showingAllItems() {
- return this.boardItems.length === this.listItemsCount;
+ return this.boardListItems.length === this.listItemsCount;
},
showingAllItemsText() {
return this.isEpicBoard
@@ -128,7 +187,7 @@ export default {
tag: 'ul',
'ghost-class': 'board-card-drag-active',
'data-list-id': this.list.id,
- value: this.boardItems,
+ value: this.boardListItems,
delay: 100,
delayOnTouchOnly: true,
};
@@ -138,9 +197,12 @@ export default {
disableScrollingWhenMutationInProgress() {
return this.hasNextPage && this.isUpdateIssueOrderInProgress;
},
+ showMoveToPosition() {
+ return !this.disabled && this.list.listType !== ListType.closed;
+ },
},
watch: {
- boardItems() {
+ boardListItems() {
this.$nextTick(() => {
this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
});
@@ -165,10 +227,10 @@ export default {
methods: {
...mapActions(['fetchItemsForList', 'moveItem']),
listHeight() {
- return this.listRef.getBoundingClientRect().height;
+ return this.listRef?.getBoundingClientRect()?.height || 0;
},
scrollHeight() {
- return this.listRef.scrollHeight;
+ return this.listRef?.scrollHeight || 0;
},
scrollTop() {
return this.listRef.scrollTop + this.listHeight();
@@ -176,8 +238,20 @@ export default {
scrollToTop() {
this.listRef.scrollTop = 0;
},
- loadNextPage() {
- this.fetchItemsForList({ listId: this.list.id, fetchNext: true });
+ async loadNextPage() {
+ if (this.isApolloBoard) {
+ this.isLoadingMore = true;
+ await this.$apollo.queries.currentList.fetchMore({
+ variables: {
+ ...this.listQueryVariables,
+ id: this.list.id,
+ after: this.currentList?.[`${this.issuableType}s`].pageInfo.endCursor,
+ },
+ });
+ this.isLoadingMore = false;
+ } else {
+ this.fetchItemsForList({ listId: this.list.id, fetchNext: true });
+ }
},
toggleForm() {
if (this.isEpicBoard) {
@@ -292,7 +366,7 @@ export default {
:data-board="list.id"
:data-board-type="list.listType"
:class="{
- 'bg-danger-100': boardItemsSizeExceedsMax,
+ 'gl-bg-red-100 gl-rounded-bottom-left-base gl-rounded-bottom-right-base': boardItemsSizeExceedsMax,
'gl-overflow-hidden': disableScrollingWhenMutationInProgress,
'gl-overflow-y-auto': !disableScrollingWhenMutationInProgress,
}"
@@ -303,7 +377,7 @@ export default {
@end="handleDragOnEnd"
>
<board-card
- v-for="(item, index) in boardItems"
+ v-for="(item, index) in boardListItems"
ref="issue"
:key="item.id"
:index="index"
@@ -312,13 +386,12 @@ export default {
:data-draggable-item-type="$options.draggableItemTypes.card"
:show-work-item-type-icon="!isEpicBoard"
>
- <!-- TODO: remove the condition when https://gitlab.com/gitlab-org/gitlab/-/issues/377862 is resolved -->
<board-card-move-to-position
- v-if="!isEpicBoard && !disabled"
+ v-if="showMoveToPosition"
:item="item"
:index="index"
:list="list"
- :list-items-length="boardItems.length"
+ :list-items-length="boardListItems.length"
/>
</board-card>
<gl-intersection-observer @appear="onReachingListBottom">
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 14dff8de70f..749fae0c426 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -125,7 +125,7 @@ export default {
return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
},
chevronIcon() {
- return this.list.collapsed ? 'chevron-right' : 'chevron-down';
+ return this.list.collapsed ? 'chevron-lg-right' : 'chevron-lg-down';
},
isNewIssueShown() {
return (this.listType === ListType.backlog || this.showListHeaderButton) && !this.isEpicBoard;
@@ -135,7 +135,9 @@ export default {
},
isSettingsShown() {
return (
- this.listType !== ListType.backlog && this.showListHeaderButton && !this.list.collapsed
+ this.listType !== ListType.backlog &&
+ this.listType !== ListType.closed &&
+ !this.list.collapsed
);
},
uniqueKey() {
@@ -321,6 +323,7 @@ export default {
v-if="listType !== 'label'"
v-gl-tooltip.hover
:class="{
+ 'gl-text-gray-500': list.collapsed,
'gl-display-block': list.collapsed || listType === 'milestone',
}"
:title="listTitle"
@@ -376,7 +379,7 @@ export default {
<!-- EE end -->
<div
- class="issue-count-badge gl-display-inline-flex gl-pr-2 no-drag gl-text-secondary"
+ class="gl-font-sm issue-count-badge gl-display-inline-flex gl-pr-2 no-drag gl-text-secondary"
data-testid="issue-count-badge"
:class="{
'gl-display-none!': list.collapsed && isSwimlanesHeader,
@@ -386,7 +389,7 @@ export default {
<span class="gl-display-inline-flex" :class="{ 'gl-rotate-90': list.collapsed }">
<gl-tooltip :target="() => $refs.itemCount" :title="itemsTooltipLabel" />
<span ref="itemCount" class="gl-display-inline-flex gl-align-items-center">
- <gl-icon class="gl-mr-2" :name="countIcon" :size="16" />
+ <gl-icon class="gl-mr-2" :name="countIcon" :size="14" />
<item-count
v-if="!isLoading"
:items-size="isEpicBoard ? list.epicsCount : boardList.issuesCount"
@@ -397,7 +400,7 @@ export default {
<template v-if="canShowTotalWeight">
<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" />
+ <gl-icon class="gl-mr-2" name="weight" :size="14" />
{{ totalWeight }}
</span>
</template>
@@ -413,6 +416,7 @@ export default {
:aria-label="$options.i18n.newIssue"
:title="$options.i18n.newIssue"
class="no-drag"
+ size="small"
icon="plus"
@click="showNewIssueForm"
/>
@@ -424,6 +428,7 @@ export default {
:aria-label="$options.i18n.newEpic"
:title="$options.i18n.newEpic"
class="no-drag"
+ size="small"
icon="plus"
@click="showNewEpicForm"
/>
@@ -434,6 +439,7 @@ export default {
v-gl-tooltip.hover
:aria-label="$options.i18n.listSettings"
class="no-drag"
+ size="small"
:title="$options.i18n.listSettings"
icon="settings"
@click="openSidebarSettings"
diff --git a/app/assets/javascripts/boards/components/board_top_bar.vue b/app/assets/javascripts/boards/components/board_top_bar.vue
index 368feba9a44..2e20ed70bb0 100644
--- a/app/assets/javascripts/boards/components/board_top_bar.vue
+++ b/app/assets/javascripts/boards/components/board_top_bar.vue
@@ -2,6 +2,7 @@
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
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 ConfigToggle from './config_toggle.vue';
import NewBoardButton from './new_board_button.vue';
import ToggleFocus from './toggle_focus.vue';
@@ -19,7 +20,46 @@ export default {
EpicBoardFilteredSearch: () =>
import('ee_component/boards/components/epic_filtered_search.vue'),
},
- inject: ['swimlanesFeatureAvailable', 'canAdminList', 'isSignedIn', 'isIssueBoard'],
+ inject: [
+ 'swimlanesFeatureAvailable',
+ 'canAdminList',
+ 'isSignedIn',
+ 'isIssueBoard',
+ 'fullPath',
+ 'boardType',
+ 'isEpicBoard',
+ 'isApolloBoard',
+ ],
+ props: {
+ boardId: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ board: {},
+ };
+ },
+ apollo: {
+ board: {
+ query() {
+ return getBoardQuery(this.boardType, this.isEpicBoard);
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ boardId: this.boardId,
+ };
+ },
+ skip() {
+ return !this.isApolloBoard;
+ },
+ update(data) {
+ return data.workspace.board;
+ },
+ },
+ },
};
</script>
@@ -31,7 +71,7 @@ export default {
<div
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-flex-grow-1 gl-lg-mb-0 gl-mb-3 gl-w-full"
>
- <boards-selector />
+ <boards-selector :board-apollo="board" @switchBoard="$emit('switchBoard', $event)" />
<new-board-button />
<issue-board-filtered-search v-if="isIssueBoard" />
<epic-board-filtered-search v-else />
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index d26aeb69dd5..a1a49386b37 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -51,6 +51,7 @@ export default {
'weights',
'boardType',
'isGroupBoard',
+ 'isApolloBoard',
],
props: {
throttleDuration: {
@@ -58,15 +59,20 @@ export default {
default: 200,
required: false,
},
+ boardApollo: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
data() {
return {
hasScrollFade: false,
- loadingBoards: 0,
- loadingRecentBoards: false,
scrollFadeInitialized: false,
boards: [],
recentBoards: [],
+ loadingBoards: false,
+ loadingRecentBoards: false,
throttledSetScrollFade: throttle(this.setScrollFade, this.throttleDuration),
contentClientHeight: 0,
maxPosition: 0,
@@ -77,11 +83,14 @@ export default {
computed: {
...mapState(['board', 'isBoardLoading']),
+ boardToUse() {
+ return this.isApolloBoard ? this.boardApollo : this.board;
+ },
parentType() {
return this.boardType;
},
loading() {
- return this.loadingRecentBoards || Boolean(this.loadingBoards);
+ return this.loadingRecentBoards || this.loadingBoards;
},
filteredBoards() {
return this.boards.filter((board) =>
@@ -94,6 +103,9 @@ export default {
showDelete() {
return this.boards.length > 1;
},
+ showDropdown() {
+ return this.showCreate || this.hasMissingBoards;
+ },
scrollFadeClass() {
return {
'fade-out': !this.hasScrollFade,
@@ -116,7 +128,7 @@ export default {
this.scrollFadeInitialized = false;
this.$nextTick(this.setScrollFade);
},
- board(newBoard) {
+ boardToUse(newBoard) {
document.title = newBoard.name;
},
},
@@ -159,8 +171,10 @@ export default {
return { fullPath: this.fullPath };
},
query: this.boardQuery,
- loadingKey: 'loadingBoards',
update: (data) => this.boardUpdate(data, 'boards'),
+ watchLoading: (isLoading) => {
+ this.loadingBoards = isLoading;
+ },
});
this.loadRecentBoards();
@@ -171,8 +185,10 @@ export default {
return { fullPath: this.fullPath };
},
query: this.recentBoardsQuery,
- loadingKey: 'loadingRecentBoards',
update: (data) => this.boardUpdate(data, 'recentIssueBoards'),
+ watchLoading: (isLoading) => {
+ this.loadingRecentBoards = isLoading;
+ },
});
},
isScrolledUp() {
@@ -210,9 +226,14 @@ export default {
boardType: this.boardType,
});
},
+ fullBoardId(boardId) {
+ return fullBoardId(boardId);
+ },
async switchBoard(boardId, e) {
if (isMetaKey(e)) {
window.open(`${this.boardBaseUrl}/${boardId}`, '_blank');
+ } else if (this.isApolloBoard) {
+ this.$emit('switchBoard', this.fullBoardId(boardId));
} else {
this.unsetActiveId();
this.fetchCurrentBoard(boardId);
@@ -230,12 +251,13 @@ export default {
<div class="boards-switcher gl-mr-3" data-testid="boards-selector">
<span class="boards-selector-wrapper">
<gl-dropdown
+ v-if="showDropdown"
data-testid="boards-dropdown"
data-qa-selector="boards_dropdown"
toggle-class="dropdown-menu-toggle"
menu-class="flex-column dropdown-extended-height"
:loading="isBoardLoading"
- :text="board.name"
+ :text="boardToUse.name"
@show="loadBoards"
>
<p class="gl-dropdown-header-top" @mousedown.prevent>
@@ -333,7 +355,7 @@ export default {
:can-admin-board="canAdminBoard"
:scoped-issue-board-feature-enabled="scopedIssueBoardFeatureEnabled"
:weights="weights"
- :current-board="board"
+ :current-board="boardToUse"
:current-page="currentPage"
@cancel="cancel"
/>
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 38a171e8889..7749391ec6f 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -7,7 +7,7 @@ import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_sea
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import issueBoardFilters from '~/boards/issue_board_filters';
-import { TYPE_USER } from '~/graphql_shared/constants';
+import { TYPENAME_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import {
@@ -181,7 +181,7 @@ export default {
return gon?.current_user_id
? [
{
- id: convertToGraphQLId(TYPE_USER, gon.current_user_id),
+ id: convertToGraphQLId(TYPENAME_USER, gon.current_user_id),
name: gon.current_user_fullname,
username: gon.current_username,
avatarUrl: gon.current_user_avatar_url,
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index b09b1d48ca5..c3f7c7d3ca2 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -102,7 +102,7 @@ export default {
<gl-tooltip :target="() => $refs.issueDueDate" :placement="tooltipPlacement">
<span class="bold">{{ __('Due date') }}</span>
<br />
- <span :class="{ 'text-danger-muted': isPastDue }">{{ title }}</span>
+ <span :class="{ 'gl-text-red-300': isPastDue }">{{ title }}</span>
</gl-tooltip>
</span>
</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
index 53e574e9942..43a2b13b81c 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput, GlLink } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
import { joinPaths } from '~/lib/utils/url_utility';
@@ -13,6 +13,7 @@ export default {
GlButton,
GlFormGroup,
GlFormInput,
+ GlLink,
BoardEditableItem,
},
directives: {
@@ -130,7 +131,11 @@ export default {
@off-click="handleOffClick"
>
<template #title>
- <span data-testid="item-title">{{ item.title }}</span>
+ <span data-testid="item-title">
+ <gl-link class="gl-reset-color gl-hover-text-blue-800" :href="item.webUrl">
+ {{ item.title }}
+ </gl-link>
+ </span>
</template>
<template #collapsed>
<span class="gl-text-gray-800">{{ item.referencePath }}</span>