From 88fe2bffd9f1c9687b93a72ecaa4a02b2ea8ac5b Mon Sep 17 00:00:00 2001
From: dat
Date: Wed, 7 May 2025 13:11:47 +0700
Subject: [PATCH] Topcoder Admin App - Misc Update 0505
---
.../ChallengeManagementPage.tsx | 50 +++++++++----------
.../BillingAccountResourcesTable.tsx | 18 -------
.../BillingAccountsFilter.module.scss | 2 +-
.../BillingAccountsFilter.tsx | 29 +++++++++--
.../ChallengeFilters.module.scss | 11 ++--
.../ChallengeFilters/ChallengeFilters.tsx | 12 ++---
.../ChallengeList/ChallengeList.tsx | 8 ++-
.../ClientsFilter/ClientsFilter.module.scss | 2 +-
.../ClientsFilter/ClientsFilter.tsx | 27 ++++++++--
.../ReviewSummaryList.module.scss | 5 +-
.../ReviewSummaryList/ReviewSummaryList.tsx | 11 ++--
.../UsersFilters/UsersFilters.module.scss | 6 +++
.../components/UsersFilters/UsersFilters.tsx | 46 +++++++++++++----
src/config/environments/default.env.ts | 1 +
.../environments/global-config.model.ts | 1 +
src/config/environments/prod.env.ts | 1 +
16 files changed, 147 insertions(+), 83 deletions(-)
diff --git a/src/apps/admin/src/challenge-management/ChallengeManagementPage/ChallengeManagementPage.tsx b/src/apps/admin/src/challenge-management/ChallengeManagementPage/ChallengeManagementPage.tsx
index 53a812aad..6476abb03 100644
--- a/src/apps/admin/src/challenge-management/ChallengeManagementPage/ChallengeManagementPage.tsx
+++ b/src/apps/admin/src/challenge-management/ChallengeManagementPage/ChallengeManagementPage.tsx
@@ -10,6 +10,7 @@ import {
useState,
} from 'react'
import { useSearchParams } from 'react-router-dom'
+import _ from 'lodash'
import { LoadingSpinner, PageDivider, PageTitle } from '~/libs/ui'
import { PaginatedResponse } from '~/libs/core'
@@ -36,6 +37,17 @@ import { useEventCallback } from '../../lib/hooks'
import styles from './ChallengeManagementPage.module.scss'
+const defaultFilter: ChallengeFilterCriteria = {
+ challengeId: '',
+ legacyId: 0,
+ name: '',
+ page: 1,
+ perPage: 25,
+ status: ChallengeStatus.Active,
+ track: null!, // eslint-disable-line @typescript-eslint/no-non-null-assertion, unicorn/no-null
+ type: null!, // eslint-disable-line @typescript-eslint/no-non-null-assertion, unicorn/no-null
+}
+
/**
* Challenge Management page.
*/
@@ -45,15 +57,9 @@ export const ChallengeManagementPage: FC = () => {
ChallengeFilterCriteria,
Dispatch>,
] = useState({
- challengeId: '',
- legacyId: 0,
- name: '',
- page: 1,
- perPage: 25,
- status: ChallengeStatus.Active,
- track: null!, // eslint-disable-line @typescript-eslint/no-non-null-assertion, unicorn/no-null
- type: null!, // eslint-disable-line @typescript-eslint/no-non-null-assertion, unicorn/no-null
+ ...defaultFilter,
})
+ const disableReset = useMemo(() => _.isEqual(filterCriteria, defaultFilter), [filterCriteria])
const [challenges, setChallenges]: [
Array,
Dispatch>>,
@@ -119,19 +125,6 @@ export const ChallengeManagementPage: FC = () => {
}
}, [pageChangeEvent]) // eslint-disable-line react-hooks/exhaustive-deps -- missing dependency: search
- // Reset
- const [resetEvent, setResetEvent] = useState(false)
- useEffect(() => {
- if (resetEvent) {
- search()
- setResetEvent(false)
- }
- }, [resetEvent]) // eslint-disable-line react-hooks/exhaustive-deps -- missing dependency: search
-
- const handleReset = useEventCallback(() => {
- previousPageChangeEvent.current = false
- setResetEvent(true)
- })
const handlePageChange = useEventCallback((page: number) => {
setFilterCriteria({ ...filterCriteria, page })
setPageChangeEvent(true)
@@ -149,12 +142,15 @@ export const ChallengeManagementPage: FC = () => {
onFilterCriteriaChange={setFilterCriteria}
onSearch={search}
disabled={searching || !filtersInited}
- showResetButton={
- previousPageChangeEvent.current
- && searched
- && challenges.length === 0
- }
- onReset={handleReset}
+ onReset={function onReset() {
+ setFilterCriteria({
+ ...defaultFilter,
+ })
+ setTimeout(() => {
+ search()
+ })
+ }}
+ disableReset={disableReset}
/>
{searching && (
diff --git a/src/apps/admin/src/lib/components/BillingAccountResourcesTable/BillingAccountResourcesTable.tsx b/src/apps/admin/src/lib/components/BillingAccountResourcesTable/BillingAccountResourcesTable.tsx
index 57250f8f6..70e241c12 100644
--- a/src/apps/admin/src/lib/components/BillingAccountResourcesTable/BillingAccountResourcesTable.tsx
+++ b/src/apps/admin/src/lib/components/BillingAccountResourcesTable/BillingAccountResourcesTable.tsx
@@ -44,11 +44,6 @@ export const BillingAccountResourcesTable: FC = (props: Props) => {
propertyName: 'name',
type: 'text',
},
- {
- label: 'Status',
- propertyName: 'status',
- type: 'text',
- },
{
className: styles.blockColumnAction,
label: '',
@@ -81,21 +76,8 @@ export const BillingAccountResourcesTable: FC = (props: Props) => {
},
],
[
- {
- label: 'Status label',
- mobileType: 'label',
- propertyName: 'status',
- renderer: () => Status:
,
- type: 'element',
- },
{
...columns[1],
- mobileType: 'last-value',
- },
- ],
- [
- {
- ...columns[2],
colSpan: 2,
mobileType: 'last-value',
},
diff --git a/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.module.scss b/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.module.scss
index f6a160a31..3ef60d8cd 100644
--- a/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.module.scss
+++ b/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.module.scss
@@ -44,7 +44,7 @@
display: flex;
justify-content: flex-end;
align-items: flex-start;
- gap: 30px;
+ gap: 15px;
flex-wrap: wrap;
@include ltemd {
diff --git a/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.tsx b/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.tsx
index 898102337..d1ca08226 100644
--- a/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.tsx
+++ b/src/apps/admin/src/lib/components/BillingAccountsFilter/BillingAccountsFilter.tsx
@@ -27,22 +27,30 @@ interface Props {
onSubmitForm?: (data: FormBillingAccountsFilter) => void
}
+const defaultValues: FormBillingAccountsFilter = {
+ endDate: undefined,
+ name: '',
+ startDate: undefined,
+ status: '1',
+ user: '',
+}
+
export const BillingAccountsFilter: FC = (props: Props) => {
const maxDate = useMemo(() => moment()
.add(20, 'y')
.toDate(), [])
const {
register,
+ reset,
handleSubmit,
control,
- formState: { isValid },
+ formState: { isValid, isDirty },
}: UseFormReturn = useForm({
- defaultValues: {
- status: '1',
- },
+ defaultValues,
mode: 'all',
resolver: yupResolver(formBillingAccountsFilterSchema),
})
+
const onSubmit = useCallback(
(data: FormBillingAccountsFilter) => {
props.onSubmitForm?.(data)
@@ -162,6 +170,19 @@ export const BillingAccountsFilter: FC = (props: Props) => {
>
Filter
+
)
diff --git a/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.module.scss b/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.module.scss
index e5270817d..a9b990d5b 100644
--- a/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.module.scss
+++ b/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.module.scss
@@ -16,10 +16,6 @@
gap: 15px 30px;
}
- .searchButton {
- margin-left: auto;
- }
-
@media (max-width: #{$lg-max}) {
.filters {
grid-template-columns: 1fr 1fr;
@@ -32,3 +28,10 @@
}
}
}
+
+.blockBtns {
+ margin-left: auto;
+ display: flex;
+ gap: 15px;
+ justify-content: flex-end;
+}
diff --git a/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.tsx b/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.tsx
index ef4b27ed7..f2f139eb8 100644
--- a/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.tsx
+++ b/src/apps/admin/src/lib/components/ChallengeFilters/ChallengeFilters.tsx
@@ -19,10 +19,10 @@ import styles from './ChallengeFilters.module.scss'
interface ChallengeFiltersProps {
filterCriteria: ChallengeFilterCriteria
disabled: boolean
- showResetButton: boolean
onFilterCriteriaChange: (newFilterCriteria: ChallengeFilterCriteria) => void
onSearch: () => void
onReset: () => void
+ disableReset: boolean
}
const ChallengeFilters: FC = props => {
@@ -188,28 +188,24 @@ const ChallengeFilters: FC = props => {
disabled={props.disabled}
/>
- {!props.showResetButton && (
+
- )}
- {props.showResetButton && (
- )}
+
)
}
diff --git a/src/apps/admin/src/lib/components/ChallengeList/ChallengeList.tsx b/src/apps/admin/src/lib/components/ChallengeList/ChallengeList.tsx
index 840279d1e..1934a915c 100644
--- a/src/apps/admin/src/lib/components/ChallengeList/ChallengeList.tsx
+++ b/src/apps/admin/src/lib/components/ChallengeList/ChallengeList.tsx
@@ -267,7 +267,13 @@ const ChallengeList: FC = props => {
propertyName: 'name',
renderer: (challenge: Challenge) => (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
-
+
{challenge.name}
),
diff --git a/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.module.scss b/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.module.scss
index 6fd5ed523..0ad94e06e 100644
--- a/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.module.scss
+++ b/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.module.scss
@@ -24,7 +24,7 @@
display: flex;
justify-content: flex-end;
align-items: flex-start;
- gap: 30px;
+ gap: 15px;
flex-wrap: wrap;
@include ltemd {
diff --git a/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.tsx b/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.tsx
index 2421dccfc..3d76ae8f2 100644
--- a/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.tsx
+++ b/src/apps/admin/src/lib/components/ClientsFilter/ClientsFilter.tsx
@@ -27,19 +27,25 @@ interface Props {
onSubmitForm?: (data: FormClientsFilter) => void
}
+const defaultValues: FormClientsFilter = {
+ endDate: undefined,
+ name: '',
+ startDate: undefined,
+ status: '1',
+}
+
export const ClientsFilter: FC = (props: Props) => {
const maxDate = useMemo(() => moment()
.add(20, 'y')
.toDate(), [])
const {
register,
+ reset,
handleSubmit,
control,
- formState: { isValid },
+ formState: { isValid, isDirty },
}: UseFormReturn = useForm({
- defaultValues: {
- status: '1',
- },
+ defaultValues,
mode: 'all',
resolver: yupResolver(formClientsFilterSchema),
})
@@ -149,6 +155,19 @@ export const ClientsFilter: FC = (props: Props) => {
>
Filter
+
)
diff --git a/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.module.scss b/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.module.scss
index 937b80419..f460fc40a 100644
--- a/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.module.scss
+++ b/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.module.scss
@@ -9,7 +9,8 @@
}
}
-.challengeTitle {
+.challengeTitleText,
+.challengeTitleLink {
min-width: 200px;
padding: 0;
justify-content: flex-start;
@@ -17,7 +18,9 @@
color: $body-color;
line-height: 16px;
white-space: break-spaces;
+}
+.challengeTitleLink {
&:hover {
color: $blue-110;
}
diff --git a/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.tsx b/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.tsx
index cf520cec4..db21dcab2 100644
--- a/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.tsx
+++ b/src/apps/admin/src/lib/components/ReviewSummaryList/ReviewSummaryList.tsx
@@ -1,6 +1,7 @@
import { FC, useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
+import { EnvironmentConfig } from '~/config'
import { useWindowSize, WindowSize } from '~/libs/shared'
import { Button, LinkButton, Table, type TableColumn } from '~/libs/ui'
import { Sort } from '~/apps/gamification-admin/src/game-lib/pagination'
@@ -45,13 +46,17 @@ const ChallengeTitle: FC<{
review: ReviewSummary
}> = props => {
const goToChallenge = useEventCallback(() => {
- window.location.href = `https://www.topcoder.com/challenges/${props.review.legacyChallengeId}`
+ window.location.href = `${EnvironmentConfig.ADMIN.CHALLENGE_URL}/${props.review.legacyChallengeId}`
})
- return (
-
+ return props.review.legacyChallengeId ? (
+
{props.review.challengeName}
+ ) : (
+
+ {props.review.challengeName}
+
)
}
diff --git a/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.module.scss b/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.module.scss
index f4c588c8b..24a973a1c 100644
--- a/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.module.scss
+++ b/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.module.scss
@@ -44,3 +44,9 @@
font-size: 14px;
color: $black-60;
}
+
+.blockBtns {
+ display: flex;
+ gap: 15px;
+ justify-content: flex-end;
+}
diff --git a/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.tsx b/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.tsx
index 6ba099e20..1f6817e30 100644
--- a/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.tsx
+++ b/src/apps/admin/src/lib/components/UsersFilters/UsersFilters.tsx
@@ -21,14 +21,22 @@ interface Props {
isLoading?: boolean
}
+const defaultValues: FormUsersFilters = {
+ email: '',
+ handle: '',
+ status: undefined,
+ userId: '',
+}
+
export const UsersFilters: FC = props => {
const {
register,
+ reset,
handleSubmit,
control,
- formState: { errors, isValid },
+ formState: { errors, isValid, isDirty },
}: UseFormReturn = useForm({
- defaultValues: {},
+ defaultValues,
mode: 'all',
resolver: yupResolver(formUsersFiltersSchema),
})
@@ -143,15 +151,31 @@ export const UsersFilters: FC = props => {
- Maximum number of searched results is 500.
-
+
+
+
+
+
)
diff --git a/src/config/environments/default.env.ts b/src/config/environments/default.env.ts
index 54ba8313a..b3f85f0ef 100644
--- a/src/config/environments/default.env.ts
+++ b/src/config/environments/default.env.ts
@@ -77,6 +77,7 @@ export const USERFLOW_SURVEYS = {
}
export const ADMIN = {
+ CHALLENGE_URL: 'https://www.topcoder-dev.com/challenges',
CONNECT_URL: 'https://connect.topcoder-dev.com',
DIRECT_URL: 'https://www.topcoder-dev.com/direct',
ONLINE_REVIEW_URL: 'https://software.topcoder-dev.com/review',
diff --git a/src/config/environments/global-config.model.ts b/src/config/environments/global-config.model.ts
index 9348ce5b0..d12bf9c09 100644
--- a/src/config/environments/global-config.model.ts
+++ b/src/config/environments/global-config.model.ts
@@ -48,5 +48,6 @@ export interface GlobalConfig {
DIRECT_URL: string
WORK_MANAGER_URL: string
ONLINE_REVIEW_URL: string
+ CHALLENGE_URL: string
}
}
diff --git a/src/config/environments/prod.env.ts b/src/config/environments/prod.env.ts
index 463f3585e..f2baacba2 100644
--- a/src/config/environments/prod.env.ts
+++ b/src/config/environments/prod.env.ts
@@ -7,6 +7,7 @@ export const VANILLA_FORUM = {
}
export const ADMIN = {
+ CHALLENGE_URL: 'https://www.topcoder.com/challenges',
CONNECT_URL: 'https://connect.topcoder.com',
DIRECT_URL: 'https://www.topcoder.com/direct',
ONLINE_REVIEW_URL: 'https://software.topcoder.com/review',