Skip to content

Commit 86334c8

Browse files
Merge pull request #3297 from nauhil/mm-leaderboard-misc-fixes
Build MM advanced submission view
2 parents 85a9f0e + ff5e1d0 commit 86334c8

File tree

10 files changed

+558
-9
lines changed

10 files changed

+558
-9
lines changed

src/shared/actions/page/challenge-details.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Actions related to the UI state of challenge details page.
33
*/
4-
4+
import _ from 'lodash';
55
import { createActions } from 'redux-actions';
66

77
/**
@@ -62,6 +62,15 @@ function toggleCheckpointFeedback(id, open) {
6262
return { id, open };
6363
}
6464

65+
/**
66+
* Creates action that toggle the submission testcase..
67+
* @param {Number} index of submission testcase.
68+
* @return {Action}
69+
*/
70+
function toggleSubmissionTestCase(index) {
71+
return index;
72+
}
73+
6574
export default createActions({
6675
PAGE: {
6776
CHALLENGE_DETAILS: {
@@ -70,6 +79,8 @@ export default createActions({
7079
TOGGLE_CHECKPOINT_FEEDBACK: toggleCheckpointFeedback,
7180
SUBMISSIONS: {
7281
TOGGLE_SUBMISSION_HISTORY: toggleSubmissionHistory,
82+
TOGGLE_SUBMISSION_TESTCASE: toggleSubmissionTestCase,
83+
CLEAR_SUBMISSION_TESTCASE_OPEN: _.identity,
7384
},
7485
},
7586
},
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/* eslint-disable jsx-a11y/click-events-have-key-events */
2+
import _ from 'lodash';
3+
import React from 'react';
4+
import PT from 'prop-types';
5+
import moment from 'moment';
6+
import { Modal, PrimaryButton } from 'topcoder-react-ui-kit';
7+
import ArrowUp from 'assets/images/icon-arrow-up.svg';
8+
import ArrowDown from 'assets/images/icon-arrow-down.svg';
9+
import LoadingIndicator from 'components/LoadingIndicator';
10+
11+
import modal from './style.scss';
12+
13+
class SubmissionInformationModal extends React.Component {
14+
constructor(props) {
15+
super(props);
16+
17+
this.getTestCaseOpen = this.getTestCaseOpen.bind(this);
18+
this.getSubmissionBasicInfo = this.getSubmissionBasicInfo.bind(this);
19+
this.getTestcases = this.getTestcases.bind(this);
20+
}
21+
22+
componentWillUnmount() {
23+
const { clearTestcaseOpen } = this.props;
24+
clearTestcaseOpen();
25+
}
26+
27+
getTestCaseOpen(index) {
28+
const { openTestcase } = this.props;
29+
return openTestcase[index.toString()] || false;
30+
}
31+
32+
33+
getSubmissionBasicInfo() {
34+
const { submission, submissionInformation } = this.props;
35+
return _.find(submission.submissions, item => item.submissionId === submissionInformation.id);
36+
}
37+
38+
getTestcases() {
39+
const { submissionInformation } = this.props;
40+
41+
let list = [];
42+
_.forEach(submissionInformation.review, (item) => {
43+
if (_.has(item, 'metadata') && _.has(item.metadata, 'testcases') && item.metadata.testcases.length > 0) {
44+
list = list.concat(item.metadata.testcases);
45+
}
46+
});
47+
48+
return list;
49+
}
50+
51+
/* eslint-disable class-methods-use-this */
52+
renderCase(key, value) {
53+
return (
54+
<React.Fragment>
55+
<span>{key}</span>
56+
<span>{value}</span>
57+
</React.Fragment>
58+
);
59+
}
60+
61+
render() {
62+
const {
63+
toggleTestcase, onClose, isLoadingSubmissionInformation,
64+
submissionInformation, isReviewPhaseComplete,
65+
} = this.props;
66+
const submissionBasicInfo = isLoadingSubmissionInformation
67+
? null : this.getSubmissionBasicInfo();
68+
const testcases = isLoadingSubmissionInformation ? [] : this.getTestcases();
69+
70+
return (
71+
<Modal theme={{ container: modal.container }} onCancel={() => onClose(false)}>
72+
{
73+
!isLoadingSubmissionInformation && (
74+
<React.Fragment>
75+
<div styleName="modal.submission-information-title">Advanced Details</div>
76+
<div styleName="modal.submission-information-details">
77+
<div styleName="modal.submission-information-details-row1">
78+
<span styleName="modal.submission-information-details-title">Submission:&nbsp;</span>
79+
<span styleName="modal.submission-information-details-id">{submissionInformation.id}</span>
80+
</div>
81+
<div styleName="modal.submission-information-details-row2">
82+
<div styleName="modal.details-header">
83+
<div styleName="modal.header-item">Final Score</div>
84+
<div styleName="modal.header-item">Provissional Score</div>
85+
<div styleName="modal.header-item">Time</div>
86+
</div>
87+
<div styleName="modal.details-grid">
88+
<div
89+
styleName="modal.details-item"
90+
>
91+
{(!submissionBasicInfo.finalScore && submissionBasicInfo.finalScore !== 0) || !isReviewPhaseComplete ? '-' : submissionBasicInfo.finalScore}
92+
</div>
93+
<div
94+
styleName="modal.details-item"
95+
>
96+
{(!submissionBasicInfo.provisionalScore && submissionBasicInfo.provisionalScore !== 0) ? '-' : submissionBasicInfo.provisionalScore}
97+
</div>
98+
<div styleName="modal.details-item">
99+
{moment(submissionBasicInfo.submissionTime)
100+
.format('DD MMM YYYY')} {moment(submissionBasicInfo.submissionTime)
101+
.format('HH:mm:ss')}
102+
</div>
103+
</div>
104+
</div>
105+
</div>
106+
{
107+
testcases.length > 0 && (
108+
<React.Fragment>
109+
<div styleName="modal.testcase-title">
110+
Test cases executed
111+
</div>
112+
{
113+
_.map(testcases, (item, index) => (
114+
<div styleName="modal.testcase-items" key={`Test case #${index + 1}`}>
115+
<div styleName="modal.testcase-header">
116+
<div>Test case #{index + 1}</div>
117+
<span onClick={() => toggleTestcase(index)} role="button" tabIndex={0}>
118+
{
119+
this.getTestCaseOpen(index) ? <ArrowUp /> : <ArrowDown />
120+
}
121+
</span>
122+
</div>
123+
{
124+
_.keys(item).length > 0 && (
125+
<div styleName={`modal.testcase-grid ${this.getTestCaseOpen(index) ? 'active' : ''}`}>
126+
{
127+
_.map(_.keys(item), (key, caseIndex) => (
128+
<div styleName="modal.testcase-row" key={`case-${caseIndex}-${key}`}>
129+
{
130+
this.renderCase(key, item[key])
131+
}
132+
</div>
133+
))
134+
}
135+
</div>
136+
)
137+
}
138+
</div>
139+
))
140+
}
141+
</React.Fragment>
142+
)
143+
}
144+
<div styleName="modal.submission-information-buttons">
145+
<div styleName="modal.submission-information-button-close">
146+
<PrimaryButton onClick={() => onClose(false)}>Dismiss</PrimaryButton>
147+
</div>
148+
</div>
149+
</React.Fragment>
150+
)
151+
}
152+
{
153+
isLoadingSubmissionInformation && (
154+
<LoadingIndicator />
155+
)
156+
}
157+
</Modal>
158+
);
159+
}
160+
}
161+
162+
SubmissionInformationModal.defaultProps = {
163+
isLoadingSubmissionInformation: false,
164+
submissionInformation: null,
165+
};
166+
167+
SubmissionInformationModal.propTypes = {
168+
isLoadingSubmissionInformation: PT.bool,
169+
submissionInformation: PT.shape(),
170+
onClose: PT.func.isRequired,
171+
toggleTestcase: PT.func.isRequired,
172+
openTestcase: PT.shape({}).isRequired,
173+
clearTestcaseOpen: PT.func.isRequired,
174+
submission: PT.shape().isRequired,
175+
isReviewPhaseComplete: PT.bool.isRequired,
176+
};
177+
178+
export default SubmissionInformationModal;

0 commit comments

Comments
 (0)