Commit 2f3f8240 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '334739-handle-policy-without-rules' into 'master'

Handle schedule linked to escalation rule removal - simple case

See merge request gitlab-org/gitlab!65766
parents fb35e253 183a78be
...@@ -27,6 +27,7 @@ export const i18n = { ...@@ -27,6 +27,7 @@ export const i18n = {
'EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} %{then} THEN %{doAction} %{schedule}', 'EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} %{then} THEN %{doAction} %{schedule}',
), ),
minutes: s__('EscalationPolicies|mins'), minutes: s__('EscalationPolicies|mins'),
noRules: s__('EscalationPolicies|This policy has no escalation rules.'),
}; };
const isRuleValid = ({ status, elapsedTimeMinutes, oncallSchedule: { name } }) => const isRuleValid = ({ status, elapsedTimeMinutes, oncallSchedule: { name } }) =>
...@@ -133,37 +134,42 @@ export default { ...@@ -133,37 +134,42 @@ export default {
{{ policy.description }} {{ policy.description }}
</p> </p>
<div class="gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base gl-p-5"> <div class="gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base gl-p-5">
<div <div v-if="!policy.rules.length" class="gl-text-red-500">
v-for="(rule, ruleIndex) in policy.rules" <gl-icon name="status_warning" class="gl-mr-3" /> {{ $options.i18n.noRules }}
:key="rule.id"
:class="{ 'gl-mb-5': ruleIndex !== policy.rules.length - 1 }"
>
<gl-icon name="clock" class="gl-mr-3" />
<gl-sprintf :message="$options.i18n.escalationRule">
<template #alertStatus>
{{ $options.ALERT_STATUSES[rule.status].toLowerCase() }}
</template>
<template #minutes>
<span class="gl-font-weight-bold">
{{ rule.elapsedTimeMinutes }} {{ $options.i18n.minutes }}
</span>
</template>
<template #then>
<span class="right-arrow">
<i class="right-arrow-head"></i>
</span>
<gl-icon name="notifications" class="gl-mr-3" />
</template>
<template #doAction>
{{ $options.ACTIONS[$options.DEFAULT_ACTION].toLowerCase() }}
</template>
<template #schedule>
<span class="gl-font-weight-bold">
{{ rule.oncallSchedule.name }}
</span>
</template>
</gl-sprintf>
</div> </div>
<template v-else>
<div
v-for="(rule, ruleIndex) in policy.rules"
:key="rule.id"
:class="{ 'gl-mb-5': ruleIndex !== policy.rules.length - 1 }"
>
<gl-icon name="clock" class="gl-mr-3" />
<gl-sprintf :message="$options.i18n.escalationRule">
<template #alertStatus>
{{ $options.ALERT_STATUSES[rule.status].toLowerCase() }}
</template>
<template #minutes>
<span class="gl-font-weight-bold">
{{ rule.elapsedTimeMinutes }} {{ $options.i18n.minutes }}
</span>
</template>
<template #then>
<span class="right-arrow">
<i class="right-arrow-head"></i>
</span>
<gl-icon name="notifications" class="gl-mr-3" />
</template>
<template #doAction>
{{ $options.ACTIONS[$options.DEFAULT_ACTION].toLowerCase() }}
</template>
<template #schedule>
<span class="gl-font-weight-bold">
{{ rule.oncallSchedule.name }}
</span>
</template>
</gl-sprintf>
</div>
</template>
</div> </div>
</gl-collapse> </gl-collapse>
</gl-card> </gl-card>
......
...@@ -10,6 +10,9 @@ export const i18n = { ...@@ -10,6 +10,9 @@ export const i18n = {
deleteScheduleMessage: s__( deleteScheduleMessage: s__(
'OnCallSchedules|Are you sure you want to delete the "%{deleteSchedule}" schedule? This action cannot be undone.', 'OnCallSchedules|Are you sure you want to delete the "%{deleteSchedule}" schedule? This action cannot be undone.',
), ),
escalationRulesWillBeDeletedMessage: s__(
'OnCallScheduless|Any escalation rules that are using this schedule will also be deleted.',
),
}; };
export default { export default {
...@@ -106,5 +109,8 @@ export default { ...@@ -106,5 +109,8 @@ export default {
<gl-sprintf :message="$options.i18n.deleteScheduleMessage"> <gl-sprintf :message="$options.i18n.deleteScheduleMessage">
<template #deleteSchedule>{{ schedule.name }}</template> <template #deleteSchedule>{{ schedule.name }}</template>
</gl-sprintf> </gl-sprintf>
<div class="gl-mt-5">
{{ $options.i18n.escalationRulesWillBeDeletedMessage }}
</div>
</gl-modal> </gl-modal>
</template> </template>
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EscalationPolicy renders policy with rules 1`] = ` exports[`EscalationPolicy renders a policy with rules 1`] = `
<div> <div>
<gl-card-stub <gl-card-stub
bodyclass="[object Object]" bodyclass="[object Object]"
...@@ -32,14 +32,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = ` ...@@ -32,14 +32,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = `
size="16" size="16"
/> />
IF alert is not IF alert is not
acknowledged acknowledged
in in
<span <span
class="gl-font-weight-bold" class="gl-font-weight-bold"
> >
1 mins 1 mins
</span> </span>
<span <span
...@@ -56,14 +56,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = ` ...@@ -56,14 +56,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = `
size="16" size="16"
/> />
THEN THEN
email on-call user in schedule email on-call user in schedule
<span <span
class="gl-font-weight-bold" class="gl-font-weight-bold"
> >
Schedule to fill in Schedule to fill in
</span> </span>
</div> </div>
<div <div
...@@ -75,14 +75,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = ` ...@@ -75,14 +75,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = `
size="16" size="16"
/> />
IF alert is not IF alert is not
resolved resolved
in in
<span <span
class="gl-font-weight-bold" class="gl-font-weight-bold"
> >
2 mins 2 mins
</span> </span>
<span <span
...@@ -99,14 +99,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = ` ...@@ -99,14 +99,14 @@ exports[`EscalationPolicy renders policy with rules 1`] = `
size="16" size="16"
/> />
THEN THEN
email on-call user in schedule email on-call user in schedule
<span <span
class="gl-font-weight-bold" class="gl-font-weight-bold"
> >
Monitor schedule Monitor schedule
</span> </span>
</div> </div>
</div> </div>
......
import { GlSprintf } from '@gitlab/ui'; import { GlSprintf, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import EditEscalationPolicyModal from 'ee/escalation_policies/components/add_edit_escalation_policy_modal.vue'; import EditEscalationPolicyModal from 'ee/escalation_policies/components/add_edit_escalation_policy_modal.vue';
import DeleteEscalationPolicyModal from 'ee/escalation_policies/components/delete_escalation_policy_modal.vue'; import DeleteEscalationPolicyModal from 'ee/escalation_policies/components/delete_escalation_policy_modal.vue';
import EscalationPolicy from 'ee/escalation_policies/components/escalation_policy.vue'; import EscalationPolicy, { i18n } from 'ee/escalation_policies/components/escalation_policy.vue';
import { import {
deleteEscalationPolicyModalId, deleteEscalationPolicyModalId,
...@@ -16,10 +16,10 @@ describe('EscalationPolicy', () => { ...@@ -16,10 +16,10 @@ describe('EscalationPolicy', () => {
let wrapper; let wrapper;
const escalationPolicy = parsePolicy(cloneDeep(mockPolicies[0])); const escalationPolicy = parsePolicy(cloneDeep(mockPolicies[0]));
const createComponent = () => { const createComponent = (policy = escalationPolicy) => {
wrapper = shallowMount(EscalationPolicy, { wrapper = shallowMount(EscalationPolicy, {
propsData: { propsData: {
policy: escalationPolicy, policy,
index: 0, index: 0,
}, },
stubs: { stubs: {
...@@ -38,11 +38,24 @@ describe('EscalationPolicy', () => { ...@@ -38,11 +38,24 @@ describe('EscalationPolicy', () => {
const findDeleteModal = () => wrapper.findComponent(DeleteEscalationPolicyModal); const findDeleteModal = () => wrapper.findComponent(DeleteEscalationPolicyModal);
const findEditModal = () => wrapper.findComponent(EditEscalationPolicyModal); const findEditModal = () => wrapper.findComponent(EditEscalationPolicyModal);
const findWarningIcon = () => wrapper.findComponent(GlIcon);
it('renders policy with rules', () => { it('renders a policy with rules', () => {
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders a policy without rules', () => {
const policyWithoutRules = {
id: mockPolicies[0].id,
name: mockPolicies[0].name,
description: mockPolicies[0].description,
rules: [],
};
createComponent(policyWithoutRules);
expect(findWarningIcon().exists()).toBe(true);
expect(wrapper.text()).toContain(i18n.noRules);
});
describe('Modals', () => { describe('Modals', () => {
describe('delete policy modal', () => { describe('delete policy modal', () => {
it('should render a modal and provide it with correct id', () => { it('should render a modal and provide it with correct id', () => {
......
...@@ -17,5 +17,13 @@ exports[`DeleteScheduleModal renders delete schedule modal layout 1`] = ` ...@@ -17,5 +17,13 @@ exports[`DeleteScheduleModal renders delete schedule modal layout 1`] = `
<gl-sprintf-stub <gl-sprintf-stub
message="Are you sure you want to delete the \\"%{deleteSchedule}\\" schedule? This action cannot be undone." message="Are you sure you want to delete the \\"%{deleteSchedule}\\" schedule? This action cannot be undone."
/> />
<div
class="gl-mt-5"
>
Any escalation rules that are using this schedule will also be deleted.
</div>
</gl-modal-stub> </gl-modal-stub>
`; `;
...@@ -13092,6 +13092,9 @@ msgstr "" ...@@ -13092,6 +13092,9 @@ msgstr ""
msgid "EscalationPolicies|The escalation policy could not be updated. Please try again" msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
msgstr "" msgstr ""
msgid "EscalationPolicies|This policy has no escalation rules."
msgstr ""
msgid "EscalationPolicies|mins" msgid "EscalationPolicies|mins"
msgstr "" msgstr ""
...@@ -22721,6 +22724,9 @@ msgstr "" ...@@ -22721,6 +22724,9 @@ msgstr ""
msgid "On-call schedules" msgid "On-call schedules"
msgstr "" msgstr ""
msgid "OnCallScheduless|Any escalation rules that are using this schedule will also be deleted."
msgstr ""
msgid "OnCallSchedules|1 day" msgid "OnCallSchedules|1 day"
msgstr "" msgstr ""
......
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