Commit efa5169e authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '343606-user-labels-widget-mr-and-epic-boards' into 'master'

Use labels widget on epic board and MR sidebar [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!73132
parents e94f48e8 d3dacc2d
...@@ -54,6 +54,9 @@ export default { ...@@ -54,6 +54,9 @@ export default {
allowLabelEdit: { allowLabelEdit: {
default: false, default: false,
}, },
labelsFilterBasePath: {
default: '',
},
}, },
inheritAttrs: false, inheritAttrs: false,
computed: { computed: {
...@@ -90,6 +93,11 @@ export default { ...@@ -90,6 +93,11 @@ export default {
labelType() { labelType() {
return this.isGroupBoard ? LabelType.group : LabelType.project; return this.isGroupBoard ? LabelType.group : LabelType.project;
}, },
labelsFilterPath() {
return this.isGroupBoard
? this.labelsFilterBasePath.replace(':project_path', this.projectPathForActiveIssue)
: this.labelsFilterBasePath;
},
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -212,7 +220,7 @@ export default { ...@@ -212,7 +220,7 @@ export default {
:footer-create-label-title="createLabelTitle" :footer-create-label-title="createLabelTitle"
:footer-manage-label-title="manageLabelTitle" :footer-manage-label-title="manageLabelTitle"
:labels-create-title="createLabelTitle" :labels-create-title="createLabelTitle"
:labels-filter-base-path="projectPathForActiveIssue" :labels-filter-base-path="labelsFilterPath"
:attr-workspace-path="attrWorkspacePath" :attr-workspace-path="attrWorkspacePath"
workspace-type="project" workspace-type="project"
:issuable-type="issuableType" :issuable-type="issuableType"
......
...@@ -37,6 +37,7 @@ import epicLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widge ...@@ -37,6 +37,7 @@ import epicLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widge
import updateEpicLabelsMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql'; import updateEpicLabelsMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql';
import groupLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql'; import groupLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql';
import issueLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql'; import issueLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql';
import mergeRequestLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql';
import projectLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql'; import projectLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql';
import getAlertAssignees from '~/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql'; import getAlertAssignees from '~/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql';
import getIssueAssignees from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql'; import getIssueAssignees from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql';
...@@ -128,6 +129,7 @@ export const issuableLabelsQueries = { ...@@ -128,6 +129,7 @@ export const issuableLabelsQueries = {
mutationName: 'updateIssue', mutationName: 'updateIssue',
}, },
[IssuableType.MergeRequest]: { [IssuableType.MergeRequest]: {
issuableQuery: mergeRequestLabelsQuery,
mutation: updateMergeRequestLabelsMutation, mutation: updateMergeRequestLabelsMutation,
mutationName: 'mergeRequestSetLabels', mutationName: 'mergeRequestSetLabels',
}, },
......
...@@ -260,6 +260,10 @@ export function mountSidebarLabels() { ...@@ -260,6 +260,10 @@ export function mountSidebarLabels() {
variant: DropdownVariant.Sidebar, variant: DropdownVariant.Sidebar,
canUpdate: parseBoolean(el.dataset.canEdit), canUpdate: parseBoolean(el.dataset.canEdit),
isClassicSidebar: true, isClassicSidebar: true,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
? IssuableType.Issue
: IssuableType.MergeRequest,
}, },
render: (createElement) => createElement(SidebarLabels), render: (createElement) => createElement(SidebarLabels),
}); });
......
...@@ -2,6 +2,7 @@ mutation mergeRequestSetLabels($input: MergeRequestSetLabelsInput!) { ...@@ -2,6 +2,7 @@ mutation mergeRequestSetLabels($input: MergeRequestSetLabelsInput!) {
mergeRequestSetLabels(input: $input) { mergeRequestSetLabels(input: $input) {
errors errors
mergeRequest { mergeRequest {
id
labels { labels {
nodes { nodes {
color color
......
...@@ -53,10 +53,6 @@ export default { ...@@ -53,10 +53,6 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
issuableType: {
type: String,
required: true,
},
isVisible: { isVisible: {
type: Boolean, type: Boolean,
required: false, required: false,
...@@ -209,7 +205,6 @@ export default { ...@@ -209,7 +205,6 @@ export default {
v-model="localSelectedLabels" v-model="localSelectedLabels"
:search-key="searchKey" :search-key="searchKey"
:allow-multiselect="allowMultiselect" :allow-multiselect="allowMultiselect"
:issuable-type="issuableType"
:full-path="fullPath" :full-path="fullPath"
:workspace-type="workspaceType" :workspace-type="workspaceType"
:attr-workspace-path="attrWorkspacePath" :attr-workspace-path="attrWorkspacePath"
......
...@@ -32,11 +32,6 @@ export default { ...@@ -32,11 +32,6 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
issuableType: {
type: String,
required: false,
default: undefined,
},
workspaceType: { workspaceType: {
type: String, type: String,
required: true, required: true,
......
...@@ -23,10 +23,6 @@ export default { ...@@ -23,10 +23,6 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
issuableType: {
type: String,
required: true,
},
localSelectedLabels: { localSelectedLabels: {
type: Array, type: Array,
required: true, required: true,
...@@ -119,13 +115,7 @@ export default { ...@@ -119,13 +115,7 @@ export default {
({ id }) => id !== getIdFromGraphQLId(label.id) && id !== label.id, ({ id }) => id !== getIdFromGraphQLId(label.id) && id !== label.id,
); );
} else { } else {
labels = [ labels = [...this.localSelectedLabels, label];
...this.localSelectedLabels,
{
...label,
id: getIdFromGraphQLId(label.id),
},
];
} }
this.$emit('input', labels); this.$emit('input', labels);
}, },
......
<script> <script>
import { GlLabel } from '@gitlab/ui'; import { GlLabel } from '@gitlab/ui';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isScopedLabel } from '~/lib/utils/common_utils'; import { isScopedLabel } from '~/lib/utils/common_utils';
export default { export default {
...@@ -47,7 +46,7 @@ export default { ...@@ -47,7 +46,7 @@ export default {
return this.allowScopedLabels && isScopedLabel(label); return this.allowScopedLabels && isScopedLabel(label);
}, },
removeLabel(labelId) { removeLabel(labelId) {
this.$emit('onLabelRemove', getIdFromGraphQLId(labelId)); this.$emit('onLabelRemove', labelId);
}, },
}, },
}; };
......
#import "~/graphql_shared/fragments/label.fragment.graphql"
query mergeRequestLabels($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
issuable: mergeRequest(iid: $iid) {
id
labels {
nodes {
...Label
}
}
}
}
}
...@@ -207,7 +207,7 @@ export default { ...@@ -207,7 +207,7 @@ export default {
return { return {
iid: currentIid, iid: currentIid,
groupPath: this.fullPath, groupPath: this.fullPath,
addLabelIds: labelIds, addLabelIds: labelIds.map((id) => getIdFromGraphQLId(id)),
removeLabelIds: this.issuableLabelIds removeLabelIds: this.issuableLabelIds
.filter((id) => !labelIds.includes(id)) .filter((id) => !labelIds.includes(id))
.map((id) => getIdFromGraphQLId(id)), .map((id) => getIdFromGraphQLId(id)),
...@@ -232,8 +232,8 @@ export default { ...@@ -232,8 +232,8 @@ export default {
} }
this.$emit('updateSelectedLabels', { this.$emit('updateSelectedLabels', {
id: data[mutationName]?.[this.issuableType].id, id: data[mutationName]?.[this.issuableType]?.id,
labels: data[mutationName]?.[this.issuableType].labels?.nodes, labels: data[mutationName]?.[this.issuableType]?.labels?.nodes,
}); });
}) })
.catch((error) => .catch((error) =>
...@@ -268,7 +268,7 @@ export default { ...@@ -268,7 +268,7 @@ export default {
case IssuableType.Epic: case IssuableType.Epic:
return { return {
iid: this.iid, iid: this.iid,
removeLabelIds: [labelId], removeLabelIds: [getIdFromGraphQLId(labelId)],
groupPath: this.fullPath, groupPath: this.fullPath,
}; };
default: default:
...@@ -341,7 +341,6 @@ export default { ...@@ -341,7 +341,6 @@ export default {
:labels-create-title="labelsCreateTitle" :labels-create-title="labelsCreateTitle"
:selected-labels="issuableLabels" :selected-labels="issuableLabels"
:variant="variant" :variant="variant"
:issuable-type="issuableType"
:is-visible="edit" :is-visible="edit"
:full-path="fullPath" :full-path="fullPath"
:workspace-type="workspaceType" :workspace-type="workspaceType"
...@@ -364,7 +363,6 @@ export default { ...@@ -364,7 +363,6 @@ export default {
:labels-create-title="labelsCreateTitle" :labels-create-title="labelsCreateTitle"
:selected-labels="issuableLabels" :selected-labels="issuableLabels"
:variant="variant" :variant="variant"
:issuable-type="issuableType"
:full-path="fullPath" :full-path="fullPath"
:workspace-type="workspaceType" :workspace-type="workspaceType"
:attr-workspace-path="attrWorkspacePath" :attr-workspace-path="attrWorkspacePath"
......
...@@ -470,6 +470,10 @@ ...@@ -470,6 +470,10 @@
.labels-select-wrapper.is-embedded .labels-select-wrapper.is-embedded { .labels-select-wrapper.is-embedded .labels-select-wrapper.is-embedded {
width: auto; width: auto;
} }
.show.dropdown .dropdown-menu {
@include gl-w-full;
}
} }
.board-header-collapsed-info-icon:hover { .board-header-collapsed-info-icon:hover {
......
...@@ -42,6 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -42,6 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml) push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml) push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml) push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml)
push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml)
# Usage data feature flags # Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
......
...@@ -43,7 +43,7 @@ module BoardsHelper ...@@ -43,7 +43,7 @@ module BoardsHelper
def build_issue_link_base def build_issue_link_base
if board.group_board? if board.group_board?
"#{group_path(@board.group)}/:project_path/issues" "/:project_path/-/issues"
else else
project_issues_path(@project) project_issues_path(@project)
end end
......
...@@ -6,11 +6,14 @@ import SidebarAncestorsWidget from 'ee_component/sidebar/components/ancestors_tr ...@@ -6,11 +6,14 @@ import SidebarAncestorsWidget from 'ee_component/sidebar/components/ancestors_tr
import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue'; import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue'; import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { ISSUABLE } from '~/boards/constants'; import { ISSUABLE } from '~/boards/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue'; import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue'; import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarParticipantsWidget from '~/sidebar/components/participants/sidebar_participants_widget.vue'; import SidebarParticipantsWidget from '~/sidebar/components/participants/sidebar_participants_widget.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue'; import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
components: { components: {
...@@ -18,6 +21,7 @@ export default { ...@@ -18,6 +21,7 @@ export default {
SidebarTodoWidget, SidebarTodoWidget,
BoardSidebarLabelsSelect, BoardSidebarLabelsSelect,
BoardSidebarTitle, BoardSidebarTitle,
SidebarLabelsWidget,
SidebarConfidentialityWidget, SidebarConfidentialityWidget,
SidebarDateWidget, SidebarDateWidget,
SidebarParticipantsWidget, SidebarParticipantsWidget,
...@@ -25,6 +29,8 @@ export default { ...@@ -25,6 +29,8 @@ export default {
SidebarAncestorsWidget, SidebarAncestorsWidget,
MountingPortal, MountingPortal,
}, },
mixins: [glFeatureFlagMixin()],
inject: ['canUpdate', 'labelsFilterBasePath'],
inheritAttrs: false, inheritAttrs: false,
computed: { computed: {
...mapGetters(['isSidebarOpen', 'activeBoardItem']), ...mapGetters(['isSidebarOpen', 'activeBoardItem']),
...@@ -40,10 +46,30 @@ export default { ...@@ -40,10 +46,30 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(['toggleBoardItem', 'setActiveItemConfidential', 'setActiveItemSubscribed']), ...mapActions([
'toggleBoardItem',
'setActiveItemConfidential',
'setActiveItemSubscribed',
'setActiveBoardItemLabels',
]),
handleClose() { handleClose() {
this.toggleBoardItem({ boardItem: this.activeBoardItem, sidebarType: this.sidebarType }); this.toggleBoardItem({ boardItem: this.activeBoardItem, sidebarType: this.sidebarType });
}, },
handleUpdateSelectedLabels({ labels, id }) {
this.setActiveBoardItemLabels({
id,
groupPath: this.fullPath,
labelIds: labels.map((label) => getIdFromGraphQLId(label.id)),
labels,
});
},
handleLabelRemove(removeLabelId) {
this.setActiveBoardItemLabels({
iid: this.activeBoardItem.iid,
groupPath: this.fullPath,
removeLabelIds: [removeLabelId],
});
},
}, },
}; };
</script> </script>
...@@ -86,7 +112,25 @@ export default { ...@@ -86,7 +112,25 @@ export default {
:issuable-type="issuableType" :issuable-type="issuableType"
:can-inherit="true" :can-inherit="true"
/> />
<board-sidebar-labels-select class="labels" /> <sidebar-labels-widget
v-if="glFeatures.labelsWidget"
class="block labels"
data-testid="sidebar-labels"
:iid="activeBoardItem.iid"
:full-path="fullPath"
:allow-label-remove="canUpdate"
:allow-multiselect="true"
:labels-filter-base-path="labelsFilterBasePath"
:attr-workspace-path="fullPath"
workspace-type="group"
:issuable-type="issuableType"
label-create-type="group"
@onLabelRemove="handleLabelRemove"
@updateSelectedLabels="handleUpdateSelectedLabels"
>
{{ __('None') }}
</sidebar-labels-widget>
<board-sidebar-labels-select v-else class="labels" />
<sidebar-confidentiality-widget <sidebar-confidentiality-widget
:iid="activeBoardItem.iid" :iid="activeBoardItem.iid"
:full-path="fullPath" :full-path="fullPath"
......
...@@ -12,6 +12,7 @@ import listsIssuesQuery from '~/boards/graphql/lists_issues.query.graphql'; ...@@ -12,6 +12,7 @@ import listsIssuesQuery from '~/boards/graphql/lists_issues.query.graphql';
import projectBoardMembersQuery from '~/boards/graphql/project_board_members.query.graphql'; import projectBoardMembersQuery from '~/boards/graphql/project_board_members.query.graphql';
import actionsCE from '~/boards/stores/actions'; import actionsCE from '~/boards/stores/actions';
import * as typesCE from '~/boards/stores/mutation_types'; import * as typesCE from '~/boards/stores/mutation_types';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { historyPushState, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { historyPushState, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { mergeUrlParams, removeParams, queryToObject } from '~/lib/utils/url_utility'; import { mergeUrlParams, removeParams, queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
...@@ -583,6 +584,8 @@ export default { ...@@ -583,6 +584,8 @@ export default {
setActiveEpicLabels: async ({ commit, getters, state }, input) => { setActiveEpicLabels: async ({ commit, getters, state }, input) => {
const { activeBoardItem } = getters; const { activeBoardItem } = getters;
if (!gon.features?.labelsWidget) {
const { data } = await gqlClient.mutate({ const { data } = await gqlClient.mutate({
mutation: updateEpicLabelsMutation, mutation: updateEpicLabelsMutation,
variables: { variables: {
...@@ -604,5 +607,20 @@ export default { ...@@ -604,5 +607,20 @@ export default {
prop: 'labels', prop: 'labels',
value: data.updateEpic.epic.labels.nodes, value: data.updateEpic.epic.labels.nodes,
}); });
return;
}
let labels = input?.labels || [];
if (input.removeLabelIds) {
labels = activeBoardItem.labels.filter(
(label) => input.removeLabelIds[0] !== getIdFromGraphQLId(label.id),
);
}
commit(types.UPDATE_BOARD_ITEM_BY_ID, {
itemId: input.id || activeBoardItem.id,
prop: 'labels',
value: labels,
});
}, },
}; };
...@@ -8,6 +8,7 @@ import { ...@@ -8,6 +8,7 @@ import {
GlFormInput, GlFormInput,
} from '@gitlab/ui'; } from '@gitlab/ui';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { formatDate } from '~/lib/utils/datetime_utility'; import { formatDate } from '~/lib/utils/datetime_utility';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
...@@ -113,7 +114,7 @@ export default { ...@@ -113,7 +114,7 @@ export default {
}, },
handleUpdateSelectedLabels(labels) { handleUpdateSelectedLabels(labels) {
if (this.glFeatures.labelsWidget) { if (this.glFeatures.labelsWidget) {
this.labels = labels; this.labels = labels.map((label) => ({ ...label, id: getIdFromGraphQLId(label.id) }));
return; return;
} }
......
...@@ -97,6 +97,9 @@ function mountBoardApp(el) { ...@@ -97,6 +97,9 @@ function mountBoardApp(el) {
iterationListsAvailable: false, iterationListsAvailable: false,
issuableType: issuableTypes.epic, issuableType: issuableTypes.epic,
emailsDisabled: parseBoolean(el.dataset.emailsDisabled), emailsDisabled: parseBoolean(el.dataset.emailsDisabled),
allowLabelCreate: parseBoolean(el.dataset.canUpdate),
allowLabelEdit: parseBoolean(el.dataset.canUpdate),
allowScopedLabels: parseBoolean(el.dataset.scopedLabels),
}, },
render: (createComponent) => createComponent(BoardApp), render: (createComponent) => createComponent(BoardApp),
}); });
......
...@@ -8,6 +8,9 @@ class Groups::EpicBoardsController < Groups::ApplicationController ...@@ -8,6 +8,9 @@ class Groups::EpicBoardsController < Groups::ApplicationController
before_action :redirect_to_recent_board, only: [:index] before_action :redirect_to_recent_board, only: [:index]
before_action :assign_endpoint_vars before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:labels_widget, group, default_enabled: :yaml)
end
track_redis_hll_event :index, :show, name: 'g_project_management_users_viewing_epic_boards' track_redis_hll_event :index, :show, name: 'g_project_management_users_viewing_epic_boards'
......
...@@ -71,6 +71,13 @@ module EE ...@@ -71,6 +71,13 @@ module EE
super super
end end
override :build_issue_link_base
def build_issue_link_base
return group_epics_path(@group) if board.is_a?(::Boards::EpicBoard)
super
end
override :board_base_url override :board_base_url
def board_base_url def board_base_url
return group_epic_boards_url(@group) if board.is_a?(::Boards::EpicBoard) return group_epic_boards_url(@group) if board.is_a?(::Boards::EpicBoard)
......
...@@ -161,9 +161,9 @@ RSpec.describe 'Epic boards sidebar', :js do ...@@ -161,9 +161,9 @@ RSpec.describe 'Epic boards sidebar', :js do
wait_for_requests wait_for_requests
click_link bug.title click_on bug.title
find('[data-testid="close-icon"]').click click_button 'Close'
wait_for_requests wait_for_requests
......
...@@ -15,6 +15,8 @@ describe('ee/BoardContent', () => { ...@@ -15,6 +15,8 @@ describe('ee/BoardContent', () => {
provide: { provide: {
timeTrackingLimitToHours: false, timeTrackingLimitToHours: false,
canAdminList: false, canAdminList: false,
canUpdate: false,
labelsFilterBasePath: '',
}, },
propsData: { propsData: {
lists: [], lists: [],
......
...@@ -45,6 +45,7 @@ describe('EpicBoardContentSidebar', () => { ...@@ -45,6 +45,7 @@ describe('EpicBoardContentSidebar', () => {
canUpdate: true, canUpdate: true,
rootPath: '/', rootPath: '/',
groupId: 1, groupId: 1,
labelsFilterBasePath: '',
}, },
store, store,
stubs: { stubs: {
......
...@@ -122,6 +122,12 @@ export const labels = [ ...@@ -122,6 +122,12 @@ export const labels = [
color: '#34ebec', color: '#34ebec',
description: null, description: null,
}, },
{
id: 'gid://gitlab/GroupLabel/6',
title: 'Brock',
color: '#e082b6',
description: null,
},
]; ];
export const rawIssue = { export const rawIssue = {
......
...@@ -14,6 +14,7 @@ import { mockMoveIssueParams, mockMoveData, mockMoveState } from 'jest/boards/mo ...@@ -14,6 +14,7 @@ import { mockMoveIssueParams, mockMoveData, mockMoveState } from 'jest/boards/mo
import { formatListIssues } from '~/boards/boards_util'; import { formatListIssues } from '~/boards/boards_util';
import listsIssuesQuery from '~/boards/graphql/lists_issues.query.graphql'; import listsIssuesQuery from '~/boards/graphql/lists_issues.query.graphql';
import * as typesCE from '~/boards/stores/mutation_types'; import * as typesCE from '~/boards/stores/mutation_types';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import * as commonUtils from '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams, removeParams } from '~/lib/utils/url_utility'; import { mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
import { import {
...@@ -1380,4 +1381,62 @@ describe('setActiveEpicLabels', () => { ...@@ -1380,4 +1381,62 @@ describe('setActiveEpicLabels', () => {
await expect(actions.setActiveEpicLabels({ getters }, input)).rejects.toThrow(Error); await expect(actions.setActiveEpicLabels({ getters }, input)).rejects.toThrow(Error);
}); });
describe('labels_widget FF on', () => {
beforeEach(() => {
window.gon = {
features: { labelsWidget: true },
};
getters.activeBoardItem = { ...mockIssue, labels };
});
afterEach(() => {
window.gon = {
features: {},
};
});
it('should assign labels', () => {
const payload = {
itemId: getters.activeBoardItem.id,
prop: 'labels',
value: labels,
};
testAction(
actions.setActiveEpicLabels,
input,
{ ...state, ...getters },
[
{
type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
[],
);
});
it('should remove label', () => {
const payload = {
itemId: getters.activeBoardItem.id,
prop: 'labels',
value: [labels[1]],
};
testAction(
actions.setActiveEpicLabels,
{ ...input, removeLabelIds: [getIdFromGraphQLId(labels[0].id)] },
{ ...state, ...getters },
[
{
type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
[],
);
});
});
}); });
...@@ -33,6 +33,19 @@ RSpec.describe BoardsHelper do ...@@ -33,6 +33,19 @@ RSpec.describe BoardsHelper do
end end
end end
describe '#build_issue_link_base' do
context 'when epic board' do
let_it_be(:epic_board) { create(:epic_board, group: group) }
it 'generates the correct url' do
assign(:board, epic_board)
assign(:group, group)
expect(helper.build_issue_link_base).to eq "/groups/#{group.full_path}/-/epics"
end
end
end
describe '#board_base_url' do describe '#board_base_url' do
context 'when epic board' do context 'when epic board' do
let_it_be(:epic_board) { create(:epic_board, group: group) } let_it_be(:epic_board) { create(:epic_board, group: group) }
......
...@@ -10,7 +10,6 @@ import VueApollo from 'vue-apollo'; ...@@ -10,7 +10,6 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { IssuableType } from '~/issue_show/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_widget/constants'; import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue'; import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue';
...@@ -57,7 +56,6 @@ describe('DropdownContentsLabelsView', () => { ...@@ -57,7 +56,6 @@ describe('DropdownContentsLabelsView', () => {
propsData: { propsData: {
...initialState, ...initialState,
localSelectedLabels, localSelectedLabels,
issuableType: IssuableType.Issue,
searchKey, searchKey,
labelCreateType: 'project', labelCreateType: 'project',
workspaceType: 'project', workspaceType: 'project',
......
...@@ -39,7 +39,6 @@ describe('DropdownContent', () => { ...@@ -39,7 +39,6 @@ describe('DropdownContent', () => {
footerManageLabelTitle: 'manage', footerManageLabelTitle: 'manage',
dropdownButtonText: 'Labels', dropdownButtonText: 'Labels',
variant: 'sidebar', variant: 'sidebar',
issuableType: 'issue',
fullPath: 'test', fullPath: 'test',
workspaceType: 'project', workspaceType: 'project',
labelCreateType: 'project', labelCreateType: 'project',
......
...@@ -23,14 +23,14 @@ RSpec.describe BoardsHelper do ...@@ -23,14 +23,14 @@ RSpec.describe BoardsHelper do
it 'returns correct path for base group' do it 'returns correct path for base group' do
assign(:board, group_board) assign(:board, group_board)
expect(helper.build_issue_link_base).to eq('/base/:project_path/issues') expect(helper.build_issue_link_base).to eq('/:project_path/-/issues')
end end
it 'returns correct path for subgroup' do it 'returns correct path for subgroup' do
subgroup = create(:group, parent: base_group, path: 'sub') subgroup = create(:group, parent: base_group, path: 'sub')
assign(:board, create(:board, group: subgroup)) assign(:board, create(:board, group: subgroup))
expect(helper.build_issue_link_base).to eq('/base/sub/:project_path/issues') expect(helper.build_issue_link_base).to eq('/:project_path/-/issues')
end end
end end
end end
...@@ -149,7 +149,7 @@ RSpec.describe BoardsHelper do ...@@ -149,7 +149,7 @@ RSpec.describe BoardsHelper do
end end
it 'returns correct path for base group' do it 'returns correct path for base group' do
expect(helper.build_issue_link_base).to eq("/#{base_group.full_path}/:project_path/issues") expect(helper.build_issue_link_base).to eq("/:project_path/-/issues")
end end
it 'returns required label endpoints' do it 'returns required label endpoints' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment