Back

85% Statements 17/20
100% Branches 2/2
62.5% Functions 5/8
87.5% Lines 14/16

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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147                                                                    2x           2x                                                                     15x 15x 15x 15x 15x 15x 15x 15x 15x 15x   15x                                                                                                                   8x    
/**
 * External dependencies
 */
import { Button } from '@jetpack-premium-analytics/externals';
import { useReportDateFilters, useSectionTab } from '@jetpack-premium-analytics/routing';
import { StatsBreadcrumbs, StatsPageIcon } from '@jetpack-premium-analytics/ui';
import {
	ReportDrilldownTable,
	ReportPageLayout,
	ReportErrorState,
	ReportPageShell,
	ReportPageTabs,
	ExporterCsvAction,
	utmCsvExporters,
	UtmUrlBuilderDialog,
	type UtmReportRow,
} from '@jetpack-premium-analytics/widgets-toolkit';
import { useCallback, useMemo, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
 * Internal dependencies
 */
import { route } from '../package.json';
import { REPORTS } from '../registry';
import { useReportParams } from '../use-report-params';
import {
	getReportUtmTabs,
	getUtmFields,
	getUtmTabLabel,
	resolveSection,
	useUtmReportRecords,
} from './config';
import type { JSX } from 'react';
 
const ROUTE_FROM = route.path;
 
/*
 * No default sort: rows arrive as UTM parents followed by their posts. The
 * unsorted view preserves that hierarchy; user sorting stays within levels.
 */
const RECORDS_VIEW = {
	layout: {
		styles: {
			utmValue: { width: '100%' },
			views: { align: 'end' as const },
		},
	},
};
 
/**
 * Stable row id for the UTM records table.
 *
 * @param item - The UTM row.
 * @return The row id.
 */
function getUtmRowId( item: UtmReportRow ): string {
	return item.id;
}
 
/**
 * Resolve the UTM parent row id for nested post rows.
 *
 * @param item - The UTM or post row.
 * @return The parent row id, if any.
 */
function getUtmRowParentId( item: UtmReportRow ): string | undefined {
	return item.parentId;
}
 
/**
 * Premium Analytics UTM report page.
 *
 * @return The UTM report page.
 */
function UtmReport(): JSX.Element {
	const reportParams = useReportParams();
	const tabs = useMemo( () => getReportUtmTabs(), [] );
	const [ activeTab, setActiveTab ] = useSectionTab( ROUTE_FROM, resolveSection );
	const records = useUtmReportRecords( activeTab, reportParams );
	const fields = useMemo( () => getUtmFields( activeTab ), [ activeTab ] );
	const dateFilters = useReportDateFilters( ROUTE_FROM );
	const { getLabel } = REPORTS.utm;
	const [ isBuilderOpen, setBuilderOpen ] = useState( false );
	const openBuilder = useCallback( () => setBuilderOpen( true ), [] );
	const closeBuilder = useCallback( () => setBuilderOpen( false ), [] );
 
	return (
		<ReportPageShell
			visual={ <StatsPageIcon /> }
			breadcrumbs={ <StatsBreadcrumbs items={ [ { label: getLabel() } ] } /> }
			actions={
				<>
					<Button variant="outline" size="compact" onClick={ openBuilder }>
						{ __( 'Build URL', 'jetpack-premium-analytics-pkg' ) }
					</Button>
					<ExporterCsvAction
						exporter={ utmCsvExporters[ activeTab ] }
						items={ records.rows }
						status={ records }
						reportParams={ reportParams }
					/>
				</>
			}
		>
			<ReportPageLayout
				title={ getUtmTabLabel( activeTab ) }
				tabs={ <ReportPageTabs tabs={ tabs } value={ activeTab } onChange={ setActiveTab } /> }
				dateFilters={ dateFilters }
				withAllTime
			>
				<ReportErrorState
					status={ records }
					retryDescription={ __(
						"We couldn't load UTM data. Please try again in a moment.",
						'jetpack-premium-analytics-pkg'
					) }
				>
					<ReportDrilldownTable< UtmReportRow >
						key={ activeTab }
						data={ records.rows }
						fields={ fields }
						getItemId={ getUtmRowId }
						getItemParentId={ getUtmRowParentId }
						isLoading={ records.isLoading }
						isFetching={ records.isFetching }
						initialView={ RECORDS_VIEW }
						searchLabel={ __( 'Search UTM values', 'jetpack-premium-analytics-pkg' ) }
						hideLevelMarkers
						collapsible
						defaultExpanded="none"
					/>
				</ReportErrorState>
			</ReportPageLayout>
			{ isBuilderOpen && <UtmUrlBuilderDialog onClose={ closeBuilder } /> }
		</ReportPageShell>
	);
}
 
/**
 * Default export for the dynamic report registry.
 *
 * @return The UTM report page.
 */
export default function UtmReportPage(): JSX.Element {
	return <UtmReport />;
}