@@ -4,12 +4,161 @@ import React, { useEffect, useState } from 'react';
44import Link from 'next/link' ;
55import { cratesInfo } from '@/app/lib/all_interface' ;
66import { useParams } from 'next/navigation' ;
7+ import { Pagination } from 'antd' ;
8+
9+ interface CVE {
10+ subtitle ?: string ;
11+ id ?: string ;
12+ reported ?: string ;
13+ issued ?: string ;
14+ package ?: string ;
15+ ttype ?: string ;
16+ aliases ?: string | string [ ] ;
17+ keywords ?: string ;
18+ patched ?: string ;
19+ unaffected ?: string ;
20+ url ?: string ;
21+ reference ?: string ;
22+ description ?: string ;
23+ }
24+
25+ const CveCard = ( { cve } : { cve : CVE } ) => (
26+ < div className = "bg-white p-4 rounded-lg border border-gray-200" >
27+ { /* 标题和ID */ }
28+ < div className = "mb-2" >
29+ < p className = "text-red-600 font-medium" >
30+ { cve . subtitle || 'No subtitle available' }
31+ </ p >
32+ < p className = "text-gray-600" >
33+ { cve . id || 'No ID available' }
34+ </ p >
35+ </ div >
36+
37+ { /* 时间信息 */ }
38+ < div className = " mb-2 " >
39+ < div >
40+ < span className = "font-medium text-gray-500 mr-4" > Reported </ span >
41+ < span className = "text-gray-600" > { cve . reported || 'Not specified' } </ span >
42+ </ div >
43+
44+ </ div >
45+
46+ { /* 时间信息 */ }
47+ < div className = "mb-2" >
48+ < span className = "font-medium text-gray-500 mr-4" > Issued </ span >
49+ < span className = "text-gray-600" > { cve . issued || 'Not specified' } </ span >
50+ </ div >
51+
52+
53+
54+ { /* 包信息 */ }
55+ < div className = "mb-2" >
56+ < span className = "text-sm font-medium text-gray-500 mr-4" > Package </ span >
57+ < span className = "text-gray-600" > { cve . package || 'No package info' } </ span >
58+ </ div >
59+
60+
61+
62+
63+ { /* 类型信息 */ }
64+ { cve . ttype && (
65+ < div className = "mb-2 " >
66+ < span className = "text-sm font-medium text-gray-500 mr-4" > Type </ span >
67+ < span className = "text-gray-600" > { cve . ttype } </ span >
68+ </ div >
69+ ) }
70+
71+
72+ { /* 别名信息 */ }
73+ { cve . aliases && (
74+ < div className = "mb-2" >
75+ < span className = "text-sm font-medium text-gray-500 mr-4" > Aliases </ span >
76+ < span className = "text-gray-600" > { Array . isArray ( cve . aliases ) ? cve . aliases . join ( ', ' ) : cve . aliases } </ span >
77+ </ div >
78+
79+ ) }
80+
81+ { /* 关键词 */ }
82+ { cve . keywords && (
83+ < div className = "mb-2" >
84+ < span className = "text-sm font-medium text-gray-500 mr-4" > Keywords </ span >
85+ < span className = "text-gray-600" > { cve . keywords } </ span >
86+ </ div >
87+ ) }
88+
89+
90+ { /* 修复状态 */ }
91+ { cve . patched && (
92+ < div className = "mb-2" >
93+ < span className = "text-sm font-medium text-gray-500 mr-4" > Patched </ span >
94+ < span className = "text-gray-600" > { cve . patched } </ span >
95+ </ div >
96+
97+ ) }
98+
99+ { /* 未受影响版本 */ }
100+ { cve . unaffected && (
101+ < div className = "mb-2" >
102+ < span className = "text-sm font-medium text-gray-500 mr-4" > Unaffected </ span >
103+ < span className = "text-gray-600" > { cve . unaffected } </ span >
104+ </ div >
105+
106+ ) }
107+
108+ { /* URL */ }
109+ { cve . url && (
110+ < div className = "mb-2" >
111+ < span className = "text-sm font-medium text-gray-500 mr-4" > Url </ span >
112+ < a
113+ href = { cve . url }
114+
115+ target = "_blank"
116+ rel = "noopener noreferrer"
117+ className = "text-blue-500 hover:underline break-all"
118+ >
119+ { cve . url }
120+ </ a >
121+ </ div >
122+ ) }
123+
124+ { /* 引用链接 */ }
125+ { cve . reference && (
126+ < div className = "mb-2" >
127+ < p className = "text-sm font-medium text-gray-500" > Reference</ p >
128+ < div className = "text-blue-500 hover:underline break-all" >
129+ { cve . reference . split ( ' ' ) . map ( ( url : string , i : number ) => (
130+ < a
131+ key = { i }
132+ href = { url }
133+ target = "_blank"
134+ rel = "noopener noreferrer"
135+ className = "block"
136+ >
137+ { url }
138+ </ a >
139+ ) ) }
140+ </ div >
141+ </ div >
142+ ) }
143+
144+ { /* 描述信息 */ }
145+ { cve . description && (
146+ < div className = "mb-2" >
147+ < p className = "text-sm font-medium text-gray-500" > Description</ p >
148+ < p className = "text-gray-600" > { cve . description } </ p >
149+ </ div >
150+ ) }
151+ </ div >
152+ ) ;
7153
8154const CratePage = ( ) => {
9155 const params = useParams ( ) ;
10156 const [ results , setResults ] = useState < cratesInfo | null > ( null ) ;
11157 const [ loading , setLoading ] = useState ( true ) ;
12158 const [ error , setError ] = useState < string | null > ( null ) ;
159+ const [ packageCurrentPage , setPackageCurrentPage ] = useState ( 1 ) ;
160+ const [ depCurrentPage , setDepCurrentPage ] = useState ( 1 ) ;
161+ const itemsPerPage = 1 ;
13162
14163 useEffect ( ( ) => {
15164 const fetchCrateData = async ( ) => {
@@ -20,6 +169,7 @@ const CratePage = () => {
20169 }
21170 const data = await response . json ( ) ;
22171 setResults ( data ) ;
172+ console . log ( 'data in overviewwwwwwwww:' , data ) ;
23173 } catch ( error ) {
24174 console . error ( 'Error fetching data:' , error ) ;
25175 setError ( 'An error occurred' ) ;
@@ -34,84 +184,109 @@ const CratePage = () => {
34184 if ( loading ) return < p > Loading...</ p > ;
35185 if ( error ) return < p > Error: { error } </ p > ;
36186
187+ // 计算当前页的 CVE 数据
188+ const getCurrentPageItems = ( items : CVE [ ] , currentPage : number ) => {
189+ const start = ( currentPage - 1 ) * itemsPerPage ;
190+ const end = start + itemsPerPage ;
191+ return items . slice ( start , end ) ;
192+ } ;
193+
37194 return (
38195 < div style = { { width : '90%' , margin : '0 auto' } } >
39196 < div className = "my-8 grid grid-cols-1 lg:grid-cols-2 gap-6" >
40197 < div className = "space-y-6" >
41198
42- { /* Security Advisories */ }
199+ { /* Security Advisories 主框 */ }
43200 < div className = "bg-white shadow-lg rounded-lg p-6 border border-gray-300" >
44-
45- < div className = "flex justify-between items-center" >
46- < h2 className = "text-3xl mb-2" > Security Advisories</ h2 >
47- < span
48- className = "text-white border border-gray-300 p-1 w-auto rounded inline-block "
49- style = { { backgroundColor : 'rgb(179, 20, 18)' } }
50- >
51- { results ? results . cves . length + results . dep_cves . length : 0 }
52- </ span >
53- </ div >
54- < h3 className = "text-xl mt-3" > In this package</ h3 >
55- < div style = { { display : 'flex' , alignItems : 'center' } } >
56- < div style = { { flex : 1 } } >
57- { results && results . cves && results . cves . length > 0 ? (
58- results . cves . map ( ( cve , index ) => (
59- < div key = { index } >
60- < p className = "text-sm mt-4" style = { { color : 'rgb(179,20,18)' } } >
61- { cve . id !== '' ? JSON . stringify ( cve . small_desc ) : 'No results available' }
62- </ p >
63- < p className = "text-grey-500 text-sm mt-0" >
64- { cve . id !== '' ? JSON . stringify ( cve . id ) : 'No results available' }
65- </ p >
66-
67- < p key = { index } className = "text-grey-500 text-sm ml-8" >
68- < div className = 'mt-0' > SIMILAR ADVISORIES</ div >
69- { cve . id !== '' ? JSON . stringify ( cve . aliases ) : 'No results available' }
70- </ p >
71- </ div >
72- ) )
73- ) : (
74- < p > No results available</ p >
75- ) }
201+ { /* Security Advisories 标题 */ }
202+ < div className = "mb-6" >
203+ < div className = "flex justify-between items-center" >
204+ < h2 className = "text-3xl" > Security Advisories</ h2 >
205+ < span
206+ className = "text-white px-3 py-1 rounded-full text-sm"
207+ style = { {
208+ backgroundColor : results && ( results . cves ?. length + results . dep_cves ?. length ) > 0
209+ ? 'rgb(179, 20, 18)'
210+ : 'rgb(34, 197, 94)'
211+ } }
212+ >
213+ { results ? ( results . cves ?. length || 0 ) + ( results . dep_cves ?. length || 0 ) : 0 }
214+ </ span >
76215 </ div >
77- { /* <button
78- style={{
79- marginLeft: '20px',
80- border: '1px solid blue',
81- color: 'blue',
82- backgroundColor: 'white',
83- padding: '10px 15px',
84- cursor: 'pointer'
85- }}
86- onClick={() => window.location.href = 'YOUR_LINK_HERE'}>
87- MORE DETAILS
88- </button> */ }
89216 </ div >
90217
218+ { /* 两个子框的容器 */ }
219+ < div className = "space-y-6" >
220+ { /* In this package 框 */ }
221+ < div className = "bg-gray-50 rounded-lg p-6 border border-gray-200" >
222+ < div className = "flex justify-between items-center mb-4" >
223+ < h3 className = "text-xl font-semibold" > In this package</ h3 >
224+ < span className = "text-white px-3 py-1 rounded-full text-sm"
225+ style = { { backgroundColor : ( results ?. cves && results . cves . length > 0 ) ? 'rgb(179, 20, 18)' : 'rgb(34, 197, 94)' } } >
226+ { results ?. cves ?. length || 0 }
227+ </ span >
228+ </ div >
229+ < div className = "space-y-4" >
230+ { results ?. cves && results . cves . length > 0 ? (
231+ < >
232+ { getCurrentPageItems ( results . cves , packageCurrentPage ) . map ( ( cve , index ) => (
233+ < CveCard key = { index } cve = { cve } />
234+ ) ) }
235+ { results . cves . length > itemsPerPage && (
236+ < div className = "mt-4 flex justify-center" >
237+ < Pagination
238+ current = { packageCurrentPage }
239+ onChange = { setPackageCurrentPage }
240+ total = { results . cves . length }
241+ pageSize = { itemsPerPage }
242+ size = "small"
243+ showSizeChanger = { false }
244+ simple
245+ />
246+ </ div >
247+ ) }
248+ </ >
249+ ) : (
250+ < p className = "text-gray-500" > No vulnerabilities found</ p >
251+ ) }
252+ </ div >
253+ </ div >
91254
92-
93- < h3 className = "text-xl mt-10" > In the dependencies</ h3 >
94- < div >
95- { results && results . dep_cves && results . dep_cves . length > 0 ? (
96- results . dep_cves . map ( ( dep_cves , index ) => (
97- < >
98- < p key = { index } className = "text-sm mt-4" style = { { color : 'rgb(179,20,18)' } } >
99- { dep_cves . id !== '' ? JSON . stringify ( dep_cves . small_desc ) : 'No results available' }
100- </ p >
101- < p key = { index } className = "text-grey-500 text-sm mt-1" >
102- { dep_cves . id !== '' ? JSON . stringify ( dep_cves . id ) : 'No results available' }
103- </ p >
104- < p key = { index } className = "text-grey-500 text-sm ml-8" >
105- < div className = 'mt-0' > SIMILAR ADVISORIES</ div >
106- { dep_cves . id !== '' ? JSON . stringify ( dep_cves . aliases ) : 'No results available' }
107- </ p >
108- </ >
109- ) )
110- ) : (
111- < p > No results available</ p >
112- ) }
255+ { /* In the dependencies 框 */ }
256+ < div className = "bg-gray-50 rounded-lg p-6 border border-gray-200" >
257+ < div className = "flex justify-between items-center mb-4" >
258+ < h3 className = "text-xl font-semibold" > In the dependencies</ h3 >
259+ < span className = "text-white px-3 py-1 rounded-full text-sm"
260+ style = { { backgroundColor : results && results . dep_cves && results . dep_cves . length > 0 ? 'rgb(179, 20, 18)' : 'rgb(34, 197, 94)' } } >
261+ { results ?. dep_cves ?. length || 0 }
262+ </ span >
263+ </ div >
264+ < div className = "space-y-4" >
265+ { results ?. dep_cves && results . dep_cves . length > 0 ? (
266+ < >
267+ { getCurrentPageItems ( results . dep_cves , depCurrentPage ) . map ( ( cve , index ) => (
268+ < CveCard key = { index } cve = { cve } />
269+ ) ) }
270+ { results . dep_cves . length > itemsPerPage && (
271+ < div className = "mt-4 flex justify-center" >
272+ < Pagination
273+ current = { depCurrentPage }
274+ onChange = { setDepCurrentPage }
275+ total = { results . dep_cves . length }
276+ pageSize = { itemsPerPage }
277+ size = "small"
278+ showSizeChanger = { false }
279+ simple
280+ />
281+ </ div >
282+ ) }
283+ </ >
284+ ) : (
285+ < p className = "text-gray-500" > No vulnerabilities found</ p >
286+ ) }
287+ </ div >
288+ </ div >
113289 </ div >
114-
115290 </ div >
116291
117292 { /* Licenses */ }
0 commit comments