Skip to content

Commit c819bdf

Browse files
committed
Merge branch 'feat/v6' of github.com:topcoder-platform/platform-ui into feat/ai-workflows
2 parents 52a803c + 52bebec commit c819bdf

File tree

9 files changed

+859
-183
lines changed

9 files changed

+859
-183
lines changed

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

Lines changed: 287 additions & 85 deletions
Large diffs are not rendered by default.

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

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ import { Link } from 'react-router-dom'
1414
import _ from 'lodash'
1515
import classNames from 'classnames'
1616

17+
import { UserRole } from '~/libs/core'
1718
import { TableMobile } from '~/apps/admin/src/lib/components/common/TableMobile'
1819
import { IsRemovingType } from '~/apps/admin/src/lib/models'
1920
import { MobileTableColumn } from '~/apps/admin/src/lib/models/MobileTableColumn.model'
2021
import { copyTextToClipboard, useWindowSize, WindowSize } from '~/libs/shared'
2122
import { IconOutline, Table, TableColumn, Tooltip } from '~/libs/ui'
2223

23-
import { ChallengeDetailContextModel, Screening, SubmissionInfo } from '../../models'
24+
import {
25+
ChallengeDetailContextModel,
26+
ReviewAppContextModel,
27+
Screening,
28+
SubmissionInfo,
29+
} from '../../models'
2430
import { TableWrapper } from '../TableWrapper'
2531
import { SubmissionHistoryModal } from '../SubmissionHistoryModal'
2632
import {
@@ -30,12 +36,14 @@ import {
3036
partitionSubmissionHistory,
3137
SubmissionHistoryPartition,
3238
} from '../../utils'
33-
import { ChallengeDetailContext } from '../../contexts'
39+
import { ChallengeDetailContext, ReviewAppContext } from '../../contexts'
3440
import { useSubmissionDownloadAccess } from '../../hooks'
3541
import type { UseSubmissionDownloadAccessResult } from '../../hooks/useSubmissionDownloadAccess'
3642

3743
import styles from './TableSubmissionScreening.module.scss'
3844

45+
const VIEW_OWN_SCORECARD_TOOLTIP = 'You can only view scorecards for your own submissions.'
46+
3947
interface Props {
4048
className?: string
4149
screenings: Screening[]
@@ -60,6 +68,11 @@ interface BaseColumnsConfig {
6068
virusScanColumn: TableColumn<Screening>
6169
}
6270

71+
interface ScreeningColumnConfig {
72+
canViewAllScorecards: boolean
73+
currentMemberId?: string
74+
}
75+
6376
interface ActionRenderer {
6477
key: string
6578
render: (isLast: boolean) => JSX.Element
@@ -216,11 +229,14 @@ const createBaseColumns = ({
216229
virusScanColumn,
217230
]
218231

219-
const createScreeningColumns = (): TableColumn<Screening>[] => [
232+
const createScreeningColumns = ({
233+
canViewAllScorecards,
234+
currentMemberId,
235+
}: ScreeningColumnConfig): TableColumn<Screening>[] => [
220236
{
221237
label: 'Screener',
222238
propertyName: 'screenerHandle',
223-
renderer: (data: Screening) => (data.screener?.id ? (
239+
renderer: (data: Screening) => (data.screener?.memberHandle ? (
224240
<a
225241
href={getHandleUrl(data.screener)}
226242
target='_blank'
@@ -251,7 +267,36 @@ const createScreeningColumns = (): TableColumn<Screening>[] => [
251267
{
252268
label: 'Screening Score',
253269
propertyName: 'score',
254-
type: 'text',
270+
renderer: (data: Screening) => {
271+
const scoreValue = data.score ?? '-'
272+
273+
if (!data.reviewId) {
274+
return <span>{scoreValue}</span>
275+
}
276+
277+
const canViewScorecard = canViewAllScorecards
278+
|| Boolean(data.memberId && data.memberId === currentMemberId)
279+
280+
if (!canViewScorecard) {
281+
return (
282+
<Tooltip content={VIEW_OWN_SCORECARD_TOOLTIP} triggerOn='click-hover'>
283+
<span className={styles.tooltipTrigger}>
284+
<span className={styles.textBlue}>{scoreValue}</span>
285+
</span>
286+
</Tooltip>
287+
)
288+
}
289+
290+
return (
291+
<Link
292+
to={`./../review/${data.reviewId}`}
293+
className={styles.textBlue}
294+
>
295+
{scoreValue}
296+
</Link>
297+
)
298+
},
299+
type: 'element',
255300
},
256301
{
257302
label: 'Screening Result',
@@ -397,14 +442,39 @@ const normalizeCreatedAt = (
397442
export const TableSubmissionScreening: FC<Props> = (props: Props) => {
398443
const { width: screenWidth }: WindowSize = useWindowSize()
399444
const isTablet = useMemo(() => screenWidth <= 984, [screenWidth])
400-
const { challengeInfo }: ChallengeDetailContextModel = useContext(
445+
const { challengeInfo, myRoles }: ChallengeDetailContextModel = useContext(
401446
ChallengeDetailContext,
402447
)
448+
const { loginUserInfo }: ReviewAppContextModel = useContext(ReviewAppContext)
403449
const {
404450
restrictionMessage,
405451
isSubmissionDownloadRestrictedForMember,
406452
getRestrictionMessageForMember,
453+
currentMemberId,
407454
}: UseSubmissionDownloadAccessResult = useSubmissionDownloadAccess()
455+
456+
const normalisedRoles = useMemo(
457+
() => (myRoles ?? []).map(role => role.toLowerCase()),
458+
[myRoles],
459+
)
460+
461+
const hasCopilotRole = useMemo(
462+
() => normalisedRoles.some(role => role.includes('copilot')),
463+
[normalisedRoles],
464+
)
465+
466+
const isAdminUser = useMemo(
467+
() => loginUserInfo?.roles?.some(
468+
role => typeof role === 'string'
469+
&& role.toLowerCase() === UserRole.administrator,
470+
) ?? false,
471+
[loginUserInfo?.roles],
472+
)
473+
474+
const canViewAllScorecards = useMemo(
475+
() => isAdminUser || hasCopilotRole,
476+
[isAdminUser, hasCopilotRole],
477+
)
408478
const showScreeningColumns = props.showScreeningColumns ?? true
409479
const submissionTypes = useMemo(
410480
() => new Set(
@@ -608,7 +678,13 @@ export const TableSubmissionScreening: FC<Props> = (props: Props) => {
608678
[handleColumn, submissionColumn, submissionDateColumn, virusScanColumn],
609679
)
610680

611-
const screeningColumns = useMemo<TableColumn<Screening>[]>(createScreeningColumns, [])
681+
const screeningColumns = useMemo<TableColumn<Screening>[]>(
682+
() => createScreeningColumns({
683+
canViewAllScorecards,
684+
currentMemberId,
685+
}),
686+
[canViewAllScorecards, currentMemberId],
687+
)
612688

613689
const actionColumn = useMemo(
614690
() => createActionColumn({

src/apps/review/src/lib/hooks/useFetchScreeningReview.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { EnvironmentConfig } from '~/config'
66
import { getRatingColor, xhrGetAsync } from '~/libs/core'
77
import { handleError } from '~/libs/shared'
88

9-
import { REVIEWER, SUBMITTER } from '../../config/index.config'
9+
import { DESIGN, REVIEWER, SUBMITTER } from '../../config/index.config'
1010
import { ChallengeDetailContext, ReviewAppContext } from '../contexts'
1111
import {
1212
BackendPhase,
@@ -2161,7 +2161,17 @@ export function useFetchScreeningReview(): useFetchScreeningReviewProps {
21612161
return 0
21622162
}
21632163

2164-
const completedReviews = filter(review, item => {
2164+
const isDesignChallenge = challengeInfo?.track.name === DESIGN
2165+
2166+
const filteredReviews = isDesignChallenge
2167+
? review
2168+
: review.filter(item => item.isLatest)
2169+
2170+
if (!filteredReviews.length) {
2171+
return 0
2172+
}
2173+
2174+
const completedReviews = filteredReviews.filter(item => {
21652175
const committed = item.review?.committed
21662176
if (typeof committed === 'boolean') {
21672177
return committed
@@ -2185,9 +2195,9 @@ export function useFetchScreeningReview(): useFetchScreeningReviewProps {
21852195
})
21862196

21872197
return Math.round(
2188-
(completedReviews.length * 100) / review.length,
2198+
(completedReviews.length * 100) / filteredReviews.length,
21892199
)
2190-
}, [review])
2200+
}, [review, challengeInfo])
21912201

21922202
useEffect(() => () => {
21932203
cancelLoadResourceAppeal()

0 commit comments

Comments
 (0)