Skip to content

Commit 15ee107

Browse files
author
vikasrohit
authored
Merge pull request #1107 from topcoder-platform/develop
Prod release - 0.6.0
2 parents 50d1664 + 3276c95 commit 15ee107

File tree

13 files changed

+231
-71
lines changed

13 files changed

+231
-71
lines changed

src/actions/challenges.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,10 @@ export function createChallenge (challengeDetails) {
245245
type: CREATE_CHALLENGE_SUCCESS,
246246
challengeDetails: challenge
247247
})
248-
}).catch(() => {
248+
}).catch((e) => {
249249
dispatch({
250-
type: CREATE_CHALLENGE_FAILURE
250+
type: CREATE_CHALLENGE_FAILURE,
251+
error: e
251252
})
252253
})
253254
}

src/components/ChallengeEditor/AssignedMember-Field/AssignedMember-Field.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
display: flex;
4040
flex-direction: row;
4141
flex-wrap: wrap;
42+
min-width: 280px;
4243
}
4344
}
4445

src/components/ChallengeEditor/ChallengeEditor.module.scss

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
span {
2929
color: $tc-red;
3030
}
31+
3132
}
3233

3334
.textRequired {
@@ -211,6 +212,18 @@
211212
}
212213
}
213214
}
215+
216+
.templateLink {
217+
text-align: center;
218+
font-size: 14px;
219+
line-height: 29px;
220+
font-weight: 400;
221+
222+
a {
223+
font-weight: 400;
224+
font-size: 12px;
225+
}
226+
}
214227
}
215228
.group:last-of-type {
216229
margin-bottom: 0;
@@ -232,10 +245,13 @@
232245
}
233246

234247
.error {
235-
text-align: right;
236248
padding-right: 40px;
237249
padding-bottom: 20px;
238-
color: $tc-red
250+
color: $tc-red;
251+
252+
.errorMessage {
253+
font-size: 25px;
254+
}
239255
}
240256

241257
.actionButtons {
@@ -332,6 +348,7 @@
332348
line-height: 36px;
333349
margin-bottom: 30px;
334350
margin-top: 0;
351+
335352
}
336353

337354
span {

src/components/ChallengeEditor/ChallengePrizes-Field/index.js

Lines changed: 99 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import PrizeInput from '../../PrizeInput'
88
import styles from './ChallengePrizes-Field.module.scss'
99
import cn from 'classnames'
1010
import { PrimaryButton } from '../../Buttons'
11-
import { CHALLENGE_PRIZE_TYPE, VALIDATION_VALUE_TYPE, PRIZE_SETS_TYPE, CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES } from '../../../config/constants'
11+
import {
12+
CHALLENGE_PRIZE_TYPE,
13+
VALIDATION_VALUE_TYPE,
14+
PRIZE_SETS_TYPE,
15+
CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES
16+
} from '../../../config/constants'
1217
import { validateValue } from '../../../util/input-check'
1318

1419
class ChallengePrizesField extends Component {
@@ -26,7 +31,10 @@ class ChallengePrizesField extends Component {
2631

2732
addNewPrize () {
2833
const challengePrize = this.getChallengePrize()
29-
challengePrize.prizes = [...challengePrize.prizes, { type: CHALLENGE_PRIZE_TYPE.USD, value: 1 }]
34+
challengePrize.prizes = [
35+
...challengePrize.prizes,
36+
{ type: CHALLENGE_PRIZE_TYPE.USD, value: 1 }
37+
]
3038
this.onUpdateValue(challengePrize)
3139
}
3240

@@ -38,7 +46,10 @@ class ChallengePrizesField extends Component {
3846

3947
onUpdateInput (value, index) {
4048
const challengePrize = this.getChallengePrize()
41-
challengePrize.prizes[index].value = validateValue(value, VALIDATION_VALUE_TYPE.INTEGER)
49+
challengePrize.prizes[index].value = validateValue(
50+
value,
51+
VALIDATION_VALUE_TYPE.INTEGER
52+
)
4253
if (parseInt(challengePrize.prizes[index].value) > 1000000) {
4354
challengePrize.prizes[index].value = '1000000'
4455
}
@@ -48,71 +59,115 @@ class ChallengePrizesField extends Component {
4859
onUpdateValue (challengePrize) {
4960
const type = PRIZE_SETS_TYPE.CHALLENGE_PRIZES
5061
const { onUpdateOthers, challenge } = this.props
51-
const existingPrizes = challenge.prizeSets ? challenge.prizeSets.filter(p => p.type !== type) : []
62+
const existingPrizes = challenge.prizeSets
63+
? challenge.prizeSets.filter(p => p.type !== type)
64+
: []
5265

53-
onUpdateOthers({ field: 'prizeSets', value: [...existingPrizes, challengePrize] })
66+
onUpdateOthers({
67+
field: 'prizeSets',
68+
value: [...existingPrizes, challengePrize]
69+
})
5470
}
5571

5672
getChallengePrize () {
5773
const type = PRIZE_SETS_TYPE.CHALLENGE_PRIZES
58-
return (this.props.challenge.prizeSets && this.props.challenge.prizeSets.length && this.props.challenge.prizeSets.find(p => p.type === type)) || { type, prizes: [{ type: CHALLENGE_PRIZE_TYPE.USD, value: 0 }] }
74+
return (
75+
(this.props.challenge.prizeSets &&
76+
this.props.challenge.prizeSets.length &&
77+
this.props.challenge.prizeSets.find(p => p.type === type)) || {
78+
type,
79+
prizes: [{ type: CHALLENGE_PRIZE_TYPE.USD, value: 0 }]
80+
}
81+
)
5982
}
6083

6184
renderPrizes () {
6285
const { currentPrizeIndex } = this.state
6386
const { readOnly, challenge } = this.props
64-
const allowMultiplePrizes = _.includes(CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES, challenge.type)
65-
return _.map(this.getChallengePrize().prizes, (prize, index, { length }) => (
66-
<div key={`${index}-${prize.amount}-edit`}>
67-
<div className={styles.row}>
68-
<div className={cn(styles.field, styles.col1)}>
69-
<label htmlFor={`${index}-prize`}>Prize {allowMultiplePrizes ? index + 1 : ''} {!readOnly && (<span>*</span>)}:</label>
70-
</div>
71-
{readOnly ? (
72-
<span>${prize.value}</span>
73-
) : (<div className={cn(styles.field, styles.col2)}>
74-
<PrizeInput
75-
prize={prize}
76-
isFocus={index === currentPrizeIndex}
77-
onUpdateInput={this.onUpdateInput}
78-
index={index} activeIndex={currentPrizeIndex} />
79-
{
80-
index > 0 && (
81-
<div className={styles.icon} onClick={() => this.removePrize(index)}>
82-
<FontAwesomeIcon icon={faTrash} />
87+
const allowMultiplePrizes = _.includes(
88+
CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES,
89+
challenge.type
90+
)
91+
return _.map(
92+
this.getChallengePrize().prizes,
93+
(prize, index, { length }) => {
94+
let errMessage = ''
95+
if (prize.value === '') {
96+
errMessage = 'Prize amount is required field'
97+
} else if (+prize.value <= 0 || +prize.value > 1000000) {
98+
errMessage =
99+
'Prize amount must be more than 0 and no more than 1000000'
100+
} else if (index > 0) {
101+
const prePrize = this.getChallengePrize().prizes[index - 1]
102+
if (+prePrize.value < +prize.value) {
103+
errMessage =
104+
'Prize for the higher place cannot be bigger than for lower place'
105+
}
106+
}
107+
return (
108+
<div key={`${index}-${prize.amount}-edit`}>
109+
<div className={styles.row}>
110+
<div className={cn(styles.field, styles.col1)}>
111+
<label htmlFor={`${index}-prize`}>
112+
Prize {allowMultiplePrizes ? index + 1 : ''}{' '}
113+
{!readOnly && <span>*</span>}:
114+
</label>
115+
</div>
116+
{readOnly ? (
117+
<span>${prize.value}</span>
118+
) : (
119+
<div className={cn(styles.field, styles.col2)}>
120+
<PrizeInput
121+
prize={prize}
122+
isFocus={index === currentPrizeIndex}
123+
onUpdateInput={this.onUpdateInput}
124+
index={index}
125+
activeIndex={currentPrizeIndex}
126+
/>
127+
{index > 0 && (
128+
<div
129+
className={styles.icon}
130+
onClick={() => this.removePrize(index)}
131+
>
132+
<FontAwesomeIcon icon={faTrash} />
133+
</div>
134+
)}
83135
</div>
84-
)
85-
}
86-
</div>)}
87-
</div>
88-
{!readOnly && challenge.submitTriggered && (prize.value === '' || (+prize.value <= 0 || +prize.value > 1000000)) && (
89-
<div className={styles.row}>
90-
<div className={cn(styles.field, styles.col1)} />
91-
<div className={cn(styles.field, styles.col2, styles.error)}>
92-
{prize.value === ''
93-
? 'Prize amount is required field'
94-
: 'Prize amount must be more than 0 and no more than 1000000'}
136+
)}
95137
</div>
138+
{!readOnly && challenge.submitTriggered && errMessage && (
139+
<div className={styles.row}>
140+
<div className={cn(styles.field, styles.col1)} />
141+
<div className={cn(styles.field, styles.col2, styles.error)}>
142+
{errMessage}
143+
</div>
144+
</div>
145+
)}
96146
</div>
97-
)}
98-
</div>
99-
))
147+
)
148+
}
149+
)
100150
}
101151

102152
render () {
103153
const { readOnly, challenge } = this.props
104-
const allowMultiplePrizes = _.includes(CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES, challenge.type)
154+
const allowMultiplePrizes = _.includes(
155+
CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES,
156+
challenge.type
157+
)
105158
return (
106159
<div className={styles.container}>
107160
<div className={styles.row}>
108161
<div className={cn(styles.field, styles.col1)}>
109162
<label htmlFor={`challengePrizes`}>Challenge Prizes :</label>
110163
</div>
111164
</div>
112-
{ this.renderPrizes() }
113-
{!readOnly && allowMultiplePrizes && (<div className={styles.button} onClick={this.addNewPrize}>
114-
<PrimaryButton text={'Add New Prize'} type={'info'} />
115-
</div>)}
165+
{this.renderPrizes()}
166+
{!readOnly && allowMultiplePrizes && (
167+
<div className={styles.button} onClick={this.addNewPrize}>
168+
<PrimaryButton text={'Add New Prize'} type={'info'} />
169+
</div>
170+
)}
116171
</div>
117172
)
118173
}

src/components/ChallengeEditor/TextEditor-Field/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class TextEditorField extends Component {
6060
</div>)}
6161
{shouldShowPrivateDescription && showShowPrivateDescriptionField && (<div className={styles.title}>
6262
<span>Private specification</span>
63+
{!readOnly && (<div>
64+
<i>Access specification templates <a href='https://github.com/topcoder-platform-templates/specification-templates' target='_blank'>here</a></i>
65+
</div>)}
6366
<i>
6467
This text will only be visible to Topcoder members that have
6568
registered for this challenge

src/components/ChallengeEditor/index.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,14 +677,19 @@ class ChallengeEditor extends Component {
677677
return false
678678
}
679679

680-
return _.every(challengePrizes.prizes, (prize) => {
680+
return _.every(challengePrizes.prizes, (prize, index) => {
681681
if (prize.value === '') {
682682
return false
683683
}
684684
const prizeNumber = parseInt(prize.value)
685685
if (prizeNumber <= 0 || prizeNumber > 1000000) {
686686
return false
687687
}
688+
if (index > 0) {
689+
if (+prize.value > +challengePrizes.prizes[index - 1].value) {
690+
return false
691+
}
692+
}
688693
return true
689694
})
690695
}
@@ -1157,6 +1162,7 @@ class ChallengeEditor extends Component {
11571162
token,
11581163
removeAttachment,
11591164
failedToLoad,
1165+
errorMessage,
11601166
projectDetail,
11611167
attachments
11621168
} = this.props
@@ -1184,6 +1190,7 @@ class ChallengeEditor extends Component {
11841190
<div className={styles.group}>
11851191
<div className={styles.row}>
11861192
<div className={styles.error}>
1193+
{errorMessage && <div className={styles.errorMessage}>{`Error : ${errorMessage}`}</div>}
11871194
Please try again later and if the issue persists contact us at&nbsp;
11881195
11891196
&nbsp;to resolve the issue as soon as possible.
@@ -1478,6 +1485,9 @@ class ChallengeEditor extends Component {
14781485
</div>
14791486
<div className={styles.group}>
14801487
<div className={styles.title}>Public specification <span>*</span></div>
1488+
<div className={styles.templateLink}>
1489+
<i>Access specification templates <a href='https://github.com/topcoder-platform-templates/specification-templates' target='_blank'>here</a></i>
1490+
</div>
14811491
<TextEditorField
14821492
challengeTags={metadata.challengeTags}
14831493
challenge={challenge}
@@ -1554,6 +1564,7 @@ ChallengeEditor.propTypes = {
15541564
attachments: PropTypes.arrayOf(PropTypes.shape()),
15551565
token: PropTypes.string.isRequired,
15561566
failedToLoad: PropTypes.bool,
1567+
errorMessage: PropTypes.string,
15571568
history: PropTypes.any.isRequired,
15581569
assignedMemberDetails: PropTypes.shape(),
15591570
updateChallengeDetails: PropTypes.func.isRequired,

0 commit comments

Comments
 (0)