@@ -4,138 +4,79 @@ import {
44 Page ,
55 Text ,
66 View ,
7- StyleSheet ,
87 Image ,
98 Svg ,
109 Path ,
1110} from '@react-pdf/renderer' ;
12-
13- const styles = StyleSheet . create ( {
14- page : {
15- padding : 30 ,
16- fontSize : 12 ,
17- } ,
18- headerContainer : {
19- flexDirection : 'row' ,
20- alignItems : 'center' ,
21- marginBottom : 40 ,
22- } ,
23- logoContainer : {
24- width : 40 ,
25- height : 40 ,
26- marginRight : 10 ,
27- } ,
28- headerText : {
29- fontSize : 24 ,
30- fontWeight : 'bold' ,
31- } ,
32- infoTable : {
33- marginBottom : 20 ,
34- } ,
35- infoRow : {
36- flexDirection : 'row' ,
37- marginBottom : 8 ,
38- } ,
39- infoLabel : {
40- width : 150 ,
41- fontWeight : 'bold' ,
42- } ,
43- infoValue : {
44- flex : 1 ,
45- } ,
46- section : {
47- marginTop : 15 ,
48- marginBottom : 10 ,
49- } ,
50- sectionTitle : {
51- fontSize : 18 ,
52- marginBottom : 10 ,
53- } ,
54- table : {
55- width : 'auto' ,
56- borderStyle : 'solid' ,
57- borderWidth : 1 ,
58- borderRightWidth : 0 ,
59- borderBottomWidth : 0 ,
60- marginBottom : 10 ,
61- } ,
62- tableRow : {
63- margin : 'auto' ,
64- flexDirection : 'row' ,
65- } ,
66- tableHeader : {
67- backgroundColor : '#f6f6f6' ,
68- } ,
69- tableCell : {
70- width : '33%' ,
71- borderStyle : 'solid' ,
72- borderWidth : 1 ,
73- borderLeftWidth : 0 ,
74- borderTopWidth : 0 ,
75- padding : 5 ,
76- } ,
77- tableCellHeader : {
78- width : '33%' ,
79- borderStyle : 'solid' ,
80- borderWidth : 1 ,
81- borderLeftWidth : 0 ,
82- borderTopWidth : 0 ,
83- padding : 5 ,
84- backgroundColor : '#f6f6f6' ,
85- fontWeight : 'bold' ,
86- } ,
87- tableCellHalf : {
88- width : '50%' ,
89- borderStyle : 'solid' ,
90- borderWidth : 1 ,
91- borderLeftWidth : 0 ,
92- borderTopWidth : 0 ,
93- padding : 5 ,
94- } ,
95- tableCellHeaderHalf : {
96- width : '50%' ,
97- borderStyle : 'solid' ,
98- borderWidth : 1 ,
99- borderLeftWidth : 0 ,
100- borderTopWidth : 0 ,
101- padding : 5 ,
102- backgroundColor : '#f6f6f6' ,
103- fontWeight : 'bold' ,
104- } ,
105- chartContainer : {
106- marginTop : 10 ,
107- marginBottom : 10 ,
108- width : '100%' ,
109- height : 200 ,
110- } ,
111- chart : {
112- width : '100%' ,
113- height : '100%' ,
114- objectFit : 'contain' ,
115- } ,
116- alertItem : {
117- marginBottom : 10 ,
118- padding : 5 ,
119- borderStyle : 'solid' ,
120- borderWidth : 1 ,
121- borderColor : '#ccc' ,
122- } ,
123- } ) ;
11+ import { styles } from '../styles/reportStyles' ;
12412
12513const formatDate = ( ) => {
12614 const now = new Date ( ) ;
12715 return now . toISOString ( ) . replace ( 'T' , ' ' ) . slice ( 0 , - 5 ) + 'Z' ;
12816} ;
12917
130- const TableRow = ( { items, isHeader = false , twoColumns = false } ) => (
131- < View style = { styles . tableRow } >
132- { items . map ( ( item , i ) => (
133- < Text key = { i } style = { isHeader ?
134- ( twoColumns ? styles . tableCellHeaderHalf : styles . tableCellHeader ) :
135- ( twoColumns ? styles . tableCellHalf : styles . tableCell )
136- } >
137- { item }
138- </ Text >
18+ const TableRow = ( { items, isHeader = false , twoColumns = false , isRepoTable = false , threeColumns = false } ) => {
19+ let cellStyle , headerStyle ;
20+
21+ if ( isRepoTable ) {
22+ if ( threeColumns ) {
23+ cellStyle = styles . repoTableCellThird ;
24+ headerStyle = styles . repoTableCellHeaderThird ;
25+ } else {
26+ cellStyle = styles . repoTableCell ;
27+ headerStyle = styles . repoTableCellHeader ;
28+ }
29+ } else if ( twoColumns ) {
30+ cellStyle = styles . tableCellHalf ;
31+ headerStyle = styles . tableCellHeaderHalf ;
32+ } else {
33+ cellStyle = styles . tableCell ;
34+ headerStyle = styles . tableCellHeader ;
35+ }
36+
37+ return (
38+ < View style = { styles . tableRow } >
39+ { items . map ( ( item , i ) => (
40+ < Text key = { i } style = { isHeader ? headerStyle : cellStyle } >
41+ { item }
42+ </ Text >
43+ ) ) }
44+ </ View >
45+ ) ;
46+ } ;
47+
48+ const RepoBreakdownTable = ( { data, showSeverity = true } ) => (
49+ < View style = { styles . repoTable } >
50+ < TableRow
51+ items = { showSeverity ?
52+ [ 'Repository' , 'Total' , 'Critical' , 'High' , 'Medium' , 'Low' ] :
53+ [ 'Repository' , 'Total' , 'Open' ]
54+ }
55+ isHeader = { true }
56+ isRepoTable = { true }
57+ threeColumns = { ! showSeverity }
58+ />
59+ { Object . entries ( data ) . map ( ( [ repoName , stats ] ) => (
60+ < TableRow
61+ key = { repoName }
62+ items = { showSeverity ?
63+ [
64+ repoName ,
65+ stats . total . toString ( ) ,
66+ stats . severity . critical . toString ( ) ,
67+ stats . severity . high . toString ( ) ,
68+ stats . severity . medium . toString ( ) ,
69+ stats . severity . low . toString ( )
70+ ] :
71+ [
72+ repoName ,
73+ stats . total . toString ( ) ,
74+ stats . open . toString ( )
75+ ]
76+ }
77+ isRepoTable = { true }
78+ threeColumns = { ! showSeverity }
79+ />
13980 ) ) }
14081 </ View >
14182) ;
@@ -193,7 +134,7 @@ const SecurityReport = ({ organization, alerts, summary, showAllAlerts, chartIma
193134 </ View >
194135 </ View >
195136
196- { /* Code Scanning Section */ }
137+ { /* Code Scanning Section - Part 1 */ }
197138 < View style = { styles . section } >
198139 < Text style = { styles . sectionTitle } > Code Scanning Alerts</ Text >
199140 { chartImages ?. codeScanning && (
@@ -208,6 +149,15 @@ const SecurityReport = ({ organization, alerts, summary, showAllAlerts, chartIma
208149 < TableRow items = { [ 'Medium' , summary . codeScanning . severity . medium . toString ( ) ] } twoColumns = { true } />
209150 < TableRow items = { [ 'Low' , summary . codeScanning . severity . low . toString ( ) ] } twoColumns = { true } />
210151 </ View >
152+ </ View >
153+ </ Page >
154+
155+ { /* New page for Repository Breakdown */ }
156+ < Page size = "A4" style = { styles . page } >
157+ { /* Code Scanning Section - Part 2 */ }
158+ < View style = { styles . section } >
159+ < Text style = { [ styles . sectionTitle , { fontSize : 14 , marginTop : 10 } ] } > Repository Breakdown</ Text >
160+ < RepoBreakdownTable data = { summary . codeScanning . byRepository } />
211161
212162 { showAllAlerts && alerts . codeScanning . map ( ( alert , index ) => (
213163 < View key = { index } style = { styles . alertItem } >
@@ -230,6 +180,9 @@ const SecurityReport = ({ organization, alerts, summary, showAllAlerts, chartIma
230180 ) ) }
231181 </ View >
232182
183+ < Text style = { [ styles . sectionTitle , { fontSize : 14 , marginTop : 10 } ] } > Repository Breakdown</ Text >
184+ < RepoBreakdownTable data = { summary . secretScanning . byRepository } showSeverity = { false } />
185+
233186 { showAllAlerts && alerts . secretScanning . map ( ( alert , index ) => (
234187 < View key = { index } style = { styles . alertItem } >
235188 < Text > Type: { alert . secret_type_display_name } </ Text >
@@ -256,6 +209,9 @@ const SecurityReport = ({ organization, alerts, summary, showAllAlerts, chartIma
256209 < TableRow items = { [ 'Low' , summary . dependabot . severity . low . toString ( ) ] } twoColumns = { true } />
257210 </ View >
258211
212+ < Text style = { [ styles . sectionTitle , { fontSize : 14 , marginTop : 10 } ] } > Repository Breakdown</ Text >
213+ < RepoBreakdownTable data = { summary . dependabot . byRepository } />
214+
259215 { showAllAlerts && alerts . dependabot . map ( ( alert , index ) => (
260216 < View key = { index } style = { styles . alertItem } >
261217 < Text > Package: { alert . dependency . package . name } </ Text >
0 commit comments