From 45e4e7704350edcde2b207822c8e3675cbbfd384 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Wed, 3 Dec 2025 22:12:35 +0100 Subject: [PATCH 01/10] fix: user should be able to add only one manual reviewer config per review phase --- .../ChallengeReviewer-Field/index.js | 85 ++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js index 218e6bf0..d19be78b 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js @@ -444,6 +444,42 @@ class ChallengeReviewerField extends Component { const isAIReviewer = this.isAIReviewer(defaultTrackReviewer) + // Prevent adding a second manual (member) reviewer for the same phase. + // If the default phase already has a manual reviewer, attempt to find another + // suitable review phase that does not yet have a manual reviewer and use it. + if (!isAIReviewer && defaultPhaseId) { + const existsManualForPhase = currentReviewers.some(r => (r.isMemberReview !== false) && (r.phaseId === defaultPhaseId)) + if (existsManualForPhase) { + const possibleAlternatePhase = (challenge.phases || []).find(p => { + const rawName = p.name ? p.name : '' + const phaseName = rawName.toLowerCase() + const phaseWithoutHyphens = phaseName.replace(/[-\s]/g, '') + const acceptedPhases = ['review', 'screening', 'checkpointscreening', 'approval', 'postmortem'] + const isSubmissionPhase = phaseName.includes('submission') + const acceptable = acceptedPhases.includes(phaseWithoutHyphens) && !isSubmissionPhase + + if (!acceptable) return false + + const phaseId = p.phaseId || p.id + const used = currentReviewers.some(r => (r.isMemberReview !== false) && (r.phaseId === phaseId)) + return !used + }) + + if (possibleAlternatePhase) { + defaultPhaseId = possibleAlternatePhase.phaseId || possibleAlternatePhase.id + // clear any prior transient error + if (this.state.error) this.setState({ error: null }) + } else { + const phase = (challenge.phases || []).find(p => (p.id === defaultPhaseId) || (p.phaseId === defaultPhaseId)) + const phaseName = phase ? (phase.name || defaultPhaseId) : defaultPhaseId + this.setState({ + error: `A manual reviewer configuration already exists for phase '${phaseName}'` + }) + return + } + } + } + // For AI reviewers, get scorecardId from the workflow if available let scorecardId = '' if (isAIReviewer) { @@ -482,6 +518,11 @@ class ChallengeReviewerField extends Component { newReviewer.memberReviewerCount = (defaultReviewer && defaultReviewer.memberReviewerCount) || 1 } + // Clear any prior transient error when add succeeds + if (this.state.error) { + this.setState({ error: null }) + } + const updatedReviewers = currentReviewers.concat([newReviewer]) onUpdateReviewers({ field: 'reviewers', value: updatedReviewers }) } @@ -513,6 +554,21 @@ class ChallengeReviewerField extends Component { // Special handling for phase and count changes if (field === 'phaseId') { + // Before changing phase, ensure we're not creating a duplicate manual reviewer for the target phase + const targetPhaseId = value + const isCurrentMember = (updatedReviewers[index] && (updatedReviewers[index].isMemberReview !== false)) + if (isCurrentMember) { + const conflict = (currentReviewers || []).some((r, i) => i !== index && (r.isMemberReview !== false) && (r.phaseId === targetPhaseId)) + if (conflict) { + const phase = (challenge.phases || []).find(p => (p.id === targetPhaseId) || (p.phaseId === targetPhaseId)) + const phaseName = phase ? (phase.name || targetPhaseId) : targetPhaseId + this.setState({ + error: `Cannot move manual reviewer to phase '${phaseName}' because a manual reviewer configuration already exists for that phase.` + }) + return + } + } + this.handlePhaseChangeWithReassign(index, value) // update payment based on default reviewer @@ -632,6 +688,21 @@ class ChallengeReviewerField extends Component { const currentReviewers = challenge.reviewers || [] const updatedReviewers = currentReviewers.slice() + // Block switching an AI reviewer to a member reviewer if another manual reviewer exists for same phase + if (!isAI) { + const existingReviewer = currentReviewers[index] || {} + const phaseId = existingReviewer.phaseId + const conflict = currentReviewers.some((r, i) => i !== index && (r.isMemberReview !== false) && (r.phaseId === phaseId)) + if (conflict) { + const phase = (challenge.phases || []).find(p => (p.id === phaseId) || (p.phaseId === phaseId)) + const phaseName = phase ? (phase.name || phaseId) : phaseId + this.setState({ + error: `Cannot switch to Member Reviewer: a manual reviewer configuration already exists for phase '${phaseName}'. Increase "Number of Reviewers" on the existing configuration instead.` + }) + return + } + } + // Update reviewer type by setting/clearing aiWorkflowId const currentReviewer = updatedReviewers[index] @@ -674,6 +745,11 @@ class ChallengeReviewerField extends Component { this.handleToggleShouldOpen(index, true) } + // Clear any transient error when successful change is applied + if (this.state.error) { + this.setState({ error: null }) + } + onUpdateReviewers({ field: 'reviewers', value: updatedReviewers }) }} > @@ -772,10 +848,10 @@ class ChallengeReviewerField extends Component { const isPostMortemPhase = norm === 'postmortem' const isCurrentlySelected = reviewer.phaseId && ((phase.id === reviewer.phaseId) || (phase.phaseId === reviewer.phaseId)) && !isSubmissionPhase - // Collect phases already assigned to other reviewers (excluding current reviewer) + // Collect phases already assigned to other manual (member) reviewers (excluding current reviewer) const assignedPhaseIds = new Set( (challenge.reviewers || []) - .filter((r, i) => i !== index) + .filter((r, i) => i !== index && (r.isMemberReview !== false)) .map(r => r.phaseId) .filter(id => id !== undefined && id !== null) ) @@ -1051,6 +1127,11 @@ class ChallengeReviewerField extends Component { /> )} + {error && !isLoading && ( +
+ {error} +
+ )} From 45fbca220137bb9fb2582a556d0a0daf0cee388e Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Wed, 3 Dec 2025 22:14:45 +0100 Subject: [PATCH 02/10] fix: user should be able to add only one manual reviewer config per review phase --- src/components/ChallengeEditor/ChallengeReviewer-Field/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js index d19be78b..8df7d303 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js @@ -467,7 +467,6 @@ class ChallengeReviewerField extends Component { if (possibleAlternatePhase) { defaultPhaseId = possibleAlternatePhase.phaseId || possibleAlternatePhase.id - // clear any prior transient error if (this.state.error) this.setState({ error: null }) } else { const phase = (challenge.phases || []).find(p => (p.id === defaultPhaseId) || (p.phaseId === defaultPhaseId)) From 22182429f3a4d17ca78acb4d44fe0958195e20d4 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Wed, 3 Dec 2025 22:17:00 +0100 Subject: [PATCH 03/10] fix: user should be able to add only one manual reviewer config per review phase --- .../ChallengeReviewer-Field.module.scss | 4 ++++ .../ChallengeEditor/ChallengeReviewer-Field/index.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/ChallengeReviewer-Field.module.scss b/src/components/ChallengeEditor/ChallengeReviewer-Field/ChallengeReviewer-Field.module.scss index ca2cf854..268b520e 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/ChallengeReviewer-Field.module.scss +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/ChallengeReviewer-Field.module.scss @@ -39,6 +39,10 @@ flex-direction: column; width: 600px; } + + .fieldError { + margin-top: 12px; + } } } diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js index 8df7d303..288d4d1f 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js @@ -1127,7 +1127,7 @@ class ChallengeReviewerField extends Component { )} {error && !isLoading && ( -
+
{error}
)} From 64c952545e70589637384c5387bf89740e49226d Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Thu, 4 Dec 2025 15:54:15 +0100 Subject: [PATCH 04/10] fix: show the duplicate reviewer config error on saving --- .../ChallengeReviewer-Field/index.js | 35 ---------------- src/components/ChallengeEditor/index.js | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js index 288d4d1f..5fbafd29 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/index.js @@ -444,41 +444,6 @@ class ChallengeReviewerField extends Component { const isAIReviewer = this.isAIReviewer(defaultTrackReviewer) - // Prevent adding a second manual (member) reviewer for the same phase. - // If the default phase already has a manual reviewer, attempt to find another - // suitable review phase that does not yet have a manual reviewer and use it. - if (!isAIReviewer && defaultPhaseId) { - const existsManualForPhase = currentReviewers.some(r => (r.isMemberReview !== false) && (r.phaseId === defaultPhaseId)) - if (existsManualForPhase) { - const possibleAlternatePhase = (challenge.phases || []).find(p => { - const rawName = p.name ? p.name : '' - const phaseName = rawName.toLowerCase() - const phaseWithoutHyphens = phaseName.replace(/[-\s]/g, '') - const acceptedPhases = ['review', 'screening', 'checkpointscreening', 'approval', 'postmortem'] - const isSubmissionPhase = phaseName.includes('submission') - const acceptable = acceptedPhases.includes(phaseWithoutHyphens) && !isSubmissionPhase - - if (!acceptable) return false - - const phaseId = p.phaseId || p.id - const used = currentReviewers.some(r => (r.isMemberReview !== false) && (r.phaseId === phaseId)) - return !used - }) - - if (possibleAlternatePhase) { - defaultPhaseId = possibleAlternatePhase.phaseId || possibleAlternatePhase.id - if (this.state.error) this.setState({ error: null }) - } else { - const phase = (challenge.phases || []).find(p => (p.id === defaultPhaseId) || (p.phaseId === defaultPhaseId)) - const phaseName = phase ? (phase.name || defaultPhaseId) : defaultPhaseId - this.setState({ - error: `A manual reviewer configuration already exists for phase '${phaseName}'` - }) - return - } - } - } - // For AI reviewers, get scorecardId from the workflow if available let scorecardId = '' if (isAIReviewer) { diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index da51eb04..73fe1f46 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -897,11 +897,52 @@ class ChallengeEditor extends Component { return !(isRequiredMissing || _.isEmpty(this.state.currentTemplate)) } + // Return array of phase names that have more than one manual (member) reviewer configured. + // If none, returns empty array. + getDuplicateManualReviewerPhases () { + const { challenge } = this.state + const reviewers = (challenge && challenge.reviewers) || [] + const phases = (challenge && challenge.phases) || [] + + const counts = {} + reviewers.forEach(r => { + // count only manual (member) reviewers; AI reviewers have isMemberReview === false + if (r && (r.isMemberReview !== false) && r.phaseId) { + const pid = String(r.phaseId) + counts[pid] = (counts[pid] || 0) + 1 + } + }) + + const duplicatedPhaseIds = Object.keys(counts).filter(pid => counts[pid] > 1) + if (duplicatedPhaseIds.length === 0) return [] + + return duplicatedPhaseIds.map(pid => { + const p = phases.find(ph => String(ph.phaseId || ph.id) === pid) + return p ? (p.name || pid) : pid + }) + } + validateChallenge () { + // First run the existing validations if (this.isValidChallenge()) { + // Additional validation: block saving draft if there are duplicate manual reviewer configs per phase + const duplicates = this.getDuplicateManualReviewerPhases() + if (duplicates && duplicates.length > 0) { + const message = `Duplicate manual reviewer configuration found for phase${duplicates.length > 1 ? 's' : ''}: ${duplicates.join(', ')}. Only one manual reviewer configuration is allowed per phase.` + // Surface the message to the top-level error so the UI shows it and prevent saving + this.setState({ hasValidationErrors: true, error: message }) + return false + } + + // clear any previous error related to this validation + if (this.state.error) { + this.setState({ error: null }) + } this.setState({ hasValidationErrors: false }) return true } + + // If base validation failed, mark submitTriggered so fields show their validation errors this.setState(prevState => ({ ...prevState, challenge: { From 060554c73cd037d9176406365280a3d370b3a2f9 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Thu, 4 Dec 2025 15:56:54 +0100 Subject: [PATCH 05/10] fix: show the duplicate reviewer config error on saving --- src/components/ChallengeEditor/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index 73fe1f46..7a318537 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -906,7 +906,6 @@ class ChallengeEditor extends Component { const counts = {} reviewers.forEach(r => { - // count only manual (member) reviewers; AI reviewers have isMemberReview === false if (r && (r.isMemberReview !== false) && r.phaseId) { const pid = String(r.phaseId) counts[pid] = (counts[pid] || 0) + 1 @@ -923,18 +922,15 @@ class ChallengeEditor extends Component { } validateChallenge () { - // First run the existing validations if (this.isValidChallenge()) { // Additional validation: block saving draft if there are duplicate manual reviewer configs per phase const duplicates = this.getDuplicateManualReviewerPhases() if (duplicates && duplicates.length > 0) { const message = `Duplicate manual reviewer configuration found for phase${duplicates.length > 1 ? 's' : ''}: ${duplicates.join(', ')}. Only one manual reviewer configuration is allowed per phase.` - // Surface the message to the top-level error so the UI shows it and prevent saving this.setState({ hasValidationErrors: true, error: message }) return false } - // clear any previous error related to this validation if (this.state.error) { this.setState({ error: null }) } @@ -942,7 +938,6 @@ class ChallengeEditor extends Component { return true } - // If base validation failed, mark submitTriggered so fields show their validation errors this.setState(prevState => ({ ...prevState, challenge: { From a72fcab0c316feab83a90f61f6908562e957c7eb Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Thu, 4 Dec 2025 16:43:27 +0100 Subject: [PATCH 06/10] fix: show the duplicate reviewer config error on saving --- src/components/ChallengeEditor/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index 7a318537..6516403f 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -926,7 +926,7 @@ class ChallengeEditor extends Component { // Additional validation: block saving draft if there are duplicate manual reviewer configs per phase const duplicates = this.getDuplicateManualReviewerPhases() if (duplicates && duplicates.length > 0) { - const message = `Duplicate manual reviewer configuration found for phase${duplicates.length > 1 ? 's' : ''}: ${duplicates.join(', ')}. Only one manual reviewer configuration is allowed per phase.` + const message = `Duplicate manual reviewer configuration found for phase(s): ${duplicates.join(', ')}. Only one manual reviewer configuration is allowed per phase.` this.setState({ hasValidationErrors: true, error: message }) return false } From 02c6bc245a595a2750da35bf337339260ae96f3d Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Mon, 8 Dec 2025 14:54:54 +1100 Subject: [PATCH 07/10] Surface the dashboard checkbox in more places to make setup easier and editable if it's missed during challenge creation --- .../ChallengeEditor/ChallengeView/index.js | 35 ++++++-- src/components/ChallengeEditor/index.js | 82 +++++++++---------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/components/ChallengeEditor/ChallengeView/index.js b/src/components/ChallengeEditor/ChallengeView/index.js index c5681f6c..ee500aaa 100644 --- a/src/components/ChallengeEditor/ChallengeView/index.js +++ b/src/components/ChallengeEditor/ChallengeView/index.js @@ -23,6 +23,9 @@ import { PHASE_PRODUCT_CHALLENGE_ID_FIELD, MULTI_ROUND_CHALLENGE_TEMPLATE_ID, DS_TRACK_ID, + DEV_TRACK_ID, + MARATHON_TYPE_ID, + CHALLENGE_TYPE_ID, COMMUNITY_APP_URL } from '../../../config/constants' import PhaseInput from '../../PhaseInput' @@ -94,11 +97,33 @@ const ChallengeView = ({ const isTask = _.get(challenge, 'task.isTask', false) const phases = _.get(challenge, 'phases', []) const showCheckpointPrizes = _.get(challenge, 'timelineTemplateId') === MULTI_ROUND_CHALLENGE_TEMPLATE_ID - const isDataScience = challenge.trackId === DS_TRACK_ID const useDashboardData = _.find(challenge.metadata, { name: 'show_data_dashboard' }) const useDashboard = useDashboardData ? (_.isString(useDashboardData.value) && useDashboardData.value === 'true') || (_.isBoolean(useDashboardData.value) && useDashboardData.value) : false + const showDashBoard = (() => { + const isSupportedTrack = challenge.trackId === DS_TRACK_ID || challenge.trackId === DEV_TRACK_ID + const isSupportedType = challenge.typeId === MARATHON_TYPE_ID || challenge.typeId === CHALLENGE_TYPE_ID + + return (isSupportedTrack && isSupportedType) || Boolean(useDashboardData) + })() + const dashboardToggle = showDashBoard && ( +
+
+ +
+
+ +
+
+ ) return (
@@ -138,13 +163,6 @@ const ChallengeView = ({
- {isDataScience && ( -
-
- Show data dashboard: {useDashboard ? 'Yes' : 'No'} -
-
- )} {isTask && } {openAdvanceSettings && ( <> + {dashboardToggle}
diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index da51eb04..30ac82d8 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -148,6 +148,7 @@ class ChallengeEditor extends Component { this.onSaveChallenge = this.onSaveChallenge.bind(this) this.getCurrentTemplate = this.getCurrentTemplate.bind(this) this.onUpdateMetadata = this.onUpdateMetadata.bind(this) + this.shouldShowDashboardSetting = this.shouldShowDashboardSetting.bind(this) this.getTemplatePhases = this.getTemplatePhases.bind(this) this.getAvailableTimelineTemplates = this.getAvailableTimelineTemplates.bind(this) this.autoUpdateChallengeThrottled = _.throttle(this.validateAndAutoUpdateChallenge.bind(this), 3000) // 3s @@ -669,6 +670,22 @@ class ChallengeEditor extends Component { this.setState({ challenge: newChallenge }) } + /** + * Determines when the data dashboard toggle should be shown. + * + * @param {Object} challenge the challenge data to evaluate + */ + shouldShowDashboardSetting (challenge = {}) { + const trackId = _.get(challenge, 'trackId') + const typeId = _.get(challenge, 'typeId') + const metadata = _.get(challenge, 'metadata', []) + const hasDashboardMetadata = _.some(metadata, { name: 'show_data_dashboard' }) + const isSupportedTrack = trackId === DS_TRACK_ID || trackId === DEV_TRACK_ID + const isSupportedType = typeId === MARATHON_TYPE_ID || typeId === CHALLENGE_TYPE_ID + + return (isSupportedTrack && isSupportedType) || hasDashboardMetadata + } + /** * Remove Phase from challenge Phases list * @param index @@ -1095,11 +1112,7 @@ class ChallengeEditor extends Component { const { challenge: { name, trackId, typeId, milestoneId, roundType, challengeType, metadata: challengeMetadata } } = this.state const { timelineTemplates } = metadata const isDesignChallenge = trackId === DES_TRACK_ID - const isDataScience = trackId === DS_TRACK_ID - const isChallengeType = typeId === CHALLENGE_TYPE_ID - const isDevChallenge = trackId === DEV_TRACK_ID - const isMM = typeId === MARATHON_TYPE_ID - const showDashBoard = (isDataScience && isChallengeType) || (isDevChallenge && isMM) || (isDevChallenge && isChallengeType) + const showDashBoard = this.shouldShowDashboardSetting({ trackId, typeId, metadata: challengeMetadata }) // indicate that creating process has started this.setState({ isSaving: true }) @@ -1754,18 +1767,33 @@ class ChallengeEditor extends Component { const showTimeline = false // disables the timeline for time being https://github.com/topcoder-platform/challenge-engine-ui/issues/706 const copilotResources = metadata.members || challengeResources const isDesignChallenge = challenge.trackId === DES_TRACK_ID - const isDevChallenge = challenge.trackId === DEV_TRACK_ID - const isMM = challenge.typeId === MARATHON_TYPE_ID const isChallengeType = challenge.typeId === CHALLENGE_TYPE_ID const showRoundType = isDesignChallenge && isChallengeType const showCheckpointPrizes = challenge.timelineTemplateId === MULTI_ROUND_CHALLENGE_TEMPLATE_ID - const showDashBoard = (challenge.trackId === DS_TRACK_ID && isChallengeType) || (isDevChallenge && isMM) || (isDevChallenge && isChallengeType) const useDashboardData = _.find(challenge.metadata, { name: 'show_data_dashboard' }) + const showDashBoard = this.shouldShowDashboardSetting(challenge) const useDashboard = useDashboardData ? (_.isString(useDashboardData.value) && useDashboardData.value === 'true') || (_.isBoolean(useDashboardData.value) && useDashboardData.value) : false + const dashboardToggle = showDashBoard && ( +
+
+ +
+
+ this.onUpdateMetadata('show_data_dashboard', e.target.checked)} + /> +
+
+ ) + const workTypes = getDomainTypes(challenge.trackId) let filteredTypes = metadata.challengeTypes.filter(type => workTypes.includes(type.abbreviation)) @@ -1792,24 +1820,9 @@ class ChallengeEditor extends Component { ) } - + { - showDashBoard && ( -
-
- -
-
- this.onUpdateMetadata('show_data_dashboard', e.target.checked)} - /> -
-
- ) + dashboardToggle } {projectDetail.version === 'v4' && } {useTask && ()} @@ -1841,24 +1854,6 @@ class ChallengeEditor extends Component {
- { - showDashBoard && ( -
-
- -
-
- this.onUpdateMetadata('show_data_dashboard', e.target.checked)} - /> -
-
- ) - } {isTask && ( {isOpenAdvanceSettings && ( + {dashboardToggle} {/* remove terms field and use default term */} {false && ()} From 6b33f0ebbfc2acca05e42e8cade15fcc3b2b469f Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Mon, 8 Dec 2025 15:46:46 +1100 Subject: [PATCH 08/10] Lint --- pnpm-lock.yaml | 12 ++++++++++-- src/components/ChallengeEditor/index.js | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31d2c028..f55e361a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -342,8 +342,8 @@ importers: specifier: ^3.3.4 version: 3.3.4(webpack@5.102.0) tc-auth-lib: - specifier: topcoder-platform/tc-auth-lib#1.0.4 - version: '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/68fdc22464810c51b703a33e529cdbd6d09437de' + specifier: topcoder-platform/tc-auth-lib#v2.0 + version: '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/56996006ee5918b3e77fc5a8ab005ae738b4de12' terser: specifier: ^5.31.0 version: 5.44.0 @@ -1518,6 +1518,10 @@ packages: resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} + '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/56996006ee5918b3e77fc5a8ab005ae738b4de12': + resolution: {tarball: https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/56996006ee5918b3e77fc5a8ab005ae738b4de12} + version: 1.0.2 + '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/68fdc22464810c51b703a33e529cdbd6d09437de': resolution: {tarball: https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/68fdc22464810c51b703a33e529cdbd6d09437de} version: 1.0.2 @@ -10189,6 +10193,10 @@ snapshots: '@tootallnate/once@1.1.2': {} + '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/56996006ee5918b3e77fc5a8ab005ae738b4de12': + dependencies: + lodash: 4.17.21 + '@topcoder-platform/tc-auth-lib@https://codeload.github.com/topcoder-platform/tc-auth-lib/tar.gz/68fdc22464810c51b703a33e529cdbd6d09437de': dependencies: lodash: 4.17.21 diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index bb6b6320..e81ae6ba 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -1856,7 +1856,7 @@ class ChallengeEditor extends Component { ) } - + { dashboardToggle } From cb975b1550110ae38433eeb10a864b7714cfa9f8 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 9 Dec 2025 12:24:58 +1100 Subject: [PATCH 09/10] Fix to not show the data dashboard flag when challenge type ID is selected --- src/components/ChallengeEditor/index.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index e81ae6ba..77576847 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -676,14 +676,13 @@ class ChallengeEditor extends Component { * @param {Object} challenge the challenge data to evaluate */ shouldShowDashboardSetting (challenge = {}) { - const trackId = _.get(challenge, 'trackId') - const typeId = _.get(challenge, 'typeId') - const metadata = _.get(challenge, 'metadata', []) - const hasDashboardMetadata = _.some(metadata, { name: 'show_data_dashboard' }) - const isSupportedTrack = trackId === DS_TRACK_ID || trackId === DEV_TRACK_ID - const isSupportedType = typeId === MARATHON_TYPE_ID || typeId === CHALLENGE_TYPE_ID - - return (isSupportedTrack && isSupportedType) || hasDashboardMetadata + const trackId = _.get(challenge, 'trackId') + const typeId = _.get(challenge, 'typeId') + const metadata = _.get(challenge, 'metadata', []) + const hasDashboardMetadata = _.some(metadata, { name: 'show_data_dashboard' }) + const isMarathonMatch = typeId === MARATHON_TYPE_ID + + return isMarathonMatch || hasDashboardMetadata } /** From 15eb792f700c04a06183c48dc25305bd1beff2ce Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 9 Dec 2025 12:29:56 +1100 Subject: [PATCH 10/10] Lint --- src/components/ChallengeEditor/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index 77576847..f5c764ca 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -25,7 +25,7 @@ import { MILESTONE_STATUS, PHASE_PRODUCT_CHALLENGE_ID_FIELD, QA_TRACK_ID, DESIGN_CHALLENGE_TYPES, ROUND_TYPES, - MULTI_ROUND_CHALLENGE_TEMPLATE_ID, DS_TRACK_ID, + MULTI_ROUND_CHALLENGE_TEMPLATE_ID, CHALLENGE_STATUS, SKILLS_OPTIONAL_BILLING_ACCOUNT_IDS } from '../../config/constants' @@ -676,10 +676,9 @@ class ChallengeEditor extends Component { * @param {Object} challenge the challenge data to evaluate */ shouldShowDashboardSetting (challenge = {}) { - const trackId = _.get(challenge, 'trackId') - const typeId = _.get(challenge, 'typeId') - const metadata = _.get(challenge, 'metadata', []) - const hasDashboardMetadata = _.some(metadata, { name: 'show_data_dashboard' }) + const typeId = _.get(challenge, 'typeId') + const metadata = _.get(challenge, 'metadata', []) + const hasDashboardMetadata = _.some(metadata, { name: 'show_data_dashboard' }) const isMarathonMatch = typeId === MARATHON_TYPE_ID return isMarathonMatch || hasDashboardMetadata