@@ -489,6 +489,78 @@ function addCopyButton() {
489489 }
490490}
491491
492+ // Calculate and display time from submission to triaged
493+ function addTriagedTimeIndicator ( ) {
494+ // Avoid duplicates; also clean up any old container id from previous implementation
495+ const existing = document . getElementById ( 'ca-triage-time-indicator' ) ;
496+ if ( existing ) {
497+ return ;
498+ }
499+ const oldExisting = document . getElementById ( 'ca-triage-time-container' ) ;
500+ if ( oldExisting ) {
501+ oldExisting . remove ( ) ;
502+ }
503+
504+ // Check current Status badge text is exactly "Triaged"
505+ const statusSpan = document . querySelector ( '#researcher-submission > div.row > div.col-md-3.col-md-push-9 > div:nth-child(1) > p:nth-child(2) > span' ) ;
506+ if ( ! statusSpan ) {
507+ return ;
508+ }
509+ const statusText = statusSpan . textContent ? statusSpan . textContent . trim ( ) : '' ;
510+ if ( statusText !== 'Triaged' ) {
511+ return ;
512+ }
513+
514+ // Get submission time
515+ const submissionTimeEl = document . querySelector ( '#researcher-submission > div.row > div.col-md-9.col-md-pull-3 > div > ul > li > ul > li:nth-child(2) > div.col-md-9.cc-tabular-nums > time' ) ;
516+ const submissionDateStr = submissionTimeEl && submissionTimeEl . getAttribute ( 'datetime' ) ;
517+ const submissionDate = submissionDateStr ? new Date ( submissionDateStr ) : null ;
518+
519+ if ( ! submissionDate ) {
520+ return ; // Cannot compute without submission date
521+ }
522+
523+ // Find triaged activity block and its time
524+ const triageBadge = document . querySelector ( '.activity-block__content .bc-badge--triaged' ) ;
525+ if ( ! triageBadge ) {
526+ return ; // Not triaged yet
527+ }
528+ const triageBlock = triageBadge . closest ( '.activity-block__content' ) ;
529+ if ( ! triageBlock ) {
530+ return ;
531+ }
532+ const triageTimeEl = triageBlock . querySelector ( '.cc-datetime-stamp__absolute time' ) || triageBlock . querySelector ( 'time' ) ;
533+ const triageDateStr = triageTimeEl && triageTimeEl . getAttribute ( 'datetime' ) ;
534+ const triageDate = triageDateStr ? new Date ( triageDateStr ) : null ;
535+ if ( ! triageDate ) {
536+ return ;
537+ }
538+
539+ // Compute duration
540+ const diffMs = Math . max ( 0 , triageDate . getTime ( ) - submissionDate . getTime ( ) ) ;
541+ const minutes = Math . floor ( diffMs / 60000 ) ;
542+ const days = Math . floor ( minutes / ( 60 * 24 ) ) ;
543+ const hours = Math . floor ( ( minutes % ( 60 * 24 ) ) / 60 ) ;
544+ const mins = minutes % 60 ;
545+
546+ const parts = [ ] ;
547+ if ( days > 0 ) parts . push ( `${ days } d` ) ;
548+ if ( hours > 0 ) parts . push ( `${ hours } h` ) ;
549+ parts . push ( `${ mins } m` ) ;
550+ const formatted = parts . join ( ' ' ) ;
551+
552+ // Build indicator right below the Status span
553+ const indicator = document . createElement ( 'div' ) ;
554+ indicator . id = 'ca-triage-time-indicator' ;
555+ indicator . textContent = `Triaged in ${ formatted } ` ;
556+ indicator . title = `Submitted: ${ submissionDate . toString ( ) } \nTriaged: ${ triageDate . toString ( ) } ` ;
557+ indicator . style . marginTop = '4px' ;
558+ indicator . style . fontSize = '12px' ;
559+ indicator . style . color = '#6b7280' ;
560+
561+ statusSpan . insertAdjacentElement ( 'afterend' , indicator ) ;
562+ }
563+
492564function addIncludeIpButton ( ) {
493565 const referenceElement = document . querySelector ( '#reply-form > div > div > div:nth-child(3)' ) ;
494566
@@ -1146,6 +1218,7 @@ function init() {
11461218 } else if ( isReportVisualizationPage ( ) ) {
11471219 // Report visualization pages: /submissions/UUID
11481220 addCopyButton ( ) ;
1221+ addTriagedTimeIndicator ( ) ;
11491222 addIncludeIpButton ( ) ;
11501223 addAiReviewButton ( ) ;
11511224 addAutoReplyButton ( ) ;
0 commit comments