diff --git a/src/components/assessment/AssessmentWorkspace.tsx b/src/components/assessment/AssessmentWorkspace.tsx old mode 100755 new mode 100644 index ddc16ce912..0cd778bd64 --- a/src/components/assessment/AssessmentWorkspace.tsx +++ b/src/components/assessment/AssessmentWorkspace.tsx @@ -1,4 +1,13 @@ -import { Button, Card, Dialog, NonIdealState, Spinner } from '@blueprintjs/core'; +import { + Button, + ButtonGroup, + Card, + Classes, + Dialog, + Intent, + NonIdealState, + Spinner +} from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; import * as React from 'react'; @@ -6,6 +15,7 @@ import { InterpreterOutput, IWorkspaceState } from '../../reducers/states'; import { beforeNow } from '../../utils/dateHelpers'; import { history } from '../../utils/history'; import { assessmentCategoryLink } from '../../utils/paramParseHelpers'; +import { controlButton } from '../commons'; import Markdown from '../commons/Markdown'; import Workspace, { WorkspaceProps } from '../workspace'; import { ControlBarProps } from '../workspace/ControlBar'; @@ -67,13 +77,15 @@ export type DispatchProps = { class AssessmentWorkspace extends React.Component< AssessmentWorkspaceProps, - { showOverlay: boolean } + { showOverlay: boolean; showResetOverlay: boolean } > { public constructor(props: AssessmentWorkspaceProps) { super(props); this.state = { - showOverlay: false + showOverlay: false, + showResetOverlay: false }; + this.props.handleEditorValueChange(''); } /** @@ -86,6 +98,20 @@ class AssessmentWorkspace extends React.Component< if (this.props.questionId === 0 && this.props.notAttempted) { this.setState({ showOverlay: true }); } + if (this.props.assessment) { + const question: IQuestion = this.props.assessment.questions[ + this.props.questionId >= this.props.assessment.questions.length + ? this.props.assessment.questions.length - 1 + : this.props.questionId + ]; + this.props.handleEditorValueChange( + question.type === QuestionTypes.programming + ? question.answer !== null + ? ((question as IProgrammingQuestion).answer as string) + : (question as IProgrammingQuestion).solutionTemplate + : '' + ); + } } /** @@ -119,24 +145,53 @@ class AssessmentWorkspace extends React.Component< ); + + const resetOverlay = ( + +
+ + +
+
+ + {controlButton('Cancel', null, () => this.setState({ showResetOverlay: false }), { + minimal: false + })} + {controlButton( + 'Confirm', + null, + () => { + this.setState({ showResetOverlay: false }); + this.props.handleEditorValueChange( + (this.props.assessment!.questions[questionId] as IProgrammingQuestion) + .solutionTemplate + ); + this.props.handleUpdateHasUnsavedChanges(true); + }, + { minimal: false, intent: Intent.DANGER } + )} + +
+
+ ); /* If questionId is out of bounds, set it to the max. */ const questionId = this.props.questionId >= this.props.assessment.questions.length ? this.props.assessment.questions.length - 1 : this.props.questionId; const question: IQuestion = this.props.assessment.questions[questionId]; - const editorValue = - question.type === QuestionTypes.programming - ? question.answer !== null - ? ((question as IProgrammingQuestion).answer as string) - : (question as IProgrammingQuestion).solutionTemplate - : null; const workspaceProps: WorkspaceProps = { controlBarProps: this.controlBarProps(this.props, questionId), editorProps: question.type === QuestionTypes.programming ? { - editorValue: editorValue!, + editorValue: this.props.editorValue!, handleEditorEval: this.props.handleEditorEval, handleEditorValueChange: this.props.handleEditorValueChange, handleUpdateHasUnsavedChanges: this.props.handleUpdateHasUnsavedChanges @@ -165,6 +220,7 @@ class AssessmentWorkspace extends React.Component< return (
{overlay} + {resetOverlay}
); @@ -194,7 +250,7 @@ class AssessmentWorkspace extends React.Component< ? question.answer !== null ? ((question as IProgrammingQuestion).answer as string) : (question as IProgrammingQuestion).solutionTemplate - : null; + : ''; this.props.handleUpdateCurrentAssessmentId(assessmentId, questionId); this.props.handleResetWorkspace({ editorValue }); this.props.handleClearContext(question.library); @@ -286,6 +342,9 @@ class AssessmentWorkspace extends React.Component< this.props.assessment!.questions[questionId].id, this.props.editorValue! ), + onClickReset: () => { + this.setState({ showResetOverlay: true }); + }, questionProgress: [questionId + 1, this.props.assessment!.questions.length], sourceChapter: this.props.assessment!.questions[questionId].library.chapter }; diff --git a/src/components/assessment/__tests__/__snapshots__/AssessmentWorkspace.tsx.snap b/src/components/assessment/__tests__/__snapshots__/AssessmentWorkspace.tsx.snap index dc954779c5..a3a3c8643e 100644 --- a/src/components/assessment/__tests__/__snapshots__/AssessmentWorkspace.tsx.snap +++ b/src/components/assessment/__tests__/__snapshots__/AssessmentWorkspace.tsx.snap @@ -10,6 +10,22 @@ exports[`AssessmentWorkspace page with MCQ question renders correctly 1`] = ` + +
+ + +
+
+ + + Cancel + + + Confirm + + +
+
" `; @@ -22,6 +38,22 @@ exports[`AssessmentWorkspace page with overdue assessment renders correctly 1`] + +
+ + +
+
+ + + Cancel + + + Confirm + + +
+
" `; @@ -34,6 +66,22 @@ exports[`AssessmentWorkspace page with programming question renders correctly 1` + +
+ + +
+
+ + + Cancel + + + Confirm + + +
+
" `; diff --git a/src/components/workspace/ControlBar.tsx b/src/components/workspace/ControlBar.tsx old mode 100755 new mode 100644 index 5bf80be90e..6b1be54a42 --- a/src/components/workspace/ControlBar.tsx +++ b/src/components/workspace/ControlBar.tsx @@ -37,6 +37,7 @@ export type ControlBarProps = { onClickPrevious?(): any; onClickReturn?(): any; onClickSave?(): any; + onClickReset?(): any; }; interface IChapter { @@ -62,7 +63,8 @@ class ControlBar extends React.PureComponent { hasShareButton: true, onClickNext: () => {}, onClickPrevious: () => {}, - onClickSave: () => {} + onClickSave: () => {}, + onClickReset: () => {} }; private shareInputElem: HTMLInputElement; @@ -130,6 +132,9 @@ class ControlBar extends React.PureComponent { this.props.hasChapterSelect && this.props.externalLibraryName !== undefined ? externalSelect(this.props.externalLibraryName, this.props.handleExternalSelect!) : undefined; + const resetButton = this.props.hasSaveButton + ? controlButton('Reset', IconNames.REPEAT, this.props.onClickReset) + : undefined; const startAutorunButton = this.props.hasEditorAutorunButton ? controlButton('Autorun', IconNames.PLAY, this.props.handleToggleEditorAutorun) : undefined; @@ -140,7 +145,7 @@ class ControlBar extends React.PureComponent {
{this.props.isEditorAutorun ? undefined : this.props.isRunning ? stopButton : runButton} {saveButton} - {shareButton} {chapterSelectButton} {externalSelectButton} + {shareButton} {chapterSelectButton} {externalSelectButton} {resetButton} {this.props.isEditorAutorun ? stopAutorunButton : startAutorunButton}
); diff --git a/src/styles/_academy.scss b/src/styles/_academy.scss index e584891821..1905c06a4a 100644 --- a/src/styles/_academy.scss +++ b/src/styles/_academy.scss @@ -129,7 +129,8 @@ } } -.betcha-dialog { +.betcha-dialog, +.assessment-reset { span.warning { font-weight: bold; color: firebrick;