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 { )}