Commit 5fcd2e8d authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Ensure we expose median as a value

The project level BE previously returned the
median as a string, we now require the raw
integer value to be returned.

Fixes median path navigation display

Ensures we correctly extract the medians for each
stage and dont display stage counts when they
are not available
parent a1124f44
...@@ -115,17 +115,23 @@ export default { ...@@ -115,17 +115,23 @@ export default {
</script> </script>
<template> <template>
<div class="cycle-analytics"> <div class="cycle-analytics">
<path-navigation
v-if="shouldDisplayPathNavigation"
:key="`path_navigation_key_${pathNavigationData.length}`"
class="js-path-navigation gl-w-full gl-pb-2"
:loading="isLoading"
:stages="pathNavigationData"
:selected-stage="selectedStage"
:with-stage-counts="false"
@selected="(ev) => onSelectStage(ev)"
/>
<gl-loading-icon v-if="isLoading" size="lg" /> <gl-loading-icon v-if="isLoading" size="lg" />
<div v-else class="wrapper"> <div v-else class="wrapper">
<path-navigation <!--
v-if="shouldDisplayPathNavigation" We wont have access to the stage counts until we move to a default value stream
:key="`path_navigation_key_${pathNavigationData.length}`" For now we can use the `withStageCounts` flag to ensure we don't display empty stage counts
class="js-path-navigation gl-w-full gl-pb-2" Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/326705
:loading="isLoading" -->
:stages="pathNavigationData"
:selected-stage="selectedStage"
@selected="(ev) => onSelectStage(ev)"
/>
<div class="card"> <div class="card">
<div class="card-header">{{ __('Recent Project Activity') }}</div> <div class="card-header">{{ __('Recent Project Activity') }}</div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
......
...@@ -4,7 +4,6 @@ export const filterStagesByHiddenStatus = (stages = [], isHidden = true) => ...@@ -4,7 +4,6 @@ export const filterStagesByHiddenStatus = (stages = [], isHidden = true) =>
stages.filter(({ hidden = false }) => hidden === isHidden); stages.filter(({ hidden = false }) => hidden === isHidden);
export const pathNavigationData = ({ stages, medians, stageCounts, selectedStage }) => { export const pathNavigationData = ({ stages, medians, stageCounts, selectedStage }) => {
console.log('medians', medians);
return transformStagesForPathNavigation({ return transformStagesForPathNavigation({
stages: filterStagesByHiddenStatus(stages, false), stages: filterStagesByHiddenStatus(stages, false),
medians, medians,
......
...@@ -21,8 +21,6 @@ export default { ...@@ -21,8 +21,6 @@ export default {
[types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, data) { [types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, data) {
state.isLoading = false; state.isLoading = false;
const { stages, summary, medians } = decorateData(data); const { stages, summary, medians } = decorateData(data);
console.log('medians', medians);
console.log('formatMedianValues::medians', formatMedianValues(medians));
state.stages = stages; state.stages = stages;
state.summary = summary; state.summary = summary;
state.medians = formatMedianValues(medians); state.medians = formatMedianValues(medians);
......
...@@ -50,10 +50,17 @@ const mapToEvent = (event, stage) => { ...@@ -50,10 +50,17 @@ const mapToEvent = (event, stage) => {
export const decorateEvents = (events, stage) => events.map((event) => mapToEvent(event, stage)); export const decorateEvents = (events, stage) => events.map((event) => mapToEvent(event, stage));
const mapToStage = (permissions, item) => { /*
const slug = dasherize(item.name.toLowerCase()); * NOTE: We currently use the `name` field since the project level stages are in memory
* once we migrate to a default value stream https://gitlab.com/gitlab-org/gitlab/-/issues/326705
* we can use the `id` to identify which median we are using
*/
const mapToStage = (permissions, { name, ...rest }) => {
const slug = dasherize(name.toLowerCase());
return { return {
...item, ...rest,
name,
id: name,
slug, slug,
active: false, active: false,
isUserAllowed: permissions[slug], isUserAllowed: permissions[slug],
...@@ -63,14 +70,15 @@ const mapToStage = (permissions, item) => { ...@@ -63,14 +70,15 @@ const mapToStage = (permissions, item) => {
}; };
const mapToSummary = ({ value, ...rest }) => ({ ...rest, value: value || '-' }); const mapToSummary = ({ value, ...rest }) => ({ ...rest, value: value || '-' });
const mapToMedians = ({ id, name, value }) => ({ id, name, value }); const mapToMedians = ({ id, value }) => ({ id, value });
export const decorateData = (data = {}) => { export const decorateData = (data = {}) => {
const { permissions, stats, summary } = data; const { permissions, stats, summary } = data;
const stages = stats?.map((item) => mapToStage(permissions, item)) || [];
return { return {
stages: stats?.map((item) => mapToStage(permissions, item)) || [], stages,
summary: summary?.map((item) => mapToSummary(item)) || [], summary: summary?.map((item) => mapToSummary(item)) || [],
medians: stats?.map((item) => mapToMedians(item)) || [], medians: stages?.map((item) => mapToMedians(item)) || [],
}; };
}; };
...@@ -90,8 +98,6 @@ export const transformStagesForPathNavigation = ({ ...@@ -90,8 +98,6 @@ export const transformStagesForPathNavigation = ({
stageCounts = {}, stageCounts = {},
selectedStage, selectedStage,
}) => { }) => {
// TODO: do we need popovers for the project path
// - medians, start / end events + descriptions
const formattedStages = stages.map((stage) => { const formattedStages = stages.map((stage) => {
return { return {
metric: medians[stage?.id], metric: medians[stage?.id],
......
...@@ -8,9 +8,5 @@ class AnalyticsStageEntity < Grape::Entity ...@@ -8,9 +8,5 @@ class AnalyticsStageEntity < Grape::Entity
expose :legend expose :legend
expose :description expose :description
expose :project_median, as: :value do |stage| expose :project_median, as: :value
# median returns a BatchLoader instance which we first have to unwrap by using to_f
# we use to_f to make sure results below 1 are presented to the end-user
stage.project_median.to_f.nonzero? ? distance_of_time_in_words(stage.project_median) : nil
end
end end
...@@ -32,12 +32,17 @@ export default { ...@@ -32,12 +32,17 @@ export default {
required: false, required: false,
default: () => {}, default: () => {},
}, },
withStageCounts: {
type: Boolean,
required: false,
default: true,
},
}, },
methods: { methods: {
showPopover({ id }) { showPopover({ id }) {
return id && id !== OVERVIEW_STAGE_ID; return id && id !== OVERVIEW_STAGE_ID;
}, },
hasStageCount({ stageCount }) { hasStageCount({ stageCount = null }) {
return stageCount !== null; return stageCount !== null;
}, },
}, },
...@@ -67,7 +72,7 @@ export default { ...@@ -67,7 +72,7 @@ export default {
<div class="gl-pb-4 gl-font-weight-bold">{{ pathItem.metric }}</div> <div class="gl-pb-4 gl-font-weight-bold">{{ pathItem.metric }}</div>
</div> </div>
</div> </div>
<div class="gl-px-4"> <div v-if="withStageCounts" class="gl-px-4">
<div class="gl-display-flex gl-justify-content-space-between"> <div class="gl-display-flex gl-justify-content-space-between">
<div class="gl-pr-4 gl-pb-4"> <div class="gl-pr-4 gl-pb-4">
{{ s__('ValueStreamEvent|Items in stage') }} {{ s__('ValueStreamEvent|Items in stage') }}
......
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