@@ -4,26 +4,65 @@ import moment from 'moment'
44import { CheckIcon , MinusCircleIcon } from '@heroicons/react/outline'
55import { useWindowSize , WindowSize } from '~/libs/shared'
66
7- import { AiWorkflowRunsResponse , useFetchAiWorkflowsRuns } from '../../hooks'
7+ import {
8+ AiWorkflowRun ,
9+ AiWorkflowRunsResponse ,
10+ AiWorkflowRunStatus ,
11+ useFetchAiWorkflowsRuns ,
12+ useRolePermissions ,
13+ UseRolePermissionsResult ,
14+ } from '../../hooks'
815import { IconAiReview } from '../../assets/icons'
916import { TABLE_DATE_FORMAT } from '../../../config/index.config'
17+ import { BackendSubmission } from '../../models'
1018
1119import styles from './AiReviewsTable.module.scss'
20+ import { IconOutline , Tooltip } from '~/libs/ui'
21+ import { run } from 'node:test'
1222
1323interface AiReviewsTableProps {
14- submissionId : string
24+ submission : Pick < BackendSubmission , 'id' | 'virusScan' >
1525 reviewers : { aiWorkflowId : string } [ ]
1626}
1727
28+ const aiRunInProgress = ( aiRun : Pick < AiWorkflowRun , 'status' > ) =>
29+ [
30+ AiWorkflowRunStatus . INIT ,
31+ AiWorkflowRunStatus . QUEUED ,
32+ AiWorkflowRunStatus . DISPATCHED ,
33+ AiWorkflowRunStatus . IN_PROGRESS ,
34+ ] . includes ( aiRun . status )
35+
36+ const aiRunFailed = ( aiRun : Pick < AiWorkflowRun , 'status' > ) =>
37+ [
38+ AiWorkflowRunStatus . FAILURE ,
39+ AiWorkflowRunStatus . CANCELLED ,
40+ ] . includes ( aiRun . status )
41+
1842const AiReviewsTable : FC < AiReviewsTableProps > = props => {
1943 const aiWorkflowIds = useMemo ( ( ) => props . reviewers . map ( r => r . aiWorkflowId ) , [ props . reviewers ] )
20- const { runs, isLoading } : AiWorkflowRunsResponse = useFetchAiWorkflowsRuns ( props . submissionId , aiWorkflowIds )
44+ const { runs, isLoading } : AiWorkflowRunsResponse = useFetchAiWorkflowsRuns ( props . submission . id , aiWorkflowIds )
2145
2246 const windowSize : WindowSize = useWindowSize ( )
2347 const isTablet = useMemo (
2448 ( ) => ( windowSize . width ?? 0 ) <= 984 ,
2549 [ windowSize . width ] ,
2650 )
51+ const { isAdmin } : UseRolePermissionsResult = useRolePermissions ( )
52+
53+ const aiRuns = useMemo ( ( ) => [
54+ ...runs ,
55+ {
56+ id : '-1' ,
57+ completedAt : ( props . submission as BackendSubmission ) . submittedDate ,
58+ status : AiWorkflowRunStatus . SUCCESS ,
59+ score : props . submission . virusScan === true ? 100 : 0 ,
60+ workflow : {
61+ name : 'Virus Scan' ,
62+ description : '' ,
63+ }
64+ } as AiWorkflowRun
65+ ] . filter ( r => isAdmin || ! aiRunFailed ( r ) ) , [ runs , props . submission ] )
2766
2867 if ( isTablet ) {
2968 return (
@@ -32,11 +71,7 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
3271 < div className = { styles . mobileLoading } > Loading...</ div >
3372 ) }
3473
35- { ! runs . length && ! isLoading && (
36- < div className = { styles . mobileLoading } > No reviews</ div >
37- ) }
38-
39- { runs . map ( run => (
74+ { aiRuns . map ( run => (
4075 < div key = { run . id } className = { styles . mobileCard } >
4176 < div className = { styles . mobileRow } >
4277 < div className = { styles . label } > Reviewer</ div >
@@ -64,16 +99,20 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
6499 < div className = { styles . mobileRow } >
65100 < div className = { styles . label } > Score</ div >
66101 < div className = { styles . value } >
67- { run . status === 'SUCCESS' ? run . score : '-' }
102+ { run . status === 'SUCCESS' ? (
103+ run . workflow . scorecard ? (
104+ < a href = { `/scorecard/${ run . workflow . scorecard . id } ` } > { run . score } </ a >
105+ ) : run . score
106+ ) : '-' }
68107 </ div >
69108 </ div >
70109
71110 < div className = { styles . mobileRow } >
72111 < div className = { styles . label } > Result</ div >
73112 < div className = { `${ styles . value } ${ styles . resultCol } ` } >
74- { run . status === 'SUCCESS' ? (
113+ { run . status === 'SUCCESS' && (
75114 < div className = { styles . result } >
76- { run . score >= run . workflow . scorecard . minimumPassingScore ? (
115+ { run . score >= ( run . workflow . scorecard ? .minimumPassingScore ?? 0 ) ? (
77116 < >
78117 < CheckIcon className = 'icon icon-xl passed' />
79118 { ' ' }
@@ -87,8 +126,22 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
87126 </ >
88127 ) }
89128 </ div >
90- ) : (
91- '-'
129+ ) }
130+ { aiRunInProgress ( run ) && (
131+ < div className = { styles . result } >
132+ < span className = 'icon pending' >
133+ < IconOutline . MinusIcon className = 'icon-sm' />
134+ </ span >
135+ { ' ' }
136+ To be filled
137+ </ div >
138+ ) }
139+ { aiRunFailed ( run ) && (
140+ < div className = { styles . result } >
141+ < span className = 'icon' >
142+ < IconOutline . XCircleIcon className = 'icon-xl' />
143+ </ span >
144+ </ div >
92145 ) }
93146 </ div >
94147 </ div >
@@ -114,15 +167,17 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
114167 </ tr >
115168 ) }
116169
117- { runs . map ( run => (
170+ { aiRuns . map ( run => (
118171 < tr key = { run . id } >
119172 < td >
120173 < div className = { styles . aiReviewer } >
121174 < span className = { styles . icon } >
122175 < IconAiReview />
123176 </ span >
124177 < span className = { styles . workflowName } title = { run . workflow . name } >
125- { run . workflow . name }
178+ < Tooltip content = { run . workflow . name } triggerOn = 'hover' >
179+ { run . workflow . name }
180+ </ Tooltip >
126181 </ span >
127182 </ div >
128183 </ td >
@@ -134,12 +189,16 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
134189 ) }
135190 </ td >
136191 < td className = { styles . scoreCol } >
137- { run . status === 'SUCCESS' && run . score }
192+ { run . status === 'SUCCESS' ? (
193+ run . workflow . scorecard ? (
194+ < a href = { `/scorecard/${ run . workflow . scorecard . id } ` } > { run . score } </ a >
195+ ) : run . score
196+ ) : '-' }
138197 </ td >
139198 < td className = { styles . resultCol } >
140199 { run . status === 'SUCCESS' && (
141200 < div className = { styles . result } >
142- { run . score >= run . workflow . scorecard . minimumPassingScore
201+ { run . score >= ( run . workflow . scorecard ? .minimumPassingScore ?? 0 )
143202 ? (
144203 < >
145204 < CheckIcon className = 'icon icon-xl passed' />
@@ -156,6 +215,22 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
156215 ) }
157216 </ div >
158217 ) }
218+ { aiRunInProgress ( run ) && (
219+ < div className = { styles . result } >
220+ < span className = 'icon pending' >
221+ < IconOutline . MinusIcon className = 'icon-sm' />
222+ </ span >
223+ { ' ' }
224+ To be filled
225+ </ div >
226+ ) }
227+ { aiRunFailed ( run ) && (
228+ < div className = { styles . result } >
229+ < span className = 'icon' >
230+ < IconOutline . XCircleIcon className = 'icon-xl' />
231+ </ span >
232+ </ div >
233+ ) }
159234 </ td >
160235 </ tr >
161236 ) ) }
0 commit comments