-
Notifications
You must be signed in to change notification settings - Fork 211
migrate: review opportunity details page to v6 review API #7110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,13 +8,14 @@ import React from 'react'; | |
| import PT from 'prop-types'; | ||
| import { connect } from 'react-redux'; | ||
|
|
||
| import { actions, errors } from 'topcoder-react-lib'; | ||
| import { errors } from 'topcoder-react-lib'; | ||
| import LoadingIndicator from 'components/LoadingIndicator'; | ||
| import { activeRoleIds } from 'utils/reviewOpportunities'; | ||
| import pageActions from 'actions/page/review-opportunity-details'; | ||
| import ReviewOpportunityDetailsPage from 'components/ReviewOpportunityDetailsPage'; | ||
| import FailedToLoad from 'components/ReviewOpportunityDetailsPage/FailedToLoad'; | ||
| import termsActions from 'actions/terms'; | ||
| import { goToLogin } from 'utils/tc'; | ||
|
|
||
| const { fireErrorMessage } = errors; | ||
|
|
||
|
|
@@ -25,26 +26,45 @@ class ReviewOpportunityDetailsContainer extends React.Component { | |
| componentDidMount() { | ||
| const { | ||
| challengeId, | ||
| opportunityId, | ||
| details, | ||
| isLoadingDetails, | ||
| loadDetails, | ||
| tokenV3, | ||
| } = this.props; | ||
|
|
||
| if (!isLoadingDetails && !details) { | ||
| loadDetails(challengeId, tokenV3); | ||
| loadDetails(challengeId, opportunityId, tokenV3); | ||
| } else if (details.challenge.id !== challengeId) { | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| loadDetails(challengeId, tokenV3); | ||
| loadDetails(challengeId, opportunityId, tokenV3); | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| handleOnHeaderApply() { | ||
| const { | ||
| isLoggedIn, | ||
| isReviewer, | ||
| openTermsModal, | ||
| terms, | ||
| termsFailure, | ||
| toggleApplyModal, | ||
| } = this.props; | ||
|
|
||
| if (!isLoggedIn) { | ||
| goToLogin('community-app-main'); | ||
| return; | ||
| } | ||
|
|
||
| if (!isReviewer) { | ||
| fireErrorMessage( | ||
| 'Permission Required', | ||
| <span> | ||
| You must have a reviewer role to apply for this review opportunity. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The removal of the link to 'Learn how to become a reviewer' may lead to confusion for users who are not aware of how to obtain a reviewer role. Consider providing guidance or a reference to where users can find more information about becoming a reviewer. |
||
| </span>, | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| if (termsFailure) { | ||
| fireErrorMessage('Error Getting Terms Details', ''); | ||
| return; | ||
|
|
@@ -130,6 +150,8 @@ ReviewOpportunityDetailsContainer.defaultProps = { | |
| termsFailure: false, | ||
| phasesExpanded: false, | ||
| tokenV3: null, | ||
| isLoggedIn: false, | ||
| isReviewer: false, | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -140,6 +162,7 @@ ReviewOpportunityDetailsContainer.propTypes = { | |
| authError: PT.bool, | ||
| cancelApplications: PT.func.isRequired, | ||
| challengeId: PT.string.isRequired, | ||
| opportunityId: PT.string.isRequired, | ||
| details: PT.shape(), | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| handle: PT.string.isRequired, | ||
| isLoadingDetails: PT.bool, | ||
|
|
@@ -157,6 +180,8 @@ ReviewOpportunityDetailsContainer.propTypes = { | |
| toggleRole: PT.func.isRequired, | ||
| onPhaseExpand: PT.func.isRequired, | ||
| tokenV3: PT.string, | ||
| isLoggedIn: PT.bool, | ||
| isReviewer: PT.bool, | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -169,12 +194,14 @@ ReviewOpportunityDetailsContainer.propTypes = { | |
| const mapStateToProps = (state, ownProps) => { | ||
| const api = state.reviewOpportunity; | ||
| const page = state.page.reviewOpportunityDetails; | ||
| const queryParams = new URLSearchParams(ownProps.location.search); | ||
| const { terms } = state; | ||
| return { | ||
| authError: api.authError, | ||
| applyModalOpened: page.applyModalOpened, | ||
| challengeId: String(ownProps.match.params.challengeId), | ||
| details: api.details, | ||
| opportunityId: queryParams.get('opportunityId'), | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| details: page.details, | ||
| handle: state.auth.user ? state.auth.user.handle : '', | ||
| isLoadingDetails: api.isLoadingDetails, | ||
| phasesExpanded: page.phasesExpanded, | ||
|
|
@@ -184,6 +211,8 @@ const mapStateToProps = (state, ownProps) => { | |
| terms: terms.terms, | ||
| termsFailure: terms.getTermsFailure, | ||
| tokenV3: state.auth.tokenV3, | ||
| isLoggedIn: Boolean(state.auth.user), | ||
| isReviewer: _.includes(state.auth.userRoles || [], 'REVIEWER'), | ||
| }; | ||
| }; | ||
|
|
||
|
|
@@ -194,16 +223,16 @@ const mapStateToProps = (state, ownProps) => { | |
| * @return {Object} | ||
| */ | ||
| function mapDispatchToProps(dispatch) { | ||
| const api = actions.reviewOpportunity; | ||
| const api = pageActions.page.reviewOpportunityDetails; | ||
| const page = pageActions.page.reviewOpportunityDetails; | ||
| return { | ||
| cancelApplications: (challengeId, roleIds, tokenV3) => { | ||
| dispatch(api.cancelApplicationsInit()); | ||
| dispatch(api.cancelApplicationsDone(challengeId, roleIds, tokenV3)); | ||
| }, | ||
| loadDetails: (challengeId, tokenV3) => { | ||
| loadDetails: (challengeId, opportunityId, tokenV3) => { | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| dispatch(api.getDetailsInit()); | ||
| dispatch(api.getDetailsDone(challengeId, tokenV3)); | ||
| dispatch(api.getDetailsDone(challengeId, opportunityId, tokenV3)); | ||
| }, | ||
| onPhaseExpand: () => dispatch(page.togglePhasesExpand()), | ||
| openTermsModal: () => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| import { config } from 'topcoder-react-utils'; | ||
| import _ from 'lodash'; | ||
|
|
||
|
|
||
| const v6ApiUrl = config.API.V6; | ||
|
|
||
|
|
@@ -24,3 +26,53 @@ export default async function getReviewOpportunities(page, pageSize) { | |
|
|
||
| return res.json(); | ||
| } | ||
|
|
||
| /** | ||
| * Sync the fields of V3 and V5 for front-end to process successfully | ||
| * @param challenge - challenge to normalize | ||
| */ | ||
| function normalizeChallengePhases(challenge) { | ||
| return { | ||
| ...challenge, | ||
| phases: _.map(challenge.phases, phase => ({ | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ...phase, | ||
| scheduledStartDate: phase.scheduledStartTime, | ||
| scheduledEndDate: phase.scheduledEndTime, | ||
| })), | ||
| }; | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Gets the details of the review opportunity for the corresponding challenge | ||
| * @param {Number} challengeId The ID of the challenge (not the opportunity id) | ||
| * @return {Object} The combined data of the review opportunity and challenge details | ||
| */ | ||
| export async function getDetails(challengeId, opportunityId) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function |
||
| const getReviewOpportunityUrl = new URL(`${v6ApiUrl}/review-opportunities/${opportunityId}`); | ||
| const getChallengeUrl = new URL(`${v6ApiUrl}/challenges/${challengeId}`); | ||
|
|
||
| try { | ||
| const [opportunityRes, challengeRes] = await Promise.all([ | ||
| fetch(getReviewOpportunityUrl.toString(), { method: 'GET' }), | ||
| fetch(getChallengeUrl.toString(), { method: 'GET' }), | ||
| ]); | ||
|
|
||
| if (!opportunityRes.ok) { | ||
| throw new Error(`Failed to load review opportunity: ${opportunityRes.statusText}`); | ||
| } | ||
| if (!challengeRes.ok) { | ||
| throw new Error(`Failed to load challenge details: ${challengeRes.statusText}`); | ||
| } | ||
|
|
||
| const opportunityData = await opportunityRes.json(); | ||
| const challengeData = await challengeRes.json(); | ||
|
|
||
| return { | ||
| ...opportunityData.result.content, | ||
himaniraghav3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| challenge: normalizeChallengePhases(challengeData), | ||
| }; | ||
| } catch (err) { | ||
| return Promise.reject(err); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.