@@ -319,7 +218,7 @@ class SubmissionsComponent extends React.Component {
const isBugHunt = _.includes(tags, 'Bug Hunt')
// copy colorStyle from registrants to submissions
- _.forEach(sortedSubmissions, s => {
+ _.forEach(submissions, s => {
if (s.registrant && s.registrant.colorStyle && !s.colorStyle) {
const { colorStyle } = s.registrant
/* eslint-disable no-param-reassign */
@@ -344,7 +243,7 @@ class SubmissionsComponent extends React.Component {
ROUND 2 (FINAL) SUBMISSIONS
- {sortedSubmissions.map(renderSubmission)}
+ {submissions.map(renderSubmission)}
{checkpoints.length > 0 && (
@@ -388,117 +287,20 @@ class SubmissionsComponent extends React.Component {
{!isF2F && !isBugHunt && (
-
+ Rating
|
)}
-
+ Username
|
-
+ Email
|
-
+ Submission Date
|
-
+ Initial / Final Score
|
|
- {sortedSubmissions.map(s => {
+ {submissions.map(s => {
const rating = s.registrant && !_.isNil(s.registrant.rating)
? s.registrant.rating
: '-'
@@ -679,7 +481,7 @@ class SubmissionsComponent extends React.Component {
const allFiles = []
let downloadedFile = 0
const checkToCompressFiles = () => {
- if (downloadedFile === sortedSubmissions.length) {
+ if (downloadedFile === submissions.length) {
if (downloadedFile > 0) {
compressFiles(allFiles, 'all-submissions.zip', () => {
this.setState({
@@ -694,7 +496,7 @@ class SubmissionsComponent extends React.Component {
}
}
checkToCompressFiles()
- _.forEach(sortedSubmissions, (submission) => {
+ _.forEach(submissions, (submission) => {
let fileName = submission.legacySubmissionId
if (!fileName) {
fileName = submission.id
@@ -721,6 +523,30 @@ class SubmissionsComponent extends React.Component {
) : null}
+
+
{alertMessage ? (
)}
- {checkAdmin(auth.token) && (
+ {(checkAdmin(auth.token) || checkManager(auth.token)) && (
)}
diff --git a/src/config/constants.js b/src/config/constants.js
index 4ca6044a..0b7de032 100644
--- a/src/config/constants.js
+++ b/src/config/constants.js
@@ -4,6 +4,7 @@
export const {
COMMUNITY_APP_URL,
CHALLENGE_API_URL,
+ COPILOTS_URL,
SUBMISSION_REVIEW_APP_URL,
STUDIO_URL,
CONNECT_APP_URL,
@@ -30,7 +31,6 @@ export const {
SKILLS_V5_API_URL,
UPDATE_SKILLS_V5_API_URL,
SALESFORCE_BILLING_ACCOUNT_LINK,
- TYPEFORM_URL,
PROFILE_URL
} = process.env
diff --git a/src/containers/ChallengeEditor/index.js b/src/containers/ChallengeEditor/index.js
index 2f55d3b5..dffcc934 100644
--- a/src/containers/ChallengeEditor/index.js
+++ b/src/containers/ChallengeEditor/index.js
@@ -62,7 +62,8 @@ class ChallengeEditor extends Component {
showLaunchModal: false,
showRejectModal: false,
cancelReason: null,
- loginUserRoleInProject: ''
+ loginUserRoleInProject: '',
+ submissionsListPage: 1
}
this.onLaunchChallenge = this.onLaunchChallenge.bind(this)
@@ -95,7 +96,8 @@ class ChallengeEditor extends Component {
loadResourceRoles,
loadSubmissions,
loadChallengeDetails,
- loadResources
+ loadResources,
+ submissionsPerPage
} = this.props
loadTimelineTemplates()
loadChallengePhases()
@@ -109,7 +111,8 @@ class ChallengeEditor extends Component {
match,
loadChallengeDetails,
loadResources,
- loadSubmissions
+ loadSubmissions,
+ submissionsPerPage
)
// this.unlisten = this.props.history.listen(() => {
// const { isLoading } = this.props
@@ -160,12 +163,16 @@ class ChallengeEditor extends Component {
newMatch,
loadChallengeDetails,
loadResources,
- loadSubmissions
+ loadSubmissions,
+ submissionsPerPage
) {
let projectId = _.get(newMatch.params, 'projectId', null)
projectId = projectId ? parseInt(projectId) : null
const challengeId = _.get(newMatch.params, 'challengeId', null)
- await [loadResources(challengeId), loadSubmissions(challengeId)]
+ await [loadResources(challengeId), loadSubmissions(challengeId, {
+ page: 1,
+ perPage: submissionsPerPage
+ })]
loadChallengeDetails(projectId, challengeId)
if (!challengeId) {
@@ -423,7 +430,11 @@ class ChallengeEditor extends Component {
isProjectPhasesLoading,
showRejectChallengeModal,
createResource,
- deleteResource
+ deleteResource,
+ totalSubmissions,
+ submissionsPerPage,
+ page,
+ loadSubmissions
// members
} = this.props
const {
@@ -623,6 +634,10 @@ class ChallengeEditor extends Component {
onApproveChallenge={this.onApproveChallenge}
createResource={createResource}
deleteResource={deleteResource}
+ loadSubmissions={loadSubmissions}
+ totalSubmissions={totalSubmissions}
+ submissionsPerPage={submissionsPerPage}
+ page={page}
/>
)}
/>
@@ -680,13 +695,16 @@ ChallengeEditor.propTypes = {
loadProject: PropTypes.func,
projectPhases: PropTypes.arrayOf(PropTypes.object),
isProjectPhasesLoading: PropTypes.bool,
- showRejectChallengeModal: PropTypes.func
+ showRejectChallengeModal: PropTypes.func,
+ totalSubmissions: PropTypes.number,
+ submissionsPerPage: PropTypes.number,
+ page: PropTypes.number
// members: PropTypes.arrayOf(PropTypes.shape())
}
const mapStateToProps = ({
projects,
- challengeSubmissions: { challengeSubmissions },
+ challengeSubmissions: { challengeSubmissions, totalSubmissions, submissionsPerPage, page },
challenges: {
challengeDetails,
challengeResources,
@@ -715,7 +733,10 @@ const mapStateToProps = ({
token: auth.token,
loggedInUser: auth.user,
failedToLoad,
- errorMessage
+ errorMessage,
+ totalSubmissions,
+ submissionsPerPage,
+ page
// members
})
}
diff --git a/src/containers/ProjectInvitations/index.js b/src/containers/ProjectInvitations/index.js
index df5b80e4..58e6f20d 100644
--- a/src/containers/ProjectInvitations/index.js
+++ b/src/containers/ProjectInvitations/index.js
@@ -24,6 +24,8 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet
const [isUpdating, setIsUpdating] = useState(automaticAction || false)
const isAccepting = isUpdating === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED
const isDeclining = isUpdating === PROJECT_MEMBER_INVITE_STATUS_REFUSED
+ const queryParams = new URLSearchParams(window.location.search)
+ const source = queryParams.get('source')
useEffect(() => {
if (!projectId) {
@@ -42,9 +44,9 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet
}
}, [projectId, auth, projectDetail, isProjectLoading, history])
- const updateInvite = useCallback(async (status) => {
+ const updateInvite = useCallback(async (status, source) => {
setIsUpdating(status)
- await updateProjectMemberInvite(projectId, invitation.id, status)
+ await updateProjectMemberInvite(projectId, invitation.id, status, source)
// await for the project details to propagate
await delay(1000)
@@ -56,8 +58,8 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet
history.push(status === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED ? `/projects/${projectId}/challenges` : '/projects')
}, [projectId, invitation, loadProjectInvites, history])
- const acceptInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_ACCEPTED), [updateInvite])
- const declineInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_REFUSED), [updateInvite])
+ const acceptInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_ACCEPTED, source), [updateInvite, source])
+ const declineInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_REFUSED, source), [updateInvite, source])
useEffect(() => {
if (!invitation || !automaticAction) {
@@ -69,7 +71,7 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet
} else if (automaticAction === PROJECT_MEMBER_INVITE_STATUS_REFUSED) {
declineInvite()
}
- }, [invitation, automaticAction])
+ }, [invitation, automaticAction, source])
return (
<>
diff --git a/src/reducers/challengeSubmissions.js b/src/reducers/challengeSubmissions.js
index 389c10a4..ab70bda7 100644
--- a/src/reducers/challengeSubmissions.js
+++ b/src/reducers/challengeSubmissions.js
@@ -11,7 +11,10 @@ const initialState = {
isLoading: true,
loadingId: null,
challengeId: null,
- challengeSubmissions: []
+ challengeSubmissions: [],
+ totalSubmissions: 0,
+ submissionsPerPage: 10,
+ page: 1
}
export default function (state = initialState, action) {
@@ -19,10 +22,13 @@ export default function (state = initialState, action) {
case LOAD_CHALLENGE_SUBMISSIONS_SUCCESS:
return {
...state,
- challengeSubmissions: action.payload,
+ challengeSubmissions: action.payload.data,
isLoading: false,
loadingId: null,
- challengeId: state.loadingId
+ challengeId: state.loadingId,
+ totalSubmissions: action.payload.headers['x-total'],
+ page: action.payload.page,
+ submissionsPerPage: action.payload.perPage
}
case LOAD_CHALLENGE_SUBMISSIONS_PENDING:
return {
@@ -30,7 +36,8 @@ export default function (state = initialState, action) {
isLoading: true,
loadingId: action.challengeId,
challengeId: null,
- challengeSubmissions: []
+ challengeSubmissions: [],
+ totalPages: 0
}
case LOAD_CHALLENGE_SUBMISSIONS_FAILURE:
return {
@@ -38,7 +45,8 @@ export default function (state = initialState, action) {
isLoading: false,
loadingId: null,
challengeId: null,
- challengeSubmissions: []
+ challengeSubmissions: [],
+ totalPages: 0
}
default:
return state
diff --git a/src/routes.js b/src/routes.js
index fed56ded..b830f9f6 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -111,7 +111,7 @@ class Routes extends React.Component {
} else {
console.error('An unexpected error occurred while getting auth token')
}
- const redirectBackToUrl = encodeURIComponent(window.location.origin + this.props.location.pathname)
+ const redirectBackToUrl = encodeURIComponent(window.location.origin + this.props.location.pathname + this.props.location.search)
window.location = `${ACCOUNTS_APP_LOGIN_URL}?retUrl=${redirectBackToUrl}`
})
}
diff --git a/src/services/challenges.js b/src/services/challenges.js
index f3c441c7..3d8ac11e 100644
--- a/src/services/challenges.js
+++ b/src/services/challenges.js
@@ -263,9 +263,15 @@ export async function fetchResources (challengeId) {
* @param challengeId Challenge id
* @returns {Promise<*>}
*/
-export async function fetchSubmissions (challengeId) {
- const response = await axiosInstance.get(`${SUBMISSIONS_API_URL}?challengeId=${challengeId}&perPage=100`)
- return _.get(response, 'data', [])
+export async function fetchSubmissions (challengeId, pageObj) {
+ const { page, perPage } = pageObj
+ const response = await axiosInstance.get(`${SUBMISSIONS_API_URL}?challengeId=${challengeId}&perPage=${perPage}&page=${page}`)
+ return {
+ data: _.get(response, 'data', []),
+ headers: _.get(response, 'headers', {}),
+ page,
+ perPage
+ }
}
export async function getReviewTypes () {
diff --git a/src/services/projectMemberInvites.js b/src/services/projectMemberInvites.js
index 783155d5..cfa9a660 100644
--- a/src/services/projectMemberInvites.js
+++ b/src/services/projectMemberInvites.js
@@ -8,9 +8,16 @@ import { PROJECTS_API_URL } from '../config/constants'
* @param {string} status the new status for invitation
* @return {object} project member invite returned by api
*/
-export function updateProjectMemberInvite (projectId, inviteId, status) {
+export function updateProjectMemberInvite (projectId, inviteId, status, source) {
const url = `${PROJECTS_API_URL}/${projectId}/invites/${inviteId}`
- return axios.patch(url, { status })
+ const body = {
+ status
+ }
+
+ if (source) {
+ body.source = source
+ }
+ return axios.patch(url, body)
.then(resp => resp.data)
}