diff --git a/src/components/ReferenceSolutions/ReferenceSolutionDetail/ReferenceSolutionDetail.js b/src/components/ReferenceSolutions/ReferenceSolutionDetail/ReferenceSolutionDetail.js
deleted file mode 100644
index 7feb618e4..000000000
--- a/src/components/ReferenceSolutions/ReferenceSolutionDetail/ReferenceSolutionDetail.js
+++ /dev/null
@@ -1,260 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import { Row, Col } from 'react-bootstrap';
-import { FormattedMessage } from 'react-intl';
-
-import SolutionFiles from '../../Solutions/SolutionFiles';
-import EvaluationDetail from '../../Solutions/EvaluationDetail';
-import TestResults from '../../Solutions/TestResults';
-import DownloadResultArchiveContainer from '../../../containers/DownloadResultArchiveContainer';
-import CommentThreadContainer from '../../../containers/CommentThreadContainer';
-import SourceCodeViewerContainer from '../../../containers/SourceCodeViewerContainer';
-import SubmissionEvaluations from '../../Solutions/SubmissionEvaluations';
-import { ScoreConfigInfoDialog } from '../../scoreConfig/ScoreConfigInfo';
-import CompilationLogs from '../../Solutions/CompilationLogs';
-import SolutionStatus from '../../Solutions/SolutionStatus';
-
-import Button from '../../widgets/TheButton';
-import Callout from '../../widgets/Callout';
-import FailureReport from '../../SubmissionFailures/FailureReport';
-import ResourceRenderer from '../../helpers/ResourceRenderer';
-import { RefreshIcon, WarningIcon } from '../../icons';
-
-import { EMPTY_OBJ, getFirstItemInOrder } from '../../../helpers/common';
-
-const getLastSubmissionId = evaluations => {
- const evalArray = Object.values(evaluations)
- .map(x => x.data)
- .filter(a => a.submittedAt);
- const first = getFirstItemInOrder(evalArray, (a, b) => b.submittedAt - a.submittedAt);
- return first && first.id;
-};
-
-class ReferenceSolutionDetail extends Component {
- state = {
- openFileId: null,
- openFileName: '',
- openZipEntry: null,
- activeSubmissionId: null,
- scoreDialogOpened: false,
- };
-
- setActiveSubmission = id => {
- this.props.fetchScoreConfigIfNeeded && this.props.fetchScoreConfigIfNeeded(id);
- this.setState({ activeSubmissionId: id });
- };
-
- openFile = (openFileId, openFileName, openZipEntry = null) =>
- this.setState({ openFileId, openFileName, openZipEntry });
-
- hideFile = () => this.setState({ openFileId: null, openFileName: '', openZipEntry: null });
-
- openScoreDialog = () => {
- const evaluationsJS = this.props.evaluations && this.props.evaluations.toJS();
- const activeSubmissionId = evaluationsJS && (this.state.activeSubmissionId || getLastSubmissionId(evaluationsJS));
- if (activeSubmissionId) {
- this.props.fetchScoreConfigIfNeeded && this.props.fetchScoreConfigIfNeeded(activeSubmissionId);
- this.setState({ scoreDialogOpened: true });
- }
- };
-
- closeScoreDialog = () => this.setState({ scoreDialogOpened: false });
-
- render() {
- const {
- solution: { id, description, runtimeEnvironmentId, createdAt, authorId, visibility, permissionHints = EMPTY_OBJ },
- files,
- download,
- exercise,
- evaluations,
- deleteEvaluation = null,
- refreshSolutionEvaluations = null,
- runtimeEnvironments,
- scoreConfigSelector = null,
- canResubmit = false,
- } = this.props;
- const { openFileId, openFileName, openZipEntry, scoreDialogOpened } = this.state;
- const evaluationsJS = evaluations && evaluations.toJS();
- const activeSubmissionId = evaluationsJS && (this.state.activeSubmissionId || getLastSubmissionId(evaluationsJS));
-
- if (activeSubmissionId && evaluationsJS[activeSubmissionId] && evaluationsJS[activeSubmissionId].data) {
- /* eslint-disable no-var */
- var { submittedBy, evaluation, failure, isDebug, ...restSub } = evaluationsJS[activeSubmissionId].data;
- }
-
- return (
-
-
-
-
-
-
-
-
- }
- />
-
-
- {evaluations && (
-
- {!evaluation && (!evaluations || evaluations.size === 0) && (
- }>
-
-
- )}
-
- {!evaluation && !failure && evaluations && evaluations.size > 0 && refreshSolutionEvaluations && (
-
-
-
-
-
-
- |
-
-
- |
-
-
-
-
- )}
-
- {failure && }
-
- {evaluation && (
-
- )}
-
- {evaluation && }
-
- {evaluation && (
-
- )}
-
- {evaluation && (
-
-
-
-
-
- )}
- {activeSubmissionId && (
-
-
-
- {evaluations => (
-
- )}
-
-
-
- )}
-
- )}
-
-
-
-
- {activeSubmissionId && scoreConfigSelector && (
-
- )}
-
- );
- }
-}
-
-ReferenceSolutionDetail.propTypes = {
- solution: PropTypes.shape({
- id: PropTypes.string.isRequired,
- description: PropTypes.string,
- runtimeEnvironmentId: PropTypes.string,
- note: PropTypes.string,
- lastSubmission: PropTypes.shape({ id: PropTypes.string.isRequired }),
- createdAt: PropTypes.number.isRequired,
- authorId: PropTypes.string.isRequired,
- submissions: PropTypes.array.isRequired,
- visibility: PropTypes.number.isRequired,
- permissionHints: PropTypes.object,
- }).isRequired,
- files: ImmutablePropTypes.map,
- download: PropTypes.func,
- exercise: PropTypes.object.isRequired,
- evaluations: PropTypes.object.isRequired,
- deleteEvaluation: PropTypes.func,
- refreshSolutionEvaluations: PropTypes.func,
- runtimeEnvironments: PropTypes.array,
- scoreConfigSelector: PropTypes.func,
- fetchScoreConfigIfNeeded: PropTypes.func,
- canResubmit: PropTypes.bool,
-};
-
-export default ReferenceSolutionDetail;
diff --git a/src/components/ReferenceSolutions/ReferenceSolutionDetail/index.js b/src/components/ReferenceSolutions/ReferenceSolutionDetail/index.js
deleted file mode 100644
index e2226dc7f..000000000
--- a/src/components/ReferenceSolutions/ReferenceSolutionDetail/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import ReferenceSolutionDetail from './ReferenceSolutionDetail';
-export default ReferenceSolutionDetail;
diff --git a/src/components/Solutions/SolutionDetail/SolutionDetail.js b/src/components/Solutions/SolutionDetail/SolutionDetail.js
index 2120993cb..dd0c85a8a 100644
--- a/src/components/Solutions/SolutionDetail/SolutionDetail.js
+++ b/src/components/Solutions/SolutionDetail/SolutionDetail.js
@@ -17,7 +17,7 @@ import ResourceRenderer from '../../helpers/ResourceRenderer';
import SolutionFiles from '../SolutionFiles';
import EvaluationDetail from '../EvaluationDetail';
import CompilationLogs from '../CompilationLogs';
-import { RefreshIcon } from '../../icons';
+import { RefreshIcon, WarningIcon } from '../../icons';
import FailureReport from '../../SubmissionFailures/FailureReport';
import Button from '../../widgets/TheButton';
import Callout from '../../widgets/Callout';
@@ -59,24 +59,27 @@ class SolutionDetail extends Component {
const {
solution: {
id,
- attemptIndex,
- note = '',
- createdAt,
- authorId,
- maxPoints,
- overriddenPoints,
- bonusPoints,
- actualPoints,
- accepted,
- review = null,
runtimeEnvironmentId,
lastSubmission,
permissionHints = EMPTY_OBJ,
+ createdAt,
+ authorId,
+ description = null,
+ note = null,
+ attemptIndex = null,
+ maxPoints = null,
+ overriddenPoints = null,
+ bonusPoints = null,
+ actualPoints = null,
+ accepted = null,
+ review = null,
+ visibility = null,
},
files,
download,
otherSolutions,
- assignment,
+ exercise = null,
+ assignment = null,
evaluations,
runtimeEnvironments,
editNote = null,
@@ -97,6 +100,8 @@ class SolutionDetail extends Component {
var { submittedBy, evaluation, failure, isDebug, ...restSub } = evaluationsJS[activeSubmissionId].data;
}
+ const referenceSolution = exercise !== null;
+
return (
@@ -110,6 +115,7 @@ class SolutionDetail extends Component {
userId={authorId}
submittedBy={submittedBy}
note={note}
+ description={description}
editNote={editNote}
accepted={accepted}
review={review}
@@ -123,9 +129,20 @@ class SolutionDetail extends Component {
otherSolutions={otherSolutions}
assignmentSolversLoading={assignmentSolversLoading}
assignmentSolverSelector={assignmentSolverSelector}
+ visibility={visibility}
+ referenceSolution={referenceSolution}
/>
+ {referenceSolution && !evaluation && (!evaluations || evaluations.size === 0) && (
+ }>
+
+
+ )}
+
{!evaluation && !failure && refreshSolutionEvaluations && (
@@ -151,7 +168,7 @@ class SolutionDetail extends Component {
{failure && }
- {activeSubmissionId !== safeGet(lastSubmission, ['id']) && (
+ {!referenceSolution && activeSubmissionId !== safeGet(lastSubmission, ['id']) && (
)}
@@ -176,14 +194,15 @@ class SolutionDetail extends Component {
- {permissionHints.setBonusPoints && (
+ {!referenceSolution && assignment && permissionHints.setBonusPoints && (
+ referenceSolution ? (
+
+ ) : (
+
+ )
}
/>
)}
@@ -219,55 +245,60 @@ class SolutionDetail extends Component {
)}
{evaluation && permissionHints.downloadResultArchive && (
-
+
)}
- {activeSubmissionId && permissionHints.viewResubmissions && evaluations && evaluations.size > 1 && (
-
-
-
- {evaluations => (
-
- )}
-
-
-
- )}
+ {activeSubmissionId &&
+ (referenceSolution || permissionHints.viewResubmissions) &&
+ evaluations &&
+ evaluations.size > 1 && (
+
+
+
+ {evaluations => (
+
+ )}
+
+
+
+ )}
)}
+
{activeSubmissionId && scoreConfigSelector && (
)}
- {evaluation && (
+ {!referenceSolution && evaluation && (
diff --git a/src/pages/ReferenceSolution/ReferenceSolution.js b/src/pages/ReferenceSolution/ReferenceSolution.js
index 2f75151bb..3f09c37c6 100644
--- a/src/pages/ReferenceSolution/ReferenceSolution.js
+++ b/src/pages/ReferenceSolution/ReferenceSolution.js
@@ -9,7 +9,7 @@ import ResubmitReferenceSolutionContainer from '../../containers/ResubmitReferen
import ReferenceSolutionActionsContainer from '../../containers/ReferenceSolutionActionsContainer';
import Page from '../../components/layout/Page';
import { ReferenceSolutionNavigation } from '../../components/layout/Navigation';
-import ReferenceSolutionDetail from '../../components/ReferenceSolutions/ReferenceSolutionDetail';
+import SolutionDetail from '../../components/Solutions/SolutionDetail';
import FetchManyResourceRenderer from '../../components/helpers/FetchManyResourceRenderer';
import ResourceRenderer from '../../components/helpers/ResourceRenderer';
import { TheButtonGroup } from '../../components/widgets/TheButton';
@@ -26,6 +26,7 @@ import {
deleteReferenceSolutionEvaluation,
} from '../../redux/modules/referenceSolutionEvaluations';
+import { loggedInUserSelector } from '../../redux/selectors/users';
import { getReferenceSolution } from '../../redux/selectors/referenceSolutions';
import { getSolutionFiles } from '../../redux/selectors/solutionFiles';
import { getExercise } from '../../redux/selectors/exercises';
@@ -63,6 +64,7 @@ class ReferenceSolution extends Component {
render() {
const {
referenceSolution,
+ currentUser,
files,
download,
exercise,
@@ -79,8 +81,8 @@ class ReferenceSolution extends Component {
}
title={}
- resource={referenceSolution}>
- {referenceSolution => (
+ resource={[referenceSolution, currentUser]}>
+ {(referenceSolution, currentUser) => (
{exercise => (
<>
@@ -135,16 +137,17 @@ class ReferenceSolution extends Component {
{() => (
-
@@ -166,6 +169,7 @@ ReferenceSolution.propTypes = {
}).isRequired,
loadAsync: PropTypes.func.isRequired,
fetchScoreConfigIfNeeded: PropTypes.func.isRequired,
+ currentUser: ImmutablePropTypes.map,
referenceSolution: ImmutablePropTypes.map,
files: ImmutablePropTypes.map,
exercise: ImmutablePropTypes.map,
@@ -181,6 +185,7 @@ ReferenceSolution.propTypes = {
export default injectIntl(
connect(
(state, { params: { exerciseId, referenceSolutionId } }) => ({
+ currentUser: loggedInUserSelector(state),
referenceSolution: getReferenceSolution(referenceSolutionId)(state),
files: getSolutionFiles(state, referenceSolutionId),
exercise: getExercise(exerciseId)(state),
diff --git a/src/pages/Solution/Solution.js b/src/pages/Solution/Solution.js
index b37b467b3..bd81b03fe 100644
--- a/src/pages/Solution/Solution.js
+++ b/src/pages/Solution/Solution.js
@@ -269,20 +269,20 @@ class Solution extends Component {
)}