Skip to content

Handling challenge api refactoring #749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 7 additions & 1 deletion config/constants/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
CHALLENGE_API_URL: `${DEV_API_HOSTNAME}/v5/challenges`,
CHALLENGE_TIMELINE_TEMPLATES_URL: `${DEV_API_HOSTNAME}/v5/timeline-templates`,
CHALLENGE_TYPES_URL: `${DEV_API_HOSTNAME}/v5/challenge-types`,
CHALLENGE_TRACKS_URL: `${DEV_API_HOSTNAME}/v5/challenge-tracks`,
CHALLENGE_PHASES_URL: `${DEV_API_HOSTNAME}/v5/challenge-phases`,
CHALLENGE_TIMELINES_URL: `${DEV_API_HOSTNAME}/v5/challenge-timelines`,
PROJECT_API_URL: `${DEV_API_HOSTNAME}/v5/projects`,
Expand All @@ -25,5 +26,10 @@ module.exports = {
ONLINE_REVIEW_URL: `https://software.${DOMAIN}`,
DEFAULT_TERM_UUID: 'ae6fc4ff-3bd1-4e3f-a987-cc60ab94b422', // Terms & Conditions of Use at TopCoder
DEFAULT_NDA_UUID: '7245bb7d-d7c9-45a0-9603-d5ff05af0977', // Appirio NDA v2.0
SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221'
SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221',
DEV_TRACK_ID: '9b6fc876-f4d9-4ccb-9dfd-419247628825',
DES_TRACK_ID: '5fa04185-041f-49a6-bfd1-fe82533cd6c8',
DS_TRACK_ID: 'c0f5d461-8219-4c14-878a-c3a3f356466d',
QA_TRACK_ID: '36e6a8d0-7e1e-4608-a673-64279d99c115',
SEGMENT_API_KEY: 'QBtLgV8vCiuRX1lDikbMjcoe9aCHkF6n'
}
8 changes: 7 additions & 1 deletion config/constants/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
CHALLENGE_API_URL: `${PROD_API_HOSTNAME}/v5/challenges`,
CHALLENGE_TIMELINE_TEMPLATES_URL: `${PROD_API_HOSTNAME}/v5/timeline-templates`,
CHALLENGE_TYPES_URL: `${PROD_API_HOSTNAME}/v5/challenge-types`,
CHALLENGE_TRACKS_URL: `${DEV_API_HOSTNAME}/v5/challenge-tracks`,
CHALLENGE_PHASES_URL: `${PROD_API_HOSTNAME}/v5/challenge-phases`,
CHALLENGE_TIMELINES_URL: `${PROD_API_HOSTNAME}/v5/challenge-timelines`,
PROJECT_API_URL: `${PROD_API_HOSTNAME}/v5/projects`,
Expand All @@ -25,5 +26,10 @@ module.exports = {
ONLINE_REVIEW_URL: `https://software.${DOMAIN}`,
DEFAULT_TERM_UUID: '5e217280-1413-4d4f-b183-454f348805ab', // Terms & Conditions of Use at TopCoder
DEFAULT_NDA_UUID: '05342dcb-3405-445e-95b2-8ea2a3834b0d', // Appirio NDA v2.0
SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221'
SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221',
DEV_TRACK_ID: '9b6fc876-f4d9-4ccb-9dfd-419247628825',
DES_TRACK_ID: '5fa04185-041f-49a6-bfd1-fe82533cd6c8',
DS_TRACK_ID: 'c0f5d461-8219-4c14-878a-c3a3f356466d',
QA_TRACK_ID: '36e6a8d0-7e1e-4608-a673-64279d99c115',
SEGMENT_API_KEY: 'QSQAW5BWmZfLoKFNRgNKaqHvLDLJoGqF'
}
14 changes: 13 additions & 1 deletion src/actions/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
fetchChallengeTerms,
fetchResources,
fetchResourceRoles,
fetchChallengeTimelines
fetchChallengeTimelines,
fetchChallengeTracks
} from '../services/challenges'
import {
LOAD_CHALLENGE_DETAILS_PENDING,
Expand Down Expand Up @@ -229,6 +230,17 @@ export function loadChallengeTypes () {
}
}

export function loadChallengeTracks () {
return async (dispatch) => {
const challengeTracks = await fetchChallengeTracks()
dispatch({
type: LOAD_CHALLENGE_METADATA_SUCCESS,
metadataKey: 'challengeTracks',
metadataValue: challengeTracks
})
}
}

export function loadChallengeTimelines () {
return async (dispatch) => {
const challengeTimelines = await fetchChallengeTimelines()
Expand Down
File renamed without changes
6 changes: 3 additions & 3 deletions src/components/ChallengeEditor/ChallengeName-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ const ChallengeNameField = ({ challenge, onUpdateInput }) => {
<>
<div className={styles.row}>
<div className={cn(styles.field, styles.col1)}>
<label htmlFor='challengeName'>Challenge Name <span>*</span> :</label>
<label htmlFor='challengeName'>Work Name <span>*</span> :</label>
</div>
<div className={cn(styles.field, styles.col2)}>
<input className={styles.challengeName} id='name' name='name' type='text' placeholder='Challenge Name' value={challenge.name} maxLength='200' required onChange={onUpdateInput} />
<input className={styles.challengeName} id='name' name='name' type='text' placeholder='Work Name' value={challenge.name} maxLength='200' required onChange={onUpdateInput} />
</div>
</div>
{ challenge.submitTriggered && !challenge.name && <div className={styles.row}>
<div className={cn(styles.field, styles.col1)} />
<div className={cn(styles.field, styles.col2, styles.error)}>
Name is required field
Work Name is required field
</div>
</div> }
</>
Expand Down
3 changes: 2 additions & 1 deletion src/components/ChallengeEditor/ChallengeView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Loader from '../../Loader'

const ChallengeView = ({ projectDetail, challenge, metadata, challengeResources, token, isLoading, challengeId }) => {
const selectedType = _.find(metadata.challengeTypes, { id: challenge.typeId })
const challengeTrack = _.find(metadata.challengeTracks, { id: challenge.trackId })

const [openAdvanceSettings, setOpenAdvanceSettings] = useState(false)

Expand Down Expand Up @@ -73,7 +74,7 @@ const ChallengeView = ({ projectDetail, challenge, metadata, challengeResources,
</div>
<div className={styles.col}>
<span className={styles.fieldTitle}>Track:</span>
<Track disabled type={challenge.track} isActive key={challenge.track} onUpdateOthers={() => {}} />
<Track disabled type={challengeTrack} isActive key={challenge.trackId} onUpdateOthers={() => {}} />
</div>
<div className={styles.col}>
<span><span className={styles.fieldTitle}>Type:</span> {selectedType ? selectedType.name : ''}</span>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ChallengeEditor/ReviewType-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const ReviewTypeField = ({ reviewers, challenge, onUpdateOthers, onUpdateSelect
<div>
<div className={styles.row}>
<div className={cn(styles.field, styles.col1)}>
<label htmlFor='reviewType'>Review Type <span>*</span> :</label>
<label htmlFor='reviewType'>Reviewer <span>*</span> :</label>
</div>
<div className={cn(styles.field, styles.col2)}>
<div className={styles.subGroup}>
Expand Down
5 changes: 1 addition & 4 deletions src/components/ChallengeEditor/TextEditor-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ class TextEditorField extends Component {
readOnly
} = this.props
const { addedNewPrivateDescription } = this.state
const challengeTrack = challenge.legacy
? challenge.legacy.track
: challenge.track
const challengeTagsFiltered = challengeTags.map(function (tag) {
return { id: tag.name, name: tag.name }
})
Expand Down Expand Up @@ -84,7 +81,7 @@ class TextEditorField extends Component {
onUpdateMultiSelect={onUpdateMultiSelect}
readOnly={readOnly}
/>
{challengeTrack && challengeTrack === CHALLENGE_TRACKS.DESIGN && (
{challenge.trackId === CHALLENGE_TRACKS.DESIGN && (
<React.Fragment>
<FinalDeliverablesField
challenge={challenge}
Expand Down
12 changes: 5 additions & 7 deletions src/components/ChallengeEditor/Track-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,31 @@ import _ from 'lodash'
import React from 'react'
import PropTypes from 'prop-types'
import styles from './Track-Field.module.scss'

import { CHALLENGE_TRACKS } from '../../../config/constants'
import Track from '../../Track'

const TrackField = ({ challenge, onUpdateOthers, disabled }) => {
const TrackField = ({ challenge, tracks, onUpdateOthers, disabled }) => {
const renderTracks = (track, currentTrack) => {
return (
<Track disabled={disabled} type={track} isActive={track === currentTrack} key={track} onUpdateOthers={onUpdateOthers} />
<Track disabled={disabled} type={track} isActive={track.id === currentTrack} key={track.id} onUpdateOthers={onUpdateOthers} />
)
}

return (
<>
<div className={styles.row}>
<div className={cn(styles.field, styles.col1)}>
<label htmlFor='track'>Track <span>*</span> :</label>
<label htmlFor='track'>Work Type <span>*</span> :</label>
</div>
<div className={cn(styles.field, styles.col2)}>
{
_.map(CHALLENGE_TRACKS, track => renderTracks(track, challenge.track))
_.map(tracks, track => renderTracks(track, challenge.trackId))
}
</div>
</div>
{ challenge.submitTriggered && !challenge.track && <div className={styles.row}>
<div className={cn(styles.field, styles.col1)} />
<div className={cn(styles.field, styles.col2, styles.error)}>
Track is required field
Work Type is required field
</div>
</div> }
</>
Expand Down
8 changes: 4 additions & 4 deletions src/components/ChallengeEditor/Type-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const TypeField = ({ types, onUpdateSelect, challenge, disabled }) => {
<>
<div className={styles.row}>
<div className={cn(styles.field, styles.col1)}>
<label htmlFor='type'>Type <span>*</span> :</label>
<label htmlFor='type'>Work Format <span>*</span> :</label>
</div>
<div className={cn(styles.field, styles.col2, { [styles.disabled]: disabled })}>
<Select
name='track'
options={_.filter(types, t => t.isActive && t.track === challenge.track)}
options={_.filter(types, t => t.isActive)}
value={challenge.typeId}
placeholder='Track Type'
placeholder='Work Format'
labelKey='name'
valueKey='id'
clearable={false}
Expand All @@ -29,7 +29,7 @@ const TypeField = ({ types, onUpdateSelect, challenge, disabled }) => {
{ challenge.submitTriggered && !challenge.typeId && <div className={styles.row}>
<div className={cn(styles.field, styles.col1)} />
<div className={cn(styles.field, styles.col2, styles.error)}>
Type is required field
Work Format is required field
</div>
</div> }
</>
Expand Down
27 changes: 13 additions & 14 deletions src/components/ChallengeEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ const theme = {

const getTitle = (isNew) => {
if (isNew) {
return 'Create New Challenge'
return 'Create New Work'
}

return 'Edit Challenge'
return 'Set-Up Work'
}

class ChallengeEditor extends Component {
Expand Down Expand Up @@ -508,8 +508,8 @@ class ChallengeEditor extends Component {
isValidChallenge () {
const { challenge } = this.state
if (this.props.isNew) {
const { name, track, typeId } = challenge
return !!name && !!track && !!typeId
const { name, trackId, typeId } = challenge
return !!name && !!trackId && !!typeId
}

const reviewType = challenge.reviewType ? challenge.reviewType.toLowerCase() : 'community'
Expand All @@ -523,7 +523,7 @@ class ChallengeEditor extends Component {
}

return !(Object.values(pick([
'track',
'trackId',
'typeId',
'name',
'description',
Expand Down Expand Up @@ -586,7 +586,7 @@ class ChallengeEditor extends Component {
const challenge = pick([
'phases',
'typeId',
'track',
'trackId',
'name',
'description',
'privateDescription',
Expand All @@ -599,8 +599,7 @@ class ChallengeEditor extends Component {
'prizeSets'
], this.state.challenge)
challenge.legacy = _.assign(this.state.challenge.legacy, {
reviewType: challenge.reviewType,
track: challenge.track
reviewType: challenge.reviewType
})
challenge.timelineTemplateId = _.get(this.getCurrentTemplate(), 'id')
challenge.projectId = this.props.projectId
Expand All @@ -618,7 +617,6 @@ class ChallengeEditor extends Component {
], p))
if (challenge.terms && challenge.terms.length === 0) delete challenge.terms
delete challenge.attachments
delete challenge.track
delete challenge.reviewType
return _.cloneDeep(challenge)
}
Expand All @@ -632,7 +630,7 @@ class ChallengeEditor extends Component {
async createNewChallenge () {
if (!this.props.isNew) return
const { metadata } = this.props
const { name, track, typeId } = this.state.challenge
const { name, trackId, typeId } = this.state.challenge
const { timelineTemplates } = metadata

// fallback template
Expand All @@ -646,9 +644,9 @@ class ChallengeEditor extends Component {
projectId: this.props.projectId,
name,
typeId,
trackId,
startDate: moment().add(1, 'days').format(),
legacy: {
track,
reviewType: 'community'
},
descriptionFormat: 'markdown',
Expand Down Expand Up @@ -996,7 +994,7 @@ class ChallengeEditor extends Component {
isNew && (
<div className={styles.buttonContainer}>
<div className={styles.button}>
<OutlineButton text={'Create Challenge'} type={'success'} submit />
<OutlineButton text={'Continue Set-Up'} type={'success'} submit />
</div>
</div>
)
Expand All @@ -1023,13 +1021,14 @@ class ChallengeEditor extends Component {
}
</React.Fragment>
const selectedType = _.find(metadata.challengeTypes, { id: challenge.typeId })
const challengeTrack = _.find(metadata.challengeTracks, { id: challenge.trackId })
const currentChallengeId = this.getCurrentChallengeId()
const showTimeline = false // disables the timeline for time being https://github.com/topcoder-platform/challenge-engine-ui/issues/706
const challengeForm = isNew
? (
<form name='challenge-new-form' noValidate autoComplete='off' onSubmit={this.createChallengeHandler}>
<div className={styles.newFormContainer}>
<TrackField challenge={challenge} onUpdateOthers={this.onUpdateOthers} />
<TrackField tracks={metadata.challengeTracks} challenge={challenge} onUpdateOthers={this.onUpdateOthers} />
<TypeField types={metadata.challengeTypes} onUpdateSelect={this.onUpdateSelect} challenge={challenge} />
<ChallengeNameField challenge={challenge} onUpdateInput={this.onUpdateInput} />
</div>
Expand All @@ -1050,7 +1049,7 @@ class ChallengeEditor extends Component {
</div>
<div className={styles.col}>
<span className={styles.fieldTitle}>Track:</span>
<Track disabled type={challenge.track} isActive key={challenge.track} onUpdateOthers={() => {}} />
<Track disabled type={challengeTrack} isActive key={challenge.trackId} onUpdateOthers={() => {}} />
</div>
<div className={styles.col}>
<span><span className={styles.fieldTitle}>Type:</span> {selectedType ? selectedType.name : ''}</span>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ChallengesComponent/ChallengeCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ class ChallengeCard extends React.Component {
<Link className={styles.col1} to={`/projects/${challenge.projectId}/challenges/${challenge.id}/view`}>
<div className={styles.name}>
<span className={styles.block}>{challenge.name}</span>
<ChallengeTag track={challenge.legacy && challenge.legacy.track} challengeType={challenge.type} />
<ChallengeTag track={challenge.trackId} challengeType={challenge.type} />
</div>
</Link>
<Link className={styles.col2} to={`/projects/${challenge.projectId}/challenges/${challenge.id}/view`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,3 @@
color: $white;
background-color: $light-blue;
}

.design {
color: $white;
background-color: $green;
}
2 changes: 1 addition & 1 deletion src/components/Sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Sidebar = ({
return (
<div className={styles.sidebar}>
<img src={TopcoderLogo} className={styles.logo} />
<div className={styles.title}>Challenge Editor</div>
<div className={styles.title}>Work Manager</div>
<Link to='/'>
<div className={cn(styles.homeLink, { [styles.active]: !projectId })} onClick={resetSidebarActiveParams}>
Active challenges
Expand Down
3 changes: 3 additions & 0 deletions src/components/Tag/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const stylizedSubTrack = (t, challengeTypes) => {
)
}

/**
* ***************** UNUSED **************************
*/
const Tag = ({ track, subTrack, value, challengeTypes, roleTag }) => {
const className = cn(styles.tag, {
[styles.dataScience]: track === CHALLENGE_TRACKS.DATA_SCIENCE,
Expand Down
23 changes: 4 additions & 19 deletions src/components/Track/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,19 @@ import React from 'react'
import PropTypes from 'prop-types'
import cn from 'classnames'
import ReactSVG from 'react-svg'
import { CHALLENGE_TRACKS } from '../../config/constants'
import styles from './Track.module.scss'

const assets = require.context('../../assets/images/tracks', false, /svg/)

const Track = ({ type, isActive, onUpdateOthers, disabled }) => {
const icon = `./${type.toLowerCase()}.svg`
const getName = (type) => {
switch (type.toUpperCase()) {
case CHALLENGE_TRACKS.DEVELOP:
return 'Development'
case CHALLENGE_TRACKS.DESIGN:
return 'Design'
case CHALLENGE_TRACKS.DATA_SCIENCE:
return 'Data Science'
case CHALLENGE_TRACKS.QA:
return CHALLENGE_TRACKS.QA
default:
return ''
}
}
const icon = `./${type.abbreviation.toLowerCase()}.svg`

return (
<div className={cn(styles.container, { [styles.active]: isActive, [styles.disabled]: disabled })} onClick={() => onUpdateOthers({ field: 'track', value: type })}>
<div className={cn(styles.container, { [styles.active]: isActive, [styles.disabled]: disabled })} onClick={() => onUpdateOthers({ field: 'trackId', value: type.id })}>
<div className={styles.icon}>
{ assets && assets.keys().includes(icon) ? <ReactSVG path={assets(`${icon}`)} /> : '' }
</div>
<span className={styles.name}>{getName(type)}</span>
<span className={styles.name}>{type.name}</span>
</div>
)
}
Expand All @@ -40,7 +25,7 @@ Track.defaultProps = {
}

Track.propTypes = {
type: PropTypes.string.isRequired,
type: PropTypes.object.isRequired,
isActive: PropTypes.bool,
disabled: PropTypes.bool,
onUpdateOthers: PropTypes.func.isRequired
Expand Down
Loading