Commit 3c20d8ba authored by Illya Klymov's avatar Illya Klymov

Merge branch 'tr-add-escalation-help-link' into 'master'

Add escalation status help link

See merge request gitlab-org/gitlab!83180
parents a0491ce9 e8893853
......@@ -21,6 +21,11 @@ export default {
return [...STATUS_LIST, null].includes(value);
},
},
preventDropdownClose: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
currentStatusLabel() {
......@@ -35,6 +40,11 @@ export default {
this.$refs.dropdown.hide();
},
getStatusLabel,
hideDropdown(event) {
if (this.preventDropdownClose) {
event.preventDefault();
}
},
},
};
</script>
......@@ -45,6 +55,7 @@ export default {
block
:text="currentStatusLabel"
toggle-class="dropdown-menu-toggle gl-mb-2"
@hide="hideDropdown"
>
<slot name="header"> </slot>
<gl-dropdown-item
......
......@@ -20,4 +20,6 @@ export const i18nStatusText = {
dropdownInfo: s__(
'IncidentManagement|Setting the status to Acknowledged or Resolved stops paging when escalation policies are selected for the incident.',
),
learnMoreShort: __('Learn More.'),
learnMoreFull: s__('IncidentManagement|Learn more about incident statuses'),
};
<script>
import { GlDropdownDivider, GlDropdownSectionHeader, GlIcon, GlPopover } from '@gitlab/ui';
import { GlDropdownDivider, GlDropdownSectionHeader, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import EscalationStatus from '~/sidebar/components/incidents/escalation_status.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { helpPagePath } from '~/helpers/help_page_helper';
import { i18nStatusText } from './constants';
export default {
i18n: i18nStatusText,
docsPath: helpPagePath('operations/incident_management/incidents.html', {
anchor: 'change-incident-status',
}),
components: {
EscalationStatus,
GlDropdownDivider,
GlDropdownSectionHeader,
GlIcon,
GlPopover,
GlLink,
},
mixins: [glFeatureFlagMixin()],
data() {
return { isHelpVisible: false };
},
computed: {
showHeader() {
return this.glFeatures.escalationPolicies;
......@@ -28,24 +36,48 @@ export default {
hide() {
this.$refs.escalationStatus.hide();
},
showPopover() {
this.isHelpVisible = true;
},
hidePopover() {
this.isHelpVisible = false;
},
},
};
</script>
<template>
<escalation-status ref="escalationStatus" v-bind="$attrs" v-on="$listeners">
<escalation-status
ref="escalationStatus"
v-bind="$attrs"
:prevent-dropdown-close="isHelpVisible"
v-on="$listeners"
>
<template v-if="showHeader" #header>
<gl-dropdown-section-header class="gl-mt-n2">
<gl-dropdown-section-header id="escalation-status-dropdown" class="gl-mt-n2">
<div class="gl-text-center">
{{ $options.i18n.dropdownHeader }}
<gl-icon id="escalation-status-help" class="gl-ml-2 gl-text-blue-600" name="question-o" />
<gl-popover
:content="$options.i18n.dropdownInfo"
ref="popover"
:title="$options.i18n.dropdownHeader"
boundary="viewport"
placement="left"
target="escalation-status-help"
/>
boundary="viewport"
@show="showPopover"
@hide="hidePopover"
>
<p @click.stop.prevent>{{ $options.i18n.dropdownInfo }}</p>
<gl-link
ref="link"
:aria-label="$options.i18n.learnMoreFull"
class="gl-font-sm"
:href="$options.docsPath"
target="_blank"
>
{{ $options.i18n.learnMoreShort }}
</gl-link>
</gl-popover>
</div>
</gl-dropdown-section-header>
<gl-dropdown-divider />
......
import { GlDropdownSectionHeader, GlPopover } from '@gitlab/ui';
import { GlDropdownSectionHeader, GlPopover, GlLink } from '@gitlab/ui';
import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import EscalationStatus from 'ee/sidebar/components/incidents/escalation_status.vue';
import { STATUS_TRIGGERED } from '~/sidebar/components/incidents/constants';
......@@ -28,16 +29,49 @@ describe('EscalationStatus', () => {
const findDropdownHeaderComponent = () => wrapper.findComponent(GlDropdownSectionHeader);
const findPopover = () => wrapper.findComponent(GlPopover);
const findLearnMoreLink = () => wrapper.findComponent(GlLink);
const findInnerStatusComponent = () => wrapper.findComponent({ ref: 'escalationStatus' });
describe('popover', () => {
it('renders a popover', () => {
const openPopover = async () => {
await findPopover().vm.$emit('show');
await nextTick();
};
const closePopover = async () => {
await findPopover().vm.$emit('hide');
await nextTick();
};
describe('help popover', () => {
beforeEach(() => {
createComponent();
});
it('renders a popover', () => {
expect(findPopover().props('title')).toBe('Assign paging status');
expect(findPopover().attributes('content')).toContain('Setting the status');
expect(findPopover().text()).toContain('Setting the status');
});
it('shows the Learn More link', () => {
expect(findLearnMoreLink().text()).toBe('Learn More.');
expect(findLearnMoreLink().attributes('href')).toContain(
'incidents.html#change-incident-status',
);
});
it('prevents self from being removed from DOM when open', async () => {
await openPopover();
expect(findInnerStatusComponent().props('preventDropdownClose')).toBe(true);
});
it('allows self to be removed from DOM when closed', async () => {
await openPopover();
await closePopover();
expect(findInnerStatusComponent().props('preventDropdownClose')).toBe(false);
});
});
describe('dropdown', () => {
it('forwards `show` calls to the child', () => {
createComponent();
......
......@@ -19799,6 +19799,9 @@ msgstr ""
msgid "IncidentManagement|Incidents"
msgstr ""
msgid "IncidentManagement|Learn more about incident statuses"
msgstr ""
msgid "IncidentManagement|Low - S4"
msgstr ""
......
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import EscalationStatus from '~/sidebar/components/incidents/escalation_status.vue';
import {
......@@ -25,6 +26,11 @@ describe('EscalationStatus', () => {
const findDropdownComponent = () => wrapper.findComponent(GlDropdown);
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findDropdownMenu = () => findDropdownComponent().find('.dropdown-menu');
const toggleDropdown = async () => {
await findDropdownComponent().findComponent('button').trigger('click');
await waitForPromises();
};
describe('status', () => {
it('shows the current status', () => {
......@@ -49,4 +55,32 @@ describe('EscalationStatus', () => {
expect(wrapper.emitted().input[0][0]).toBe(STATUS_ACKNOWLEDGED);
});
});
describe('close behavior', () => {
it('allows the dropdown to be closed by default', async () => {
createComponent();
// Open dropdown
await toggleDropdown();
expect(findDropdownMenu().classes('show')).toBe(true);
// Attempt to close dropdown
await toggleDropdown();
expect(findDropdownMenu().classes('show')).toBe(false);
});
it('preventDropdownClose prevents the dropdown from closing', async () => {
createComponent({ preventDropdownClose: true });
// Open dropdown
await toggleDropdown();
expect(findDropdownMenu().classes('show')).toBe(true);
// Attempt to close dropdown
await toggleDropdown();
expect(findDropdownMenu().classes('show')).toBe(true);
});
});
});
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