Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
f0839d4
Initial reports portal
jmgasper Mar 5, 2026
78a9b48
Deploy reports
jmgasper Mar 5, 2026
1bd0f02
Remove project manager rights from reports portal
jmgasper Mar 5, 2026
61fdca1
PM-4075 Fix manager comment access
himaniraghav3 Mar 10, 2026
eee8edf
PM-3707
hentrymartin Mar 10, 2026
166144b
Merge pull request #1521 from topcoder-platform/reports
jmgasper Mar 10, 2026
4db3c1b
Better RBAC for reports access for PM / TM roles
jmgasper Mar 11, 2026
39388d9
Merge branch 'dev' of github.com:topcoder-platform/platform-ui into dev
jmgasper Mar 11, 2026
000b697
Fix up for copilot issue
jmgasper Mar 11, 2026
394ce8a
Merge pull request #1518 from topcoder-platform/PM-4075
kkartunov Mar 11, 2026
9a347c2
PM-3926 - show locked state
vas3a Mar 11, 2026
dcca61b
PM-4075 Don't allow copilots to add/edit manager comments
himaniraghav3 Mar 11, 2026
866d600
PM-4182 #time 15min qa tweaks
vas3a Mar 11, 2026
5b57cfb
Merge pull request #1524 from topcoder-platform/PM-4075
himaniraghav3 Mar 11, 2026
6478d10
PM-4198 #time 15m qa feedback
vas3a Mar 11, 2026
b5917f0
Merge pull request #1525 from topcoder-platform/PM-4182_open-to-work-…
vas3a Mar 11, 2026
3acb31e
lint
vas3a Mar 11, 2026
a5f8a12
Merge pull request #1526 from topcoder-platform/PM-4198_customer-port…
vas3a Mar 11, 2026
834f9fc
Merge branch 'dev' of github.com:topcoder-platform/platform-ui into P…
vas3a Mar 11, 2026
47bdd90
PM-3906 wip
vas3a Mar 11, 2026
53181db
fix: lint
hentrymartin Mar 11, 2026
afe9c36
fix: review comments
hentrymartin Mar 11, 2026
06cc95c
PM-4288 #time 3h implemented open to work filter and showing it in th…
hentrymartin Mar 11, 2026
0574d01
rearranged the columns
hentrymartin Mar 11, 2026
67d03b7
fix: lint
hentrymartin Mar 11, 2026
cd5f83c
Date validation
jmgasper Mar 12, 2026
a83ce50
Merge branch 'dev' of github.com:topcoder-platform/platform-ui into dev
jmgasper Mar 12, 2026
04f6157
Merge pull request #1527 from topcoder-platform/pm-4288
kkartunov Mar 12, 2026
cf47e7c
Merge pull request #1520 from topcoder-platform/pm-3707
kkartunov Mar 12, 2026
8feee49
PM-3907 - ai review status
vas3a Mar 12, 2026
682e619
lint
vas3a Mar 12, 2026
cf5d97e
Merge pull request #1528 from topcoder-platform/PM-3907_ai-review-sta…
kkartunov Mar 12, 2026
60125ea
Update Trivy action to use latest version
kkartunov Mar 12, 2026
64332d7
Update trivy.yaml
kkartunov Mar 12, 2026
15e3c42
PM-3907 #time 2h refactor layout, move "rerun" tooltip to button,
vas3a Mar 12, 2026
2bc2aff
lint
vas3a Mar 12, 2026
4ebc8e4
PM-3907 #time 15m pr feedback
vas3a Mar 12, 2026
9c05037
PM-4203 #time 4h implemented filter by skills in customer app
hentrymartin Mar 12, 2026
c151b62
fix: lint
hentrymartin Mar 12, 2026
b04348e
fix: lint
hentrymartin Mar 12, 2026
2a2921a
Merge pull request #1529 from topcoder-platform/PM-3907_ai-review-sta…
vas3a Mar 13, 2026
ce935d0
Merge branch 'dev' of github.com:topcoder-platform/platform-ui into P…
vas3a Mar 13, 2026
fcb817d
PM-3906 #time 4.5h review escalation
vas3a Mar 13, 2026
022306f
PM-4265 Add score info and gating indicator
himaniraghav3 Mar 13, 2026
6bc93a4
Merge branch 'dev' into PM-4265
himaniraghav3 Mar 13, 2026
145bca3
Show score info only if ai review config
himaniraghav3 Mar 13, 2026
1882714
PM-4265 Fix linting
himaniraghav3 Mar 13, 2026
9caa8c1
Merge pull request #1531 from topcoder-platform/PM-4265
kkartunov Mar 13, 2026
b7ff0e5
fix: modified the logic to display open to work column
hentrymartin Mar 13, 2026
6294433
Merge pull request #1532 from topcoder-platform/pm-4288_1
hentrymartin Mar 13, 2026
63e2e6b
fix: review comment
hentrymartin Mar 14, 2026
8019000
PM-4179 #time 1h find root cause and fix pagination in permission man…
hentrymartin Mar 14, 2026
698747a
PM-4267 #time 10m modified copy in engagements app
hentrymartin Mar 14, 2026
10f5899
Merge pull request #1534 from topcoder-platform/pm-4267
hentrymartin Mar 14, 2026
e984e74
PM-3906 #time 1.5h fixes to modals & lint
vas3a Mar 14, 2026
031d917
PM-3906 #time 30m use ai decission.escalation, unlock submission
vas3a Mar 14, 2026
7672e1d
PM-3906 #time 5m re-validate ai decissions once we submit escalation
vas3a Mar 14, 2026
a5aede1
Merge pull request #1533 from topcoder-platform/pm-4179
kkartunov Mar 15, 2026
90eea56
Merge pull request #1530 from topcoder-platform/pm-4203
kkartunov Mar 15, 2026
8b762a5
Hotfix for PS-536 bad scorecard display
jmgasper Mar 15, 2026
6383f1e
Merge pull request #1536 from topcoder-platform/PS-536
jmgasper Mar 15, 2026
4854149
PM-4265 Add overall score, fix css
himaniraghav3 Mar 15, 2026
b347d15
PM-4265 Fix typos
himaniraghav3 Mar 15, 2026
6574fae
re-use data model
vas3a Mar 16, 2026
a64c13b
Merge pull request #1537 from topcoder-platform/PM-4265
kkartunov Mar 16, 2026
5b237f8
Fix lint
vas3a Mar 16, 2026
9afa572
Merge pull request #1535 from topcoder-platform/PM-3906_ai-review-esc…
vas3a Mar 16, 2026
699d4f3
PM-4307 #time 30m For f2f make sure the ai screening phase is shown a…
vas3a Mar 16, 2026
b11c49c
Merge pull request #1539 from topcoder-platform/PM-4302_ai-screening-…
vas3a Mar 16, 2026
b463a98
PM-4349 - show ai failed submissions in review tab
vas3a Mar 17, 2026
a7ddb56
Merge pull request #1540 from topcoder-platform/PM-4349_show-ai-faile…
vas3a Mar 17, 2026
d9c5352
factory fix
kkartunov Mar 17, 2026
3d44a3e
PM-4314 Fix Submission locked text
himaniraghav3 Mar 18, 2026
af5a603
template literal removal
himaniraghav3 Mar 18, 2026
ac7ee68
Merge pull request #1541 from topcoder-platform/PM-4314
kkartunov Mar 18, 2026
236db51
Merge pull request #1542 from topcoder-platform/PM-4364
kkartunov Mar 18, 2026
d76d58c
PM-4390 #time 1h fix layout issues in AI reviewer scorecard
hentrymartin Mar 18, 2026
e8972e6
Hotfix for download permissions issue - PM-4281
jmgasper Mar 19, 2026
8a3438d
Merge branch 'dev' into PM-4281
jmgasper Mar 20, 2026
7031ecc
Merge pull request #1546 from topcoder-platform/PM-4281
jmgasper Mar 20, 2026
0b71bfc
Merge pull request #1544 from topcoder-platform/pm-4390
kkartunov Mar 20, 2026
6ccf2ea
Show and allow search by SSO ID (PM-4425)
jmgasper Mar 23, 2026
d420277
Better stats handling on profiles page for members
jmgasper Mar 23, 2026
395a754
Fix for stats history page rendering
jmgasper Mar 23, 2026
d41160d
Additional updtes for system-admin app and SSO ID sorting / searching
jmgasper Mar 23, 2026
e032978
Stats update to show new challenge ID instead of legacy ID
jmgasper Mar 23, 2026
e582055
Updates for new engagements assignments fields, and wallet-admin role…
jmgasper Mar 23, 2026
2a08b90
Better handling of stats displays.
jmgasper Mar 23, 2026
3727ed1
Lint fixes
jmgasper Mar 24, 2026
f8dfcdd
Lint fixes
jmgasper Mar 24, 2026
0598f7f
Alignment issue with new role selector in wallet-admin
jmgasper Mar 24, 2026
cf69ad6
Fix up stats views for non-complete challenges
jmgasper Mar 24, 2026
960e22e
Engagements v4 QA updates
jmgasper Mar 24, 2026
c21f30d
Pad $ amounts out to 2 decimals
jmgasper Mar 24, 2026
22fd124
Merge branch 'master' into dev
kkartunov Mar 25, 2026
aa3d27a
PM-4465 - submission locked message
vas3a Mar 25, 2026
0c2b97d
lint
vas3a Mar 25, 2026
672ad63
Merge pull request #1550 from topcoder-platform/PM-4465_submission-lo…
vas3a Mar 25, 2026
82a2ecf
PM-4465 - update text
vas3a Mar 25, 2026
fb9872f
Merge pull request #1551 from topcoder-platform/PM-4465_submission-lo…
vas3a Mar 25, 2026
9709f74
Support decimal hours per week in engagement agreement PM-4497
jmgasper Mar 25, 2026
74a0085
Merge branch 'dev' of github.com:topcoder-platform/platform-ui into dev
jmgasper Mar 25, 2026
7bab437
Fix payment list view for admin vs. engagement approver
jmgasper Mar 26, 2026
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
4 changes: 0 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,6 @@ workflows:
branches:
only:
- dev
- mm-final-2025-reveal
- engagements
- HOTFIX-PM-3269
- PM-4281

- deployQa:
context: org-global
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/trivy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4

- name: Run Trivy scanner in repo mode
uses: aquasecurity/trivy-action@0.33.1
uses: aquasecurity/trivy-action@0.35.0
with:
scan-type: "fs"
ignore-unfixed: true
Expand Down
22 changes: 22 additions & 0 deletions src/apps/admin/src/AdminHomeRedirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FC } from 'react'
import { Navigate } from 'react-router-dom'

import { reportsRootRoute } from '~/apps/reports'
import { ProfileContextData, useProfileContext } from '~/libs/core'

import { manageChallengeRouteId } from './config/routes.config'
import { isAdministrator } from './lib/utils'

/**
* Redirects authenticated admin-app users to the first route they can access.
*/
const AdminHomeRedirect: FC = () => {
const { profile }: ProfileContextData = useProfileContext()
const defaultRoute: string = isAdministrator(profile?.roles)
? manageChallengeRouteId
: reportsRootRoute

return <Navigate replace to={defaultRoute} />
}

export default AdminHomeRedirect
26 changes: 11 additions & 15 deletions src/apps/admin/src/admin-app.routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import {
lazyLoad,
LazyLoadedComponent,
PlatformRoute,
Rewrite,
UserRole,
} from '~/libs/core'

import {
Expand All @@ -17,12 +15,13 @@ import {
paymentsRouteId,
permissionManagementRouteId,
platformRouteId,
reportsRouteId,
rootRoute,
termsRouteId,
userManagementRouteId,
} from './config/routes.config'
import { administratorOnlyRoles, adminReportsAccessRoles } from './lib/utils'
import { platformSkillRouteId } from './platform/routes.config'
import AdminHomeRedirect from './AdminHomeRedirect'

const AdminApp: LazyLoadedComponent = lazyLoad(() => import('./AdminApp'))

Expand Down Expand Up @@ -173,10 +172,6 @@ const PaymentsPage: LazyLoadedComponent = lazyLoad(
() => import('./payments/PaymentsPage'),
'PaymentsPage',
)
const ReportsPage: LazyLoadedComponent = lazyLoad(
() => import('./reports/ReportsPage'),
'ReportsPage',
)

export const toolTitle: string = ToolTitle.admin

Expand All @@ -186,7 +181,7 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
authRequired: true,
children: [
{
element: <Rewrite to={manageChallengeRouteId} />,
element: <AdminHomeRedirect />,
route: '',
},
// Challenge Management Module
Expand Down Expand Up @@ -220,12 +215,14 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
],
element: <ChallengeManagement />,
id: manageChallengeRouteId,
rolesRequired: administratorOnlyRoles,
route: manageChallengeRouteId,
},
// User Management Module
{
element: <UserManagementPage />,
id: userManagementRouteId,
rolesRequired: administratorOnlyRoles,
route: userManagementRouteId,
},
// Reviewer Management Module
Expand All @@ -244,6 +241,7 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
],
element: <ReviewManagement />,
id: manageReviewRouteId,
rolesRequired: administratorOnlyRoles,
route: manageReviewRouteId,
},
// Billing Account Module
Expand Down Expand Up @@ -297,6 +295,7 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
],
element: <BillingAccount />,
id: billingAccountRouteId,
rolesRequired: administratorOnlyRoles,
route: billingAccountRouteId,
},
// Permission Management Module
Expand Down Expand Up @@ -335,6 +334,7 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
],
element: <PermissionManagement />,
id: permissionManagementRouteId,
rolesRequired: administratorOnlyRoles,
route: permissionManagementRouteId,
},

Expand Down Expand Up @@ -408,25 +408,21 @@ export const adminRoutes: ReadonlyArray<PlatformRoute> = [
],
element: <Platform />,
id: platformRouteId,
rolesRequired: administratorOnlyRoles,
route: platformRouteId,
},
// Payments Module
{
element: <PaymentsPage />,
id: paymentsRouteId,
rolesRequired: administratorOnlyRoles,
route: paymentsRouteId,
},
// Reports Module
{
element: <ReportsPage />,
id: reportsRouteId,
route: reportsRouteId,
},
],
domain: AppSubdomain.admin,
element: <AdminApp />,
id: toolTitle,
rolesRequired: [UserRole.administrator],
rolesRequired: adminReportsAccessRoles,
route: rootRoute,
title: toolTitle,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@
gap: $sp-3;
}

.exportDescription {
margin: 0;
color: #555;
}

.exportActions {
display: flex;
flex-wrap: wrap;
gap: $sp-3;
}

.exportButton {
min-width: 220px;
}

.sectionTitle {
margin: 0;
font-size: 20px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ChangeEvent,
FC,
MouseEvent,
useEffect,
useMemo,
useState,
Expand Down Expand Up @@ -32,6 +33,10 @@ import {
getResourceRoles,
updateChallengeById,
} from '../../lib/services'
import {
downloadBlobFile,
downloadReportAsCsv,
} from '../../lib/services/reports.service'
import { createChallengeQueryString, handleError } from '../../lib/utils'

import styles from './ChallengeDetailsPage.module.scss'
Expand Down Expand Up @@ -62,6 +67,22 @@ type RouteState = {

type WinnerUpdate = Pick<ChallengeWinner, 'handle' | 'placement' | 'userId'>

type ChallengeExportReportKey =
| 'registered-users'
| 'submitters'
| 'valid-submitters'
| 'winners'

const CHALLENGE_EXPORT_REPORTS: Array<{
key: ChallengeExportReportKey
label: string
}> = [
{ key: 'registered-users', label: 'Registered Users' },
{ key: 'submitters', label: 'Submitters' },
{ key: 'valid-submitters', label: 'Valid Submitters' },
{ key: 'winners', label: 'Winners' },
]

function formatStatusLabel(rawStatus: string): string {
const normalized = rawStatus
.trim()
Expand Down Expand Up @@ -188,6 +209,8 @@ export const ChallengeDetailsPage: FC = () => {
const [isLoading, setIsLoading] = useState(false)
const [isSavingStatus, setIsSavingStatus] = useState(false)
const [isSavingWinners, setIsSavingWinners] = useState(false)
const [downloadingReportKey, setDownloadingReportKey]
= useState<ChallengeExportReportKey | undefined>()
const [isLoadingSubmitters, setIsLoadingSubmitters] = useState(false)
const [submitterOptions, setSubmitterOptions] = useState<InputSelectOption[]>([
{ label: 'Select submitter', value: '' },
Expand Down Expand Up @@ -328,6 +351,7 @@ export const ChallengeDetailsPage: FC = () => {
}, [routeState.previousChallengeListFilter])

const pageTitle = challengeInfo?.name || 'Challenge Details'
const isMarathonMatch = challengeInfo?.type?.name === 'Marathon Match'
const currentWinnerHandleByUserId = useMemo(
() => Object.fromEntries(
(challengeInfo?.winners ?? []).map(winner => [`${winner.userId}`, winner.handle]),
Expand Down Expand Up @@ -414,6 +438,37 @@ export const ChallengeDetailsPage: FC = () => {
}
})

const handleExportReport = useEventCallback(async (reportKey: ChallengeExportReportKey) => {
if (!challengeId) {
return
}

setDownloadingReportKey(reportKey)

try {
const path = `/challenges/${encodeURIComponent(challengeId)}/${reportKey}`
const blob = await downloadReportAsCsv(path)
const fileName = `challenge-${reportKey}_${challengeId}.csv`

downloadBlobFile(blob, fileName)
} catch (error) {
handleError(error)
} finally {
setDownloadingReportKey(undefined)
}
})

const handleExportButtonClick = useEventCallback(
(event: MouseEvent<HTMLButtonElement>) => {
const reportKey = event.currentTarget.value as ChallengeExportReportKey
if (!reportKey) {
return
}

handleExportReport(reportKey)
},
)

return (
<PageWrapper
pageTitle={pageTitle}
Expand Down Expand Up @@ -457,6 +512,34 @@ export const ChallengeDetailsPage: FC = () => {
)}
{!isLoading && challengeInfo && (
<>
<section className={styles.section}>
<h4 className={styles.sectionTitle}>Exports</h4>
<p className={styles.exportDescription}>
Download challenge detail reports as CSV.
{isMarathonMatch && (
' Marathon Match submission-based exports include provisional '
+ 'score and final rank.'
)}
</p>
<div className={styles.exportActions}>
{CHALLENGE_EXPORT_REPORTS.map(report => (
<Button
key={report.key}
secondary
size='lg'
className={styles.exportButton}
value={report.key}
disabled={downloadingReportKey !== undefined}
onClick={handleExportButtonClick}
>
{downloadingReportKey === report.key
? `Downloading ${report.label}…`
: `Export ${report.label}`}
</Button>
))}
</div>
</section>

<section className={styles.section}>
<h4 className={styles.sectionTitle}>Status</h4>
<div className={styles.statusRow}>
Expand Down
1 change: 0 additions & 1 deletion src/apps/admin/src/config/routes.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ export const termsRouteId = 'terms'
export const defaultReviewersRouteId = 'default-reviewers'
export const platformRouteId = 'platform'
export const paymentsRouteId = 'payments'
export const reportsRouteId = 'reports'
Loading
Loading