Commit 0d858c23 authored by Tristan Read's avatar Tristan Read Committed by Olena Horal-Koretska

Consolidate incident SLA component

parent 09c2a929
......@@ -102,7 +102,7 @@ export default {
GlIcon,
PublishedCell: () => import('ee_component/incidents/components/published_cell.vue'),
ServiceLevelAgreementCell: () =>
import('ee_component/incidents/components/service_level_agreement_cell.vue'),
import('ee_component/vue_shared/components/incidents/service_level_agreement.vue'),
GlEmptyState,
SeverityToken,
PaginatedTableWithSearchAndTabs,
......
<script>
import { GlIcon } from '@gitlab/ui';
import ServiceLevelAgreement from 'ee_component/vue_shared/components/incidents/service_level_agreement.vue';
import { isValidSlaDueAt } from 'ee/vue_shared/components/incidents/utils';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import { formatTime, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import getSlaDueAt from './graphql/queries/get_sla_due_at.graphql';
export default {
components: { GlIcon, TimeAgoTooltip },
components: { GlIcon, ServiceLevelAgreement },
inject: ['fullPath', 'iid', 'slaFeatureAvailable'],
apollo: {
slaDueAt: {
......@@ -21,9 +22,14 @@ export default {
update(data) {
return data?.project?.issue?.slaDueAt;
},
result({ data } = {}) {
const slaDueAt = data?.project?.issue?.slaDueAt;
this.$emit('update', Boolean(slaDueAt));
result({ data }) {
const isValidSla = isValidSlaDueAt(data?.project?.issue?.slaDueAt);
// Render component
this.hasData = isValidSla;
// Render parent component
this.$emit('update', isValidSla);
},
error() {
createFlash({
......@@ -35,6 +41,7 @@ export default {
data() {
return {
slaDueAt: null,
hasData: false,
};
},
computed: {
......@@ -49,13 +56,11 @@ export default {
</script>
<template>
<div v-if="slaFeatureAvailable && slaDueAt">
<div v-if="slaFeatureAvailable && hasData">
<span class="gl-font-weight-bold">{{ s__('HighlightBar|Time to SLA:') }}</span>
<span class="gl-white-space-nowrap">
<gl-icon name="timer" />
<time-ago-tooltip :time="slaDueAt">
{{ displayValue }}
</time-ago-tooltip>
<service-level-agreement :sla-due-at="slaDueAt" />
</span>
</div>
</template>
......@@ -2,26 +2,26 @@
import { GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { formatTime, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import { isValidSlaDueAt } from './utils';
export default {
i18n: {
longText: s__('IncidentManagement|%{hours} hours, %{minutes} minutes remaining'),
shortText: s__('IncidentManagement|%{minutes} minutes remaining'),
longTitle: s__('IncidentManagement|%{hours} hours, %{minutes} minutes remaining'),
shortTitle: s__('IncidentManagement|%{minutes} minutes remaining'),
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
slaDueAt: {
type: String,
type: String, // ISODateString
required: false,
default: null,
},
},
computed: {
shouldShow() {
// Checks for a valid date string
return this.slaDueAt && !Number.isNaN(Date.parse(this.slaDueAt));
return isValidSlaDueAt(this.slaDueAt);
},
remainingTime() {
return calculateRemainingMilliseconds(this.slaDueAt);
......@@ -37,9 +37,9 @@ export default {
const hours = Math.floor(this.remainingTime / 1000 / 60 / 60);
if (hours > 0) {
return sprintf(this.$options.i18n.longText, { hours, minutes });
return sprintf(this.$options.i18n.longTitle, { hours, minutes });
}
return sprintf(this.$options.i18n.shortText, { hours, minutes });
return sprintf(this.$options.i18n.shortTitle, { minutes });
},
},
};
......
// Checks for a valid date string
export const isValidSlaDueAt = (slaDueAt) =>
Boolean(slaDueAt) && !Number.isNaN(Date.parse(slaDueAt));
import { shallowMount } from '@vue/test-utils';
import { merge } from 'lodash';
import IncidentSla from 'ee/issue_show/components/incidents/incident_sla.vue';
import { formatTime } from '~/lib/utils/datetime_utility';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import ServiceLevelAgreement from 'ee_component/vue_shared/components/incidents/service_level_agreement.vue';
jest.mock('~/lib/utils/datetime_utility');
const defaultProvide = { fullPath: 'test', iid: 1, slaFeatureAvailable: true };
const mockSlaDueAt = '2020-01-01T00:00:00.000Z';
describe('Incident SLA', () => {
let wrapper;
......@@ -17,7 +17,7 @@ describe('Incident SLA', () => {
merge(
{
data() {
return { slaDueAt: '2020-01-01T00:00:00.000Z' };
return { slaDueAt: mockSlaDueAt, hasData: true };
},
provide: { ...defaultProvide },
},
......@@ -26,10 +26,6 @@ describe('Incident SLA', () => {
);
};
beforeEach(() => {
formatTime.mockImplementation(() => '12:34:56');
});
afterEach(() => {
if (wrapper) {
wrapper.destroy();
......@@ -37,28 +33,16 @@ describe('Incident SLA', () => {
}
});
const findTimer = () => wrapper.find(TimeAgoTooltip);
const findSLA = () => wrapper.find(ServiceLevelAgreement);
it('does not render an SLA when no sla is present', () => {
it('renders a blank component when there is no data', () => {
mountComponent({
data() {
return { slaDueAt: null };
return { hasData: false };
},
});
expect(findTimer().exists()).toBe(false);
});
it('renders an incident SLA when sla is present', () => {
mountComponent();
expect(findTimer().text()).toBe('12:34');
});
it('renders a component when feature is available', () => {
mountComponent();
expect(wrapper.exists()).toBe(true);
expect(wrapper.isVisible()).toBe(false);
});
it('renders a blank component when feature is not available', () => {
......@@ -69,6 +53,13 @@ describe('Incident SLA', () => {
},
});
expect(wrapper.html()).toBe('');
expect(wrapper.isVisible()).toBe(false);
});
it('renders an incident SLA when sla is present and feature is available', () => {
mountComponent();
expect(wrapper.isVisible()).toBe(true);
expect(findSLA().attributes('sladueat')).toBe(mockSlaDueAt);
});
});
import { shallowMount } from '@vue/test-utils';
import ServiceLevelAgreementCell from 'ee/incidents/components/service_level_agreement_cell.vue';
import ServiceLevelAgreementCell from 'ee/vue_shared/components/incidents/service_level_agreement.vue';
import { calculateRemainingMilliseconds, formatTime } from '~/lib/utils/datetime_utility';
jest.mock('~/lib/utils/datetime_utility', () => ({
......
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