@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
2
2
import { Spinner , Table } from "react-bootstrap" ;
3
3
import { formatProcessDuration } from "../../utils" ;
4
4
import CopyableHash from "../CopyableHash" ;
5
+ import CopyButton from "../CopyButton" ;
5
6
import IconBadge from "../IconBadge" ;
6
7
import LocalDateTime from "../LocalDateTime" ;
7
8
@@ -28,12 +29,32 @@ const eventPosition = {
28
29
afterTable : 3 ,
29
30
} ;
30
31
32
+ function CertificateHash ( { hash, onClick, showLink, linkVariant = "dark" } ) {
33
+ function clicked ( event ) {
34
+ event . preventDefault ( ) ;
35
+ onClick ( hash ) ;
36
+ }
37
+
38
+ return showLink ? (
39
+ < >
40
+ < a href = "#" target = "_blank" className = { `link-${ linkVariant } ` } onClick = { clicked } >
41
+ { hash }
42
+ </ a > { " " }
43
+ < CopyButton textToCopy = { hash } />
44
+ </ >
45
+ ) : (
46
+ < CopyableHash hash = { hash } />
47
+ ) ;
48
+ }
49
+
31
50
export default function CertificateVerifier ( {
32
51
client,
33
52
certificate,
34
- showSpinner = true ,
53
+ hideSpinner = false ,
54
+ showCertificateLinks = false ,
35
55
onStepChange = ( step ) => { } ,
36
56
onChainValidationError = ( error ) => { } ,
57
+ onCertificateClick = ( hash ) => { } ,
37
58
} ) {
38
59
const [ currentStep , setCurrentStep ] = useState ( certificateValidationSteps . ready ) ;
39
60
const [ validationError , setValidationError ] = useState ( undefined ) ;
@@ -99,16 +120,7 @@ export default function CertificateVerifier({
99
120
break ;
100
121
case certificateChainValidationEvents . certificateValidated :
101
122
position = eventPosition . inTable ;
102
- message = (
103
- < >
104
- < td >
105
- < CopyableHash hash = { event . payload . certificate_hash } />
106
- </ td >
107
- < td >
108
- < IconBadge tooltip = "Valid Certificate" variant = "success" icon = "mithril" />
109
- </ td >
110
- </ >
111
- ) ;
123
+ message = { certificateHash : event . payload . certificate_hash } ;
112
124
break ;
113
125
case certificateChainValidationEvents . done :
114
126
message = (
@@ -133,7 +145,15 @@ export default function CertificateVerifier({
133
145
{ Object . entries ( certificate ) . length > 0 && (
134
146
< div >
135
147
< h4 > Certificate Details</ h4 >
136
- < div > Certificate hash: { certificate . hash } </ div >
148
+ < div >
149
+ Certificate hash:{ " " }
150
+ < CertificateHash
151
+ hash = { certificate . hash }
152
+ onClick = { ( ) => onCertificateClick ( certificate . hash ) }
153
+ showLink = { showCertificateLinks }
154
+ linkVariant = "primary"
155
+ />
156
+ </ div >
137
157
< div > Epoch: { certificate . beacon . epoch } </ div >
138
158
< div className = "d-flex justify-content-between" >
139
159
< div >
@@ -142,7 +162,7 @@ export default function CertificateVerifier({
142
162
{ currentStep === certificateValidationSteps . validationInProgress && (
143
163
< div className = "d-flex align-items-center" >
144
164
< div className = "ms-1 pe-1" > Verifying the certificate chain...</ div >
145
- { showSpinner && < Spinner animation = "border" variant = "primary" /> }
165
+ { ! hideSpinner && < Spinner animation = "border" variant = "primary" /> }
146
166
</ div >
147
167
) }
148
168
{ currentStep === certificateValidationSteps . done && (
@@ -170,7 +190,18 @@ export default function CertificateVerifier({
170
190
{ verificationEvents
171
191
. filter ( ( evt ) => evt . position === eventPosition . inTable )
172
192
. map ( ( evt ) => (
173
- < tr key = { evt . id } > { evt . message } </ tr >
193
+ < tr key = { evt . id } >
194
+ < td >
195
+ < CertificateHash
196
+ hash = { evt . message . certificateHash }
197
+ onClick = { ( ) => onCertificateClick ( evt . message . certificateHash ) }
198
+ showLink = { showCertificateLinks }
199
+ />
200
+ </ td >
201
+ < td >
202
+ < IconBadge tooltip = "Valid Certificate" variant = "success" icon = "mithril" />
203
+ </ td >
204
+ </ tr >
174
205
) ) }
175
206
</ tbody >
176
207
</ Table >
0 commit comments