Skip to content

Commit 27e2c6e

Browse files
committed
Merge branch 'develop' into issue-917
2 parents 0e8c3e3 + 9cfe023 commit 27e2c6e

File tree

15 files changed

+390
-154
lines changed

15 files changed

+390
-154
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ npm-debug.log*
2424
yarn-debug.log*
2525
yarn-error.log*
2626

27-
*.env
27+
*.env
28+
29+
*.vscode

config/constants/development.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = {
2525
DIRECT_PROJECT_URL: `https://www.${DOMAIN}/direct`,
2626
ONLINE_REVIEW_URL: `https://software.${DOMAIN}`,
2727
DEFAULT_TERM_UUID: '64d6e249-d7a5-4591-8ff5-e872f8a051f9', // Terms & Conditions of Use at TopCoder
28-
DEFAULT_NDA_UUID: '77f558c1-56fb-427c-b974-61ea0a060ca7', // Appirio NDA v2.0
28+
DEFAULT_NDA_UUID: 'e5811a7b-43d1-407a-a064-69e5015b4900', // NDA v3.0
2929
SUBMITTER_ROLE_UUID: '732339e7-8e30-49d7-9198-cccf9451e221',
3030
DEV_TRACK_ID: '9b6fc876-f4d9-4ccb-9dfd-419247628825',
3131
DES_TRACK_ID: '5fa04185-041f-49a6-bfd1-fe82533cd6c8',

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"sass-loader": "7.1.0",
9191
"simplemde": "^1.11.2",
9292
"style-loader": "0.23.0",
93-
"tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.1",
93+
"tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.3",
9494
"terser": "^3.16.1",
9595
"terser-webpack-plugin": "1.1.0",
9696
"topcoder-healthcheck-dropin": "^1.0.3",

src/components/Buttons/PrimaryButton/PrimaryButton.module.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414
border: none;
1515
padding: 0 20px;
1616

17+
// don't underline if button is done as a link
18+
&:hover {
19+
text-decoration: none;
20+
}
21+
22+
// hide outline for buttons and links
23+
&:focus,
24+
&:active,
25+
&:visited {
26+
outline: none;
27+
}
28+
1729
span {
1830
color: $white;
1931
}

src/components/ChallengeEditor/ChallengeView/ChallengeView.module.scss

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,15 @@
244244

245245
.actionButtonsRight {
246246
right: 20px;
247-
248-
button:not(:last-child),
247+
248+
.button:not(:last-child),
249249
a:not(:last-child) {
250250
margin-right: 20px;
251251
}
252+
253+
button {
254+
white-space: nowrap;
255+
}
252256
}
253257

254258
.button {

src/components/ChallengeEditor/ChallengeView/index.js

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import Loader from '../../Loader'
2020
import PhaseInput from '../../PhaseInput'
2121
import LegacyLinks from '../../LegacyLinks'
2222
import AssignedMemberField from '../AssignedMember-Field'
23+
import { getResourceRoleByName } from '../../../util/tc'
24+
import Tooltip from '../../Tooltip'
25+
import { MESSAGE } from '../../../config/constants'
2326

2427
const ChallengeView = ({
2528
projectDetail,
@@ -31,19 +34,17 @@ const ChallengeView = ({
3134
isLoading,
3235
challengeId,
3336
assignedMemberDetails,
34-
enableEdit }) => {
37+
enableEdit,
38+
onLaunchChallenge,
39+
onCloseTask }) => {
3540
const selectedType = _.find(metadata.challengeTypes, { id: challenge.typeId })
3641
const challengeTrack = _.find(metadata.challengeTracks, { id: challenge.trackId })
3742

3843
const [openAdvanceSettings, setOpenAdvanceSettings] = useState(false)
3944

40-
const getResourceRoleByName = (name) => {
41-
const { resourceRoles } = metadata
42-
return resourceRoles ? resourceRoles.find(role => role.name === name) : null
43-
}
44-
4545
const getResourceFromProps = (name) => {
46-
const role = getResourceRoleByName(name)
46+
const { resourceRoles } = metadata
47+
const role = getResourceRoleByName(resourceRoles, name)
4748
return challengeResources && role && challengeResources.find(resource => resource.roleId === role.id)
4849
}
4950

@@ -74,6 +75,34 @@ const ChallengeView = ({
7475
</div>
7576
<div className={styles.title}>View Details</div>
7677
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsRight)}>
78+
{
79+
challenge.status === 'Draft' && (
80+
<div className={styles.button}>
81+
{challenge.legacyId ? (
82+
<PrimaryButton text={'Launch'} type={'info'} onClick={onLaunchChallenge} />
83+
) : (
84+
<Tooltip content={MESSAGE.NO_LEGACY_CHALLENGE}>
85+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
86+
<PrimaryButton text={'Launch'} type={'disabled'} />
87+
</Tooltip>
88+
)}
89+
</div>
90+
)
91+
}
92+
{
93+
isTask && challenge.status === 'Active' && (
94+
<div className={styles.button}>
95+
{ assignedMemberDetails ? (
96+
<PrimaryButton text={'Close Task'} type={'danger'} onClick={onCloseTask} />
97+
) : (
98+
<Tooltip content={MESSAGE.NO_TASK_ASSIGNEE}>
99+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
100+
<PrimaryButton text={'Close Task'} type={'disabled'} />
101+
</Tooltip>
102+
)}
103+
</div>
104+
)
105+
}
77106
{ enableEdit && <PrimaryButton text={'Edit'} type={'info'} submit link={`./edit`} /> }
78107
<PrimaryButton text={'Back'} type={'info'} submit link={`..`} />
79108
</div>
@@ -222,7 +251,9 @@ ChallengeView.propTypes = {
222251
challengeId: PropTypes.string.isRequired,
223252
challengeResources: PropTypes.arrayOf(PropTypes.object),
224253
assignedMemberDetails: PropTypes.shape(),
225-
enableEdit: PropTypes.bool
254+
enableEdit: PropTypes.bool,
255+
onLaunchChallenge: PropTypes.func,
256+
onCloseTask: PropTypes.func
226257
}
227258

228259
export default withRouter(ChallengeView)

src/components/ChallengeEditor/index.js

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
DEFAULT_TERM_UUID,
1717
DEFAULT_NDA_UUID,
1818
SUBMITTER_ROLE_UUID,
19-
CREATE_FORUM_TYPE_IDS
19+
CREATE_FORUM_TYPE_IDS,
20+
MESSAGE
2021
} from '../../config/constants'
2122
import { PrimaryButton, OutlineButton } from '../Buttons'
2223
import TrackField from './Track-Field'
@@ -44,6 +45,8 @@ import AlertModal from '../Modal/AlertModal'
4445
import PhaseInput from '../PhaseInput'
4546
import LegacyLinks from '../LegacyLinks'
4647
import AssignedMemberField from './AssignedMember-Field'
48+
import Tooltip from '../Tooltip'
49+
import { getResourceRoleByName } from '../../util/tc'
4750

4851
const theme = {
4952
container: styles.modalContainer
@@ -113,6 +116,7 @@ class ChallengeEditor extends Component {
113116
this.getTemplatePhases = this.getTemplatePhases.bind(this)
114117
this.getAvailableTimelineTemplates = this.getAvailableTimelineTemplates.bind(this)
115118
this.autoUpdateChallengeThrottled = _.throttle(this.autoUpdateChallenge.bind(this), 3000) // 3s
119+
this.updateResource = this.updateResource.bind(this)
116120
}
117121

118122
componentDidMount () {
@@ -193,22 +197,25 @@ class ChallengeEditor extends Component {
193197
* Close task when user confirm it
194198
*/
195199
onCloseTask () {
196-
const { challenge: oldChallenge, assignedMemberDetails } = this.state
197-
198-
// set assigned user as the only one winner
199-
const newChallenge = {
200-
...oldChallenge,
201-
winners: [{
202-
userId: assignedMemberDetails.userId,
203-
handle: assignedMemberDetails.handle,
204-
placement: 1
205-
}]
206-
}
200+
// before marking challenge as complete, save all the changes user might have made
201+
this.updateAllChallengeInfo(this.state.challenge.status, () => {
202+
const { challenge: oldChallenge, assignedMemberDetails } = this.state
203+
204+
// set assigned user as the only one winner
205+
const newChallenge = {
206+
...oldChallenge,
207+
winners: [{
208+
userId: assignedMemberDetails.userId,
209+
handle: assignedMemberDetails.handle,
210+
placement: 1
211+
}]
212+
}
207213

208-
this.setState({
209-
challenge: newChallenge
210-
}, () => {
211-
this.updateAllChallengeInfo('Completed')
214+
this.setState({
215+
challenge: newChallenge
216+
}, () => {
217+
this.updateAllChallengeInfo('Completed')
218+
})
212219
})
213220
}
214221

@@ -629,15 +636,24 @@ class ChallengeEditor extends Component {
629636
return false
630637
}
631638

632-
return !(Object.values(pick([
639+
const requiredFields = [
633640
'trackId',
634641
'typeId',
635642
'name',
636643
'description',
637644
'tags',
638645
'prizeSets'
639-
], challenge)).filter(v => !v.length).length ||
640-
_.isEmpty(this.state.currentTemplate))
646+
]
647+
let isRequiredMissing = false
648+
649+
requiredFields.forEach((key) => {
650+
const value = challenge[key]
651+
652+
// this check works for string and array values
653+
isRequiredMissing = isRequiredMissing || !value || !value.length
654+
})
655+
656+
return !(isRequiredMissing || _.isEmpty(this.state.currentTemplate))
641657
}
642658

643659
validateChallenge () {
@@ -939,13 +955,9 @@ class ChallengeEditor extends Component {
939955
this.updateAllChallengeInfo(this.state.challenge.status)
940956
}
941957

942-
getResourceRoleByName (name) {
943-
const { resourceRoles } = this.props.metadata
944-
return resourceRoles ? resourceRoles.find(role => role.name === name) : null
945-
}
946-
947958
async updateResource (challengeId, name, value, prevValue) {
948-
const resourceRole = this.getResourceRoleByName(name)
959+
const { resourceRoles } = this.props.metadata
960+
const resourceRole = getResourceRoleByName(resourceRoles, name)
949961
const roleId = resourceRole.id
950962
await this.props.replaceResourceInRole(challengeId, roleId, value, prevValue)
951963
}
@@ -966,8 +978,8 @@ class ChallengeEditor extends Component {
966978
}
967979

968980
getResourceFromProps (name) {
969-
const { challengeResources } = this.props
970-
const role = this.getResourceRoleByName(name)
981+
const { challengeResources, metadata: { resourceRoles } } = this.props
982+
const role = getResourceRoleByName(resourceRoles, name)
971983
return challengeResources && role && challengeResources.find(resource => resource.roleId === role.id)
972984
}
973985

@@ -1175,9 +1187,18 @@ class ChallengeEditor extends Component {
11751187
<div className={styles.button}>
11761188
<PrimaryButton text={'Save Draft'} type={'info'} onClick={this.createDraftHandler} />
11771189
</div>
1178-
{ isDraft && <div className={styles.button}>
1179-
<PrimaryButton text={'Launch as Active'} type={'info'} onClick={this.toggleLaunch} />
1180-
</div>}
1190+
{isDraft && (
1191+
<div className={styles.button}>
1192+
{challenge.legacyId ? (
1193+
<PrimaryButton text={'Launch as Active'} type={'info'} onClick={this.toggleLaunch} />
1194+
) : (
1195+
<Tooltip content={MESSAGE.NO_LEGACY_CHALLENGE}>
1196+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
1197+
<PrimaryButton text={'Launch as Active'} type={'disabled'} />
1198+
</Tooltip>
1199+
)}
1200+
</div>
1201+
)}
11811202
</div>}
11821203
{!isLoading && isActive && <div className={styles.buttonContainer}>
11831204
{/* <div className={styles.button}>

src/components/ChallengesComponent/ChallengeCard/ChallengeCard.module.scss

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
text-decoration-line: underline;
5050
}
5151

52+
span.link,
53+
span.link:hover,
54+
span.link:visited {
55+
color: $inactive;
56+
cursor: default;
57+
}
58+
5259
&.onlyOne {
5360
justify-content: center;
5461
}
@@ -160,6 +167,13 @@
160167
text-decoration-line: underline;
161168
}
162169

170+
span.link,
171+
span.link:hover,
172+
span.link:visited {
173+
color: $inactive;
174+
cursor: default;
175+
}
176+
163177
&.onlyOne {
164178
justify-content: center;
165179
}
@@ -171,14 +185,19 @@
171185
height: 100%;
172186
justify-content: center;
173187

174-
span {
188+
span.linkDivider {
175189
margin: 0 5px;
176190
}
177191

178192
.linkGroupLeftBottom {
179-
a {
193+
a,
194+
span {
180195
font-size: 12px;
181196
}
197+
198+
span.linkDivider {
199+
font-size: 16px;
200+
}
182201
}
183202
}
184203
}
@@ -227,6 +246,15 @@
227246
align-items: center;
228247
color: $status-green;
229248
}
249+
250+
&.activateButtonDisabled {
251+
border-color: $inactive;
252+
cursor: default;
253+
254+
> span {
255+
color: $inactive;
256+
}
257+
}
230258
}
231259

232260
.icon {

0 commit comments

Comments
 (0)