diff options
Diffstat (limited to 'app/assets/javascripts/boards')
16 files changed, 69 insertions, 87 deletions
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue index 692ca6bf59b..c441a718dd8 100644 --- a/app/assets/javascripts/boards/components/board_card_inner.vue +++ b/app/assets/javascripts/boards/components/board_card_inner.vue @@ -20,6 +20,7 @@ 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'; @@ -45,6 +46,7 @@ export default { }, mixins: [boardCardInner], inject: [ + 'allowSubEpics', 'rootPath', 'scopedLabelsAvailable', 'isEpicBoard', @@ -85,7 +87,7 @@ export default { }; }, computed: { - ...mapState(['isShowingLabels', 'allowSubEpics']), + ...mapState(['isShowingLabels']), isLoading() { return this.item.isLoading || this.item.iid === '-1'; }, @@ -175,7 +177,8 @@ export default { }, }, methods: { - ...mapActions(['performSearch', 'setError']), + ...mapActions(['performSearch']), + setError, isIndexLessThanlimit(index) { return index < this.limitBeforeCounter; }, @@ -288,7 +291,7 @@ export default { <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-5" /> <span v-if="item.referencePath && !isLoading" - class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3 gl-font-sm gl-text-secondary" + class="board-card-number gl-overflow-hidden gl-display-flex gl-gap-2 gl-mr-3 gl-mt-3 gl-font-sm gl-text-secondary" :class="{ 'gl-font-base': isEpicBoard }" > <work-item-type-icon diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue index 5e1e46dd198..bb740c0e7eb 100644 --- a/app/assets/javascripts/boards/components/board_content_sidebar.vue +++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue @@ -222,7 +222,7 @@ export default { <template #default> <board-sidebar-title :active-item="activeBoardIssuable" data-testid="sidebar-title" /> <sidebar-assignees-widget - v-if="activeBoardItem.assignees" + v-if="activeBoardIssuable.assignees" :iid="activeBoardIssuable.iid" :full-path="projectPathForActiveIssue" :initial-assignees="activeBoardIssuable.assignees" @@ -232,7 +232,7 @@ export default { /> <sidebar-dropdown-widget v-if="epicFeatureAvailable && !isIncidentSidebar" - :key="`epic-${activeBoardItem.iid}`" + :key="`epic-${activeBoardIssuable.iid}`" :iid="activeBoardIssuable.iid" issuable-attribute="epic" :workspace-path="projectPathForActiveIssue" @@ -242,7 +242,7 @@ export default { /> <div> <sidebar-dropdown-widget - :key="`milestone-${activeBoardItem.iid}`" + :key="`milestone-${activeBoardIssuable.iid}`" :iid="activeBoardIssuable.iid" issuable-attribute="milestone" :workspace-path="projectPathForActiveIssue" @@ -252,7 +252,7 @@ export default { /> <sidebar-iteration-widget v-if="iterationFeatureAvailable && !isIncidentSidebar" - :key="`iteration-${activeBoardItem.iid}`" + :key="`iteration-${activeBoardIssuable.iid}`" :iid="activeBoardIssuable.iid" :workspace-path="projectPathForActiveIssue" :attr-workspace-path="groupPathForActiveIssue" diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue index 4986c3780e5..d12478b42d8 100644 --- a/app/assets/javascripts/boards/components/board_form.vue +++ b/app/assets/javascripts/boards/components/board_form.vue @@ -178,6 +178,9 @@ export default { }, methods: { ...mapActions(['setError', 'unsetError', 'setBoard']), + isFocusMode() { + return Boolean(document.querySelector('.content-wrapper > .js-focus-mode-board.is-focused')); + }, cancel() { this.$emit('cancel'); }, @@ -281,6 +284,7 @@ export default { modal-class="board-config-modal" content-class="gl-absolute gl-top-7" visible + :static="isFocusMode()" :hide-footer="readonly" :title="title" :action-primary="primaryProps" diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index 67bfcfb9d97..1bb7e88122a 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -88,6 +88,7 @@ export default { toListId: null, toList: {}, addItemToListInProgress: false, + updateIssueOrderInProgress: false, }; }, apollo: { @@ -253,7 +254,9 @@ export default { return this.canMoveIssue ? options : {}; }, disableScrollingWhenMutationInProgress() { - return this.hasNextPage && this.isUpdateIssueOrderInProgress; + return ( + this.hasNextPage && (this.isUpdateIssueOrderInProgress || this.updateIssueOrderInProgress) + ); }, showMoveToPosition() { return !this.disabled && this.list.listType !== ListType.closed; @@ -343,7 +346,7 @@ export default { sortableStart(); this.track('drag_card', { label: 'board' }); }, - handleDragOnEnd({ + async handleDragOnEnd({ newIndex: originalNewIndex, oldIndex, from, @@ -394,7 +397,8 @@ export default { } if (this.isApolloBoard) { - this.moveBoardItem( + this.updateIssueOrderInProgress = true; + await this.moveBoardItem( { epicId: itemId, iid: itemIid, @@ -404,7 +408,9 @@ export default { moveAfterId, }, newIndex, - ); + ).finally(() => { + this.updateIssueOrderInProgress = false; + }); } else { this.moveItem({ itemId, diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index 068db98a750..42c30dc8245 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -490,7 +490,11 @@ 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"> + <span + ref="itemCount" + class="gl-display-inline-flex gl-align-items-center" + data-testid="item-count" + > <gl-icon class="gl-mr-2" :name="countIcon" :size="14" /> <item-count v-if="!isLoading" diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue index 58db2c9ac2a..89e13625210 100644 --- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue +++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue @@ -166,7 +166,7 @@ export default { <mounting-portal mount-to="#js-right-sidebar-portal" name="board-settings-sidebar" append> <gl-drawer v-bind="$attrs" - class="js-board-settings-sidebar gl-absolute boards-sidebar" + class="js-board-settings-sidebar boards-sidebar" :open="showSidebar" variant="sidebar" @close="unsetActiveListId" diff --git a/app/assets/javascripts/boards/components/board_top_bar.vue b/app/assets/javascripts/boards/components/board_top_bar.vue index 2b8418333a8..7fd1a934381 100644 --- a/app/assets/javascripts/boards/components/board_top_bar.vue +++ b/app/assets/javascripts/boards/components/board_top_bar.vue @@ -93,6 +93,9 @@ export default { }); return hasScope; }, + isLoading() { + return this.$apollo.queries.board.loading; + }, }, }; </script> @@ -105,7 +108,11 @@ 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 gl-min-w-0" > - <boards-selector :board-apollo="board" @switchBoard="$emit('switchBoard', $event)" /> + <boards-selector + :board-apollo="board" + :is-current-board-loading="isLoading" + @switchBoard="$emit('switchBoard', $event)" + /> <new-board-button /> <issue-board-filtered-search v-if="isIssueBoard" diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue index b3fe52944dc..cc6fde92f9b 100644 --- a/app/assets/javascripts/boards/components/boards_selector.vue +++ b/app/assets/javascripts/boards/components/boards_selector.vue @@ -70,6 +70,11 @@ export default { required: false, default: () => ({}), }, + isCurrentBoardLoading: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -92,6 +97,9 @@ export default { boardToUse() { return this.isApolloBoard ? this.boardApollo : this.board; }, + isBoardToUseLoading() { + return this.isApolloBoard ? this.isCurrentBoardLoading : this.isBoardLoading; + }, parentType() { return this.boardType; }, @@ -301,7 +309,7 @@ export default { data-qa-selector="boards_dropdown" toggle-class="dropdown-menu-toggle" menu-class="flex-column dropdown-extended-height" - :loading="isBoardLoading" + :loading="isBoardToUseLoading" :text="boardToUse.name" @show="loadBoards" > 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 f60f00be368..a7b3f5536a4 100644 --- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue +++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue @@ -62,7 +62,7 @@ export default { tokensCE() { const { issue, incident } = this.$options.i18n; const { types } = this.$options; - const { fetchUsers, fetchLabels, fetchMilestones } = issueBoardFilters( + const { fetchUsers, fetchLabels } = issueBoardFilters( this.$apollo, this.fullPath, this.isGroupBoard, @@ -148,7 +148,8 @@ export default { token: MilestoneToken, unique: true, shouldSkipSort: true, - fetchMilestones, + isProject: !this.isGroupBoard, + fullPath: this.fullPath, }, { icon: 'issues', diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue index 1f28974afd1..46009df2bd3 100644 --- a/app/assets/javascripts/boards/components/issue_due_date.vue +++ b/app/assets/javascripts/boards/components/issue_due_date.vue @@ -52,11 +52,14 @@ export default { if (timeDifference === 0) { return __('Today'); - } else if (timeDifference === 1) { + } + if (timeDifference === 1) { return __('Tomorrow'); - } else if (timeDifference === -1) { + } + if (timeDifference === -1) { return __('Yesterday'); - } else if (timeDifference > 0 && timeDifference < 7) { + } + if (timeDifference > 0 && timeDifference < 7) { return dateFormat(issueDueDate, 'dddd'); } 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 1c2c0022ddf..a2c4b42b6c5 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue @@ -7,6 +7,7 @@ import { joinPaths } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; import { titleQueries } from 'ee_else_ce/boards/constants'; +import { setError } from '../../graphql/cache_updates'; export default { components: { @@ -65,7 +66,7 @@ export default { }, }, methods: { - ...mapActions(['setActiveItemTitle', 'setError']), + ...mapActions(['setActiveItemTitle']), getPendingChangesKey(item) { if (!item) { return ''; @@ -130,7 +131,7 @@ export default { this.showChangesAlert = false; } catch (e) { this.title = this.item.title; - this.setError({ error: e, message: this.$options.i18n.updateTitleError }); + setError({ error: e, message: this.$options.i18n.updateTitleError }); } finally { this.loading = false; } diff --git a/app/assets/javascripts/boards/graphql/cache_updates.js b/app/assets/javascripts/boards/graphql/cache_updates.js index e54701a63c0..3551c3ed982 100644 --- a/app/assets/javascripts/boards/graphql/cache_updates.js +++ b/app/assets/javascripts/boards/graphql/cache_updates.js @@ -109,9 +109,9 @@ export function updateEpicsCount({ epicBoardList: { ...epicBoardList, metadata: { + ...epicBoardList.metadata, epicsCount: epicBoardList.metadata.epicsCount - 1, totalWeight: epicBoardList.metadata.totalWeight - epicWeight, - ...epicBoardList.metadata, }, }, }), @@ -127,9 +127,9 @@ export function updateEpicsCount({ epicBoardList: { ...epicBoardList, metadata: { + ...epicBoardList.metadata, epicsCount: epicBoardList.metadata.epicsCount + 1, totalWeight: epicBoardList.metadata.totalWeight + epicWeight, - ...epicBoardList.metadata, }, }, }), diff --git a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql deleted file mode 100644 index 252e8c1ab06..00000000000 --- a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql +++ /dev/null @@ -1,15 +0,0 @@ -#import "~/graphql_shared/fragments/user.fragment.graphql" - -query GroupBoardMembers($fullPath: ID!, $search: String) { - workspace: group(fullPath: $fullPath) { - id - assignees: groupMembers(search: $search, relations: [DIRECT, DESCENDANTS, INHERITED]) { - nodes { - id - user { - ...User - } - } - } - } -} diff --git a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql deleted file mode 100644 index 5279680b03c..00000000000 --- a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql +++ /dev/null @@ -1,15 +0,0 @@ -#import "~/graphql_shared/fragments/user.fragment.graphql" - -query ProjectBoardMembers($fullPath: ID!, $search: String) { - workspace: project(fullPath: $fullPath) { - id - assignees: projectMembers(search: $search) { - nodes { - id - user { - ...User - } - } - } - } -} diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index a03ec9193ea..9d7b7a38c6d 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -102,6 +102,7 @@ function mountBoardApp(el) { swimlanesFeatureAvailable: gon.licensed_features?.swimlanes, multipleIssueBoardsAvailable: parseBoolean(el.dataset.multipleBoardsAvailable), scopedIssueBoardFeatureEnabled: parseBoolean(el.dataset.scopedIssueBoardFeatureEnabled), + allowSubEpics: false, }, render: (createComponent) => createComponent(BoardApp), }); diff --git a/app/assets/javascripts/boards/issue_board_filters.js b/app/assets/javascripts/boards/issue_board_filters.js index 27efb3f775c..ba5da70c6ec 100644 --- a/app/assets/javascripts/boards/issue_board_filters.js +++ b/app/assets/javascripts/boards/issue_board_filters.js @@ -1,7 +1,5 @@ -import groupBoardMembers from '~/boards/graphql/group_board_members.query.graphql'; -import projectBoardMembers from '~/boards/graphql/project_board_members.query.graphql'; -import groupBoardMilestonesQuery from './graphql/group_board_milestones.query.graphql'; -import projectBoardMilestonesQuery from './graphql/project_board_milestones.query.graphql'; +import { BoardType } from 'ee_else_ce/boards/constants'; +import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql'; import boardLabels from './graphql/board_labels.query.graphql'; export default function issueBoardFilters(apollo, fullPath, isGroupBoard) { @@ -9,20 +7,15 @@ export default function issueBoardFilters(apollo, fullPath, isGroupBoard) { return isGroupBoard ? data.group?.labels.nodes || [] : data.project?.labels.nodes || []; }; - const boardAssigneesQuery = () => { - return isGroupBoard ? groupBoardMembers : projectBoardMembers; - }; - const fetchUsers = (usersSearchTerm) => { + const namespace = isGroupBoard ? BoardType.group : BoardType.project; + return apollo .query({ - query: boardAssigneesQuery(), - variables: { - fullPath, - search: usersSearchTerm, - }, + query: usersAutocompleteQuery, + variables: { fullPath, search: usersSearchTerm, isProject: !isGroupBoard }, }) - .then(({ data }) => data.workspace?.assignees.nodes.map(({ user }) => user)); + .then(({ data }) => data[namespace]?.autocompleteUsers); }; const fetchLabels = (labelSearchTerm) => { @@ -39,27 +32,8 @@ export default function issueBoardFilters(apollo, fullPath, isGroupBoard) { .then(transformLabels); }; - const fetchMilestones = (searchTerm) => { - const variables = { - fullPath, - searchTerm, - }; - - const query = isGroupBoard ? groupBoardMilestonesQuery : projectBoardMilestonesQuery; - - return apollo - .query({ - query, - variables, - }) - .then(({ data }) => { - return data.workspace?.milestones.nodes; - }); - }; - return { fetchLabels, fetchUsers, - fetchMilestones, }; } |