Skip to content
代码片段 群组 项目
未验证 提交 f14c9849 编辑于 作者: Enrique Alcántara's avatar Enrique Alcántara 提交者: GitLab
浏览文件

Merge branch '458457-update-work-item-sticky-header-to-add-state-badge' into 'master'

No related branches found
No related tags found
无相关合并请求
...@@ -561,6 +561,7 @@ export default { ...@@ -561,6 +561,7 @@ export default {
@toggleWorkItemConfidentiality="toggleConfidentiality" @toggleWorkItemConfidentiality="toggleConfidentiality"
@error="updateError = $event" @error="updateError = $event"
@promotedToObjective="$emit('promotedToObjective', workItemIid)" @promotedToObjective="$emit('promotedToObjective', workItemIid)"
@toggleEditMode="enableEditMode"
/> />
<div data-testid="work-item-overview" class="work-item-overview"> <div data-testid="work-item-overview" class="work-item-overview">
<section> <section>
......
<script> <script>
import { GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui'; import { GlLoadingIcon, GlIntersectionObserver, GlButton, GlLink } from '@gitlab/ui';
import LockedBadge from '~/issuable/components/locked_badge.vue'; import LockedBadge from '~/issuable/components/locked_badge.vue';
import { WORKSPACE_PROJECT } from '~/issues/constants'; import { WORKSPACE_PROJECT } from '~/issues/constants';
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue'; import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
import { isNotesWidget } from '../utils'; import { isNotesWidget } from '../utils';
import WorkItemActions from './work_item_actions.vue'; import WorkItemActions from './work_item_actions.vue';
import WorkItemTodos from './work_item_todos.vue'; import WorkItemTodos from './work_item_todos.vue';
import WorkItemStateBadge from './work_item_state_badge.vue';
export default { export default {
components: { components: {
...@@ -15,6 +16,9 @@ export default { ...@@ -15,6 +16,9 @@ export default {
WorkItemActions, WorkItemActions,
WorkItemTodos, WorkItemTodos,
ConfidentialityBadge, ConfidentialityBadge,
WorkItemStateBadge,
GlButton,
GlLink,
}, },
props: { props: {
workItem: { workItem: {
...@@ -78,6 +82,9 @@ export default { ...@@ -78,6 +82,9 @@ export default {
projectFullPath() { projectFullPath() {
return this.workItem.namespace?.fullPath; return this.workItem.namespace?.fullPath;
}, },
workItemState() {
return this.workItem.state;
},
}, },
WORKSPACE_PROJECT, WORKSPACE_PROJECT,
}; };
...@@ -95,18 +102,33 @@ export default { ...@@ -95,18 +102,33 @@ export default {
data-testid="work-item-sticky-header" data-testid="work-item-sticky-header"
> >
<div <div
class="work-item-sticky-header-text gl-align-items-center gl-mx-auto gl-px-6 gl-display-flex gl-gap-3" class="work-item-sticky-header-text gl-items-center gl-mx-auto gl-px-5 xl:gl-px-6 gl-flex gl-gap-3"
> >
<span class="gl-text-truncate gl-font-weight-bold gl-pr-3 gl-mr-auto"> <work-item-state-badge v-if="workItemState" :work-item-state="workItemState" />
{{ workItem.title }}
</span>
<gl-loading-icon v-if="updateInProgress" /> <gl-loading-icon v-if="updateInProgress" />
<confidentiality-badge <confidentiality-badge
v-if="workItem.confidential" v-if="workItem.confidential"
:issuable-type="workItemType" :issuable-type="workItemType"
:workspace-type="$options.WORKSPACE_PROJECT" :workspace-type="$options.WORKSPACE_PROJECT"
hide-text-in-small-screens
/> />
<locked-badge v-if="isDiscussionLocked" :issuable-type="workItemType" /> <locked-badge v-if="isDiscussionLocked" :issuable-type="workItemType" />
<gl-link
class="gl-truncate gl-block gl-font-bold gl-pr-3 gl-mr-auto gl-text-black"
href="#top"
:title="workItem.title"
>
{{ workItem.title }}
</gl-link>
<gl-button
v-if="canUpdate"
category="secondary"
data-testid="work-item-edit-button-sticky"
class="shortcut-edit-wi-description"
@click="$emit('toggleEditMode')"
>
{{ __('Edit') }}
</gl-button>
<work-item-todos <work-item-todos
v-if="showWorkItemCurrentUserTodos" v-if="showWorkItemCurrentUserTodos"
:work-item-id="workItem.id" :work-item-id="workItem.id"
......
...@@ -684,7 +684,7 @@ describe('WorkItemDetail component', () => { ...@@ -684,7 +684,7 @@ describe('WorkItemDetail component', () => {
describe('work item two column view', () => { describe('work item two column view', () => {
beforeEach(async () => { beforeEach(async () => {
createComponent({ workItemsBeta: true }); createComponent();
await waitForPromises(); await waitForPromises();
}); });
...@@ -701,10 +701,24 @@ describe('WorkItemDetail component', () => { ...@@ -701,10 +701,24 @@ describe('WorkItemDetail component', () => {
}); });
}); });
describe('work item sticky header', () => {
beforeEach(async () => {
createComponent();
await waitForPromises();
});
it('enables the edit mode when event `toggleEditMode` is emitted', async () => {
findStickyHeader().vm.$emit('toggleEditMode');
await nextTick();
expect(findWorkItemDescription().props('editMode')).toBe(true);
});
});
describe('edit button for work item title and description', () => { describe('edit button for work item title and description', () => {
describe('with permissions to update', () => { describe('with permissions to update', () => {
beforeEach(async () => { beforeEach(async () => {
createComponent({ workItemsBeta: true }); createComponent();
await waitForPromises(); await waitForPromises();
}); });
......
import { GlIntersectionObserver } from '@gitlab/ui'; import { GlIntersectionObserver, GlLink } from '@gitlab/ui';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { STATE_OPEN } from '~/work_items/constants'; import { STATE_OPEN } from '~/work_items/constants';
...@@ -8,14 +8,19 @@ import WorkItemStickyHeader from '~/work_items/components/work_item_sticky_heade ...@@ -8,14 +8,19 @@ import WorkItemStickyHeader from '~/work_items/components/work_item_sticky_heade
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue'; import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
import WorkItemActions from '~/work_items/components/work_item_actions.vue'; import WorkItemActions from '~/work_items/components/work_item_actions.vue';
import WorkItemTodos from '~/work_items/components/work_item_todos.vue'; import WorkItemTodos from '~/work_items/components/work_item_todos.vue';
import WorkItemStateBadge from '~/work_items/components/work_item_state_badge.vue';
describe('WorkItemStickyHeader', () => { describe('WorkItemStickyHeader', () => {
let wrapper; let wrapper;
const createComponent = ({ confidential = false, discussionLocked = false } = {}) => { const createComponent = ({
confidential = false,
discussionLocked = false,
canUpdate = true,
} = {}) => {
wrapper = shallowMountExtended(WorkItemStickyHeader, { wrapper = shallowMountExtended(WorkItemStickyHeader, {
propsData: { propsData: {
workItem: workItemResponseFactory({ canUpdate: true, confidential, discussionLocked }).data workItem: workItemResponseFactory({ canUpdate, confidential, discussionLocked }).data
.workItem, .workItem,
fullPath: '/test', fullPath: '/test',
isStickyHeaderShowing: true, isStickyHeaderShowing: true,
...@@ -36,6 +41,9 @@ describe('WorkItemStickyHeader', () => { ...@@ -36,6 +41,9 @@ describe('WorkItemStickyHeader', () => {
const findWorkItemActions = () => wrapper.findComponent(WorkItemActions); const findWorkItemActions = () => wrapper.findComponent(WorkItemActions);
const findWorkItemTodos = () => wrapper.findComponent(WorkItemTodos); const findWorkItemTodos = () => wrapper.findComponent(WorkItemTodos);
const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver); const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver);
const findWorkItemStateBadge = () => wrapper.findComponent(WorkItemStateBadge);
const findEditButton = () => wrapper.findByTestId('work-item-edit-button-sticky');
const findWorkItemTitle = () => wrapper.findComponent(GlLink);
const triggerPageScroll = () => findIntersectionObserver().vm.$emit('disappear'); const triggerPageScroll = () => findIntersectionObserver().vm.$emit('disappear');
it('has the sticky header when the page is scrolled', async () => { it('has the sticky header when the page is scrolled', async () => {
...@@ -50,11 +58,35 @@ describe('WorkItemStickyHeader', () => { ...@@ -50,11 +58,35 @@ describe('WorkItemStickyHeader', () => {
it('renders title, todos, and actions', () => { it('renders title, todos, and actions', () => {
createComponent(); createComponent();
expect(wrapper.findByText('Updated title').exists()).toBe(true); expect(findWorkItemTitle().exists()).toBe(true);
expect(findWorkItemTodos().exists()).toBe(true); expect(findWorkItemTodos().exists()).toBe(true);
expect(findWorkItemActions().exists()).toBe(true); expect(findWorkItemActions().exists()).toBe(true);
}); });
it('has title with the link to the top', () => {
createComponent();
expect(findWorkItemTitle().attributes('href')).toBe('#top');
});
it('renders the state badge', () => {
createComponent();
expect(findWorkItemStateBadge().exists()).toBe(true);
});
describe('edit button', () => {
it('renders the button when it has permissions to edit', () => {
createComponent({ canUpdate: true });
expect(findEditButton().exists()).toBe(true);
});
it('does not render the button when it does not have permissions to edit', () => {
createComponent({ canUpdate: false });
expect(findEditButton().exists()).toBe(false);
});
});
describe('confidential badge', () => { describe('confidential badge', () => {
describe('when not confidential', () => { describe('when not confidential', () => {
beforeEach(() => { beforeEach(() => {
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册