Back

96.42% Statements 27/28
96.55% Branches 28/29
100% Functions 7/7
96.15% Lines 25/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                3x         86x   86x     3x   2x                               40x 40x 43x   40x 43x 43x 43x       43x   43x 43x   43x 26x       43x 43x 6x       40x                                     36x 36x   36x                                                 144x    
/**
 * External dependencies
 */
import { resolveBucketStamp } from '@jetpack-premium-analytics/datetime';
import { __, _n } from '@wordpress/i18n';
import type { StatsVisitsResponse } from '@jetpack-premium-analytics/data';
import type { TooltipExtraSeries } from '@jetpack-premium-analytics/widgets-toolkit';
 
const VIEWS_PER_VISITOR_FORMAT = { type: 'average' as const };
 
type ExtraPoints = TooltipExtraSeries[ 'data' ];
 
function numberOf( point: Record< string, unknown >, field: string ): number | undefined {
	const value = point[ field ];
 
	return typeof value === 'number' ? value : undefined;
}
 
const postsPublishedLabel: NonNullable< TooltipExtraSeries[ 'countLabel' ] > = count =>
	/* translators: %s: number of posts published. */
	_n( '%s Post published', '%s Posts published', count, 'jetpack-premium-analytics-pkg' );
 
/**
 * Read one period's views per visitor and posts published, bucket by bucket.
 *
 * @param report    - The period's views/visitors report, with `post_titles` requested.
 * @param zone      - The report's reporting timezone.
 * @param axisDates - For a comparison period, the current period's bucket dates: each
 *                  bucket is read at the current bucket in the same position.
 * @return The points of both rows, and the period's own bucket dates.
 */
function readPeriod(
	report: StatsVisitsResponse | undefined,
	zone: string,
	axisDates?: Array< Date | undefined >
) {
	const viewsPerVisitor: ExtraPoints = [];
	const postsPublished: ExtraPoints = [];
	const dates = ( report?.data ?? [] ).map( point => resolveBucketStamp( point.date_start, zone ) );
 
	( report?.data ?? [] ).forEach( ( point, index ) => {
		const ownDate = dates[ index ];
		const date = axisDates ? axisDates[ index ] : ownDate;
		Iif ( ! date || ! ownDate ) {
			return;
		}
		// `realDate` is the date the tooltip row reads; `date` only places it.
		const stamp = axisDates ? { date, realDate: ownDate } : { date };
 
		const views = numberOf( point, 'views' );
		const visitors = numberOf( point, 'visitors' );
		// A ratio with no visitors has nothing to say, as in classic Stats.
		if ( views !== undefined && visitors !== undefined && visitors > 0 ) {
			viewsPerVisitor.push( { ...stamp, value: views / visitors } );
		}
 
		// An untitled post arrives as `''` and still counts, as in classic Stats.
		const posts = Array.isArray( point.post_titles ) ? point.post_titles.length : 0;
		if ( posts ) {
			postsPublished.push( { ...stamp, value: posts } );
		}
	} );
 
	return { viewsPerVisitor, postsPublished, dates };
}
 
/**
 * The rows classic Stats adds under the traffic chart's tooltip: views per
 * visitor, and the number of posts published in the bucket. Both are read from
 * the `stats/visits` report the Views and Visitors tabs already fetch.
 *
 * @param report     - The current-period views/visitors report, with `post_titles` requested.
 * @param zone       - The report's reporting timezone.
 * @param comparison - The comparison-period report, when a comparison is on.
 * @return The extra series, each omitted when no bucket has a reading for it; a
 *         comparison row follows its current-period row.
 */
export function buildTrafficTooltipExtras(
	report: StatsVisitsResponse | undefined,
	zone: string,
	comparison?: StatsVisitsResponse
): TooltipExtraSeries[] {
	const current = readPeriod( report, zone );
	const previous = comparison ? readPeriod( comparison, zone, current.dates ) : undefined;
 
	const rows: TooltipExtraSeries[] = [
		{
			label: __( 'Views per visitor', 'jetpack-premium-analytics-pkg' ),
			data: current.viewsPerVisitor,
			dataFormat: VIEWS_PER_VISITOR_FORMAT,
		},
		{
			label: __( 'Views per visitor', 'jetpack-premium-analytics-pkg' ),
			key: 'views-per-visitor-comparison',
			data: previous?.viewsPerVisitor ?? [],
			dataFormat: VIEWS_PER_VISITOR_FORMAT,
		},
		{
			label: __( 'Posts published', 'jetpack-premium-analytics-pkg' ),
			data: current.postsPublished,
			countLabel: postsPublishedLabel,
		},
		{
			label: __( 'Posts published', 'jetpack-premium-analytics-pkg' ),
			key: 'posts-published-comparison',
			data: previous?.postsPublished ?? [],
			countLabel: postsPublishedLabel,
		},
	];
 
	return rows.filter( row => row.data.length );
}