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',