Skip to content

Commit 3f5ee69

Browse files
committed
Merge branch 'PM-2136_aiworkflow-sidebar-nav' into feat/ai-workflows
2 parents ff9432d + 38e15cd commit 3f5ee69

38 files changed

+965
-447
lines changed

src/apps/review/src/config/routes.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export const activeReviewAssignmentsRouteId = 'active-challenges'
1212
export const openOpportunitiesRouteId = 'open-opportunities'
1313
export const pastReviewAssignmentsRouteId = 'past-challenges'
1414
export const challengeDetailRouteId = ':challengeId'
15-
export const pastChallengeDetailContainerRouteId = 'past-challenge-details'
1615
export const scorecardRouteId = 'scorecard'
16+
export const aiScorecardRouteId = 'ai-scorecard'
1717
export const viewScorecardRouteId = ':scorecardId'

src/apps/review/src/lib/components/AiReviewsTable/AiReviewsTable.module.scss

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,6 @@
4949
}
5050
}
5151

52-
.result {
53-
display: flex;
54-
align-items: center;
55-
gap: $sp-2;
56-
57-
:global(.icon) {
58-
color: #C1294F;
59-
&:global(.passed) {
60-
color: $teal-160;
61-
}
62-
&:global(.pending) {
63-
color: $black-20;
64-
display: flex;
65-
width: 16px;
66-
height: 16px;
67-
border-radius: 15px;
68-
border: 1px solid;
69-
align-items: center;
70-
justify-content: center;
71-
}
72-
}
73-
}
74-
7552
.mobileCard {
7653
border-top: 1px solid #A8A8A8;
7754
margin-top: $sp-2;

src/apps/review/src/lib/components/AiReviewsTable/AiReviewsTable.tsx

Lines changed: 7 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,27 @@
11
import { FC, useMemo } from 'react'
22
import moment from 'moment'
33

4-
import { CheckIcon, MinusCircleIcon } from '@heroicons/react/outline'
54
import { useWindowSize, WindowSize } from '~/libs/shared'
6-
import { IconOutline, Tooltip } from '~/libs/ui'
5+
import { Tooltip } from '~/libs/ui'
76

87
import {
98
AiWorkflowRun,
109
AiWorkflowRunsResponse,
11-
AiWorkflowRunStatus,
10+
AiWorkflowRunStatusEnum,
1211
useFetchAiWorkflowsRuns,
13-
useRolePermissions,
14-
UseRolePermissionsResult,
1512
} from '../../hooks'
1613
import { IconAiReview } from '../../assets/icons'
1714
import { TABLE_DATE_FORMAT } from '../../../config/index.config'
1815
import { BackendSubmission } from '../../models'
1916

17+
import { AiWorkflowRunStatus } from './AiWorkflowRunStatus'
2018
import styles from './AiReviewsTable.module.scss'
2119

2220
interface AiReviewsTableProps {
2321
submission: Pick<BackendSubmission, 'id'|'virusScan'>
2422
reviewers: { aiWorkflowId: string }[]
2523
}
2624

27-
const aiRunInProgress = (aiRun: Pick<AiWorkflowRun, 'status'>): boolean => [
28-
AiWorkflowRunStatus.INIT,
29-
AiWorkflowRunStatus.QUEUED,
30-
AiWorkflowRunStatus.DISPATCHED,
31-
AiWorkflowRunStatus.IN_PROGRESS,
32-
].includes(aiRun.status)
33-
34-
const aiRunFailed = (aiRun: Pick<AiWorkflowRun, 'status'>): boolean => [
35-
AiWorkflowRunStatus.FAILURE,
36-
AiWorkflowRunStatus.CANCELLED,
37-
].includes(aiRun.status)
38-
3925
const AiReviewsTable: FC<AiReviewsTableProps> = props => {
4026
const aiWorkflowIds = useMemo(() => props.reviewers.map(r => r.aiWorkflowId), [props.reviewers])
4127
const { runs, isLoading }: AiWorkflowRunsResponse = useFetchAiWorkflowsRuns(props.submission.id, aiWorkflowIds)
@@ -45,21 +31,20 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
4531
() => (windowSize.width ?? 0) <= 984,
4632
[windowSize.width],
4733
)
48-
const { isAdmin }: UseRolePermissionsResult = useRolePermissions()
4934

5035
const aiRuns = useMemo(() => [
5136
...runs,
5237
{
5338
completedAt: (props.submission as BackendSubmission).submittedDate,
5439
id: '-1',
5540
score: props.submission.virusScan === true ? 100 : 0,
56-
status: AiWorkflowRunStatus.SUCCESS,
41+
status: AiWorkflowRunStatusEnum.SUCCESS,
5742
workflow: {
5843
description: '',
5944
name: 'Virus Scan',
6045
},
6146
} as AiWorkflowRun,
62-
].filter(r => isAdmin || !aiRunFailed(r)), [runs, props.submission])
47+
], [runs, props.submission])
6348

6449
if (isTablet) {
6550
return (
@@ -107,39 +92,7 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
10792
<div className={styles.mobileRow}>
10893
<div className={styles.label}>Result</div>
10994
<div className={`${styles.value} ${styles.resultCol}`}>
110-
{run.status === 'SUCCESS' && (
111-
<div className={styles.result}>
112-
{run.score >= (run.workflow.scorecard?.minimumPassingScore ?? 0) ? (
113-
<>
114-
<CheckIcon className='icon icon-xl passed' />
115-
{' '}
116-
Passed
117-
</>
118-
) : (
119-
<>
120-
<MinusCircleIcon className='icon icon-xl' />
121-
{' '}
122-
Failed
123-
</>
124-
)}
125-
</div>
126-
)}
127-
{aiRunInProgress(run) && (
128-
<div className={styles.result}>
129-
<span className='icon pending'>
130-
<IconOutline.MinusIcon className='icon-sm' />
131-
</span>
132-
{' '}
133-
To be filled
134-
</div>
135-
)}
136-
{aiRunFailed(run) && (
137-
<div className={styles.result}>
138-
<span className='icon'>
139-
<IconOutline.XCircleIcon className='icon-xl' />
140-
</span>
141-
</div>
142-
)}
95+
<AiWorkflowRunStatus run={run} />
14396
</div>
14497
</div>
14598
</div>
@@ -196,41 +149,7 @@ const AiReviewsTable: FC<AiReviewsTableProps> = props => {
196149
) : '-'}
197150
</td>
198151
<td className={styles.resultCol}>
199-
{run.status === 'SUCCESS' && (
200-
<div className={styles.result}>
201-
{run.score >= (run.workflow.scorecard?.minimumPassingScore ?? 0)
202-
? (
203-
<>
204-
<CheckIcon className='icon icon-xl passed' />
205-
{' '}
206-
Passed
207-
</>
208-
)
209-
: (
210-
<>
211-
<MinusCircleIcon className='icon icon-xl' />
212-
{' '}
213-
Failed
214-
</>
215-
)}
216-
</div>
217-
)}
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-
)}
152+
<AiWorkflowRunStatus run={run} />
234153
</td>
235154
</tr>
236155
))}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.result {
4+
display: flex;
5+
align-items: center;
6+
gap: $sp-2;
7+
}
8+
9+
.icon {
10+
display: flex;
11+
width: 20px;
12+
height: 20px;
13+
border-radius: 10px;
14+
border: 1px solid #e9ecef;
15+
background: #fff;
16+
align-items: center;
17+
justify-content: center;
18+
19+
&.failed,
20+
&.failed-score {
21+
color: #C1294F;
22+
}
23+
24+
&.passed {
25+
color: $teal-160;
26+
}
27+
28+
&.pending {
29+
color: $black-20;
30+
border-color: $black-20;
31+
}
32+
}
33+
34+
.score {
35+
font-size: 14px;
36+
.failed-score {
37+
color: #C1294F;
38+
}
39+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { FC, useMemo } from 'react'
2+
3+
import { IconOutline } from '~/libs/ui'
4+
5+
import { aiRunFailed, aiRunInProgress, AiWorkflowRun } from '../../hooks'
6+
7+
import StatusLabel from './StatusLabel'
8+
9+
interface AiWorkflowRunStatusProps {
10+
run: Pick<AiWorkflowRun, 'status'|'score'|'workflow'>
11+
hideLabel?: boolean
12+
showScore?: boolean
13+
}
14+
15+
export const AiWorkflowRunStatus: FC<AiWorkflowRunStatusProps> = props => {
16+
const isInProgress = useMemo(() => aiRunInProgress(props.run), [props.run.status])
17+
const isFailed = useMemo(() => aiRunFailed(props.run), [props.run.status])
18+
const isPassing = (
19+
props.run.status === 'SUCCESS'
20+
&& props.run.score >= (props.run.workflow.scorecard?.minimumPassingScore ?? 0)
21+
)
22+
const status = isInProgress ? 'pending' : isFailed ? 'failed' : (
23+
isPassing ? 'passed' : 'failed-score'
24+
)
25+
26+
const score = props.showScore ? props.run.score : undefined
27+
28+
return (
29+
<>
30+
{props.run.status === 'SUCCESS' && isPassing && (
31+
<StatusLabel
32+
icon={<IconOutline.CheckIcon className='icon-xl' />}
33+
hideLabel={props.hideLabel}
34+
label='Passed'
35+
status={status}
36+
score={score}
37+
/>
38+
)}
39+
{props.run.status === 'SUCCESS' && !isPassing && (
40+
<StatusLabel
41+
icon={<IconOutline.MinusCircleIcon className='icon-xl' />}
42+
hideLabel={props.hideLabel}
43+
label='Failed'
44+
status={status}
45+
score={score}
46+
/>
47+
)}
48+
{isInProgress && (
49+
<StatusLabel
50+
icon={<IconOutline.MinusIcon className='icon-md' />}
51+
hideLabel={props.hideLabel}
52+
label='To be filled'
53+
status={status}
54+
score={score}
55+
/>
56+
)}
57+
{isFailed && (
58+
<StatusLabel
59+
icon={<IconOutline.XCircleIcon className='icon-xl' />}
60+
status={status}
61+
score={score}
62+
/>
63+
)}
64+
</>
65+
)
66+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.wrap {
4+
display: flex;
5+
align-items: center;
6+
gap: $sp-2;
7+
}
8+
9+
.icon {
10+
display: flex;
11+
width: 20px;
12+
height: 20px;
13+
border-radius: 10px;
14+
border: 1px solid #e9ecef;
15+
background: #fff;
16+
align-items: center;
17+
justify-content: center;
18+
19+
&.failed,
20+
&.failed-score {
21+
color: #C1294F;
22+
}
23+
24+
&.passed {
25+
color: $teal-160;
26+
}
27+
28+
&.pending {
29+
color: #e9ecef;
30+
border-color: #e9ecef;
31+
}
32+
}
33+
34+
.score {
35+
font-size: 14px;
36+
&.failed-score {
37+
color: #C1294F;
38+
}
39+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { FC, ReactNode } from 'react'
2+
import classNames from 'classnames'
3+
4+
import styles from './StatusLabel.module.scss'
5+
6+
interface StatusLabelProps {
7+
icon: ReactNode
8+
hideLabel?: boolean
9+
label?: string
10+
score?: number
11+
status: 'pending' | 'failed' | 'passed' | 'failed-score'
12+
}
13+
14+
const StatusLabel: FC<StatusLabelProps> = props => (
15+
<div className={styles.wrap}>
16+
{props.score && (
17+
<span className={classNames(styles[props.status], styles.score)}>{props.score}</span>
18+
)}
19+
{props.icon && (
20+
<span className={classNames(styles.icon, styles[props.status])}>
21+
{props.icon}
22+
</span>
23+
)}
24+
{!props.hideLabel && props.label}
25+
</div>
26+
)
27+
28+
export default StatusLabel
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default as AiReviewsTable } from './AiReviewsTable'
2+
export * from './AiWorkflowRunStatus'

0 commit comments

Comments
 (0)