Skip to content

Commit eff3ee3

Browse files
committed
feat: list ratings
1 parent 926dab0 commit eff3ee3

File tree

8 files changed

+208
-5
lines changed

8 files changed

+208
-5
lines changed

config/constants/development.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
RESOURCES_API_URL: `${DEV_API_HOSTNAME}/v5/resources`,
2626
RESOURCE_ROLES_API_URL: `${DEV_API_HOSTNAME}/v5/resource-roles`,
2727
SUBMISSIONS_API_URL: `${DEV_API_HOSTNAME}/v5/submissions`,
28+
REVIEW_TYPE_API_URL: `${DEV_API_HOSTNAME}/v5/reviewTypes`,
2829
SUBMISSION_REVIEW_APP_URL: `https://submission-review.${DOMAIN}/challenges`,
2930
STUDIO_URL: `https://studio.${DOMAIN}`,
3031
CONNECT_APP_URL: `https://connect.${DOMAIN}`,

config/constants/production.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = {
2424
RESOURCES_API_URL: `${PROD_API_HOSTNAME}/v5/resources`,
2525
RESOURCE_ROLES_API_URL: `${PROD_API_HOSTNAME}/v5/resource-roles`,
2626
SUBMISSIONS_API_URL: `${PROD_API_HOSTNAME}/v5/submissions`,
27+
REVIEW_TYPE_API_URL: `${PROD_API_HOSTNAME}/v5/reviewTypes`,
2728
SUBMISSION_REVIEW_APP_URL: `https://submission-review.${DOMAIN}/challenges`,
2829
STUDIO_URL: `https://studio.${DOMAIN}`,
2930
CONNECT_APP_URL: `https://connect.${DOMAIN}`,
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
@import "../../../styles/includes";
2+
3+
.container {
4+
box-sizing: border-box;
5+
background: $white;
6+
opacity: 1;
7+
position: relative;
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: flex-start;
11+
border-radius: 6px;
12+
margin: 0 auto;
13+
width: 800px;
14+
min-height: 350px;
15+
padding-top: 60px;
16+
.list {
17+
.header {
18+
border-bottom: 1px solid $tc-gray-60;
19+
padding-bottom: 10px;
20+
display: flex;
21+
padding-left: 40px;
22+
padding-right: 40px;
23+
color: $tc-gray-70;
24+
font-weight: 500;
25+
26+
.header-item {
27+
flex: 1;
28+
}
29+
}
30+
.list-item {
31+
border-bottom: 1px solid $tc-gray-60;
32+
padding-bottom: 10px;
33+
padding-top: 10px;
34+
display: flex;
35+
padding-left: 40px;
36+
padding-right: 40px;
37+
color: $tc-gray-70;
38+
.list-col-item {
39+
display: flex;
40+
flex: 1;
41+
}
42+
}
43+
}
44+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import React, { useCallback, useEffect, useState } from 'react'
2+
import Modal from '../../Modal'
3+
4+
import styles from './RatingsListModal.module.scss'
5+
import PropTypes from 'prop-types'
6+
import { getTopcoderReactLib } from '../../../util/topcoder-react-lib'
7+
import Loader from '../../Loader'
8+
import { getReviewTypes } from '../../../services/challenges'
9+
import { SystemReviewers } from '../../../config/constants'
10+
11+
export const RatingsListModal = ({ onClose, theme, token, submissionId, challengeId }) => {
12+
const [reviews, setReviews] = useState([])
13+
const [loading, setLoading] = useState(false)
14+
15+
const enrichSources = useCallback(async (submissionReviews, reviewSummation) => {
16+
const reactLib = getTopcoderReactLib()
17+
const { getService } = reactLib.services.members
18+
const membersService = getService(token)
19+
const resources = await membersService.getChallengeResources(challengeId)
20+
const reviewTypes = await getReviewTypes()
21+
22+
const finalReview = {
23+
reviewType: 'Final score',
24+
reviewer: '',
25+
score: reviewSummation ? reviewSummation.aggregateScore : 'N/A',
26+
isPassing: reviewSummation ? reviewSummation.isPassing : undefined
27+
}
28+
29+
return [...submissionReviews.map(review => {
30+
const reviewType = reviewTypes.find(rt => rt.id === review.typeId)
31+
const reviewer = resources.find(resource => resource.memberHandle === review.reviewerId) || SystemReviewers.Default
32+
return {
33+
...review,
34+
reviewType: reviewType ? reviewType.name : '',
35+
reviewer
36+
}
37+
}), finalReview]
38+
}, [token])
39+
40+
const getSubmission = useCallback(async () => {
41+
const reactLib = getTopcoderReactLib()
42+
const { getService } = reactLib.services.submissions
43+
const submissionsService = getService(token)
44+
const submissionInfo = await submissionsService.getSubmissionInformation(submissionId)
45+
setReviews(await enrichSources(submissionInfo.review, submissionInfo.reviewSummation[0]))
46+
setLoading(false)
47+
}, [submissionId, token])
48+
49+
useEffect(() => {
50+
setLoading(true)
51+
getSubmission()
52+
}, [submissionId])
53+
54+
return (
55+
<Modal theme={theme} onCancel={onClose}>
56+
<div className={styles['container']}>
57+
<div className={styles['list']}>
58+
<div className={styles['header']}>
59+
<div className={styles['header-item']}>Review Type</div>
60+
<div className={styles['header-item']}>Reviewer</div>
61+
<div className={styles['header-item']}>Score</div>
62+
<div className={styles['header-item']}>Status</div>
63+
</div>
64+
{reviews.map(review => {
65+
const { isPassing } = review
66+
const isFailed = isPassing === false
67+
const isPassed = isPassing === true
68+
const statusIsDefined = isPassed || isFailed
69+
const status = isPassing ? 'Passed' : 'Failed'
70+
71+
return (
72+
<div className={styles['list-item']}>
73+
<div className={styles['list-col-item']}>
74+
{review.reviewType}
75+
</div>
76+
<div className={styles['list-col-item']}>
77+
<strong>{review.reviewer}</strong>
78+
</div>
79+
<div className={styles['list-col-item']}>
80+
{review.score}
81+
</div>
82+
<div className={styles['list-col-item']}>
83+
{statusIsDefined ? status : 'N/A'}
84+
</div>
85+
</div>
86+
)
87+
})}
88+
</div>
89+
90+
{
91+
loading && <Loader />
92+
}
93+
</div>
94+
</Modal>
95+
)
96+
}
97+
98+
RatingsListModal.defaultProps = {
99+
onClose: () => {},
100+
theme: '',
101+
token: '',
102+
submissionId: '',
103+
challengeId: ''
104+
}
105+
106+
RatingsListModal.propTypes = {
107+
onClose: PropTypes.func,
108+
theme: PropTypes.shape(),
109+
token: PropTypes.string,
110+
submissionId: PropTypes.string,
111+
challengeId: PropTypes.string
112+
}

src/components/ChallengeEditor/Submissions/index.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ import styles from './Submissions.module.scss'
3131
import modalStyles from '../../../styles/modal.module.scss'
3232
import { ArtifactsListModal } from '../ArtifactsListModal'
3333
import Tooltip from '../../Tooltip'
34+
import { RatingsListModal } from '../RatingsListModal'
3435
const assets = require.context('../../../assets/images', false, /svg/)
3536
const ArrowDown = './arrow-down.svg'
3637
const Lock = './lock.svg'
3738
const Download = './IconSquareDownload.svg'
3839
const DownloadArtifact = './IconDownloadArtifacts.svg'
40+
const ReviewRatingList = './IconReviewRatingList.svg'
3941

4042
const theme = {
4143
container: modalStyles.modalContainer
@@ -54,7 +56,9 @@ class SubmissionsComponent extends React.Component {
5456
sortedSubmissions: [],
5557
downloadingAll: false,
5658
alertMessage: '',
57-
selectedSubmissionId: ''
59+
selectedSubmissionId: '',
60+
showArtifactsListModal: false,
61+
showRatingsListModal: false
5862
}
5963
this.getSubmissionsSortParam = this.getSubmissionsSortParam.bind(this)
6064
this.updateSortedSubmissions = this.updateSortedSubmissions.bind(this)
@@ -227,7 +231,8 @@ class SubmissionsComponent extends React.Component {
227231

228232
closeArtifactsModal () {
229233
this.setState({
230-
selectedSubmissionId: ''
234+
selectedSubmissionId: '',
235+
showArtifactsListModal: false
231236
})
232237
}
233238

@@ -600,12 +605,23 @@ class SubmissionsComponent extends React.Component {
600605
<button
601606
className={styles['download-submission-button']}
602607
onClick={async () => {
603-
this.setState({ selectedSubmissionId: s.id })
608+
this.setState({ selectedSubmissionId: s.id, showArtifactsListModal: true })
604609
}}
605610
>
606611
<ReactSVG path={assets(`${DownloadArtifact}`)} />
607612
</button>
608613
</Tooltip>
614+
615+
<Tooltip content='Ratings'>
616+
<button
617+
className={styles['download-submission-button']}
618+
onClick={() => {
619+
this.setState({ selectedSubmissionId: s.id, showRatingsListModal: true })
620+
}}
621+
>
622+
<ReactSVG path={assets(`${ReviewRatingList}`)} />
623+
</button>
624+
</Tooltip>
609625
</div>
610626
</td>) : null}
611627
</tr>
@@ -616,20 +632,35 @@ class SubmissionsComponent extends React.Component {
616632
</div>
617633

618634
{
619-
this.state.selectedSubmissionId ? (
635+
this.state.showArtifactsListModal ? (
620636
<ArtifactsListModal
621637
submissionId={this.state.selectedSubmissionId}
622638
token={this.props.token}
623639
theme={theme}
624640
onClose={() => {
625641
this.setState({
626-
selectedSubmissionId: ''
642+
selectedSubmissionId: '',
643+
showArtifactsListModal: false
627644
})
628645
}}
629646
/>
630647
) : null
631648
}
632649

650+
{
651+
this.state.showRatingsListModal ? (
652+
<RatingsListModal
653+
token={this.props.token}
654+
theme={theme}
655+
onClose={() => {
656+
this.setState({ showRatingsListModal: false })
657+
}}
658+
submissionId={this.state.selectedSubmissionId}
659+
challengeId={this.props.challenge.id}
660+
/>
661+
) : null
662+
}
663+
633664
{canDownloadSubmission ? (<div className={styles['top-title']} >
634665

635666
<div className={styles.btnManageSubmissions} >

src/config/constants.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,13 @@ export const CANCEL_REASONS = [
363363
'Cancelled - Zero Registrations'
364364
]
365365

366+
/**
367+
* System reviewers
368+
*/
369+
export const SystemReviewers = {
370+
Default: 'TC System'
371+
}
372+
366373
/**
367374
* Milestone product details
368375
*/

src/services/challenges.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const {
1212
CHALLENGE_PHASES_URL,
1313
CHALLENGE_TIMELINES_URL,
1414
SUBMISSIONS_API_URL,
15+
REVIEW_TYPE_API_URL,
1516
GROUPS_API_URL,
1617
TERMS_API_URL,
1718
RESOURCES_API_URL,
@@ -267,6 +268,11 @@ export async function fetchSubmissions (challengeId) {
267268
return _.get(response, 'data', [])
268269
}
269270

271+
export async function getReviewTypes () {
272+
const response = await axiosInstance.get(`${REVIEW_TYPE_API_URL}?perPage=500&page=1`)
273+
return _.get(response, 'data', [])
274+
}
275+
270276
/**
271277
* Api request for fetching resource roles
272278
* @returns {Promise<*>}

0 commit comments

Comments
 (0)