11/* global Highcharts */
22
3- // Hardcoded distribution data — will be replaced by API fetch when the endpoint is finalized
4- import distributionData from './cwvDistributionData.json' ;
3+ import { Constants } from './utils/constants' ;
4+ // Fallback data used until the API endpoint is deployed (see tech-report-apis#105)
5+ import fallbackData from './cwvDistributionData.json' ;
56
67const METRIC_CONFIG = {
78 LCP : { bucketField : 'loading_bucket' , originsField : 'lcp_origins' , unit : 'ms' , label : 'LCP (ms)' } ,
@@ -26,11 +27,12 @@ const ZONE_COLORS = {
2627} ;
2728
2829class CwvDistribution {
29- // pageConfig, config, filters, data are accepted to satisfy the Section component contract
30+ // pageConfig, config are accepted to satisfy the Section component contract
3031 constructor ( id , pageConfig , config , filters , data ) {
3132 this . id = id ;
3233 this . pageFilters = filters ;
3334 this . data = data ;
35+ this . distributionData = null ;
3436 this . selectedMetric = 'LCP' ;
3537 this . chart = null ;
3638 this . root = document . querySelector ( `[data-id="${ this . id } "]` ) ;
@@ -46,16 +48,16 @@ class CwvDistribution {
4648 root . querySelectorAll ( '.cwv-distribution-metric-selector' ) . forEach ( dropdown => {
4749 dropdown . addEventListener ( 'change' , event => {
4850 this . selectedMetric = event . target . value ;
49- this . renderChart ( ) ;
51+ if ( this . distributionData ) this . renderChart ( ) ;
5052 } ) ;
5153 } ) ;
5254
53- // Lazy render on <details> toggle
55+ // Lazy fetch + render on <details> toggle
5456 const details = root . closest ( 'details' ) ;
5557 if ( details ) {
5658 details . addEventListener ( 'toggle' , ( ) => {
57- if ( details . open && ! this . chart ) {
58- this . renderChart ( ) ;
59+ if ( details . open && ! this . distributionData ) {
60+ this . fetchData ( ) ;
5961 } else if ( details . open && this . chart ) {
6062 this . chart . reflow ( ) ;
6163 }
@@ -64,7 +66,34 @@ class CwvDistribution {
6466 }
6567
6668 updateContent ( ) {
67- if ( this . chart ) this . renderChart ( ) ;
69+ if ( this . distributionData ) this . renderChart ( ) ;
70+ }
71+
72+ fetchData ( ) {
73+ const technology = this . pageFilters . app . map ( encodeURIComponent ) . join ( ',' ) ;
74+ const rank = encodeURIComponent ( this . pageFilters . rank || 'ALL' ) ;
75+ const date = this . root ?. dataset ?. latestDate || '' ;
76+
77+ let url = `${ Constants . apiBase } /cwv-distribution?technology=${ technology } &rank=${ rank } ` ;
78+ if ( date ) {
79+ url += `&date=${ encodeURIComponent ( date ) } ` ;
80+ }
81+
82+ fetch ( url )
83+ . then ( r => {
84+ if ( ! r . ok ) throw new Error ( `HTTP ${ r . status } ` ) ;
85+ return r . json ( ) ;
86+ } )
87+ . then ( rows => {
88+ if ( ! Array . isArray ( rows ) || rows . length === 0 ) throw new Error ( 'Empty response' ) ;
89+ this . distributionData = rows ;
90+ this . renderChart ( ) ;
91+ } )
92+ . catch ( ( ) => {
93+ // Fall back to bundled sample data until the API is deployed
94+ this . distributionData = fallbackData ;
95+ this . renderChart ( ) ;
96+ } ) ;
6897 }
6998
7099 trimWithOverflow ( rows , originsField , percentile ) {
@@ -88,15 +117,15 @@ class CwvDistribution {
88117 }
89118
90119 renderChart ( ) {
91- if ( ! distributionData || distributionData . length === 0 ) return ;
120+ if ( ! this . distributionData || this . distributionData . length === 0 ) return ;
92121 if ( ! this . root ) return ;
93122
94123 const client = this . root . dataset . client || 'mobile' ;
95124 const metricCfg = METRIC_CONFIG [ this . selectedMetric ] ;
96125 const thresholds = THRESHOLDS [ this . selectedMetric ] || [ ] ;
97126
98127 // Filter by client and sort by bucket
99- const clientRows = distributionData
128+ const clientRows = this . distributionData
100129 . filter ( row => row . client === client )
101130 . sort ( ( a , b ) => a [ metricCfg . bucketField ] - b [ metricCfg . bucketField ] ) ;
102131
@@ -210,7 +239,6 @@ class CwvDistribution {
210239 } ] ,
211240 credits : { enabled : false } ,
212241 } ) ;
213-
214242 }
215243}
216244
0 commit comments