@@ -6,16 +6,20 @@ window.gsocData = {
66 reportData : [ ]
77} ;
88
9- // Silent logger (replaces console.error)
10- function safeLog ( ) { }
9+ // Safe error logging
10+ function safeLog ( message , ...args ) {
11+ if ( window . Sentry && typeof window . Sentry . captureMessage === 'function' ) {
12+ window . Sentry . captureMessage ( message , { extra : { args } } ) ;
13+ }
14+ }
1115
1216// Function to extract chart data (callable from both chart rendering and PDF generation)
1317function getChartData ( ) {
1418 let yearlyCategories = [ ] ;
1519 let yearlySeriesData = [ ] ;
1620 let topReposLabels = [ ] ;
1721 let topReposSeries = [ ] ;
18-
22+
1923 // Process Yearly Chart Data
2024 if ( window . gsocData . yearlyChart ) {
2125 if ( Array . isArray ( window . gsocData . yearlyChart ) && window . gsocData . yearlyChart . length > 0 ) {
@@ -37,7 +41,7 @@ function getChartData() {
3741 }
3842 }
3943 }
40-
44+
4145 // Process Top Repos Data
4246 if ( window . gsocData . topReposChart ) {
4347 if ( Array . isArray ( window . gsocData . topReposChart ) ) {
@@ -59,7 +63,7 @@ function getChartData() {
5963 topReposSeries = window . gsocData . topReposChart . data . map ( Number ) ;
6064 }
6165 }
62-
66+
6367 return {
6468 yearlyCategories,
6569 yearlySeriesData,
@@ -74,15 +78,15 @@ function parseEscapedJSON(str) {
7478
7579 try {
7680 // First, unescape the string (convert \u0022 to ", etc.)
77- const unescapedStr = str . replace ( / \\ u ( [ 0 - 9 a - f A - F ] { 4 } ) / g, ( match , hex ) =>
81+ const unescapedStr = str . replace ( / \\ u ( [ 0 - 9 a - f A - F ] { 4 } ) / g, ( match , hex ) =>
7882 String . fromCharCode ( parseInt ( hex , 16 ) )
7983 ) ;
8084 // Also handle other common escapes
8185 const finalStr = unescapedStr
8286 . replace ( / \\ " / g, '"' )
8387 . replace ( / \\ ' / g, "'" )
8488 . replace ( / \\ \\ / g, '\\' ) ;
85-
89+
8690 return JSON . parse ( finalStr ) ;
8791 } catch ( err ) {
8892 safeLog ( "JSON parse failed:" , err , str ) ;
@@ -143,7 +147,7 @@ document.addEventListener('DOMContentLoaded', function () {
143147
144148 // Get chart data
145149 const { yearlyCategories, yearlySeriesData, topReposLabels, topReposSeries } = getChartData ( ) ;
146-
150+
147151 // Store the chart data globally for PDF generation
148152 window . chartData = {
149153 yearlyCategories,
@@ -156,7 +160,7 @@ document.addEventListener('DOMContentLoaded', function () {
156160 if ( yearlyChartElement ) {
157161 if ( yearlyCategories . length > 0 && yearlySeriesData . length > 0 ) {
158162 const maxValue = Math . max ( ...yearlySeriesData ) ;
159- const yAxisMax = Math . ceil ( maxValue * 1.1 ) ;
163+ const yAxisMax = Math . max ( 5 , Math . ceil ( maxValue * 1.1 ) ) ; // minimum scale of 5
160164
161165 const isDarkMode = document . documentElement . classList . contains ( 'dark' ) ;
162166 const textColor = isDarkMode ? '#E5E7EB' : '#374151' ;
@@ -476,28 +480,28 @@ function exportChartData() {
476480// Helper function for fallback chart
477481async function addFallbackChart ( doc , categories , series , x , y ) {
478482 if ( ! categories || ! series || categories . length === 0 ) return ;
479-
483+
480484 // Draw a simple bar chart representation
481485 const maxValue = Math . max ( ...series ) ;
482486 const chartWidth = 150 ;
483487 const chartHeight = 50 ;
484488 const barWidth = chartWidth / categories . length ;
485-
489+
486490 // Draw bars
487491 series . forEach ( ( value , index ) => {
488492 const barHeight = ( value / maxValue ) * chartHeight ;
489493 const barX = x + ( index * barWidth ) ;
490494 const barY = y + chartHeight - barHeight ;
491-
495+
492496 doc . setFillColor ( 220 , 38 , 38 ) ; // Red color
493497 doc . rect ( barX , barY , barWidth - 2 , barHeight , 'F' ) ;
494-
498+
495499 // Add value label
496500 doc . setFontSize ( 6 ) ;
497501 doc . setTextColor ( 0 , 0 , 0 ) ;
498502 doc . text ( String ( value ) , barX + ( barWidth / 2 ) , barY - 2 , { align : 'center' } ) ;
499503 } ) ;
500-
504+
501505 // Draw X axis
502506 categories . forEach ( ( label , index ) => {
503507 const labelX = x + ( index * barWidth ) + ( barWidth / 2 ) ;
@@ -529,6 +533,9 @@ async function downloadReport(event) {
529533 await loadScript ( 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js' , {
530534 integrity : 'sha512-BNaRQnYJYiPSqHHDb58B0yaPfCu+Wgds8Gp/gU33kqBtgNS4tSPHuGibyoeqMV/TJlSKda6FXzoEyYGjTe+vXA=='
531535 } ) ;
536+ if ( ! window . jspdf || ! window . html2canvas ) {
537+ throw new Error ( 'Required libraries failed to load. Please check your connection or disable ad blockers.' ) ;
538+ }
532539 const { jsPDF } = window . jspdf ;
533540 const doc = new jsPDF ( 'p' , 'mm' , 'a4' ) ;
534541
@@ -657,7 +664,7 @@ async function downloadReport(event) {
657664
658665 doc . setFontSize ( 12 ) ;
659666 doc . setTextColor ( 0 , 0 , 0 ) ;
660- doc . text ( `GSOC ${ year . year } (${ year . total_prs || 0 } PRs, ${ year . repos ?. length || 0 } Repositories)` , 20 , yPosition ) ;
667+ doc . text ( `GSOC ${ String ( year . year ) } (${ String ( year . total_prs || 0 ) } PRs, ${ String ( year . repos ?. length || 0 ) } Repositories)` , 20 , yPosition ) ;
661668 yPosition += 10 ;
662669
663670 if ( year . repos && year . repos . length > 0 ) {
@@ -667,7 +674,7 @@ async function downloadReport(event) {
667674 doc . addPage ( ) ;
668675 yPosition = 20 ;
669676 }
670- doc . text ( `• ${ repo . repo__name || 'Unknown' } : ${ repo . pr_count || 0 } PRs (${ repo . unique_contributors || 0 } contributors)` , 25 , yPosition ) ;
677+ doc . text ( `• ${ String ( repo . repo__name || 'Unknown' ) } : ${ String ( repo . pr_count || 0 ) } PRs (${ String ( repo . unique_contributors || 0 ) } contributors)` , 25 , yPosition ) ;
671678 yPosition += 7 ;
672679 } ) ;
673680 }
@@ -687,7 +694,8 @@ async function downloadReport(event) {
687694 }
688695
689696 // Save the PDF
690- const fileName = `gsoc_pr_report_${ window . gsocData . summary . start_year || '' } _${ window . gsocData . summary . end_year || '' } _${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .pdf` ;
697+ const fileName = `gsoc_pr_report_${ window . gsocData . summary . start_year || 'unknown' } _${ window . gsocData . summary . end_year || 'unknown' } _${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .pdf` ;
698+
691699 doc . save ( fileName ) ;
692700
693701 // Restore button state
@@ -883,7 +891,7 @@ function downloadHTMLReport() {
883891 const url = URL . createObjectURL ( blob ) ;
884892 const a = document . createElement ( 'a' ) ;
885893 a . href = url ;
886- a . download = `gsoc_pr_report_${ escapeHtml ( reportData . summary . start_year || '' ) } _${ escapeHtml ( reportData . summary . end_year || '' ) } _${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .html` ;
894+ a . download = `gsoc_pr_report_${ reportData . summary . start_year || 'unknown' } _${ reportData . summary . end_year || 'unknown' } _${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } .html` ;
887895 document . body . appendChild ( a ) ;
888896 a . click ( ) ;
889897 document . body . removeChild ( a ) ;
0 commit comments