-
Notifications
You must be signed in to change notification settings - Fork 211
PROD - PM-3080 / PS-476 #7159
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
PROD - PM-3080 / PS-476 #7159
Changes from all commits
21396c9
861c229
c276688
c9a0f8d
2cda17a
2825da0
d73daf7
3cddd60
8acb26b
b117c10
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 |
|---|---|---|
|
|
@@ -42,6 +42,7 @@ export default function Submission(props) { | |
| onOpenRatingsListModal, | ||
| status, | ||
| allowDelete, | ||
| isWorkflowRunComplete, | ||
| } = props; | ||
| const formatDate = date => moment(+new Date(date)).format('MMM DD, YYYY hh:mm A'); | ||
| const onDownloadSubmission = onDownload.bind(1, submissionObject.id); | ||
|
|
@@ -66,6 +67,10 @@ export default function Submission(props) { | |
| } | ||
| } | ||
|
|
||
| const showDeleteButton = status !== CHALLENGE_STATUS.COMPLETED | ||
| && track === COMPETITION_TRACKS.DES | ||
| && safeForDownloadCheck === true; | ||
|
|
||
| return ( | ||
| <tr styleName="submission-row"> | ||
| <td styleName="id-col"> | ||
|
|
@@ -146,17 +151,33 @@ export default function Submission(props) { | |
| onClick={() => onDownload(submissionObject.id)} | ||
| ><DownloadIcon /></button> | ||
| */ } | ||
| {status !== CHALLENGE_STATUS.COMPLETED | ||
| && track === COMPETITION_TRACKS.DES | ||
| && safeForDownloadCheck === true && ( | ||
| <button | ||
| styleName="delete-icon" | ||
| onClick={() => onDelete(submissionObject.id)} | ||
| disabled={!allowDelete} | ||
| type="button" | ||
| > | ||
| <DeleteIcon /> | ||
| </button> | ||
| {showDeleteButton && ( | ||
| isWorkflowRunComplete ? ( | ||
|
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. [💡 |
||
| <button | ||
| styleName="delete-icon" | ||
| onClick={() => onDelete(submissionObject.id)} | ||
| type="button" | ||
| disabled={!allowDelete} | ||
| > | ||
| <DeleteIcon /> | ||
| </button> | ||
| ) : ( | ||
| // Disabled delete button with tooltip when workflow run is pending | ||
| <Tooltip content={() => ( | ||
| <div styleName="tooltip-content"> | ||
| You can delete this submission only after the review is complete. | ||
| </div> | ||
| )} | ||
| > | ||
| <button | ||
| styleName="delete-icon" | ||
| disabled | ||
| type="button" | ||
| > | ||
| <DeleteIcon /> | ||
| </button> | ||
| </Tooltip> | ||
| ) | ||
| ) | ||
| } | ||
| { !isTopCrowdChallenge | ||
|
|
@@ -217,4 +238,5 @@ Submission.propTypes = { | |
| allowDelete: PT.bool.isRequired, | ||
| onOpenDownloadArtifactsModal: PT.func, | ||
| onOpenRatingsListModal: PT.func, | ||
| isWorkflowRunComplete: PT.bool.isRequired, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,9 +74,29 @@ export default function SubmissionsTable(props) { | |
| submissionObjects.forEach((subObject) => { | ||
| // submissionPhaseStartDate will be the start date of | ||
| // the current submission/checkpoint or empty string if any other phase | ||
|
|
||
| const TERMINAL_STATUSES = [ | ||
|
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. [💡 |
||
| 'COMPLETED', | ||
| 'FAILURE', | ||
| 'CANCELLED', | ||
| 'SUCCESS', | ||
| ]; | ||
|
|
||
| const workflowRunsForSubmission = submissionWorkflowRuns | ||
| && submissionWorkflowRuns[subObject.id] | ||
| ? submissionWorkflowRuns[subObject.id] | ||
| : null; | ||
|
|
||
| const hasRuns = workflowRunsForSubmission && workflowRunsForSubmission.length > 0; | ||
|
|
||
| const isWorkflowRunComplete = !hasRuns | ||
|
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. [💡 |
||
| ? true | ||
| : workflowRunsForSubmission.every(run => TERMINAL_STATUSES.includes(run.status)); | ||
|
|
||
| const allowDelete = submissionPhaseStartDate | ||
| && moment(subObject.submissionDate).isAfter(submissionPhaseStartDate); | ||
|
|
||
|
|
||
| const submission = ( | ||
| <Submission | ||
| challenge={challenge} | ||
|
|
@@ -91,13 +111,10 @@ export default function SubmissionsTable(props) { | |
| allowDelete={allowDelete} | ||
| onOpenDownloadArtifactsModal={onOpenDownloadArtifactsModal} | ||
| onOpenRatingsListModal={onOpenRatingsListModal} | ||
| isWorkflowRunComplete={isWorkflowRunComplete} | ||
| /> | ||
| ); | ||
| submissionsWithDetails.push(submission); | ||
| const workflowRunsForSubmission = submissionWorkflowRuns | ||
| && submissionWorkflowRuns[subObject.id] | ||
| ? submissionWorkflowRuns[subObject.id] | ||
| : null; | ||
|
|
||
| const submissionDetail = ( | ||
| <tr key={subObject.id} styleName="submission-row"> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import { config } from 'topcoder-react-utils'; | ||
| import { withEstimatedReviewerPayments } from 'utils/reviewOpportunities'; | ||
|
|
||
| const v6ApiUrl = config.API.V6; | ||
|
|
||
|
|
@@ -22,7 +23,10 @@ export default async function getReviewOpportunities(page, pageSize) { | |
| throw new Error(res.statusText); | ||
| } | ||
|
|
||
| return res.json(); | ||
| const data = await res.json(); | ||
|
|
||
| const opportunities = Array.isArray(data) ? data : []; | ||
|
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. [ |
||
| return opportunities.map(opportunity => withEstimatedReviewerPayments(opportunity)); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -51,7 +55,7 @@ export async function getDetails(challengeId, opportunityId) { | |
| const challengeData = await challengeRes.json(); | ||
|
|
||
| return { | ||
| ...opportunityData.result.content, | ||
| ...withEstimatedReviewerPayments(opportunityData.result.content), | ||
|
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. [ |
||
| challenge: challengeData, | ||
| }; | ||
| } catch (err) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,54 @@ import _ from 'lodash'; | |
| import moment from 'moment'; | ||
| import { REVIEW_OPPORTUNITY_TYPES } from './tc'; | ||
|
|
||
| export const DEFAULT_ESTIMATED_SUBMISSIONS = 2; | ||
|
|
||
| export const calculateEstimatedReviewerPayment = ( | ||
| basePayment, | ||
| incrementalPayment, | ||
| estimatedSubmissions = DEFAULT_ESTIMATED_SUBMISSIONS, | ||
| ) => { | ||
| const base = _.toNumber(basePayment); | ||
| const incremental = _.toNumber(incrementalPayment); | ||
| const submissions = _.toNumber(estimatedSubmissions); | ||
|
|
||
| if (_.isNaN(base) || _.isNaN(submissions)) { | ||
|
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. [ |
||
| return null; | ||
| } | ||
|
|
||
| const incrementalValue = _.isNaN(incremental) ? 0 : incremental; | ||
| return base + (submissions * incrementalValue); | ||
| }; | ||
|
|
||
| export const withEstimatedReviewerPayments = ( | ||
| opportunity, | ||
| estimatedSubmissions = DEFAULT_ESTIMATED_SUBMISSIONS, | ||
| ) => { | ||
| if (!opportunity) return opportunity; | ||
|
|
||
| const estimatedPayment = calculateEstimatedReviewerPayment( | ||
|
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. [ |
||
| _.get(opportunity, 'basePayment', _.get(opportunity, 'payments[0].payment')), | ||
| _.get(opportunity, 'incrementalPayment', 0), | ||
| estimatedSubmissions, | ||
| ); | ||
|
|
||
| if (!_.isNumber(estimatedPayment)) { | ||
|
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. [💡 |
||
| return opportunity; | ||
| } | ||
|
|
||
| const payments = Array.isArray(opportunity.payments) | ||
| ? opportunity.payments.map(payment => ({ | ||
| ...payment, | ||
| payment: estimatedPayment, | ||
| })) | ||
| : opportunity.payments; | ||
|
|
||
| return { | ||
| ...opportunity, | ||
| payments, | ||
| }; | ||
| }; | ||
|
|
||
| /** | ||
| * Infers open positions using review opportunity details and organizes them by role | ||
| * | ||
|
|
@@ -14,7 +62,10 @@ import { REVIEW_OPPORTUNITY_TYPES } from './tc'; | |
| export const openPositionsByRole = (details) => { | ||
| if (!details.payments) return []; | ||
|
|
||
| const roleCount = details.payments.length; | ||
| const detailsWithPayments = withEstimatedReviewerPayments(details); | ||
| const payments = detailsWithPayments.payments || []; | ||
|
|
||
| const roleCount = payments.length; | ||
|
|
||
| let approved; | ||
| if (details.applications && details.openPositions === 1 && roleCount === 2) { | ||
|
|
@@ -28,7 +79,7 @@ export const openPositionsByRole = (details) => { | |
| return details.openPositions / roleCount; | ||
| }; | ||
|
|
||
| return details.payments.map(({ role, roleId, payment }) => ({ | ||
| return payments.map(({ role, roleId, payment }) => ({ | ||
| role, | ||
| roleId, | ||
| payment, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[⚠️
maintainability]The
showDeleteButtonlogic is duplicated in the JSX rendering. Consider refactoring this logic into a helper function to improve maintainability and reduce redundancy.