diff --git a/config/constants/development.js b/config/constants/development.js index ad9b6b81..7043e5b0 100644 --- a/config/constants/development.js +++ b/config/constants/development.js @@ -24,7 +24,7 @@ module.exports = { CONNECT_APP_URL: `https://connect.${DOMAIN}`, DIRECT_PROJECT_URL: `https://www.${DOMAIN}/direct`, ONLINE_REVIEW_URL: `https://software.${DOMAIN}`, - DEFAULT_TERM_UUID: '64d6e249-d7a5-4591-8ff5-e872f8a051f9', // Terms & Conditions of Use at TopCoder + DEFAULT_TERM_UUID: '317cd8f9-d66c-4f2a-8774-63c612d99cd4', // Terms & Conditions of Use at TopCoder DEFAULT_NDA_UUID: 'e5811a7b-43d1-407a-a064-69e5015b4900', // NDA v3.0 SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221', DEV_TRACK_ID: '9b6fc876-f4d9-4ccb-9dfd-419247628825', diff --git a/src/actions/challenges.js b/src/actions/challenges.js index 99f487a9..eca362f6 100644 --- a/src/actions/challenges.js +++ b/src/actions/challenges.js @@ -258,10 +258,11 @@ export function partiallyUpdateChallengeDetails (challengeId, partialChallengeDe type: UPDATE_CHALLENGE_DETAILS_SUCCESS, challengeDetails: challenge }) - }).catch(() => { + }).catch((error) => { dispatch({ type: UPDATE_CHALLENGE_DETAILS_FAILURE }) + throw error }) } } diff --git a/src/components/ChallengeEditor/ReviewType-Field/index.js b/src/components/ChallengeEditor/ReviewType-Field/index.js index a5b8f323..283fbde5 100644 --- a/src/components/ChallengeEditor/ReviewType-Field/index.js +++ b/src/components/ChallengeEditor/ReviewType-Field/index.js @@ -3,11 +3,31 @@ import PropTypes from 'prop-types' import Select from '../../Select' import cn from 'classnames' import styles from './ReviewType-Field.module.scss' +import Tooltip from '../../Tooltip' +import { DES_TRACK_ID, REVIEW_TYPES, MESSAGE } from '../../../config/constants' const ReviewTypeField = ({ reviewers, challenge, onUpdateOthers, onUpdateSelect }) => { - const reviewType = challenge.reviewType ? challenge.reviewType.toLowerCase() : 'community' - const isCommunity = reviewType === 'community' - const isInternal = reviewType === 'internal' + const isDesignChallenge = challenge.trackId === DES_TRACK_ID + const defaultReviewType = isDesignChallenge ? REVIEW_TYPES.INTERNAL : REVIEW_TYPES.COMMUNITY + const reviewType = challenge.reviewType ? challenge.reviewType.toLowerCase() : defaultReviewType + const isCommunity = reviewType === REVIEW_TYPES.COMMUNITY + const isInternal = reviewType === REVIEW_TYPES.INTERNAL + const communityOption = (disabled) => (
+ e.target.checked && onUpdateOthers({ field: 'reviewType', value: 'community' })} + /> + +
) return (
@@ -17,21 +37,14 @@ const ReviewTypeField = ({ reviewers, challenge, onUpdateOthers, onUpdateSelect
-
- e.target.checked && onUpdateOthers({ field: 'reviewType', value: 'community' })} - /> - -
+ { isDesignChallenge && + + { communityOption(true) } + + } + { !isDesignChallenge && + communityOption() + }
diff --git a/src/components/ChallengeEditor/index.js b/src/components/ChallengeEditor/index.js index 0b945a38..66aa6cb6 100644 --- a/src/components/ChallengeEditor/index.js +++ b/src/components/ChallengeEditor/index.js @@ -18,7 +18,9 @@ import { SUBMITTER_ROLE_UUID, CREATE_FORUM_TYPE_IDS, MESSAGE, - COMMUNITY_APP_URL + COMMUNITY_APP_URL, + DES_TRACK_ID, + REVIEW_TYPES } from '../../config/constants' import { PrimaryButton, OutlineButton } from '../Buttons' import TrackField from './Track-Field' @@ -784,6 +786,7 @@ class ChallengeEditor extends Component { const { metadata, createChallenge } = this.props const { name, trackId, typeId } = this.state.challenge const { timelineTemplates } = metadata + const isDesignChallenge = trackId === DES_TRACK_ID // indicate that creating process has started this.setState({ isSaving: true }) @@ -802,7 +805,7 @@ class ChallengeEditor extends Component { trackId, startDate: moment().add(1, 'days').format(), legacy: { - reviewType: 'community' + reviewType: isDesignChallenge ? REVIEW_TYPES.INTERNAL : REVIEW_TYPES.COMMUNITY }, descriptionFormat: 'markdown', timelineTemplateId: defaultTemplate.id, diff --git a/src/components/ChallengesComponent/ChallengeCard/index.js b/src/components/ChallengesComponent/ChallengeCard/index.js index e97b7b6b..9da8123f 100644 --- a/src/components/ChallengesComponent/ChallengeCard/index.js +++ b/src/components/ChallengesComponent/ChallengeCard/index.js @@ -15,7 +15,6 @@ import ChallengeTag from '../ChallengeTag' import styles from './ChallengeCard.module.scss' import { getFormattedDuration, formatDate } from '../../../util/date' import { CHALLENGE_STATUS, COMMUNITY_APP_URL, DIRECT_PROJECT_URL, MESSAGE, ONLINE_REVIEW_URL } from '../../../config/constants' -import { patchChallenge } from '../../../services/challenges' import ConfirmationModal from '../../Modal/ConfirmationModal' import AlertModal from '../../Modal/AlertModal' import Tooltip from '../../Tooltip' @@ -201,12 +200,16 @@ class ChallengeCard extends React.Component { } async onLaunchChallenge () { + const { partiallyUpdateChallengeDetails } = this.props if (this.state.isSaving) return const { challenge } = this.props try { this.setState({ isSaving: true }) - const response = await patchChallenge(challenge.id, { status: 'Active' }) - this.setState({ isLaunch: true, isConfirm: response.id, isSaving: false }) + // call action to update the challenge with a new status + await partiallyUpdateChallengeDetails(challenge.id, { + status: 'Active' + }) + this.setState({ isLaunch: true, isConfirm: challenge.id, isSaving: false }) } catch (e) { const error = _.get(e, 'response.data.message', 'Unable to activate the challenge') this.setState({ isSaving: false, error }) @@ -287,7 +290,8 @@ ChallengeCard.propTypes = { challenge: PropTypes.object, shouldShowCurrentPhase: PropTypes.bool, showError: PropTypes.func, - reloadChallengeList: PropTypes.func + reloadChallengeList: PropTypes.func, + partiallyUpdateChallengeDetails: PropTypes.func.isRequired } export default withRouter(ChallengeCard) diff --git a/src/components/ChallengesComponent/ChallengeList/index.js b/src/components/ChallengesComponent/ChallengeList/index.js index 552050c0..fe33891d 100644 --- a/src/components/ChallengesComponent/ChallengeList/index.js +++ b/src/components/ChallengesComponent/ChallengeList/index.js @@ -101,7 +101,9 @@ class ChallengeList extends Component { status, page, perPage, - totalChallenges } = this.props + totalChallenges, + partiallyUpdateChallengeDetails + } = this.props if (warnMessage) { return } @@ -206,7 +208,13 @@ class ChallengeList extends Component { map(challenges, (c) => { return (
  • - +
  • ) }) @@ -247,7 +255,8 @@ ChallengeList.propTypes = { loadChallengesByPage: PropTypes.func.isRequired, page: PropTypes.number.isRequired, perPage: PropTypes.number.isRequired, - totalChallenges: PropTypes.number.isRequired + totalChallenges: PropTypes.number.isRequired, + partiallyUpdateChallengeDetails: PropTypes.func.isRequired } export default ChallengeList diff --git a/src/components/ChallengesComponent/index.js b/src/components/ChallengesComponent/index.js index 3042ff10..c173492f 100644 --- a/src/components/ChallengesComponent/index.js +++ b/src/components/ChallengesComponent/index.js @@ -25,7 +25,8 @@ const ChallengesComponent = ({ activeProjectId, page, perPage, - totalChallenges + totalChallenges, + partiallyUpdateChallengeDetails }) => { return ( @@ -84,6 +85,7 @@ const ChallengesComponent = ({ page={page} perPage={perPage} totalChallenges={totalChallenges} + partiallyUpdateChallengeDetails={partiallyUpdateChallengeDetails} /> )}
    @@ -106,7 +108,8 @@ ChallengesComponent.propTypes = { loadChallengesByPage: PropTypes.func.isRequired, page: PropTypes.number.isRequired, perPage: PropTypes.number.isRequired, - totalChallenges: PropTypes.number.isRequired + totalChallenges: PropTypes.number.isRequired, + partiallyUpdateChallengeDetails: PropTypes.func.isRequired } ChallengesComponent.defaultProps = { diff --git a/src/config/constants.js b/src/config/constants.js index 581b9eb0..ead24fe1 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -110,6 +110,11 @@ export const PRIZE_SETS_TYPE = { CHECKPOINT_PRIZES: 'checkpoint' } +export const REVIEW_TYPES = { + INTERNAL: 'internal', + COMMUNITY: 'community' +} + // List of subtracks that should be considered as Marathon Matches export const MARATHON_MATCH_SUBTRACKS = [ 'DEVELOP_MARATHON_MATCH' @@ -186,5 +191,6 @@ export const MESSAGE = { NO_LEGACY_CHALLENGE: 'Legacy challenge is not yet created', NO_TASK_ASSIGNEE: 'Task is not assigned yet', TASK_CLOSE_SUCCESS: 'Task closed successfully', - CHALLENGE_LAUNCH_SUCCESS: 'Challenge activated successfully' + CHALLENGE_LAUNCH_SUCCESS: 'Challenge activated successfully', + COMMUNITY_REVIEW_DISABLED: 'Community review is NOT available for design challenges' } diff --git a/src/containers/ChallengeEditor/index.js b/src/containers/ChallengeEditor/index.js index c4033093..ab0c4796 100644 --- a/src/containers/ChallengeEditor/index.js +++ b/src/containers/ChallengeEditor/index.js @@ -153,21 +153,25 @@ class ChallengeEditor extends Component { } async activateChallenge () { + const { partiallyUpdateChallengeDetails } = this.props if (this.state.isLaunching) return const { challengeDetails } = this.props try { this.setState({ isLaunching: true }) - const response = await patchChallenge(challengeDetails.id, { status: 'Active' }) + // call action to update the challenge status + const action = await partiallyUpdateChallengeDetails(challengeDetails.id, { + status: 'Active' + }) this.setState({ isLaunching: false, showLaunchModal: false, showSuccessModal: true, suceessMessage: MESSAGE.CHALLENGE_LAUNCH_SUCCESS, - challengeDetails: { ...challengeDetails, status: response.status } + challengeDetails: action.challengeDetails }) } catch (e) { const error = _.get(e, 'response.data.message', 'Unable to activate the challenge') - this.setState({ isLaunching: false, showLaunchModal: false, launchError: error }) + this.setState({ isLaunching: false, launchError: error }) } } diff --git a/src/containers/Challenges/index.js b/src/containers/Challenges/index.js index c24257bc..e0b9ef5d 100644 --- a/src/containers/Challenges/index.js +++ b/src/containers/Challenges/index.js @@ -10,7 +10,7 @@ import { DebounceInput } from 'react-debounce-input' import ChallengesComponent from '../../components/ChallengesComponent' import ProjectCard from '../../components/ProjectCard' import Loader from '../../components/Loader' -import { loadChallengesByPage } from '../../actions/challenges' +import { loadChallengesByPage, partiallyUpdateChallengeDetails } from '../../actions/challenges' import { loadProject } from '../../actions/projects' import { loadProjects, setActiveProject, resetSidebarActiveParams } from '../../actions/sidebar' import { @@ -85,7 +85,8 @@ class Challenges extends Component { page, perPage, totalChallenges, - setActiveProject + setActiveProject, + partiallyUpdateChallengeDetails } = this.props const { searchProjectName, onlyMyProjects } = this.state const projectInfo = _.find(projects, { id: activeProjectId }) || {} @@ -145,6 +146,7 @@ class Challenges extends Component { page={page} perPage={perPage} totalChallenges={totalChallenges} + partiallyUpdateChallengeDetails={partiallyUpdateChallengeDetails} /> } @@ -170,7 +172,8 @@ Challenges.propTypes = { perPage: PropTypes.number.isRequired, totalChallenges: PropTypes.number.isRequired, loadProjects: PropTypes.func.isRequired, - setActiveProject: PropTypes.func.isRequired + setActiveProject: PropTypes.func.isRequired, + partiallyUpdateChallengeDetails: PropTypes.func.isRequired } const mapStateToProps = ({ challenges, sidebar, projects }) => ({ @@ -187,7 +190,8 @@ const mapDispatchToProps = { resetSidebarActiveParams, loadProject, loadProjects, - setActiveProject + setActiveProject, + partiallyUpdateChallengeDetails } export default connect(mapStateToProps, mapDispatchToProps)(Challenges)