From 9dc93a4519d9d5d7be48ff274127136236a3adb3 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 20 Apr 2021 23:50:22 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-11-stable-ee --- app/assets/javascripts/boards/boards_util.js | 33 ++- .../boards/components/board_add_new_column.vue | 56 ++-- .../components/board_add_new_column_form.vue | 119 +++++--- .../components/board_add_new_column_trigger.vue | 4 +- .../boards/components/board_blocked_icon.vue | 192 +++++++++++++ .../boards/components/board_card_inner.vue | 28 +- .../components/board_card_loading_skeleton.vue | 26 ++ .../boards/components/board_content.vue | 29 +- .../boards/components/board_content_sidebar.vue | 96 +++++++ .../boards/components/board_extra_actions.vue | 57 ---- .../javascripts/boards/components/board_form.vue | 33 ++- .../javascripts/boards/components/board_list.vue | 2 +- .../boards/components/board_list_deprecated.vue | 7 +- .../boards/components/board_list_header.vue | 1 + .../boards/components/board_new_issue.vue | 15 +- .../components/board_new_issue_deprecated.vue | 2 +- .../boards/components/board_settings_sidebar.vue | 8 +- .../boards/components/config_toggle.vue | 12 +- .../boards/components/filtered_search.vue | 54 ---- .../boards/components/modal/empty_state.vue | 84 ------ .../javascripts/boards/components/modal/filters.js | 27 -- .../javascripts/boards/components/modal/footer.vue | 80 ------ .../javascripts/boards/components/modal/header.vue | 80 ------ .../javascripts/boards/components/modal/index.vue | 151 ---------- .../javascripts/boards/components/modal/list.vue | 141 ---------- .../boards/components/modal/lists_dropdown.vue | 49 ---- .../javascripts/boards/components/modal/tabs.vue | 42 --- .../components/sidebar/board_editable_item.vue | 4 +- .../components/sidebar/board_sidebar_due_date.vue | 7 +- .../sidebar/board_sidebar_issue_title.vue | 169 ------------ .../sidebar/board_sidebar_labels_select.vue | 12 +- .../sidebar/board_sidebar_milestone_select.vue | 19 +- .../sidebar/board_sidebar_subscription.vue | 18 +- .../sidebar/board_sidebar_time_tracker.vue | 25 ++ .../components/sidebar/board_sidebar_title.vue | 169 ++++++++++++ .../javascripts/boards/components/toggle_focus.vue | 4 +- app/assets/javascripts/boards/config_toggle.js | 5 +- app/assets/javascripts/boards/constants.js | 29 ++ app/assets/javascripts/boards/ee_functions.js | 1 - app/assets/javascripts/boards/filtered_search.js | 25 -- .../graphql/board_blocking_issues.query.graphql | 16 ++ .../boards/graphql/issue.fragment.graphql | 4 + .../issue_set_subscription.mutation.graphql | 2 +- .../graphql/issue_set_title.mutation.graphql | 2 +- app/assets/javascripts/boards/index.js | 71 +---- .../javascripts/boards/mixins/board_new_issue.js | 6 + .../javascripts/boards/mixins/modal_footer.js | 1 - .../javascripts/boards/mixins/modal_mixins.js | 12 - app/assets/javascripts/boards/stores/actions.js | 306 +++++++++++++++------ app/assets/javascripts/boards/stores/getters.js | 12 +- .../javascripts/boards/stores/modal_store.js | 95 ------- .../javascripts/boards/stores/mutation_types.js | 15 +- app/assets/javascripts/boards/stores/mutations.js | 70 ++--- 53 files changed, 1070 insertions(+), 1457 deletions(-) create mode 100644 app/assets/javascripts/boards/components/board_blocked_icon.vue create mode 100644 app/assets/javascripts/boards/components/board_card_loading_skeleton.vue create mode 100644 app/assets/javascripts/boards/components/board_content_sidebar.vue delete mode 100644 app/assets/javascripts/boards/components/board_extra_actions.vue delete mode 100644 app/assets/javascripts/boards/components/filtered_search.vue delete mode 100644 app/assets/javascripts/boards/components/modal/empty_state.vue delete mode 100644 app/assets/javascripts/boards/components/modal/filters.js delete mode 100644 app/assets/javascripts/boards/components/modal/footer.vue delete mode 100644 app/assets/javascripts/boards/components/modal/header.vue delete mode 100644 app/assets/javascripts/boards/components/modal/index.vue delete mode 100644 app/assets/javascripts/boards/components/modal/list.vue delete mode 100644 app/assets/javascripts/boards/components/modal/lists_dropdown.vue delete mode 100644 app/assets/javascripts/boards/components/modal/tabs.vue delete mode 100644 app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue create mode 100644 app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue create mode 100644 app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue delete mode 100644 app/assets/javascripts/boards/filtered_search.js create mode 100644 app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql create mode 100644 app/assets/javascripts/boards/mixins/board_new_issue.js delete mode 100644 app/assets/javascripts/boards/mixins/modal_footer.js delete mode 100644 app/assets/javascripts/boards/mixins/modal_mixins.js delete mode 100644 app/assets/javascripts/boards/stores/modal_store.js (limited to 'app/assets/javascripts/boards') diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js index 2cd25f58770..a8b870f9b8e 100644 --- a/app/assets/javascripts/boards/boards_util.js +++ b/app/assets/javascripts/boards/boards_util.js @@ -1,4 +1,4 @@ -import { sortBy } from 'lodash'; +import { sortBy, cloneDeep } from 'lodash'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { ListType, NOT_FILTER } from './constants'; @@ -113,6 +113,37 @@ export function formatIssueInput(issueInput, boardConfig) { }; } +export function shouldCloneCard(fromListType, toListType) { + const involvesClosed = fromListType === ListType.closed || toListType === ListType.closed; + const involvesBacklog = fromListType === ListType.backlog || toListType === ListType.backlog; + + if (involvesClosed || involvesBacklog) { + return false; + } + + if (fromListType !== toListType) { + return true; + } + + return false; +} + +export function getMoveData(state, params) { + const { boardItems, boardItemsByListId, boardLists } = state; + const { itemId, fromListId, toListId } = params; + const fromListType = boardLists[fromListId].listType; + const toListType = boardLists[toListId].listType; + + return { + reordering: fromListId === toListId, + shouldClone: shouldCloneCard(fromListType, toListType), + itemNotInToList: !boardItemsByListId[toListId].includes(itemId), + originalIssue: cloneDeep(boardItems[itemId]), + originalIndex: boardItemsByListId[fromListId].indexOf(itemId), + ...params, + }; +} + export function moveItemListHelper(item, fromList, toList) { const updatedItem = item; if ( diff --git a/app/assets/javascripts/boards/components/board_add_new_column.vue b/app/assets/javascripts/boards/components/board_add_new_column.vue index 3c7c792b787..d4b559add6e 100644 --- a/app/assets/javascripts/boards/components/board_add_new_column.vue +++ b/app/assets/javascripts/boards/components/board_add_new_column.vue @@ -1,23 +1,16 @@ @@ -62,51 +88,64 @@ export default { class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-white" >

{{ $options.i18n.newList }}

-
- -
-
+
+
+

+ {{ $options.i18n.scope }} +

+

{{ $options.i18n.scopeDescription }}

+
-

{{ formDescription }}

+ -
- - -
{{ $options.i18n.noneSelected }}
-
-
+ + + - - - + -
- - - - - -
+
+ + + + + +
- -

{{ $options.i18n.noResults }}

-
+ +

{{ $options.i18n.noResults }}

+
+
+
diff --git a/app/assets/javascripts/boards/components/board_blocked_icon.vue b/app/assets/javascripts/boards/components/board_blocked_icon.vue new file mode 100644 index 00000000000..0f92e714752 --- /dev/null +++ b/app/assets/javascripts/boards/components/board_blocked_icon.vue @@ -0,0 +1,192 @@ + + diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue index d4d6b17a589..9ff2cdd76d0 100644 --- a/app/assets/javascripts/boards/components/board_card_inner.vue +++ b/app/assets/javascripts/boards/components/board_card_inner.vue @@ -10,6 +10,7 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import { ListType } from '../constants'; import eventHub from '../eventhub'; +import BoardBlockedIcon from './board_blocked_icon.vue'; import IssueDueDate from './issue_due_date.vue'; import IssueTimeEstimate from './issue_time_estimate.vue'; @@ -22,6 +23,7 @@ export default { IssueDueDate, IssueTimeEstimate, IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'), + BoardBlockedIcon, }, directives: { GlTooltip: GlTooltipDirective, @@ -52,7 +54,7 @@ export default { }; }, computed: { - ...mapState(['isShowingLabels']), + ...mapState(['isShowingLabels', 'issuableType']), ...mapGetters(['isEpicBoard']), cappedAssignees() { // e.g. maxRender is 4, @@ -114,7 +116,7 @@ export default { }, }, methods: { - ...mapActions(['performSearch']), + ...mapActions(['performSearch', 'setError']), isIndexLessThanlimit(index) { return index < this.limitBeforeCounter; }, @@ -164,14 +166,12 @@ export default {
diff --git a/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue b/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue new file mode 100644 index 00000000000..15bff1226a6 --- /dev/null +++ b/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue @@ -0,0 +1,26 @@ + + + diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue index e9c4237d759..a4b1e6adacf 100644 --- a/app/assets/javascripts/boards/components/board_content.vue +++ b/app/assets/javascripts/boards/components/board_content.vue @@ -17,21 +17,20 @@ export default { gon.features?.graphqlBoardLists || gon.features?.epicBoards ? BoardColumn : BoardColumnDeprecated, - BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'), + BoardContentSidebar: () => import('~/boards/components/board_content_sidebar.vue'), + EpicBoardContentSidebar: () => + import('ee_component/boards/components/epic_board_content_sidebar.vue'), EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'), GlAlert, }, mixins: [glFeatureFlagMixin()], + inject: ['canAdminList'], props: { lists: { type: Array, required: false, default: () => [], }, - canAdminList: { - type: Boolean, - required: true, - }, disabled: { type: Boolean, required: true, @@ -69,7 +68,7 @@ export default { }, }, methods: { - ...mapActions(['moveList']), + ...mapActions(['moveList', 'unsetError']), afterFormEnters() { const el = this.canDragColumns ? this.$refs.list.$el : this.$refs.list; el.scrollTo({ left: el.scrollWidth, behavior: 'smooth' }); @@ -99,8 +98,8 @@ export default { diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue new file mode 100644 index 00000000000..46359cc2bca --- /dev/null +++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue @@ -0,0 +1,96 @@ + + + diff --git a/app/assets/javascripts/boards/components/board_extra_actions.vue b/app/assets/javascripts/boards/components/board_extra_actions.vue deleted file mode 100644 index b802ccc7882..00000000000 --- a/app/assets/javascripts/boards/components/board_extra_actions.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue index d8504dcfb0f..78da4137d69 100644 --- a/app/assets/javascripts/boards/components/board_form.vue +++ b/app/assets/javascripts/boards/components/board_form.vue @@ -107,7 +107,7 @@ export default { }; }, computed: { - ...mapGetters(['isEpicBoard', 'isGroupBoard', 'isProjectBoard']), + ...mapGetters(['isIssueBoard', 'isGroupBoard', 'isProjectBoard']), isNewForm() { return this.currentPage === formType.new; }, @@ -127,7 +127,7 @@ export default { if (this.isDeleteForm) { return 'danger'; } - return 'info'; + return 'confirm'; }, title() { if (this.readonly) { @@ -163,6 +163,9 @@ export default { currentMutation() { return this.board.id ? updateBoardMutation : createBoardMutation; }, + deleteMutation() { + return destroyBoardMutation; + }, baseMutationVariables() { const { board } = this; const variables = { @@ -182,7 +185,7 @@ export default { groupPath: this.isGroupBoard ? this.fullPath : undefined, }; }, - boardScopeMutationVariables() { + issueBoardScopeMutationVariables() { /* eslint-disable @gitlab/require-i18n-strings */ return { weight: this.board.weight, @@ -193,13 +196,18 @@ export default { this.board.milestone?.id || this.board.milestone?.id === 0 ? convertToGraphQLId('Milestone', this.board.milestone.id) : null, - labelIds: this.board.labels.map(fullLabelId), iterationId: this.board.iteration_id ? convertToGraphQLId('Iteration', this.board.iteration_id) : null, }; /* eslint-enable @gitlab/require-i18n-strings */ }, + boardScopeMutationVariables() { + return { + labelIds: this.board.labels.map(fullLabelId), + ...(this.isIssueBoard && this.issueBoardScopeMutationVariables), + }; + }, mutationVariables() { return { ...this.baseMutationVariables, @@ -239,17 +247,20 @@ export default { return this.boardUpdateResponse(response.data); }, + async deleteBoard() { + await this.$apollo.mutate({ + mutation: this.deleteMutation, + variables: { + id: fullBoardId(this.board.id), + }, + }); + }, async submit() { if (this.board.name.length === 0) return; this.isLoading = true; if (this.isDeleteForm) { try { - await this.$apollo.mutate({ - mutation: destroyBoardMutation, - variables: { - id: fullBoardId(this.board.id), - }, - }); + await this.deleteBoard(); visitUrl(this.rootPath); } catch { Flash(this.$options.i18n.deleteErrorMessage); @@ -324,7 +335,7 @@ export default { /> {{ __('Submit issue') }}{{ __('Create issue') }} -import { mapActions } from 'vuex'; -import { historyPushState } from '~/lib/utils/common_utils'; -import { setUrlParams } from '~/lib/utils/url_utility'; -import { __ } from '~/locale'; -import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; - -export default { - i18n: { - search: __('Search'), - }, - components: { FilteredSearch }, - props: { - search: { - type: String, - required: false, - default: '', - }, - }, - computed: { - initialSearch() { - return [{ type: 'filtered-search-term', value: { data: this.search } }]; - }, - }, - methods: { - ...mapActions(['performSearch']), - handleSearch(filters) { - let itemValue = ''; - const [item] = filters; - - if (filters.length === 0) { - itemValue = ''; - } else { - itemValue = item?.value?.data; - } - - historyPushState(setUrlParams({ search: itemValue }, window.location.href)); - - this.performSearch(); - }, - }, -}; - - - diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue deleted file mode 100644 index 486b012e3d2..00000000000 --- a/app/assets/javascripts/boards/components/modal/empty_state.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - diff --git a/app/assets/javascripts/boards/components/modal/filters.js b/app/assets/javascripts/boards/components/modal/filters.js deleted file mode 100644 index 2fb38a549f3..00000000000 --- a/app/assets/javascripts/boards/components/modal/filters.js +++ /dev/null @@ -1,27 +0,0 @@ -import FilteredSearchContainer from '../../../filtered_search/container'; -import FilteredSearchBoards from '../../filtered_search_boards'; - -export default { - name: 'modal-filters', - props: { - store: { - type: Object, - required: true, - }, - }, - mounted() { - FilteredSearchContainer.container = this.$el; - - this.filteredSearch = new FilteredSearchBoards(this.store); - this.filteredSearch.setup(); - this.filteredSearch.removeTokens(); - this.filteredSearch.handleInputPlaceholder(); - this.filteredSearch.toggleClearSearchButton(); - }, - destroyed() { - this.filteredSearch.cleanup(); - FilteredSearchContainer.container = document; - this.store.path = ''; - }, - template: '#js-board-modal-filter', -}; diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue deleted file mode 100644 index 05e1219bc70..00000000000 --- a/app/assets/javascripts/boards/components/modal/footer.vue +++ /dev/null @@ -1,80 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue deleted file mode 100644 index c3a71e7177a..00000000000 --- a/app/assets/javascripts/boards/components/modal/header.vue +++ /dev/null @@ -1,80 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue deleted file mode 100644 index 5af90c1ee66..00000000000 --- a/app/assets/javascripts/boards/components/modal/index.vue +++ /dev/null @@ -1,151 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue deleted file mode 100644 index e66cae0ce18..00000000000 --- a/app/assets/javascripts/boards/components/modal/list.vue +++ /dev/null @@ -1,141 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue deleted file mode 100644 index 2065568d275..00000000000 --- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue +++ /dev/null @@ -1,49 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue deleted file mode 100644 index 0b717f516db..00000000000 --- a/app/assets/javascripts/boards/components/modal/tabs.vue +++ /dev/null @@ -1,42 +0,0 @@ - - diff --git a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue index 61863bbe2a9..352a25ef6d9 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue @@ -98,14 +98,14 @@ export default { {{ __('Edit') }} -
+
{{ __('None') }}
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue index 6d928337396..13e1e232676 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue @@ -18,16 +18,16 @@ export default { }; }, computed: { - ...mapGetters(['activeIssue', 'projectPathForActiveIssue']), + ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']), hasDueDate() { - return this.activeIssue.dueDate != null; + return this.activeBoardItem.dueDate != null; }, parsedDueDate() { if (!this.hasDueDate) { return null; } - return parsePikadayDate(this.activeIssue.dueDate); + return parsePikadayDate(this.activeBoardItem.dueDate); }, formattedDueDate() { if (!this.hasDueDate) { @@ -69,6 +69,7 @@ export default { -import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui'; -import { mapGetters, mapActions } from 'vuex'; -import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue'; -import createFlash from '~/flash'; -import { joinPaths } from '~/lib/utils/url_utility'; -import { __ } from '~/locale'; -import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; - -export default { - components: { - GlForm, - GlAlert, - GlButton, - GlFormGroup, - GlFormInput, - BoardEditableItem, - }, - directives: { - autofocusonshow, - }, - data() { - return { - title: '', - loading: false, - showChangesAlert: false, - }; - }, - computed: { - ...mapGetters({ issue: 'activeIssue' }), - pendingChangesStorageKey() { - return this.getPendingChangesKey(this.issue); - }, - projectPath() { - const referencePath = this.issue.referencePath || ''; - return referencePath.slice(0, referencePath.indexOf('#')); - }, - validationState() { - return Boolean(this.title); - }, - }, - watch: { - issue: { - handler(updatedIssue, formerIssue) { - if (formerIssue?.title !== this.title) { - localStorage.setItem(this.getPendingChangesKey(formerIssue), this.title); - } - - this.title = updatedIssue.title; - this.setPendingState(); - }, - immediate: true, - }, - }, - methods: { - ...mapActions(['setActiveIssueTitle']), - getPendingChangesKey(issue) { - if (!issue) { - return ''; - } - - return joinPaths( - window.location.pathname.slice(1), - String(issue.id), - 'issue-title-pending-changes', - ); - }, - async setPendingState() { - const pendingChanges = localStorage.getItem(this.pendingChangesStorageKey); - - if (pendingChanges) { - this.title = pendingChanges; - this.showChangesAlert = true; - await this.$nextTick(); - this.$refs.sidebarItem.expand(); - } else { - this.showChangesAlert = false; - } - }, - cancel() { - this.title = this.issue.title; - this.$refs.sidebarItem.collapse(); - this.showChangesAlert = false; - localStorage.removeItem(this.pendingChangesStorageKey); - }, - async setTitle() { - this.$refs.sidebarItem.collapse(); - - if (!this.title || this.title === this.issue.title) { - return; - } - - try { - this.loading = true; - await this.setActiveIssueTitle({ title: this.title, projectPath: this.projectPath }); - localStorage.removeItem(this.pendingChangesStorageKey); - this.showChangesAlert = false; - } catch (e) { - this.title = this.issue.title; - createFlash({ message: this.$options.i18n.updateTitleError }); - } finally { - this.loading = false; - } - }, - handleOffClick() { - if (this.title !== this.issue.title) { - this.showChangesAlert = true; - localStorage.setItem(this.pendingChangesStorageKey, this.title); - } else { - this.$refs.sidebarItem.collapse(); - } - }, - }, - i18n: { - issueTitlePlaceholder: __('Issue title'), - submitButton: __('Save changes'), - cancelButton: __('Cancel'), - updateTitleError: __('An error occurred when updating the issue title'), - invalidFeedback: __('An issue title is required'), - reviewYourChanges: __('Changes to the title have not been saved'), - }, -}; - - - diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue index 55b1596ee18..f78be83cd82 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue @@ -21,9 +21,9 @@ export default { }; }, computed: { - ...mapGetters(['activeIssue', 'projectPathForActiveIssue']), + ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']), selectedLabels() { - const { labels = [] } = this.activeIssue; + const { labels = [] } = this.activeBoardItem; return labels.map((label) => ({ ...label, @@ -31,7 +31,7 @@ export default { })); }, issueLabels() { - const { labels = [] } = this.activeIssue; + const { labels = [] } = this.activeBoardItem; return labels.map((label) => ({ ...label, @@ -40,7 +40,7 @@ export default { }, }, methods: { - ...mapActions(['setActiveIssueLabels']), + ...mapActions(['setActiveBoardItemLabels']), async setLabels(payload) { this.loading = true; this.$refs.sidebarItem.collapse(); @@ -52,7 +52,7 @@ export default { .map((label) => label.id); const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue }; - await this.setActiveIssueLabels(input); + await this.setActiveBoardItemLabels(input); } catch (e) { createFlash({ message: __('An error occurred while updating labels.') }); } finally { @@ -65,7 +65,7 @@ export default { try { const removeLabelIds = [getIdFromGraphQLId(id)]; const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue }; - await this.setActiveIssueLabels(input); + await this.setActiveBoardItemLabels(input); } catch (e) { createFlash({ message: __('An error occurred when removing the label.') }); } finally { diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue index 829f1c72806..ad225c7bf5c 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue @@ -56,20 +56,20 @@ export default { }, }, computed: { - ...mapGetters(['activeIssue']), + ...mapGetters(['activeBoardItem']), hasMilestone() { - return this.activeIssue.milestone !== null; + return this.activeBoardItem.milestone !== null; }, groupFullPath() { - const { referencePath = '' } = this.activeIssue; + const { referencePath = '' } = this.activeBoardItem; return referencePath.slice(0, referencePath.indexOf('/')); }, projectPath() { - const { referencePath = '' } = this.activeIssue; + const { referencePath = '' } = this.activeBoardItem; return referencePath.slice(0, referencePath.indexOf('#')); }, dropdownText() { - return this.activeIssue.milestone?.title ?? this.$options.i18n.noMilestone; + return this.activeBoardItem.milestone?.title ?? this.$options.i18n.noMilestone; }, }, methods: { @@ -113,11 +113,12 @@ export default { ref="sidebarItem" :title="$options.i18n.milestone" :loading="loading" - @open="handleOpen()" + data-testid="sidebar-milestones" + @open="handleOpen" @close="handleClose" > {{ $options.i18n.noMilestone }} @@ -142,7 +143,7 @@ export default { v-for="milestone in milestones" :key="milestone.id" :is-check-item="true" - :is-checked="activeIssue.milestone && milestone.id === activeIssue.milestone.id" + :is-checked="activeBoardItem.milestone && milestone.id === activeBoardItem.milestone.id" data-testid="milestone-item" @click="setMilestone(milestone.id)" > diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue index f01c8e8fa20..376985f7cb6 100644 --- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue @@ -21,27 +21,31 @@ export default { components: { GlToggle, }, + inject: ['emailsDisabled'], data() { return { loading: false, }; }, computed: { - ...mapGetters(['activeIssue', 'projectPathForActiveIssue']), + ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue', 'isEpicBoard']), + isEmailsDisabled() { + return this.isEpicBoard ? this.emailsDisabled : this.activeBoardItem.emailsDisabled; + }, notificationText() { - return this.activeIssue.emailsDisabled + return this.isEmailsDisabled ? this.$options.i18n.header.subscribeDisabledDescription : this.$options.i18n.header.title; }, }, methods: { - ...mapActions(['setActiveIssueSubscribed']), + ...mapActions(['setActiveItemSubscribed']), async handleToggleSubscription() { this.loading = true; try { - await this.setActiveIssueSubscribed({ - subscribed: !this.activeIssue.subscribed, + await this.setActiveItemSubscribed({ + subscribed: !this.activeBoardItem.subscribed, projectPath: this.projectPathForActiveIssue, }); } catch (error) { @@ -61,8 +65,8 @@ export default { > {{ notificationText }} +import { mapGetters } from 'vuex'; +import IssuableTimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue'; + +export default { + components: { + IssuableTimeTracker, + }, + inject: ['timeTrackingLimitToHours'], + computed: { + ...mapGetters(['activeBoardItem']), + }, +}; + + + diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue new file mode 100644 index 00000000000..b8d3107c377 --- /dev/null +++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue @@ -0,0 +1,169 @@ + + + diff --git a/app/assets/javascripts/boards/components/toggle_focus.vue b/app/assets/javascripts/boards/components/toggle_focus.vue index 74805f8a681..49f5e7d20a9 100644 --- a/app/assets/javascripts/boards/components/toggle_focus.vue +++ b/app/assets/javascripts/boards/components/toggle_focus.vue @@ -38,14 +38,16 @@ export default {