@@ -219,6 +219,9 @@ function formatXyDataset(
219219 color: accent .value ,
220220 temperatureColors ,
221221 useArea: true ,
222+ dashIndices: dataset
223+ .map ((item , index ) => (item .hasAnomaly ? index : - 1 ))
224+ .filter (index => index !== - 1 ),
222225 }
223226
224227 if (selectedGranularity === ' weekly' && isWeeklyDataset (dataset )) {
@@ -275,19 +278,26 @@ function formatXyDataset(
275278function extractSeriesPoints(
276279 selectedGranularity : ChartTimeGranularity ,
277280 dataset : EvolutionData ,
278- ): Array <{ timestamp: number ; value: number }> {
281+ ): Array <{ timestamp: number ; value: number ; hasAnomaly : boolean }> {
279282 if (selectedGranularity === ' weekly' && isWeeklyDataset (dataset )) {
280- return dataset .map (d => ({ timestamp: d .timestampEnd , value: d .value }))
283+ return dataset .map (d => ({
284+ timestamp: d .timestampEnd ,
285+ value: d .value ,
286+ hasAnomaly: !! d .hasAnomaly ,
287+ }))
281288 }
282289 if (
283290 (selectedGranularity === ' daily' && isDailyDataset (dataset )) ||
284291 (selectedGranularity === ' monthly' && isMonthlyDataset (dataset )) ||
285292 (selectedGranularity === ' yearly' && isYearlyDataset (dataset ))
286293 ) {
287- return (dataset as Array <{ timestamp: number ; value: number }>).map (d => ({
288- timestamp: d .timestamp ,
289- value: d .value ,
290- }))
294+ return (dataset as Array <{ timestamp: number ; value: number ; hasAnomaly? : boolean }>).map (
295+ d => ({
296+ timestamp: d .timestamp ,
297+ value: d .value ,
298+ hasAnomaly: !! d .hasAnomaly ,
299+ }),
300+ )
291301 }
292302 return []
293303}
@@ -380,6 +390,11 @@ const isEstimationGranularity = computed(
380390const supportsEstimation = computed (
381391 () => isEstimationGranularity .value && selectedMetric .value !== ' contributors' ,
382392)
393+
394+ const hasDownloadAnomalies = computed (() =>
395+ normalisedDataset .value ?.some (datapoint => !! datapoint .dashIndices .length ),
396+ )
397+
383398const shouldRenderEstimationOverlay = computed (() => ! pending .value && supportsEstimation .value )
384399
385400const startDate = usePermalink <string >(' start' , ' ' , {
@@ -955,11 +970,13 @@ const effectiveDataSingle = computed<EvolutionData>(() => {
955970 granularity: displayedGranularity .value ,
956971 })
957972 }
973+
958974 return applyDataCorrection (
959975 data as Array <{ value: number }>,
960976 settings .value .chartFilter ,
961977 ) as EvolutionData
962978 }
979+
963980 return data
964981})
965982
@@ -991,7 +1008,10 @@ const chartData = computed<{
9911008 const granularity = displayedGranularity .value
9921009
9931010 const timestampSet = new Set <number >()
994- const pointsByPackage = new Map <string , Array <{ timestamp: number ; value: number }>>()
1011+ const pointsByPackage = new Map <
1012+ string ,
1013+ Array < { timestamp : number ; value : number ; hasAnomaly ?: boolean }>
1014+ > ()
9951015
9961016 for (const pkg of names ) {
9971017 let data = state .evolutionsByPackage [pkg ] ?? []
@@ -1005,6 +1025,7 @@ const chartData = computed<{
10051025 ) as EvolutionData
10061026 }
10071027 const points = extractSeriesPoints (granularity , data )
1028+
10081029 pointsByPackage .set (pkg , points )
10091030 for (const p of points ) timestampSet .add (p .timestamp )
10101031 }
@@ -1023,6 +1044,9 @@ const chartData = computed<{
10231044 name: pkg ,
10241045 type: ' line' ,
10251046 series ,
1047+ dashIndices: points
1048+ .map ((item , index ) => (item .hasAnomaly ? index : - 1 ))
1049+ .filter (index => index !== - 1 ),
10261050 } as VueUiXyDatasetItem
10271051
10281052 if (isListedFramework (pkg )) {
@@ -1045,6 +1069,7 @@ const normalisedDataset = computed(() => {
10451069 return {
10461070 ... d ,
10471071 series: [... d .series .slice (0 , - 1 ), projectedLastValue ],
1072+ dashIndices: d .dashIndices ?? [],
10481073 }
10491074 })
10501075})
@@ -1408,7 +1433,10 @@ function drawSvgPrintLegend(svg: Record<string, any>) {
14081433 })
14091434
14101435 // Inject the estimation legend item when necessary
1411- if (supportsEstimation .value && ! isEndDateOnPeriodEnd .value && ! isZoomed .value ) {
1436+ if (
1437+ (supportsEstimation .value && ! isEndDateOnPeriodEnd .value && ! isZoomed .value ) ||
1438+ hasDownloadAnomalies .value
1439+ ) {
14121440 seriesNames .push (`
14131441 <line
14141442 x1="${svg .drawingArea .left + 12 }"
@@ -1955,7 +1983,10 @@ watch(selectedMetric, value => {
19551983 </template >
19561984
19571985 <!-- Estimation extra legend item -->
1958- <div class =" flex gap-1 place-items-center" v-if =" supportsEstimation" >
1986+ <div
1987+ class =" flex gap-1 place-items-center"
1988+ v-if =" supportsEstimation || hasDownloadAnomalies"
1989+ >
19591990 <svg viewBox =" 0 0 20 2" width =" 20" >
19601991 <line
19611992 x1 =" 0"
0 commit comments