Commit f01d1b45 authored by wortschi's avatar wortschi

Add stage time to path popovers

- Adds the median stage time
to path popovers in
group level VSA
parent 0c171090
......@@ -5,6 +5,7 @@ import {
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import { OVERVIEW_STAGE_ID } from '../constants';
export default {
name: 'PathNavigation',
......@@ -33,8 +34,8 @@ export default {
},
},
methods: {
showPopover({ startEventHtmlDescription, endEventHtmlDescription }) {
return startEventHtmlDescription || endEventHtmlDescription;
showPopover({ id }) {
return id && id !== OVERVIEW_STAGE_ID;
},
},
popoverOptions: {
......@@ -51,24 +52,41 @@ export default {
v-if="showPopover(pathItem)"
v-bind="$options.popoverOptions"
:target="pathId"
:css-classes="['stage-item-popover']"
data-testid="stage-item-popover"
>
<template #title>{{ pathItem.title }}</template>
<div class="gl-display-table">
<div v-if="pathItem.startEventHtmlDescription" class="gl-display-table-row">
<div class="gl-display-table-cell gl-pr-4 gl-pb-4">
<div class="gl-px-4">
<div class="gl-display-flex gl-justify-content-space-between">
<div class="gl-pr-4 gl-pb-4">
{{ s__('ValueStreamEvent|Stage time (median)') }}
</div>
<div class="gl-pb-4 gl-font-weight-bold">{{ pathItem.metric }}</div>
</div>
</div>
<div class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50">
<div
v-if="pathItem.startEventHtmlDescription"
class="gl-display-flex gl-flex-direction-row"
>
<div class="gl-display-flex gl-flex-direction-column gl-pr-4 gl-pb-4 metric-label">
{{ s__('ValueStreamEvent|Start') }}
</div>
<div
v-safe-html="pathItem.startEventHtmlDescription"
class="gl-display-table-cell gl-pb-4 stage-event-description"
class="gl-display-flex gl-flex-direction-column gl-pb-4 stage-event-description"
></div>
</div>
<div v-if="pathItem.endEventHtmlDescription" class="gl-display-table-row">
<div class="gl-display-table-cell gl-pr-4">{{ s__('ValueStreamEvent|Stop') }}</div>
<div
v-if="pathItem.endEventHtmlDescription"
class="gl-display-flex gl-flex-direction-row"
>
<div class="gl-display-flex gl-flex-direction-column gl-pr-4 metric-label">
{{ s__('ValueStreamEvent|Stop') }}
</div>
<div
v-safe-html="pathItem.endEventHtmlDescription"
class="gl-display-table-cell stage-event-description"
class="gl-display-flex gl-flex-direction-column stage-event-description"
></div>
</div>
</div>
......
......@@ -40,6 +40,17 @@
// Since backend wraps event description in a paragraph
// we need to remove common styles, i.e., spacing
.stage-event-description p {
margin: 0 !important;
.stage-item-popover {
.stage-event-description p {
margin: 0 !important;
}
.popover-body {
padding-left: 0 !important;
padding-right: 0 !important;
}
.metric-label {
flex: 0 0 20%;
}
}
---
title: Add stage time to path popovers in group level VSA
merge_request: 59606
author:
type: added
......@@ -70,13 +70,35 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
>
<div
class="gl-display-table"
class="gl-px-4"
>
<div
class="gl-display-table-row"
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-display-table-cell gl-pr-4 gl-pb-4"
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<div
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-flex gl-flex-direction-column gl-pr-4 gl-pb-4 metric-label"
>
Start
......@@ -84,7 +106,7 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-cell gl-pb-4 stage-event-description"
class="gl-display-flex gl-flex-direction-column gl-pb-4 stage-event-description"
>
<p
data-sourcepos="1:1-1:13"
......@@ -96,16 +118,18 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-row"
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-table-cell gl-pr-4"
class="gl-display-flex gl-flex-direction-column gl-pr-4 metric-label"
>
Stop
Stop
</div>
<div
class="gl-display-table-cell stage-event-description"
class="gl-display-flex gl-flex-direction-column stage-event-description"
>
<p
data-sourcepos="1:1-1:71"
......@@ -138,13 +162,35 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
>
<div
class="gl-display-table"
class="gl-px-4"
>
<div
class="gl-display-table-row"
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-display-table-cell gl-pr-4 gl-pb-4"
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<div
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-flex gl-flex-direction-column gl-pr-4 gl-pb-4 metric-label"
>
Start
......@@ -152,7 +198,7 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-cell gl-pb-4 stage-event-description"
class="gl-display-flex gl-flex-direction-column gl-pb-4 stage-event-description"
>
<p
data-sourcepos="1:1-1:71"
......@@ -164,16 +210,18 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-row"
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-table-cell gl-pr-4"
class="gl-display-flex gl-flex-direction-column gl-pr-4 metric-label"
>
Stop
Stop
</div>
<div
class="gl-display-table-cell stage-event-description"
class="gl-display-flex gl-flex-direction-column stage-event-description"
>
<p
data-sourcepos="1:1-1:33"
......@@ -206,13 +254,35 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
>
<div
class="gl-display-table"
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<div
class="gl-display-table-row"
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-table-cell gl-pr-4 gl-pb-4"
class="gl-display-flex gl-flex-direction-column gl-pr-4 gl-pb-4 metric-label"
>
Start
......@@ -220,7 +290,7 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-cell gl-pb-4 stage-event-description"
class="gl-display-flex gl-flex-direction-column gl-pb-4 stage-event-description"
>
<p
data-sourcepos="1:1-1:33"
......@@ -232,16 +302,18 @@ exports[`PathNavigation displays correctly loading is false matches the snapshot
</div>
<div
class="gl-display-table-row"
class="gl-display-flex gl-flex-direction-row"
>
<div
class="gl-display-table-cell gl-pr-4"
class="gl-display-flex gl-flex-direction-column gl-pr-4 metric-label"
>
Stop
Stop
</div>
<div
class="gl-display-table-cell stage-event-description"
class="gl-display-flex gl-flex-direction-column stage-event-description"
>
<p
data-sourcepos="1:1-1:21"
......
......@@ -17,12 +17,16 @@ describe('PathNavigation', () => {
});
};
const pathNavigationItems = () => {
const pathNavigationTitles = () => {
return wrapper.findAll('.gl-path-button');
};
const pathNavigationItems = () => {
return wrapper.findAll('.gl-path-nav-list-item');
};
const clickItemAt = (index) => {
pathNavigationItems().at(index).trigger('click');
pathNavigationTitles().at(index).trigger('click');
};
beforeEach(() => {
......@@ -62,21 +66,20 @@ describe('PathNavigation', () => {
});
describe('popovers', () => {
const modifiedStages = [
...transformedStagePathData.slice(0, 3),
{
...transformedStagePathData[3],
startEventHtmlDescription: null,
endEventHtmlDescription: null,
},
];
beforeEach(() => {
wrapper = createComponent({ stages: modifiedStages });
wrapper = createComponent({ stages: transformedStagePathData });
});
it('renders popovers only for stages with either a start event and/or and end event', () => {
expect(wrapper.findAll('[data-testid="stage-item-popover"]')).toHaveLength(2);
it('renders popovers for all stages except for the overview stage', () => {
const pathItemContent = pathNavigationItems().wrappers;
const [overviewStage, ...popoverStages] = pathItemContent;
expect(overviewStage.text()).toContain('Overview');
expect(overviewStage.find('[data-testid="stage-item-popover"]').exists()).toBe(false);
popoverStages.forEach((stage) => {
expect(stage.find('[data-testid="stage-item-popover"]').exists()).toBe(true);
});
});
it('shows the sanitized start event description for the first stage item', () => {
......@@ -91,6 +94,11 @@ describe('PathNavigation', () => {
'Issue first associated with a milestone or issue first added to a board';
expect(firstPopover.text()).toContain(expectedStartEventDescription);
});
it('shows the median stage time for the first stage item', () => {
const firstPopover = wrapper.findAll('[data-testid="stage-item-popover"]').at(0);
expect(firstPopover.text()).toContain('Stage time (median)');
});
});
});
......
......@@ -34593,6 +34593,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
msgid "ValueStreamEvent|Start"
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