Commit 5ee329f6 authored by Brandon Labuschagne's avatar Brandon Labuschagne Committed by Martin Wortschack

Resolve "[VSA] "Days to completion" chart should display averages"

parent b2e96410
......@@ -50,7 +50,7 @@ export default {
<p>
{{
s__(
'CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items.',
'CycleAnalytics|The average time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items.',
)
}}
</p>
......@@ -63,7 +63,7 @@ export default {
<scatterplot
v-if="hasData"
:x-axis-title="s__('CycleAnalytics|Date')"
:y-axis-title="s__('CycleAnalytics|Total days to completion')"
:y-axis-title="s__('CycleAnalytics|Average days to completion')"
:tooltip-date-format="$options.durationChartTooltipDateFormat"
:scatter-data="durationChartPlottableData"
/>
......
......@@ -132,8 +132,8 @@ export const prepareStageErrors = (stages, errors) =>
* selected: true,
* data: [
* {
* 'duration_in_seconds': 1234,
* 'finished_at': '2019-09-02T18:25:43.511Z'
* 'average_duration_in_seconds': 1234,
* 'date': '2019-09-02T18:25:43.511Z'
* },
* ...
* ]
......@@ -144,31 +144,31 @@ export const prepareStageErrors = (stages, errors) =>
* The data is then transformed and flattened into the following format;
* [
* {
* 'duration_in_seconds': 1234,
* 'finished_at': '2019-09-02'
* 'average_duration_in_seconds': 1234,
* 'date': '2019-09-02'
* },
* ...
* ]
*
* @param {Array} data - The duration data for selected stages
* @returns {Array} An array with each item being an object containing the duration_in_seconds and finished_at values for an event
* @returns {Array} An array with each item being an object containing the average_duration_in_seconds and date values for an event
*/
export const flattenDurationChartData = (data) =>
data
.map((stage) =>
stage.data.map((event) => {
const date = new Date(event.finished_at);
const date = new Date(event.date);
return {
...event,
finished_at: dateFormat(date, dateFormats.isoDate),
date: dateFormat(date, dateFormats.isoDate),
};
}),
)
.flat();
/**
* Takes the duration data for selected stages, groups the data by day and calculates the total duration
* per day.
* Takes the duration data for selected stages, groups the data by day and calculates the average duration
* per day, for stages with values on that specific day.
*
* The received data is expected to be the following format; One top level object in the array per stage,
* each potentially having multiple data entries.
......@@ -178,8 +178,8 @@ export const flattenDurationChartData = (data) =>
* selected: true,
* data: [
* {
* 'duration_in_seconds': 1234,
* 'finished_at': '2019-09-02T18:25:43.511Z'
* 'average_duration_in_seconds': 1234,
* 'date': '2019-09-02T18:25:43.511Z'
* },
* ...
* ]
......@@ -203,12 +203,11 @@ export const flattenDurationChartData = (data) =>
* @param {Array} data - The duration data for selected stages
* @param {Date} startDate - The globally selected Value Stream Analytics start date
* @param {Date} endDate - The globally selected Value Stream Analytics end date
* @returns {Array} An array with each item being another arry of three items (plottable date, computed total, tooltip display date)
* @returns {Array} An array with each item being another arry of three items (plottable date, computed average, tooltip display date)
*/
export const getDurationChartData = (data, startDate, endDate) => {
const flattenedData = flattenDurationChartData(data);
const eventData = [];
const endOfDay = newDate(endDate);
endOfDay.setHours(23, 59, 59); // make sure we're at the end of the day
......@@ -218,11 +217,13 @@ export const getDurationChartData = (data, startDate, endDate) => {
currentDate = dayAfter(currentDate)
) {
const currentISODate = dateFormat(newDate(currentDate), dateFormats.isoDate);
const valuesForDay = flattenedData.filter((object) => object.finished_at === currentISODate);
const summedData = valuesForDay.reduce((total, value) => total + value.duration_in_seconds, 0);
const summedDataInDays = secondsToDays(summedData);
const valuesForDay = flattenedData.filter((object) => object.date === currentISODate);
const averagedData =
valuesForDay.reduce((total, value) => total + value.average_duration_in_seconds, 0) /
valuesForDay.length;
const averagedDataInDays = secondsToDays(averagedData);
if (summedDataInDays) eventData.push([currentISODate, summedDataInDays, currentISODate]);
if (averagedDataInDays) eventData.push([currentISODate, averagedDataInDays, currentISODate]);
}
return eventData;
......
......@@ -28,7 +28,7 @@ export default {
cycleAnalyticsStagePath:
'/groups/:id/-/analytics/value_stream_analytics/value_streams/:value_stream_id/stages/:stage_id',
cycleAnalyticsDurationChartPath:
'/groups/:id/-/analytics/value_stream_analytics/value_streams/:value_stream_id/stages/:stage_id/duration_chart',
'/groups/:id/-/analytics/value_stream_analytics/value_streams/:value_stream_id/stages/:stage_id/average_duration_chart',
cycleAnalyticsGroupLabelsPath: '/groups/:namespace_path/-/labels.json',
codeReviewAnalyticsPath: '/api/:version/analytics/code_review',
groupActivityIssuesPath: '/api/:version/analytics/group_activity/issues_count',
......
---
title: VSA - Update duration chart to use averages
merge_request: 59453
author:
type: changed
......@@ -355,7 +355,7 @@ RSpec.describe 'Group value stream analytics filters and data', :js do
it 'will have data available' do
duration_chart_content = page.find('[data-testid="vsa-duration-chart"]')
expect(duration_chart_content).not_to have_text(_("There is no data available. Please change your selection."))
expect(duration_chart_content).to have_text(_('Total days to completion'))
expect(duration_chart_content).to have_text(s_('CycleAnalytics|Average days to completion'))
tasks_by_type_chart_content = page.find('.js-tasks-by-type-chart')
expect(tasks_by_type_chart_content).not_to have_text(_("There is no data available. Please change your selection."))
......@@ -370,7 +370,7 @@ RSpec.describe 'Group value stream analytics filters and data', :js do
it 'will filter the data' do
duration_chart_content = page.find('[data-testid="vsa-duration-chart"]')
expect(duration_chart_content).not_to have_text(_('Total days to completion'))
expect(duration_chart_content).not_to have_text(s_('CycleAnalytics|Average days to completion'))
expect(duration_chart_content).to have_text(_("There is no data available. Please change your selection."))
tasks_by_type_chart_content = page.find('.js-tasks-by-type-chart')
......
......@@ -13,7 +13,7 @@ exports[`DurationChart renders the duration chart 1`] = `
<p>
The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items.
The average time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items.
</p>
......@@ -25,10 +25,10 @@ exports[`DurationChart renders the duration chart 1`] = `
<scatterplot-stub
medianlinedata=""
scatterdata="2019-01-01,29,2019-01-01,2019-01-02,100,2019-01-02"
scatterdata="2019-01-01,14,2019-01-01,2019-01-02,50,2019-01-02"
tooltipdateformat="mmm d, yyyy"
xaxistitle="Date"
yaxistitle="Total days to completion"
yaxistitle="Average days to completion"
/>
</div>
`;
......@@ -30,7 +30,7 @@ export const endpoints = {
groupLabels: /groups\/[A-Z|a-z|\d|\-|_]+\/-\/labels.json/,
recentActivityData: /analytics\/value_stream_analytics\/summary/,
timeMetricsData: /analytics\/value_stream_analytics\/time_summary/,
durationData: /analytics\/value_stream_analytics\/value_streams\/\w+\/stages\/\w+\/duration_chart/,
durationData: /analytics\/value_stream_analytics\/value_streams\/\w+\/stages\/\w+\/average_duration_chart/,
stageData: /analytics\/value_stream_analytics\/value_streams\/\w+\/stages\/\w+\/records/,
stageMedian: /analytics\/value_stream_analytics\/value_streams\/\w+\/stages\/\w+\/median/,
baseStagesEndpoint: /analytics\/value_stream_analytics\/value_streams\/\w+\/stages$/,
......@@ -241,12 +241,12 @@ export const taskByTypeFilters = {
export const rawDurationData = [
{
duration_in_seconds: 1234000,
finished_at: '2019-01-01T00:00:00.000Z',
average_duration_in_seconds: 1234000,
date: '2019-01-01T00:00:00.000Z',
},
{
duration_in_seconds: 4321000,
finished_at: '2019-01-02T00:00:00.000Z',
average_duration_in_seconds: 4321000,
date: '2019-01-02T00:00:00.000Z',
},
];
......@@ -264,25 +264,25 @@ export const transformedDurationData = [
];
export const flattenedDurationData = [
{ duration_in_seconds: 1234000, finished_at: '2019-01-01' },
{ duration_in_seconds: 4321000, finished_at: '2019-01-02' },
{ duration_in_seconds: 1234000, finished_at: '2019-01-01' },
{ duration_in_seconds: 4321000, finished_at: '2019-01-02' },
{ average_duration_in_seconds: 1234000, date: '2019-01-01' },
{ average_duration_in_seconds: 4321000, date: '2019-01-02' },
{ average_duration_in_seconds: 1234000, date: '2019-01-01' },
{ average_duration_in_seconds: 4321000, date: '2019-01-02' },
];
export const durationChartPlottableData = [
['2019-01-01', 29, '2019-01-01'],
['2019-01-02', 100, '2019-01-02'],
['2019-01-01', 14, '2019-01-01'],
['2019-01-02', 50, '2019-01-02'],
];
export const rawDurationMedianData = [
{
duration_in_seconds: 1234000,
finished_at: '2018-12-01T00:00:00.000Z',
average_duration_in_seconds: 1234000,
date: '2018-12-01T00:00:00.000Z',
},
{
duration_in_seconds: 4321000,
finished_at: '2018-12-02T00:00:00.000Z',
average_duration_in_seconds: 4321000,
date: '2018-12-02T00:00:00.000Z',
},
];
......
......@@ -553,7 +553,7 @@ describe('Api', () => {
const params = { ...defaultParams };
const expectedUrl = valueStreamBaseUrl({
id: valueStreamId,
resource: `stages/${stageId}/duration_chart`,
resource: `stages/${stageId}/average_duration_chart`,
});
mock.onGet(expectedUrl).reply(httpStatus.OK, response);
......
......@@ -9829,6 +9829,9 @@ msgstr ""
msgid "CycleAnalytics|All stages"
msgstr ""
msgid "CycleAnalytics|Average days to completion"
msgstr ""
msgid "CycleAnalytics|Date"
msgstr ""
......@@ -9875,13 +9878,10 @@ msgstr ""
msgid "CycleAnalytics|Tasks by type"
msgstr ""
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
msgid "CycleAnalytics|The average time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
msgstr ""
msgid "CycleAnalytics|Total days to completion"
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
msgid "CycleAnalytics|Type of work"
......@@ -33268,9 +33268,6 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
msgid "Total days to completion"
msgstr ""
msgid "Total issues"
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