Skip to content

Commit 7c4bafc

Browse files
author
vikasrohit
authored
Merge pull request #842 from topcoder-platform/develop
Moving to latest and greatest to production
2 parents 2c1e593 + 065e812 commit 7c4bafc

File tree

15 files changed

+151
-100
lines changed

15 files changed

+151
-100
lines changed

src/actions/challenges.js

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ import {
2020
deleteResource as deleteResourceAPI
2121
} from '../services/challenges'
2222
import {
23-
LOAD_CHALLENGE_DETAILS_PENDING,
24-
LOAD_CHALLENGE_DETAILS_SUCCESS,
25-
LOAD_CHALLENGE_DETAILS_FAILURE,
26-
LOAD_CHALLENGE_MEMBERS_SUCCESS,
23+
LOAD_CHALLENGE_DETAILS,
2724
LOAD_CHALLENGE_METADATA_SUCCESS,
2825
LOAD_CHALLENGES_FAILURE,
2926
LOAD_CHALLENGES_PENDING,
@@ -45,7 +42,6 @@ import {
4542
CREATE_CHALLENGE_SUCCESS,
4643
CREATE_CHALLENGE_FAILURE
4744
} from '../config/constants'
48-
import { fetchProjectById } from '../services/projects'
4945
import { loadProject } from './projects'
5046

5147
/**
@@ -171,41 +167,19 @@ export function loadChallenges (projectId, status, filterChallengeName = null) {
171167
* Loads Challenge details
172168
*/
173169
export function loadChallengeDetails (projectId, challengeId) {
174-
return async (dispatch, getState) => {
175-
dispatch({
176-
type: LOAD_CHALLENGE_DETAILS_PENDING,
177-
challengeDetails: {}
178-
})
179-
170+
return (dispatch, getState) => {
180171
if (challengeId) {
181-
fetchChallenge(challengeId).then((challenge) => {
182-
dispatch({
183-
type: LOAD_CHALLENGE_DETAILS_SUCCESS,
184-
challengeDetails: challenge
185-
})
186-
loadProject(challenge.projectId)(dispatch, getState)
187-
}).catch(() => {
188-
dispatch({
189-
type: LOAD_CHALLENGE_DETAILS_FAILURE
172+
return dispatch({
173+
type: LOAD_CHALLENGE_DETAILS,
174+
payload: fetchChallenge(challengeId).then((challenge) => {
175+
// TODO remove this unncessary check, or better utilize the the case when given project id
176+
// does not match with challenge's project id
177+
if (challenge.projectId === projectId) {
178+
dispatch(loadProject(projectId))
179+
}
180+
return challenge
190181
})
191182
})
192-
} else {
193-
dispatch({
194-
type: LOAD_CHALLENGE_DETAILS_SUCCESS,
195-
challengeDetails: null
196-
})
197-
198-
if (projectId) {
199-
fetchProjectById(projectId).then((selectedProject) => {
200-
if (!selectedProject) return
201-
const members = selectedProject.members
202-
.filter(m => m.role === 'manager' || m.role === 'copilot')
203-
dispatch({
204-
type: LOAD_CHALLENGE_MEMBERS_SUCCESS,
205-
members
206-
})
207-
})
208-
}
209183
}
210184
}
211185
}
@@ -427,7 +401,7 @@ export function loadResources (challengeId) {
427401
})
428402

429403
if (challengeId) {
430-
fetchResources(challengeId).then((resources) => {
404+
return fetchResources(challengeId).then((resources) => {
431405
dispatch({
432406
type: LOAD_CHALLENGE_RESOURCES_SUCCESS,
433407
challengeResources: resources
@@ -457,6 +431,12 @@ export function loadResourceRoles () {
457431
}
458432
}
459433

434+
/**
435+
* Deletes a resource for the given challenge in given role
436+
* @param {UUID} challengeId id of the challenge for which resource is to be deleted
437+
* @param {UUID} roleId id of the role, the resource is in
438+
* @param {String} memberHandle handle of the resource
439+
*/
460440
export function deleteResource (challengeId, roleId, memberHandle) {
461441
const resource = {
462442
challengeId,
@@ -471,6 +451,12 @@ export function deleteResource (challengeId, roleId, memberHandle) {
471451
}
472452
}
473453

454+
/**
455+
* Creates a resource for the given challenge in given role
456+
* @param {UUID} challengeId id of the challenge for which resource is to be created
457+
* @param {UUID} roleId id of the role, the resource should be in
458+
* @param {String} memberHandle handle of the resource
459+
*/
474460
export function createResource (challengeId, roleId, memberHandle) {
475461
const resource = {
476462
challengeId,
@@ -485,6 +471,13 @@ export function createResource (challengeId, roleId, memberHandle) {
485471
}
486472
}
487473

474+
/**
475+
* Replaces the given resource in given role with new resource for the provided challenge
476+
* @param {UUID} challengeId id of the challenge for which resource is to be replaced
477+
* @param {UUID} roleId id of the role, the resource is in
478+
* @param {String} newMember handle of the new resource
479+
* @param {String} oldMember handle of the existing resource
480+
*/
488481
export function replaceResourceInRole (challengeId, roleId, newMember, oldMember) {
489482
return async (dispatch) => {
490483
if (newMember === oldMember) {

src/actions/projects.js

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,26 @@
11
import {
2-
LOAD_PROJECT_DETAILS_SUCCESS,
3-
LOAD_PROJECT_DETAILS_PENDING,
4-
LOAD_PROJECT_DETAILS_FAILURE,
5-
LOAD_CHALLENGE_MEMBERS_SUCCESS
2+
LOAD_CHALLENGE_MEMBERS_SUCCESS,
3+
LOAD_PROJECT_DETAILS
64
} from '../config/constants'
75
import { fetchProjectById } from '../services/projects'
86

97
/**
108
* Loads project details
119
*/
1210
export function loadProject (projectId) {
13-
return async (dispatch, getState) => {
14-
dispatch({
15-
type: LOAD_PROJECT_DETAILS_PENDING,
16-
projectDetail: {}
17-
})
18-
if (projectId) {
19-
fetchProjectById(projectId).then((project) => {
20-
dispatch({
21-
type: LOAD_PROJECT_DETAILS_SUCCESS,
22-
projectDetail: project
23-
})
24-
11+
return (dispatch, getState) => {
12+
return dispatch({
13+
type: LOAD_PROJECT_DETAILS,
14+
payload: fetchProjectById(projectId).then((project) => {
2515
if (project && project.members) {
2616
const members = project.members.filter(m => m.role === 'manager' || m.role === 'copilot')
2717
dispatch({
2818
type: LOAD_CHALLENGE_MEMBERS_SUCCESS,
2919
members
3020
})
3121
}
32-
}).catch(() => {
33-
dispatch({
34-
type: LOAD_PROJECT_DETAILS_FAILURE
35-
})
22+
return project
3623
})
37-
} else {
38-
dispatch({
39-
type: LOAD_PROJECT_DETAILS_SUCCESS,
40-
projectDetail: null
41-
})
42-
}
24+
})
4325
}
4426
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class FinalDeliverablesField extends Component {
3434
const { challenge, readOnly, removeFileType } = this.props
3535
const fileTypesMetadata = _.find(challenge.metadata, { name: 'fileTypes' })
3636
const fileTypes = (fileTypesMetadata && JSON.parse(fileTypesMetadata.value)) || []
37-
const isDuplicateValue = _.includes(fileTypes, this.state.newFileType.trim())
37+
const isDuplicateValue = _.includes(fileTypes.map((fileType) => fileType.toLowerCase()), this.state.newFileType.toLowerCase().trim())
3838

3939
return (
4040
<React.Fragment>

src/components/ChallengeEditor/index.js

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,18 @@ class ChallengeEditor extends Component {
113113
this.getTemplatePhases = this.getTemplatePhases.bind(this)
114114
this.getAvailableTimelineTemplates = this.getAvailableTimelineTemplates.bind(this)
115115
this.autoUpdateChallengeThrottled = _.throttle(this.autoUpdateChallenge.bind(this), 3000) // 3s
116-
this.resetChallengeData((newState, finish) => {
117-
this.state = {
118-
...this.state,
119-
...newState
120-
}
121-
if (finish) {
122-
finish()
123-
}
124-
})
125116
}
126117

127-
componentDidUpdate () {
118+
componentDidMount () {
128119
this.resetChallengeData(this.setState.bind(this))
129120
}
130121

131-
componentWillReceiveProps (nextProps) {
132-
// if member details weren't initially loaded and now they got loaded, then set them to the state
133-
if (!this.state.assignedMemberDetails && nextProps.assignedMemberDetails) {
134-
this.setState({ assignedMemberDetails: nextProps.assignedMemberDetails })
135-
}
122+
componentDidUpdate () {
123+
this.resetChallengeData(this.setState.bind(this))
136124
}
137125

138126
async resetChallengeData (setState = () => {}) {
139-
const { isNew, challengeDetails, metadata, attachments, challengeId } = this.props
127+
const { isNew, challengeDetails, metadata, attachments, challengeId, assignedMemberDetails } = this.props
140128
if (
141129
challengeDetails &&
142130
challengeDetails.id &&
@@ -160,10 +148,11 @@ class ChallengeEditor extends Component {
160148
}
161149
challengeData.copilot = copilot || copilotFromResources
162150
challengeData.reviewer = reviewer || reviewerFromResources
163-
const challengeDetail = { ...dropdowns['newChallenge'], ...challengeData }
151+
const challengeDetail = { ...challengeData }
164152
const isOpenAdvanceSettings = challengeDetail.groups.length > 0
165153
setState({
166154
challenge: challengeDetail,
155+
assignedMemberDetails,
167156
draftChallenge: { data: {
168157
..._.cloneDeep(challengeDetails),
169158
copilot: challengeData.copilot,
@@ -303,7 +292,7 @@ class ChallengeEditor extends Component {
303292
*/
304293
onUpdateAssignedMember (option) {
305294
const { challenge: oldChallenge } = this.state
306-
const newChallenge = { ...oldChallenge, task: { isAssigned: false, memberId: null, isTask: true } }
295+
const newChallenge = { ...oldChallenge }
307296
let assignedMemberDetails
308297

309298
if (option && option.value) {
@@ -716,7 +705,6 @@ class ChallengeEditor extends Component {
716705
'startDate',
717706
'terms',
718707
'prizeSets',
719-
'task',
720708
'winners'
721709
], this.state.challenge)
722710
challenge.legacy = _.assign(this.state.challenge.legacy, {

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
flex: 6;
8686
flex-wrap: nowrap;
8787
display: flex;
88+
text-decoration: none;
8889

8990
.name {
9091
flex:1;
@@ -102,6 +103,7 @@
102103
flex-direction: column;
103104
justify-content: center;
104105
align-items: center;
106+
text-decoration: none;
105107
}
106108

107109
.col3 {
@@ -180,6 +182,26 @@
180182
}
181183
}
182184
}
185+
186+
.createdAt {
187+
color: $gray;
188+
font-size: 10px;
189+
190+
&:hover {
191+
text-decoration: none;
192+
}
193+
}
194+
195+
.lastUpdated {
196+
text-decoration: none;
197+
.lastUpdatedAt {
198+
color: $tc-black;
199+
}
200+
.lastUpdatedBy {
201+
color: $gray;
202+
font-size: 10px;
203+
}
204+
}
183205
}
184206

185207
.activateButton {

src/components/ChallengesComponent/ChallengeCard/index.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { faFile, faUser } from '@fortawesome/free-solid-svg-icons'
1313
import ChallengeStatus from '../ChallengeStatus'
1414
import ChallengeTag from '../ChallengeTag'
1515
import styles from './ChallengeCard.module.scss'
16-
import { getFormattedDuration } from '../../../util/date'
16+
import { getFormattedDuration, formatDate } from '../../../util/date'
1717
import { CHALLENGE_STATUS, COMMUNITY_APP_URL, DIRECT_PROJECT_URL, ONLINE_REVIEW_URL } from '../../../config/constants'
1818
import { patchChallenge } from '../../../services/challenges'
1919
import ConfirmationModal from '../../Modal/ConfirmationModal'
@@ -172,6 +172,15 @@ const renderStatus = (status) => {
172172
}
173173
}
174174

175+
const renderLastUpdated = (challenge) => {
176+
return (
177+
<Link className={cn(styles.col2, styles.lastUpdated)} to={`/projects/${challenge.projectId}/challenges/${challenge.id}/view`}>
178+
<div className={styles.lastUpdatedAt}>{formatDate(challenge.updated)}</div>
179+
<div className={styles.lastUpdatedBy}>{challenge.updatedBy}</div>
180+
</Link>
181+
)
182+
}
183+
175184
class ChallengeCard extends React.Component {
176185
constructor (props) {
177186
super(props)
@@ -206,7 +215,7 @@ class ChallengeCard extends React.Component {
206215
try {
207216
this.setState({ isSaving: true })
208217
const response = await patchChallenge(challenge.id, { status: 'Active' })
209-
this.setState({ isLaunch: true, isConfirm: response.data.id, isSaving: false })
218+
this.setState({ isLaunch: true, isConfirm: response.id, isSaving: false })
210219
} catch (e) {
211220
const error = _.get(e, 'response.data.message', 'Unable to activate the challenge')
212221
this.setState({ isSaving: false, error })
@@ -248,8 +257,10 @@ class ChallengeCard extends React.Component {
248257
<div className={styles.name}>
249258
<span className={styles.block}>{challenge.name}</span>
250259
<ChallengeTag track={challenge.trackId} challengeType={challenge.type} />
260+
<span className={styles.createdAt}>{`Created by ${challenge.createdBy} at ${formatDate(challenge.created)}`}</span>
251261
</div>
252262
</Link>
263+
{renderLastUpdated(challenge)}
253264
<Link className={styles.col2} to={`/projects/${challenge.projectId}/challenges/${challenge.id}/view`}>
254265
{renderStatus(challenge.status.toUpperCase())}
255266
</Link>

src/components/ChallengesComponent/ChallengeList/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ class ChallengeList extends Component {
192192
challenges.length > 0 && (
193193
<div className={styles.header}>
194194
<div className={styles.col1}>Challenges Name</div>
195+
<div className={styles.col2}>Last Updated</div>
195196
<div className={styles.col2}>Status</div>
196197
{(selectedTab === 0) && (<div className={styles.col3}>Current phase</div>)}
197198
<div className={styles.col4}>&nbsp;</div>

src/components/Track/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import styles from './Track.module.scss'
77
const assets = require.context('../../assets/images/tracks', false, /svg/)
88

99
const Track = ({ type, isActive, onUpdateOthers, disabled }) => {
10-
const icon = `./${type.abbreviation.toLowerCase()}.svg`
10+
const icon = type ? `./${type.abbreviation.toLowerCase()}.svg` : ''
1111

1212
return (
1313
<div className={cn(styles.container, { [styles.active]: isActive, [styles.disabled]: disabled })} onClick={() => onUpdateOthers({ field: 'trackId', value: type.id })}>
1414
<div className={styles.icon}>
1515
{ assets && assets.keys().includes(icon) ? <ReactSVG path={assets(`${icon}`)} /> : '' }
1616
</div>
17-
<span className={styles.name}>{type.name}</span>
17+
<span className={styles.name}>{type ? type.name : 'Unkown'}</span>
1818
</div>
1919
)
2020
}

src/config/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const LOAD_CHALLENGES_SUCCESS = 'LOAD_CHALLENGES_SUCCESS'
3434
export const LOAD_CHALLENGES_PENDING = 'LOAD_CHALLENGES_PENDING'
3535
export const LOAD_CHALLENGES_FAILURE = 'LOAD_CHALLENGES_FAILURE'
3636

37+
export const LOAD_CHALLENGE_DETAILS = 'LOAD_CHALLENGE_DETAILS'
3738
export const LOAD_CHALLENGE_DETAILS_SUCCESS = 'LOAD_CHALLENGE_DETAILS_SUCCESS'
3839
export const LOAD_CHALLENGE_DETAILS_PENDING = 'LOAD_CHALLENGE_DETAILS_PENDING'
3940
export const LOAD_CHALLENGE_DETAILS_FAILURE = 'LOAD_CHALLENGE_DETAILS_FAILURE'
@@ -46,6 +47,7 @@ export const CREATE_CHALLENGE_SUCCESS = 'CREATE_CHALLENGE_SUCCESS'
4647
export const CREATE_CHALLENGE_PENDING = 'CREATE_CHALLENGE_PENDING'
4748
export const CREATE_CHALLENGE_FAILURE = 'CREATE_CHALLENGE_FAILURE'
4849

50+
export const LOAD_PROJECT_DETAILS = 'LOAD_PROJECT_DETAILS'
4951
export const LOAD_PROJECT_DETAILS_SUCCESS = 'LOAD_PROJECT_DETAILS_SUCCESS'
5052
export const LOAD_PROJECT_DETAILS_PENDING = 'LOAD_PROJECT_DETAILS_PENDING'
5153
export const LOAD_PROJECT_DETAILS_FAILURE = 'LOAD_PROJECT_DETAILS_FAILURE'
@@ -54,7 +56,7 @@ export const LOAD_CHALLENGE_SUBMISSIONS_SUCCESS = 'LOAD_CHALLENGE_SUBMISSIONS_SU
5456
export const LOAD_CHALLENGE_SUBMISSIONS_PENDING = 'LOAD_CHALLENGE_SUBMISSIONS_PENDING'
5557
export const LOAD_CHALLENGE_SUBMISSIONS_FAILURE = 'LOAD_CHALLENGE_SUBMISSIONS_FAILURE'
5658

57-
export const LOAD_CHALLENGE_MEMBERS_SUCCESS = 'LOAD_CHALLENGE_MEMBERS'
59+
export const LOAD_CHALLENGE_MEMBERS_SUCCESS = 'LOAD_CHALLENGE_MEMBERS_SUCCESS'
5860
export const LOAD_CHALLENGE_METADATA_SUCCESS = 'LOAD_CHALLENGE_METADATA_SUCCESS'
5961

6062
export const SAVE_AUTH_TOKEN = 'SAVE_AUTH_TOKEN'

0 commit comments

Comments
 (0)