diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
commit | 0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch) | |
tree | 7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /app/assets/javascripts/boards | |
parent | 72123183a20411a36d607d70b12d57c484394c8e (diff) |
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'app/assets/javascripts/boards')
11 files changed, 96 insertions, 91 deletions
diff --git a/app/assets/javascripts/boards/components/board_app.vue b/app/assets/javascripts/boards/components/board_app.vue index 858aabb0f05..af753151be8 100644 --- a/app/assets/javascripts/boards/components/board_app.vue +++ b/app/assets/javascripts/boards/components/board_app.vue @@ -1,5 +1,6 @@ <script> -import { mapActions, mapGetters } from 'vuex'; +import { mapGetters } from 'vuex'; +import { refreshCurrentPage } from '~/lib/utils/url_utility'; import BoardContent from '~/boards/components/board_content.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardTopBar from '~/boards/components/board_top_bar.vue'; @@ -14,11 +15,11 @@ export default { computed: { ...mapGetters(['isSidebarOpen']), }, - mounted() { - this.performSearch(); + created() { + window.addEventListener('popstate', refreshCurrentPage); }, - methods: { - ...mapActions(['performSearch']), + destroyed() { + window.removeEventListener('popstate', refreshCurrentPage); }, }; </script> diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue index 9d972860d06..9f359a25234 100644 --- a/app/assets/javascripts/boards/components/board_form.vue +++ b/app/assets/javascripts/boards/components/board_form.vue @@ -1,7 +1,8 @@ <script> import { GlModal, GlAlert } from '@gitlab/ui'; import { mapGetters, mapActions, mapState } from 'vuex'; -import { getParameterByName, visitUrl } from '~/lib/utils/url_utility'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import { visitUrl, updateHistory, getParameterByName } from '~/lib/utils/url_utility'; import { __, s__ } from '~/locale'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { formType } from '../constants'; @@ -170,17 +171,7 @@ export default { } }, methods: { - ...mapActions(['setError', 'unsetError']), - boardCreateResponse(data) { - return data.createBoard.board.webPath; - }, - boardUpdateResponse(data) { - const path = data.updateBoard.board.webPath; - const param = getParameterByName('group_by') - ? `?group_by=${getParameterByName('group_by')}` - : ''; - return `${path}${param}`; - }, + ...mapActions(['setError', 'unsetError', 'setBoard']), cancel() { this.$emit('cancel'); }, @@ -191,10 +182,10 @@ export default { }); if (!this.board.id) { - return this.boardCreateResponse(response.data); + return response.data.createBoard.board; } - return this.boardUpdateResponse(response.data); + return response.data.updateBoard.board; }, async deleteBoard() { await this.$apollo.mutate({ @@ -218,8 +209,14 @@ export default { } } else { try { - const url = await this.createOrUpdateBoard(); - visitUrl(url); + const board = await this.createOrUpdateBoard(); + this.setBoard(board); + this.cancel(); + + const param = getParameterByName('group_by') + ? `?group_by=${getParameterByName('group_by')}` + : ''; + updateHistory({ url: `${this.boardBaseUrl}/${getIdFromGraphQLId(board.id)}${param}` }); } catch { this.setError({ message: this.$options.i18n.saveErrorMessage }); } finally { diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index a4298eb2544..a65269de743 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -45,9 +45,6 @@ export default { }, mixins: [Tracking.mixin(), glFeatureFlagMixin()], inject: { - boardId: { - default: '', - }, weightFeatureAvailable: { default: false, }, @@ -78,7 +75,7 @@ export default { }, }, computed: { - ...mapState(['activeId', 'filterParams']), + ...mapState(['activeId', 'filterParams', 'boardId']), ...mapGetters(['isEpicBoard', 'isSwimlanesOn']), isLoggedIn() { return Boolean(this.currentUserId); @@ -155,6 +152,12 @@ export default { isLoading() { return this.$apollo.queries.boardList.loading; }, + totalWeight() { + return this.boardList?.totalWeight; + }, + canShowTotalWeight() { + return this.weightFeatureAvailable && !this.isLoading; + }, }, apollo: { boardList: { @@ -359,7 +362,7 @@ export default { <div v-if="weightFeatureAvailable && !isLoading"> • <gl-sprintf :message="__('%{totalWeight} total weight')"> - <template #totalWeight>{{ boardList.totalWeight }}</template> + <template #totalWeight>{{ totalWeight }}</template> </gl-sprintf> </div> </gl-tooltip> @@ -384,11 +387,11 @@ export default { /> </span> <!-- EE start --> - <template v-if="weightFeatureAvailable && !isEpicBoard && !isLoading"> + <template v-if="canShowTotalWeight"> <gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" /> - <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3"> + <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3" data-testid="weight"> <gl-icon class="gl-mr-2" name="weight" /> - {{ boardList.totalWeight }} + {{ totalWeight }} </span> </template> <!-- EE end --> diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue index 2951eda1112..eaf3facb450 100644 --- a/app/assets/javascripts/boards/components/boards_selector.vue +++ b/app/assets/javascripts/boards/components/boards_selector.vue @@ -14,15 +14,16 @@ import { mapActions, mapGetters, mapState } from 'vuex'; 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 eventHub from '../eventhub'; import groupBoardsQuery from '../graphql/group_boards.query.graphql'; import projectBoardsQuery from '../graphql/project_boards.query.graphql'; -import groupBoardQuery from '../graphql/group_board.query.graphql'; -import projectBoardQuery from '../graphql/project_board.query.graphql'; import groupRecentBoardsQuery from '../graphql/group_recent_boards.query.graphql'; import projectRecentBoardsQuery from '../graphql/project_recent_boards.query.graphql'; +import { fullBoardId } from '../boards_util'; const MIN_BOARDS_TO_VIEW_RECENT = 10; @@ -69,48 +70,15 @@ export default { maxPosition: 0, filterTerm: '', currentPage: '', - board: {}, }; }, - apollo: { - board: { - query() { - return this.currentBoardQuery; - }, - variables() { - return { - fullPath: this.fullPath, - boardId: this.fullBoardId, - }; - }, - update(data) { - const board = data.workspace?.board; - this.setBoardConfig(board); - return { - ...board, - labels: board?.labels?.nodes, - }; - }, - error() { - this.setError({ message: this.$options.i18n.errorFetchingBoard }); - }, - }, - }, + computed: { - ...mapState(['boardType', 'fullBoardId']), + ...mapState(['boardType', 'board', 'isBoardLoading']), ...mapGetters(['isGroupBoard', 'isProjectBoard']), parentType() { return this.boardType; }, - currentBoardQueryCE() { - return this.isGroupBoard ? groupBoardQuery : projectBoardQuery; - }, - currentBoardQuery() { - return this.currentBoardQueryCE; - }, - isBoardLoading() { - return this.$apollo.queries.board.loading; - }, loading() { return this.loadingRecentBoards || Boolean(this.loadingBoards); }, @@ -147,6 +115,9 @@ export default { this.scrollFadeInitialized = false; this.$nextTick(this.setScrollFade); }, + board(newBoard) { + document.title = newBoard.name; + }, }, created() { eventHub.$on('showBoardModal', this.showPage); @@ -155,7 +126,7 @@ export default { eventHub.$off('showBoardModal', this.showPage); }, methods: { - ...mapActions(['setError', 'setBoardConfig']), + ...mapActions(['setError', 'fetchBoard', 'unsetActiveId']), showPage(page) { this.currentPage = page; }, @@ -231,6 +202,22 @@ export default { this.hasScrollFade = this.isScrolledUp(); }, + fetchCurrentBoard(boardId) { + this.fetchBoard({ + fullPath: this.fullPath, + fullBoardId: fullBoardId(boardId), + boardType: this.boardType, + }); + }, + async switchBoard(boardId, e) { + if (isMetaKey(e)) { + window.open(`${this.boardBaseUrl}/${boardId}`, '_blank'); + } else { + this.unsetActiveId(); + this.fetchCurrentBoard(boardId); + updateHistory({ url: `${this.boardBaseUrl}/${boardId}` }); + } + }, }, i18n: { errorFetchingBoard: s__('Board|An error occurred while fetching the board, please try again.'), @@ -277,8 +264,8 @@ export default { <gl-dropdown-item v-for="recentBoard in recentBoards" :key="`recent-${recentBoard.id}`" - :href="`${boardBaseUrl}/${recentBoard.id}`" data-testid="dropdown-item" + @click.prevent="switchBoard(recentBoard.id, $event)" > {{ recentBoard.name }} </gl-dropdown-item> @@ -293,8 +280,8 @@ export default { <gl-dropdown-item v-for="otherBoard in filteredBoards" :key="otherBoard.id" - :href="`${boardBaseUrl}/${otherBoard.id}`" data-testid="dropdown-item" + @click.prevent="switchBoard(otherBoard.id, $event)" > {{ otherBoard.name }} </gl-dropdown-item> diff --git a/app/assets/javascripts/boards/graphql/board_create.mutation.graphql b/app/assets/javascripts/boards/graphql/board_create.mutation.graphql index b3ea79d6443..42e164f4f3c 100644 --- a/app/assets/javascripts/boards/graphql/board_create.mutation.graphql +++ b/app/assets/javascripts/boards/graphql/board_create.mutation.graphql @@ -1,8 +1,9 @@ +#import "ee_else_ce/boards/graphql/board_scope.fragment.graphql" + mutation createBoard($input: CreateBoardInput!) { createBoard(input: $input) { board { - id - webPath + ...BoardScopeFragment } errors } diff --git a/app/assets/javascripts/boards/graphql/board_update.mutation.graphql b/app/assets/javascripts/boards/graphql/board_update.mutation.graphql index 3abe09079c7..90de7713ff3 100644 --- a/app/assets/javascripts/boards/graphql/board_update.mutation.graphql +++ b/app/assets/javascripts/boards/graphql/board_update.mutation.graphql @@ -1,8 +1,9 @@ +#import "ee_else_ce/boards/graphql/board_scope.fragment.graphql" + mutation UpdateBoard($input: UpdateBoardInput!) { updateBoard(input: $input) { board { - id - webPath + ...BoardScopeFragment } errors } diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index 8af7da1e0aa..854717ed4c4 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -54,7 +54,6 @@ function mountBoardApp(el) { apolloProvider, provide: { disabled: parseBoolean(el.dataset.disabled), - boardId, groupId: Number(groupId), rootPath, fullPath, diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index a84b678a5d9..791182af806 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -31,10 +31,12 @@ import { import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql'; import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql'; import totalCountAndWeightQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql'; +import { fetchPolicies } from '~/lib/graphql'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { queryToObject } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; +import eventHub from '../eventhub'; import { gqlClient } from '../graphql'; import projectBoardQuery from '../graphql/project_board.query.graphql'; import groupBoardQuery from '../graphql/group_board.query.graphql'; @@ -49,6 +51,8 @@ import * as types from './mutation_types'; export default { fetchBoard: ({ commit, dispatch }, { fullPath, fullBoardId, boardType }) => { + commit(types.REQUEST_CURRENT_BOARD); + const variables = { fullPath, boardId: fullBoardId, @@ -60,9 +64,12 @@ export default { variables, }) .then(({ data }) => { - const board = data.workspace?.board; - commit(types.RECEIVE_BOARD_SUCCESS, board); - dispatch('setBoardConfig', board); + if (data.workspace?.errors) { + commit(types.RECEIVE_BOARD_FAILURE); + } else { + const board = data.workspace?.board; + dispatch('setBoard', board); + } }) .catch(() => commit(types.RECEIVE_BOARD_FAILURE)); }, @@ -87,6 +94,13 @@ export default { commit(types.SET_BOARD_CONFIG, config); }, + setBoard: async ({ commit, dispatch }, board) => { + commit(types.RECEIVE_BOARD_SUCCESS, board); + await dispatch('setBoardConfig', board); + dispatch('performSearch', { resetLists: true }); + eventHub.$emit('updateTokens'); + }, + setActiveId({ commit }, { id, sidebarType }) { commit(types.SET_ACTIVE_ID, { id, sidebarType }); }, @@ -107,16 +121,16 @@ export default { ); }, - performSearch({ dispatch }) { + performSearch({ dispatch }, { resetLists = false } = {}) { dispatch( 'setFilters', convertObjectPropsToCamelCase(queryToObject(window.location.search, { gatherArrays: true })), ); - dispatch('fetchLists'); + dispatch('fetchLists', { resetLists }); dispatch('resetIssues'); }, - fetchLists: ({ commit, state, dispatch }) => { + fetchLists: ({ commit, state, dispatch }, { resetLists = false } = {}) => { const { boardType, filterParams, fullPath, fullBoardId, issuableType } = state; const variables = { @@ -133,6 +147,7 @@ export default { .query({ query: listsQuery[issuableType].query, variables, + ...(resetLists ? { fetchPolicy: fetchPolicies.NO_CACHE } : {}), }) .then(({ data }) => { const { lists, hideBacklogList } = data[boardType].board; @@ -404,9 +419,6 @@ export default { fetchItemsForList: ({ state, commit }, { listId, fetchNext = false }) => { if (!listId) return null; - if (!fetchNext) { - commit(types.RESET_ITEMS_FOR_LIST, listId); - } commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext }); const { fullPath, fullBoardId, boardType, filterParams } = state; @@ -428,6 +440,7 @@ export default { isSingleRequest: true, }, variables, + ...(!fetchNext ? { fetchPolicy: fetchPolicies.NO_CACHE } : {}), }) .then(({ data }) => { const { lists } = data[boardType].board; diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js index 668a3b5e0f9..43268f21f96 100644 --- a/app/assets/javascripts/boards/stores/mutation_types.js +++ b/app/assets/javascripts/boards/stores/mutation_types.js @@ -1,3 +1,4 @@ +export const REQUEST_CURRENT_BOARD = 'REQUEST_CURRENT_BOARD'; export const RECEIVE_BOARD_SUCCESS = 'RECEIVE_BOARD_SUCCESS'; export const RECEIVE_BOARD_FAILURE = 'RECEIVE_BOARD_FAILURE'; export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA'; @@ -17,7 +18,6 @@ export const MOVE_LISTS = 'MOVE_LISTS'; export const TOGGLE_LIST_COLLAPSED = 'TOGGLE_LIST_COLLAPSED'; export const REMOVE_LIST = 'REMOVE_LIST'; export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE'; -export const RESET_ITEMS_FOR_LIST = 'RESET_ITEMS_FOR_LIST'; export const REQUEST_ITEMS_FOR_LIST = 'REQUEST_ITEMS_FOR_LIST'; export const RECEIVE_ITEMS_FOR_LIST_FAILURE = 'RECEIVE_ITEMS_FOR_LIST_FAILURE'; export const RECEIVE_ITEMS_FOR_LIST_SUCCESS = 'RECEIVE_ITEMS_FOR_LIST_SUCCESS'; diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 9a50dcf05b8..04e7d3643e7 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -1,5 +1,6 @@ import { cloneDeep, pull, union } from 'lodash'; import Vue from 'vue'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { s__, __ } from '~/locale'; import { formatIssue } from '../boards_util'; import { issuableTypes } from '../constants'; @@ -33,15 +34,23 @@ export const addItemToList = ({ state, listId, itemId, moveBeforeId, moveAfterId }; export default { + [mutationTypes.REQUEST_CURRENT_BOARD]: (state) => { + state.isBoardLoading = true; + }, + [mutationTypes.RECEIVE_BOARD_SUCCESS]: (state, board) => { state.board = { ...board, labels: board?.labels?.nodes || [], }; + state.fullBoardId = board.id; + state.boardId = getIdFromGraphQLId(board.id); + state.isBoardLoading = false; }, [mutationTypes.RECEIVE_BOARD_FAILURE]: (state) => { state.error = s__('Boards|An error occurred while fetching the board. Please reload the page.'); + state.isBoardLoading = false; }, [mutationTypes.SET_INITIAL_BOARD_DATA](state, data) { @@ -136,11 +145,6 @@ export default { state.boardLists = listsBackup; }, - [mutationTypes.RESET_ITEMS_FOR_LIST]: (state, listId) => { - Vue.set(state, 'backupItemsList', state.boardItemsByListId[listId]); - Vue.set(state.boardItemsByListId, listId, []); - }, - [mutationTypes.REQUEST_ITEMS_FOR_LIST]: (state, { listId, fetchNext }) => { Vue.set(state.listsFlags, listId, { [fetchNext ? 'isLoadingMore' : 'isLoading']: true }); }, @@ -176,7 +180,6 @@ export default { 'Boards|An error occurred while fetching the board issues. Please reload the page.', ); Vue.set(state.listsFlags, listId, { isLoading: false, isLoadingMore: false }); - Vue.set(state.boardItemsByListId, listId, state.backupItemsList); }, [mutationTypes.RESET_ISSUES]: (state) => { diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js index 7af4e5a8798..b62c032b921 100644 --- a/app/assets/javascripts/boards/stores/state.js +++ b/app/assets/javascripts/boards/stores/state.js @@ -2,6 +2,7 @@ import { inactiveId, ListType } from '~/boards/constants'; export default () => ({ board: {}, + isBoardLoading: false, boardType: null, issuableType: null, fullPath: null, @@ -12,7 +13,6 @@ export default () => ({ boardLists: {}, listsFlags: {}, boardItemsByListId: {}, - backupItemsList: [], isSettingAssignees: false, pageInfoByListId: {}, boardItems: {}, |