Commit 06155c81 authored by David O'Regan's avatar David O'Regan

Merge branch 'fix-project-epic-swimlane-sidebar-epic' into 'master'

Fix epics select in sidebar for project epics swimlane  [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!55954
parents 712121c3 5918bf63
...@@ -4,6 +4,7 @@ fragment EpicNode on Epic { ...@@ -4,6 +4,7 @@ fragment EpicNode on Epic {
title title
state state
reference reference
webPath
webUrl webUrl
createdAt createdAt
closedAt closedAt
......
...@@ -18,7 +18,7 @@ module BoardsHelper ...@@ -18,7 +18,7 @@ module BoardsHelper
time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s, time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s,
recent_boards_endpoint: recent_boards_path, recent_boards_endpoint: recent_boards_path,
parent: current_board_parent.model_name.param_key, parent: current_board_parent.model_name.param_key,
group_id: @group&.id, group_id: group_id,
labels_filter_base_path: build_issue_link_base, labels_filter_base_path: build_issue_link_base,
labels_fetch_path: labels_fetch_path, labels_fetch_path: labels_fetch_path,
labels_manage_path: labels_manage_path, labels_manage_path: labels_manage_path,
...@@ -26,6 +26,12 @@ module BoardsHelper ...@@ -26,6 +26,12 @@ module BoardsHelper
} }
end end
def group_id
return @group.id if board.group_board?
@project&.group&.id
end
def full_path def full_path
if board.group_board? if board.group_board?
@group.full_path @group.full_path
......
<script> <script>
import { GlLink } from '@gitlab/ui';
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/base.vue'; import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/base.vue';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue'; import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
...@@ -11,6 +12,7 @@ export default { ...@@ -11,6 +12,7 @@ export default {
components: { components: {
BoardEditableItem, BoardEditableItem,
EpicsSelect, EpicsSelect,
GlLink,
}, },
i18n: { i18n: {
epic: __('Epic'), epic: __('Epic'),
...@@ -99,13 +101,14 @@ export default { ...@@ -99,13 +101,14 @@ export default {
ref="sidebarItem" ref="sidebarItem"
:title="$options.i18n.epic" :title="$options.i18n.epic"
:loading="epicFetchInProgress" :loading="epicFetchInProgress"
data-testid="sidebar-epic"
@open="handleOpen" @open="handleOpen"
@close="handleClose" @close="handleClose"
> >
<template v-if="epicData.title" #collapsed> <template v-if="epicData.title" #collapsed>
<a class="gl-text-gray-900! gl-font-weight-bold" href="#"> <gl-link class="gl-text-gray-900! gl-font-weight-bold" :href="epicData.webPath">
{{ epicData.title }} {{ epicData.title }}
</a> </gl-link>
</template> </template>
<epics-select <epics-select
v-if="!epicFetchInProgress" v-if="!epicFetchInProgress"
......
...@@ -4,6 +4,7 @@ fragment BoardEpicNode on BoardEpic { ...@@ -4,6 +4,7 @@ fragment BoardEpicNode on BoardEpic {
title title
state state
reference reference
webPath
webUrl webUrl
createdAt createdAt
closedAt closedAt
......
---
title: Fix epics dropdown to work in project epic swimlanes
merge_request: 55954
author:
type: fixed
...@@ -11,6 +11,7 @@ RSpec.describe 'epics swimlanes sidebar', :js do ...@@ -11,6 +11,7 @@ RSpec.describe 'epics swimlanes sidebar', :js do
let_it_be(:label) { create(:label, project: project, name: 'Label 1') } let_it_be(:label) { create(:label, project: project, name: 'Label 1') }
let_it_be(:list) { create(:list, board: board, label: label, position: 0) } let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
let_it_be(:epic1) { create(:epic, group: group) } let_it_be(:epic1) { create(:epic, group: group) }
let_it_be(:epic2) { create(:epic, group: group) }
let_it_be(:issue1, reload: true) { create(:issue, project: project) } let_it_be(:issue1, reload: true) { create(:issue, project: project) }
let_it_be(:epic_issue1, reload: true) { create(:epic_issue, epic: epic1, issue: issue1) } let_it_be(:epic_issue1, reload: true) { create(:epic_issue, epic: epic1, issue: issue1) }
...@@ -40,6 +41,40 @@ RSpec.describe 'epics swimlanes sidebar', :js do ...@@ -40,6 +41,40 @@ RSpec.describe 'epics swimlanes sidebar', :js do
end end
end end
context 'epic dropdown' do
before do
group.add_owner(user)
end
context 'when the issue is associated with an epic' do
it 'displays name of epic and links to it' do
load_epic_swimlanes
click_first_issue_card
page.within('[data-testid="sidebar-epic"]') do
expect(page).to have_link(epic1.title, href: epic_path(epic1))
end
end
it 'updates the epic associated with the issue' do
load_epic_swimlanes
click_first_issue_card
page.within('[data-testid="sidebar-epic"]') do
find("[data-testid='edit-button']").click
wait_for_all_requests
find('.gl-new-dropdown-item', text: epic2.title).click
wait_for_all_requests
expect(page).to have_link(epic2.title, href: epic_path(epic2))
end
end
end
end
context 'notifications subscription' do context 'notifications subscription' do
it 'displays notifications toggle' do it 'displays notifications toggle' do
load_epic_swimlanes load_epic_swimlanes
......
import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import BoardSidebarEpicSelect from 'ee/boards/components/sidebar/board_sidebar_epic_select.vue'; import BoardSidebarEpicSelect from 'ee/boards/components/sidebar/board_sidebar_epic_select.vue';
...@@ -69,6 +70,7 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => { ...@@ -69,6 +70,7 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => {
const findEpicSelect = () => wrapper.find({ ref: 'epicSelect' }); const findEpicSelect = () => wrapper.find({ ref: 'epicSelect' });
const findItemWrapper = () => wrapper.find({ ref: 'sidebarItem' }); const findItemWrapper = () => wrapper.find({ ref: 'sidebarItem' });
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]'); const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
const findEpicLink = () => wrapper.find(GlLink);
const findBoardEditableItem = () => wrapper.find(BoardEditableItem); const findBoardEditableItem = () => wrapper.find(BoardEditableItem);
describe('when not editing', () => { describe('when not editing', () => {
...@@ -173,7 +175,9 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => { ...@@ -173,7 +175,9 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => {
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(findCollapsed().text()).toBe(mockAssignedEpic.title); expect(findEpicLink().isVisible()).toBe(true);
expect(findEpicLink().text()).toBe(mockAssignedEpic.title);
expect(findEpicLink().attributes('href')).toBe(mockAssignedEpic.webPath);
}); });
}); });
...@@ -212,8 +216,9 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => { ...@@ -212,8 +216,9 @@ describe('ee/boards/components/sidebar/board_sidebar_epic_select.vue', () => {
}); });
it('collapses sidebar and renders epic title', () => { it('collapses sidebar and renders epic title', () => {
expect(findCollapsed().isVisible()).toBe(true); expect(findEpicLink().isVisible()).toBe(true);
expect(findCollapsed().text()).toBe(mockAssignedEpic.title); expect(findEpicLink().text()).toBe(mockAssignedEpic.title);
expect(findEpicLink().attributes('href')).toBe(mockAssignedEpic.webPath);
}); });
describe('when the selected epic did not change', () => { describe('when the selected epic did not change', () => {
......
...@@ -226,7 +226,14 @@ export const mockEpic = { ...@@ -226,7 +226,14 @@ export const mockEpic = {
labels: [], labels: [],
}; };
export const mockIssueWithEpic = { ...mockIssue3, epic: { id: mockEpic.id, iid: mockEpic.iid } }; export const mockIssueWithEpic = {
...mockIssue3,
epic: {
id: mockEpic.id,
iid: mockEpic.iid,
webPath: '/gitlab-org/-/epics/41',
},
};
export const mockAssignedEpic = { ...mockIssueWithEpic.epic, title: mockEpic.title }; export const mockAssignedEpic = { ...mockIssueWithEpic.epic, title: mockEpic.title };
export const mockEpics = [ export const mockEpics = [
......
...@@ -4,8 +4,8 @@ require 'spec_helper' ...@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe BoardsHelper do RSpec.describe BoardsHelper do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:base_group) { create(:group, path: 'base') } let_it_be(:base_group) { create(:group, path: 'base') }
let_it_be(:project) { create(:project, group: base_group) }
let_it_be(:project_board) { create(:board, project: project) } let_it_be(:project_board) { create(:board, project: project) }
let_it_be(:group_board) { create(:board, group: base_group) } let_it_be(:group_board) { create(:board, group: base_group) }
...@@ -82,6 +82,10 @@ RSpec.describe BoardsHelper do ...@@ -82,6 +82,10 @@ RSpec.describe BoardsHelper do
expect(helper.board_data[:labels_fetch_path]).to eq("/#{project.full_path}/-/labels.json?include_ancestor_groups=true") expect(helper.board_data[:labels_fetch_path]).to eq("/#{project.full_path}/-/labels.json?include_ancestor_groups=true")
expect(helper.board_data[:labels_manage_path]).to eq("/#{project.full_path}/-/labels") expect(helper.board_data[:labels_manage_path]).to eq("/#{project.full_path}/-/labels")
end end
it 'returns the group id of a project' do
expect(helper.board_data[:group_id]).to eq(project.group.id)
end
end end
context 'group board' do context 'group board' do
...@@ -102,6 +106,10 @@ RSpec.describe BoardsHelper do ...@@ -102,6 +106,10 @@ RSpec.describe BoardsHelper do
expect(helper.board_data[:labels_fetch_path]).to eq("/groups/#{base_group.full_path}/-/labels.json?include_ancestor_groups=true&only_group_labels=true") expect(helper.board_data[:labels_fetch_path]).to eq("/groups/#{base_group.full_path}/-/labels.json?include_ancestor_groups=true&only_group_labels=true")
expect(helper.board_data[:labels_manage_path]).to eq("/groups/#{base_group.full_path}/-/labels") expect(helper.board_data[:labels_manage_path]).to eq("/groups/#{base_group.full_path}/-/labels")
end end
it 'returns the group id' do
expect(helper.board_data[:group_id]).to eq(base_group.id)
end
end end
end end
......
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