Skip to content
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
30 changes: 6 additions & 24 deletions src/actions/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ import {
UPLOAD_ATTACHMENT_FAILURE,
UPLOAD_ATTACHMENT_PENDING,
UPLOAD_ATTACHMENT_SUCCESS,
LOAD_CHALLENGE_RESOURCES_PENDING,
LOAD_CHALLENGE_RESOURCES_SUCCESS,
LOAD_CHALLENGE_RESOURCES_FAILURE,
CREATE_CHALLENGE_RESOURCE,
DELETE_CHALLENGE_RESOURCE,
REMOVE_ATTACHMENT,
Expand All @@ -40,7 +37,8 @@ import {
UPDATE_CHALLENGE_DETAILS_FAILURE,
CREATE_CHALLENGE_PENDING,
CREATE_CHALLENGE_SUCCESS,
CREATE_CHALLENGE_FAILURE
CREATE_CHALLENGE_FAILURE,
LOAD_CHALLENGE_RESOURCES
} from '../config/constants'
import { loadProject } from './projects'

Expand Down Expand Up @@ -396,27 +394,11 @@ export function loadChallengeTerms () {
}

export function loadResources (challengeId) {
return async (dispatch) => {
dispatch({
type: LOAD_CHALLENGE_RESOURCES_PENDING,
challengeResources: {}
})

return (dispatch, getState) => {
if (challengeId) {
return fetchResources(challengeId).then((resources) => {
dispatch({
type: LOAD_CHALLENGE_RESOURCES_SUCCESS,
challengeResources: resources
})
}).catch(() => {
dispatch({
type: LOAD_CHALLENGE_RESOURCES_FAILURE
})
})
} else {
dispatch({
type: LOAD_CHALLENGE_RESOURCES_SUCCESS,
challengeResources: null
return dispatch({
type: LOAD_CHALLENGE_RESOURCES,
payload: fetchResources(challengeId)
})
}
}
Expand Down
16 changes: 13 additions & 3 deletions src/components/ChallengeEditor/ChallengeView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ import PhaseInput from '../../PhaseInput'
import LegacyLinks from '../../LegacyLinks'
import AssignedMemberField from '../AssignedMember-Field'

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

Expand Down Expand Up @@ -64,7 +73,7 @@ const ChallengeView = ({ projectDetail, challenge, metadata, challengeResources,
</div>
<div className={styles.title}>View Details</div>
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsRight)}>
<PrimaryButton text={'Edit'} type={'info'} submit link={`./edit`} />
{ enableEdit && <PrimaryButton text={'Edit'} type={'info'} submit link={`./edit`} /> }
<PrimaryButton text={'Back'} type={'info'} submit link={`..`} />
</div>
<div className={styles.container}>
Expand Down Expand Up @@ -202,7 +211,8 @@ ChallengeView.propTypes = {
isLoading: PropTypes.bool.isRequired,
challengeId: PropTypes.string.isRequired,
challengeResources: PropTypes.arrayOf(PropTypes.object),
assignedMemberDetails: PropTypes.shape()
assignedMemberDetails: PropTypes.shape(),
enableEdit: PropTypes.bool
}

export default withRouter(ChallengeView)
1 change: 1 addition & 0 deletions src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const UPLOAD_ATTACHMENT_PENDING = 'UPLOAD_ATTACHMENT_PENDING'
export const UPLOAD_ATTACHMENT_FAILURE = 'UPLOAD_ATTACHMENT_FAILURE'
export const UPLOAD_ATTACHMENT_SUCCESS = 'UPLOAD_ATTACHMENT_SUCCESS'

export const LOAD_CHALLENGE_RESOURCES = 'LOAD_CHALLENGE_RESOURCES'
export const LOAD_CHALLENGE_RESOURCES_SUCCESS = 'LOAD_CHALLENGE_RESOURCES_SUCCESS'
export const LOAD_CHALLENGE_RESOURCES_PENDING = 'LOAD_CHALLENGE_RESOURCES_PENDING'
export const LOAD_CHALLENGE_RESOURCES_FAILURE = 'LOAD_CHALLENGE_RESOURCES_FAILURE'
Expand Down
7 changes: 7 additions & 0 deletions src/containers/ChallengeEditor/ChallengeEditor.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@import "../../styles/includes";


.errorContainer {
color: $red;
padding: 10px;
}
29 changes: 26 additions & 3 deletions src/containers/ChallengeEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { withRouter, Route } from 'react-router-dom'
import ChallengeEditorComponent from '../../components/ChallengeEditor'
import ChallengeViewComponent from '../../components/ChallengeEditor/ChallengeView'
import Loader from '../../components/Loader'
import styles from './ChallengeEditor.module.scss'

import {
loadTimelineTemplates,
Expand Down Expand Up @@ -113,10 +114,21 @@ class ChallengeEditor extends Component {
loadChallengeDetails(projectId, challengeId)
}

isEditable () {
const { hasProjectAccess, metadata: { resourceRoles }, challengeResources, loggedInUser } = this.props
if (!hasProjectAccess) {
return false
}
const userRoles = _.filter(challengeResources, cr => cr.memberId === `${loggedInUser.userId}`)
const userResourceRoles = _.filter(resourceRoles, rr => _.some(userRoles, ur => ur.roleId === rr.id))
return _.some(userResourceRoles, urr => urr.fullAccess && urr.isActive)
}

render () {
const {
match,
isLoading,
isProjectLoading,
challengeDetails,
challengeResources,
metadata,
Expand All @@ -132,6 +144,7 @@ class ChallengeEditor extends Component {
replaceResourceInRole
// members
} = this.props
if (isProjectLoading || isLoading) return <Loader />
const challengeId = _.get(match.params, 'challengeId', null)
if (challengeId && (!challengeDetails || !challengeDetails.id)) {
return (<Loader />)
Expand All @@ -144,6 +157,7 @@ class ChallengeEditor extends Component {
handle: submitters[0].memberHandle
}
}
const enableEdit = this.isEditable()
return <div>
<Route
exact
Expand Down Expand Up @@ -171,7 +185,8 @@ class ChallengeEditor extends Component {
/>
))
} />
<Route
{ !enableEdit && <div className={styles.errorContainer}>You don't have access to edit the challenge</div>}
{ enableEdit && <Route
exact
path={`${this.props.match.path}/edit`}
render={({ match }) => ((
Expand All @@ -196,6 +211,7 @@ class ChallengeEditor extends Component {
/>
))
} />
}
<Route
exact
path={`${this.props.match.path}/view`}
Expand All @@ -209,6 +225,7 @@ class ChallengeEditor extends Component {
token={token}
challengeId={challengeId}
assignedMemberDetails={assignedMemberDetails}
enableEdit={enableEdit}
/>
))
} />
Expand Down Expand Up @@ -237,6 +254,8 @@ ChallengeEditor.propTypes = {
loadResourceRoles: PropTypes.func,
challengeResources: PropTypes.arrayOf(PropTypes.object),
challengeDetails: PropTypes.object,
isProjectLoading: PropTypes.bool,
hasProjectAccess: PropTypes.bool,
projectDetail: PropTypes.object,
// history: PropTypes.object,
metadata: PropTypes.shape({
Expand All @@ -246,6 +265,7 @@ ChallengeEditor.propTypes = {
createAttachment: PropTypes.func,
attachments: PropTypes.arrayOf(PropTypes.shape()),
token: PropTypes.string,
loggedInUser: PropTypes.object,
removeAttachment: PropTypes.func,
failedToLoad: PropTypes.bool,
loadMemberDetails: PropTypes.func,
Expand All @@ -256,14 +276,17 @@ ChallengeEditor.propTypes = {
// members: PropTypes.arrayOf(PropTypes.shape())
}

const mapStateToProps = ({ projects: { projectDetail }, challenges: { challengeDetails, challengeResources, metadata, isLoading, attachments, failedToLoad }, auth: { token }, members: { members } }) => ({
const mapStateToProps = ({ projects, challenges: { challengeDetails, challengeResources, metadata, isLoading, attachments, failedToLoad }, auth: { token, user }, members: { members } }) => ({
challengeDetails,
projectDetail,
hasProjectAccess: projects.hasProjectAccess,
projectDetail: projects.projectDetail,
challengeResources,
metadata,
isLoading,
isProjectLoading: projects.isLoading,
attachments,
token,
loggedInUser: user,
failedToLoad
// members
})
Expand Down
2 changes: 1 addition & 1 deletion src/reducers/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default function (state = initialState, action) {
case LOAD_CHALLENGE_RESOURCES_SUCCESS:
return {
...state,
challengeResources: action.challengeResources,
challengeResources: action.payload,
isLoading: false,
failedToLoad: false
}
Expand Down
8 changes: 6 additions & 2 deletions src/reducers/projects.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* Reducer to process actions related to project
*/
import _ from 'lodash'
import {
LOAD_PROJECT_DETAILS_FAILURE,
LOAD_PROJECT_DETAILS_PENDING,
Expand All @@ -16,12 +17,15 @@ export default function (state = initialState, action) {
switch (action.type) {
case LOAD_PROJECT_DETAILS_PENDING:
return { ...state, isLoading: true }
case LOAD_PROJECT_DETAILS_FAILURE:
return { ...state, isLoading: false }
case LOAD_PROJECT_DETAILS_FAILURE: {
const status = _.get(action, 'payload.response.status', 500)
return { ...state, isLoading: false, hasProjectAccess: status !== 403 }
}
case LOAD_PROJECT_DETAILS_SUCCESS:
return {
...state,
projectDetail: action.payload,
hasProjectAccess: true,
isLoading: false
}
default:
Expand Down