Skip to content
Merged

Feat/v6 #1283

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,15 @@ const Actions: FC<{
{hasLegacyId && (
<a
href={
`${EnvironmentConfig.ADMIN.ONLINE_REVIEW_URL}/actions/ViewProjectDetails?pid=${props.challenge.legacyId}` /* eslint-disable-line max-len */
`${EnvironmentConfig.ADMIN.REVIEW_UI_URL}/=${props.challenge.id}` /* eslint-disable-line max-len */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
The URL structure seems incorrect. The = character after REVIEW_UI_URL appears misplaced and might lead to an invalid URL. Ensure the URL is constructed correctly to avoid broken links.

}
target='_blank'
rel='noreferrer'
>
Online Review
Review UI
</a>
)}
{!hasLegacyId && <span>Online Review</span>}
{!hasLegacyId && <span>Review UI</span>}
</li>
</ul>
</DropdownMenu>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* Challenge Details Content.
*/
import { FC, ReactNode, useContext, useMemo } from 'react'
import { FC, ReactNode, useCallback, useContext, useMemo } from 'react'
import { toast } from 'react-toastify'

import { ActionLoading } from '~/apps/admin/src/lib'

Expand Down Expand Up @@ -185,6 +186,37 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
isLoadingBool: isDownloadingSubmissionBool,
downloadSubmission,
}: useDownloadSubmissionProps = useDownloadSubmission()
const submissionsById = useMemo(() => {
const map = new Map<string, BackendSubmission>()
props.submissions.forEach(submission => {
if (submission?.id) {
map.set(submission.id, submission)
}
})
return map
}, [props.submissions])
const handleSubmissionDownload = useCallback((submissionId: string) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The useCallback dependency array includes submissionsById, which is derived from props.submissions. Ensure that props.submissions is stable or memoized to prevent unnecessary recalculations of handleSubmissionDownload.

const submission = submissionsById.get(submissionId)
if (submission && submission.isFileSubmission === false) {
const targetUrl = submission.url?.trim()
if (targetUrl) {
if (typeof window !== 'undefined') {
const openedWindow = window.open(targetUrl, '_blank', 'noopener,noreferrer')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ security]
When opening a new window with window.open, consider checking if targetUrl is a valid URL to prevent potential issues with malformed URLs.

if (openedWindow === null) {
toast.error('We could not open the submission URL. Check your pop-up blocker and try again.')
}
} else {
toast.error('Unable to open the submission URL from this environment.')
}
} else {
toast.error('Submission URL is not available for this entry.')
}

return
}

downloadSubmission(submissionId)
}, [downloadSubmission, submissionsById])
const {
isLoading: isLoadingProjectResult,
projectResults,
Expand Down Expand Up @@ -335,7 +367,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {

if (SUBMISSION_TAB_KEYS.has(selectedTabNormalized)) {
return renderSubmissionTab({
downloadSubmission,
downloadSubmission: handleSubmissionDownload,
isActiveChallenge: props.isActiveChallenge,
isDownloadingSubmission,
isLoadingSubmission: props.isLoadingSubmission,
Expand All @@ -361,7 +393,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
checkpointReviewMinimumPassingScore={props.checkpointReviewMinimumPassingScore}
isLoading={props.isLoadingSubmission}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
mode={checkpointMode}
/>
)
Expand All @@ -373,7 +405,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
isLoading={isLoadingProjectResult}
projectResults={projectResults}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
/>
)
}
Expand All @@ -386,7 +418,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
approvalMinimumPassingScore={props.approvalMinimumPassingScore}
isLoadingReview={props.isLoadingSubmission}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
isActiveChallenge={props.isActiveChallenge}
/>
)
Expand All @@ -400,7 +432,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
postMortemMinimumPassingScore={props.postMortemMinimumPassingScore}
isLoadingReview={props.isLoadingSubmission}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
isActiveChallenge={props.isActiveChallenge}
columnLabel='Post-Mortem'
/>
Expand All @@ -415,7 +447,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
postMortemMinimumPassingScore={props.postMortemMinimumPassingScore}
isLoadingReview={props.isLoadingSubmission}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
isActiveChallenge={props.isActiveChallenge}
phaseIdFilter={props.selectedPhaseId}
/>
Expand All @@ -430,7 +462,7 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
reviewMinimumPassingScore={props.reviewMinimumPassingScore}
isLoadingReview={props.isLoadingSubmission}
isDownloading={isDownloadingSubmission}
downloadSubmission={downloadSubmission}
downloadSubmission={handleSubmissionDownload}
mappingReviewAppeal={props.mappingReviewAppeal}
isActiveChallenge={props.isActiveChallenge}
/>
Expand Down
5 changes: 5 additions & 0 deletions src/apps/review/src/lib/models/BackendSubmission.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export interface BackendSubmission {
* Indicates whether the submission is the latest for the member.
*/
isLatest?: boolean
/**
* Flag indicating whether the submission includes a downloadable file.
* When false the submission is represented only by a URL.
*/
isFileSubmission?: boolean
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/apps/review/src/lib/models/SubmissionInfo.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export interface SubmissionInfo {
* Submission type (e.g. CONTEST_SUBMISSION, CHECKPOINT_SUBMISSION).
*/
type?: string
/**
* Flag indicating whether the submission includes an uploaded file.
*/
isFileSubmission?: boolean
}

/**
Expand Down Expand Up @@ -118,6 +122,7 @@ export function convertBackendSubmissionToSubmissionInfo(
return {
aggregateScore,
id: data.id,
isFileSubmission: data.isFileSubmission,
isLatest: data.isLatest,
isPassingReview,
memberId: data.memberId,
Expand Down
7 changes: 4 additions & 3 deletions src/config/environments/default.env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,21 @@ export const ADMIN = {
DEFAULT_PAYMENT_TERMS: 1,
DIRECT_URL: 'https://www.topcoder-dev.com/direct',
ONLINE_REVIEW_URL: 'https://software.topcoder-dev.com/review',
REVIEW_UI_URL: 'https://review.topcoder-dev.com',
SUBMISSION_SCAN_TOPIC: 'submission.scan.complete',
WORK_MANAGER_URL: 'https://challenges.topcoder-dev.com',
}

const REVIEW_OPPORTUNITIES_URL_DEFAULT = getReactEnv<string>(
'REVIEW_OPPORTUNITIES_URL',
'https://www-v6.topcoder-dev.com/challenges/?bucket=reviewOpportunities&'
'https://www.topcoder-dev.com/challenges/?bucket=reviewOpportunities&'
+ 'tracks[DS]=true&tracks[Des]=true&tracks[Dev]=true&tracks[QA]=true',
)

export const REVIEW = {
CHALLENGE_PAGE_URL: 'https://www-v6.topcoder-dev.com/challenges',
CHALLENGE_PAGE_URL: 'https://www.topcoder-dev.com/challenges',
OPPORTUNITIES_URL: REVIEW_OPPORTUNITIES_URL_DEFAULT,
PROFILE_PAGE_URL: 'https://profiles-v6.topcoder-dev.com/profiles',
PROFILE_PAGE_URL: 'https://profiles.topcoder-dev.com/profiles',
}

const FILESTACK_SECURITY_POLICY = getReactEnv<string | undefined>('FILESTACK_SECURITY_POLICY', undefined)
Expand Down
1 change: 1 addition & 0 deletions src/config/environments/global-config.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface GlobalConfig {
DIRECT_URL: string
WORK_MANAGER_URL: string
ONLINE_REVIEW_URL: string
REVIEW_UI_URL: string
CHALLENGE_URL: string
AV_SCAN_SCORER_REVIEW_TYPE_ID: string
AGREE_ELECTRONICALLY: string
Expand Down
1 change: 1 addition & 0 deletions src/config/environments/prod.env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const ADMIN = {
DEFAULT_PAYMENT_TERMS: 1,
DIRECT_URL: 'https://www.topcoder.com/direct',
ONLINE_REVIEW_URL: 'https://software.topcoder.com/review',
REVIEW_UI_URL: 'https://review.topcoder.com',
SUBMISSION_SCAN_TOPIC: 'submission.scan.complete',
WORK_MANAGER_URL: 'https://challenges.topcoder.com',
}
Expand Down