Skip to content

Commit efd01df

Browse files
authored
Merge pull request #1095 from yoution/issue-1046
fix: issue #1046
2 parents e9c57a3 + 0225d7c commit efd01df

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

src/components/ChallengesComponent/ChallengeCard/index.js

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import styles from './ChallengeCard.module.scss'
1616
import { getFormattedDuration, formatDate } from '../../../util/date'
1717
import { CHALLENGE_STATUS, COMMUNITY_APP_URL, DIRECT_PROJECT_URL, MESSAGE, ONLINE_REVIEW_URL } from '../../../config/constants'
1818
import ConfirmationModal from '../../Modal/ConfirmationModal'
19+
import { checkChallengeEditPermission } from '../../../util/tc'
1920
import AlertModal from '../../Modal/AlertModal'
2021
import Tooltip from '../../Tooltip'
2122

@@ -28,6 +29,9 @@ const DRAFT_MSG = 'In Draft'
2829
const STALLED_TIME_LEFT_MSG = 'Challenge is currently on hold'
2930
const FF_TIME_LEFT_MSG = 'Winner is working on fixes'
3031

32+
const PERMISSION_DELETE_MESSAGE_ERROR =
33+
"You don't have permission to delete this challenge"
34+
3135
/**
3236
* Format the remaining time of a challenge phase
3337
* @param phase Challenge phase
@@ -187,7 +191,9 @@ class ChallengeCard extends React.Component {
187191
isConfirm: false,
188192
isLaunch: false,
189193
isDeleteLaunch: false,
190-
isSaving: false
194+
isSaving: false,
195+
isCheckChalengePermission: false,
196+
hasEditChallengePermission: false
191197
}
192198
this.onUpdateConfirm = this.onUpdateConfirm.bind(this)
193199
this.onUpdateLaunch = this.onUpdateLaunch.bind(this)
@@ -208,8 +214,19 @@ class ChallengeCard extends React.Component {
208214
}
209215

210216
deleteModalLaunch () {
217+
const { challenge } = this.props
211218
if (!this.state.isDeleteLaunch) {
212-
this.setState({ isDeleteLaunch: true })
219+
checkChallengeEditPermission(challenge.id).then(hasPermission => {
220+
this.setState({
221+
isCheckChalengePermission: false,
222+
hasEditChallengePermission: hasPermission
223+
})
224+
})
225+
this.setState({
226+
isDeleteLaunch: true,
227+
isCheckChalengePermission: true,
228+
hasEditChallengePermission: false
229+
})
213230
}
214231
}
215232

@@ -254,25 +271,32 @@ class ChallengeCard extends React.Component {
254271
}
255272

256273
render () {
257-
const { isLaunch, isConfirm, isSaving, isDeleteLaunch } = this.state
274+
const { isLaunch, isConfirm, isSaving, isDeleteLaunch, isCheckChalengePermission, hasEditChallengePermission } = this.state
258275
const { challenge, shouldShowCurrentPhase, reloadChallengeList } = this.props
259276
const { phaseMessage, endTime } = getPhaseInfo(challenge)
277+
const deleteMessage = isCheckChalengePermission
278+
? 'Checking permissions...'
279+
: `Do you want to delete "${challenge.name}"?`
280+
260281
return (
261282
<div className={styles.item}>
262-
{
263-
isDeleteLaunch && !isConfirm && (
264-
<ConfirmationModal
265-
title='Confirm Delete'
266-
message={`Do you want to delete "${challenge.name}"?`}
267-
theme={theme}
268-
isProcessing={isSaving}
269-
errorMessage={this.state.error}
270-
onCancel={this.resetModal}
271-
onConfirm={this.onDeleteChallenge}
272-
/>
273-
)
274-
}
275-
{ isLaunch && !isConfirm && (
283+
{isDeleteLaunch && !isConfirm && (
284+
<ConfirmationModal
285+
title='Confirm Delete'
286+
message={deleteMessage}
287+
theme={theme}
288+
isProcessing={isSaving}
289+
disableConfirmButton={!hasEditChallengePermission}
290+
errorMessage={
291+
!isCheckChalengePermission && !hasEditChallengePermission
292+
? PERMISSION_DELETE_MESSAGE_ERROR
293+
: this.state.error
294+
}
295+
onCancel={this.resetModal}
296+
onConfirm={this.onDeleteChallenge}
297+
/>
298+
)}
299+
{isLaunch && !isConfirm && (
276300
<ConfirmationModal
277301
title='Confirm Launch'
278302
message={`Do you want to launch "${challenge.name}"?`}

src/components/Modal/ConfirmationModal.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import styles from './ConfirmationModal.module.scss'
66
import OutlineButton from '../Buttons/OutlineButton'
77
import PrimaryButton from '../Buttons/PrimaryButton'
88

9-
const ConfirmationModal = ({ title, message, errorMessage, theme, isProcessing, onCancel, onConfirm }) => (
9+
const ConfirmationModal = ({ title, message, errorMessage, theme, isProcessing, onCancel, onConfirm, disableConfirmButton }) => (
1010
<Modal theme={theme} onCancel={onCancel}>
1111
<div className={styles.contentContainer}>
1212
<div className={styles.title}>{title}</div>
@@ -23,6 +23,7 @@ const ConfirmationModal = ({ title, message, errorMessage, theme, isProcessing,
2323
<div className={styles.button}>
2424
<PrimaryButton
2525
text={isProcessing ? 'Processing...' : 'Confirm'}
26+
disabled={disableConfirmButton}
2627
type={'info'}
2728
onClick={onConfirm}
2829
/>
@@ -39,6 +40,7 @@ ConfirmationModal.propTypes = {
3940
errorMessage: PropTypes.string,
4041
theme: PropTypes.shape(),
4142
isProcessing: PropTypes.bool,
43+
disableConfirmButton: PropTypes.bool,
4244
onCancel: PropTypes.func,
4345
onConfirm: PropTypes.func
4446
}

src/util/tc.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import { MARATHON_MATCH_SUBTRACKS, CHALLENGE_TRACKS, ALLOWED_USER_ROLES, ADMIN_ROLES, SUBMITTER_ROLE_UUID } from '../config/constants'
55
import _ from 'lodash'
66
import { decodeToken } from 'tc-auth-lib'
7+
import { fetchResources, fetchResourceRoles } from '../services/challenges'
8+
import store from '../config/store'
79

810
export const RATING_COLORS = [{
911
color: '#9D9FA0' /* Grey */,
@@ -77,3 +79,40 @@ export const getResourceRoleByName = (resourceRoles, name) => {
7779
return _.find(resourceRoles, { name }) || null
7880
}
7981
}
82+
83+
/**
84+
* check edit permission
85+
* @param {number} challengeId challenge Id
86+
*
87+
* @returns {boolean} hasPermission
88+
*/
89+
export const checkChallengeEditPermission = async (challengeId) => {
90+
const state = store.getState()
91+
const token = state.auth.token
92+
const loggedInUser = state.auth.user
93+
const hasProjectAccess = state.projects.hasProjectAccess
94+
95+
const isAdmin = checkAdmin(token)
96+
if (isAdmin) {
97+
return true
98+
}
99+
if (!hasProjectAccess) {
100+
return false
101+
}
102+
103+
return Promise.all([fetchResources(challengeId), fetchResourceRoles()]).then(
104+
([challengeResources, resourceRoles]) => {
105+
const userRoles = _.filter(
106+
challengeResources,
107+
cr => cr.memberId === `${loggedInUser.userId}`
108+
)
109+
const userResourceRoles = _.filter(resourceRoles, rr =>
110+
_.some(userRoles, ur => ur.roleId === rr.id)
111+
)
112+
return _.some(
113+
userResourceRoles,
114+
urr => urr.fullWriteAccess && urr.isActive
115+
)
116+
}
117+
)
118+
}

0 commit comments

Comments
 (0)