Skip to content

Commit 7480501

Browse files
ning-yremo5000
authored andcommitted
Load editorValue from solutionTemplate or answer (#215)
* Allow all questions loaded to use solutionTemplate * Implement the submit answer api call * Lengthen duration of toasters aka notifications * Load saved answer into editorValue for ProgrammingQuestions * Fix typing wrt IQuestion * Add specific error message for status code 403 * Update answer in local store on SUBMIT_ANSWER * Use tslint directly in travis CI * Update editorValue on assessment workspace mount * Add warning for trying to save an empty answer * Change empty editorValue to use null * Fix editor value in state not being updated initially * Bump version number v0.1.4 -> v0.1.5
1 parent f0bf8c4 commit 7480501

File tree

18 files changed

+197
-52
lines changed

18 files changed

+197
-52
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ branches:
88
script:
99
- yarn format:ci
1010
- yarn build-css
11-
- yarn build-js
11+
- yarn tslint -p .
1212
- yarn test-coveralls

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "cadet-frontend",
4-
"version": "0.1.4",
4+
"version": "0.1.5",
55
"scripts-info": {
66
"format": "Format source code",
77
"start": "Start the Webpack development server",

src/actions/actionTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export const LOGIN = 'LOGIN'
5353
export const SET_ROLE = 'SET_ROLE'
5454
export const SET_TOKENS = 'SET_TOKENS'
5555
export const SET_USERNAME = 'SET_USERNAME'
56+
export const SUBMIT_ANSWER = 'SUBMIT_ANSWER'
5657
export const UPDATE_HISTORY_HELPERS = 'UPDATE_HISTORY_HELPERS'
5758
export const UPDATE_ASSESSMENT_OVERVIEWS = 'UPDATE_ASSESSMENT_OVERVIEWS'
5859
export const UPDATE_ASSESSMENT = 'UPDATE_ASSESSMENT'

src/actions/session.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ export const setUsername: ActionCreator<actionTypes.IAction> = (username: string
5555
payload: username
5656
})
5757

58+
export const submitAnswer: ActionCreator<actionTypes.IAction> = (
59+
id: number,
60+
answer: string | number
61+
) => ({
62+
type: actionTypes.SUBMIT_ANSWER,
63+
payload: {
64+
id,
65+
answer
66+
}
67+
})
68+
5869
export const updateHistoryHelpers: ActionCreator<actionTypes.IAction> = (loc: string) => ({
5970
type: actionTypes.UPDATE_HISTORY_HELPERS,
6071
payload: loc

src/components/academy/grading/GradingWorkspace.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export type GradingWorkspaceProps = DispatchProps & OwnProps & StateProps
2222
export type StateProps = {
2323
activeTab: number
2424
grading?: Grading
25-
editorValue?: string
25+
editorValue: string | null
2626
editorWidth: string
2727
isRunning: boolean
2828
output: InterpreterOutput[]
@@ -69,15 +69,16 @@ class GradingWorkspace extends React.Component<GradingWorkspaceProps> {
6969
* occurs after the call to checkWorkspaceReset finishes.
7070
*/
7171
public componentDidMount() {
72-
this.checkWorkspaceReset(this.props)
7372
this.props.handleGradingFetch(this.props.submissionId)
7473
}
7574

7675
/**
7776
* After the Grading is fetched, there is a check for wether the
7877
* workspace needs to be udpated (a change in submissionId or questionId)
7978
*/
80-
public componentDidUpdate() {}
79+
public componentDidUpdate() {
80+
this.checkWorkspaceReset(this.props)
81+
}
8182

8283
public render() {
8384
if (this.props.grading === undefined) {
@@ -97,15 +98,18 @@ class GradingWorkspace extends React.Component<GradingWorkspaceProps> {
9798
: this.props.questionId
9899
/* Get the question to be graded */
99100
const question = this.props.grading[questionId].question as IQuestion
101+
const editorValue =
102+
question.type === QuestionTypes.programming
103+
? question.answer !== null
104+
? ((question as IProgrammingQuestion).answer as string)
105+
: (question as IProgrammingQuestion).solutionTemplate
106+
: null
100107
const workspaceProps: WorkspaceProps = {
101108
controlBarProps: this.controlBarProps(this.props, questionId),
102109
editorProps:
103110
question.type === QuestionTypes.programming
104111
? {
105-
editorValue:
106-
this.props.editorValue !== undefined
107-
? this.props.editorValue
108-
: (question as IProgrammingQuestion).solutionTemplate,
112+
editorValue: editorValue!,
109113
handleEditorEval: this.props.handleEditorEval,
110114
handleEditorValueChange: this.props.handleEditorValueChange
111115
}
@@ -150,12 +154,22 @@ class GradingWorkspace extends React.Component<GradingWorkspaceProps> {
150154
this.props.storedSubmissionId !== submissionId ||
151155
this.props.storedQuestionId !== questionId
152156
) {
153-
const chapter = this.props.grading[questionId].question.library.chapter
154-
const externalName = this.props.grading[questionId].question.library.externalLibraryName
155-
const externals = this.props.grading[questionId].question.library.externals
157+
const question = this.props.grading[questionId].question as IQuestion
158+
const chapter = question.library.chapter
159+
const externalName = question.library.externalLibraryName
160+
const externals = question.library.externals
161+
const editorValue =
162+
question.type === QuestionTypes.programming
163+
? question.answer !== null
164+
? ((question as IProgrammingQuestion).answer as string)
165+
: (question as IProgrammingQuestion).solutionTemplate
166+
: null
156167
this.props.handleUpdateCurrentSubmissionId(submissionId, questionId)
157168
this.props.handleResetWorkspace()
158169
this.props.handleClearContext(chapter, externals, externalName)
170+
if (editorValue) {
171+
this.props.handleEditorValueChange(editorValue)
172+
}
159173
}
160174
}
161175

src/components/academy/grading/gradingShape.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export type GradingQuestion = {
4343
*/
4444
interface IAnsweredQuestion extends IQuestion {
4545
solution?: number
46-
answer?: string | number
46+
answer: string | number | null
4747
solutionTemplate?: string
4848
choices?: MCQChoice[]
4949
}

src/components/assessment/AssessmentWorkspace.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type AssessmentWorkspaceProps = DispatchProps & OwnProps & StateProps
2323
export type StateProps = {
2424
activeTab: number
2525
assessment?: IAssessment
26-
editorValue?: string
26+
editorValue: string | null
2727
editorWidth: string
2828
isRunning: boolean
2929
output: InterpreterOutput[]
@@ -58,6 +58,7 @@ export type DispatchProps = {
5858
handleReplOutputClear: () => void
5959
handleReplValueChange: (newValue: string) => void
6060
handleResetWorkspace: () => void
61+
handleSave: (id: number, answer: number | string) => void
6162
handleSideContentHeightChange: (heightChange: number) => void
6263
handleUpdateCurrentAssessmentId: (assessmentId: number, questionId: number) => void
6364
}
@@ -76,13 +77,16 @@ class AssessmentWorkspace extends React.Component<
7677
* occurs after the call to checkWorkspaceReset finishes.
7778
*/
7879
public componentDidMount() {
79-
this.checkWorkspaceReset(this.props)
8080
this.props.handleAssessmentFetch(this.props.assessmentId)
8181
if (this.props.questionId === 0) {
8282
this.setState({ showOverlay: true })
8383
}
8484
}
8585

86+
public componentDidUpdate() {
87+
this.checkWorkspaceReset(this.props)
88+
}
89+
8690
public render() {
8791
if (this.props.assessment === undefined || this.props.assessment.questions.length === 0) {
8892
return (
@@ -112,15 +116,18 @@ class AssessmentWorkspace extends React.Component<
112116
? this.props.assessment.questions.length - 1
113117
: this.props.questionId
114118
const question: IQuestion = this.props.assessment.questions[questionId]
119+
const editorValue =
120+
question.type === QuestionTypes.programming
121+
? question.answer !== null
122+
? ((question as IProgrammingQuestion).answer as string)
123+
: (question as IProgrammingQuestion).solutionTemplate
124+
: null
115125
const workspaceProps: WorkspaceProps = {
116126
controlBarProps: this.controlBarProps(this.props, questionId),
117127
editorProps:
118128
question.type === QuestionTypes.programming
119129
? {
120-
editorValue:
121-
this.props.editorValue !== undefined
122-
? this.props.editorValue
123-
: (question as IProgrammingQuestion).solutionTemplate,
130+
editorValue: editorValue!,
124131
handleEditorEval: this.props.handleEditorEval,
125132
handleEditorValueChange: this.props.handleEditorValueChange
126133
}
@@ -151,8 +158,6 @@ class AssessmentWorkspace extends React.Component<
151158
/**
152159
* Checks if there is a need to reset the workspace, then executes
153160
* a dispatch (in the props) if needed.
154-
*
155-
* @param props the props passed to the component
156161
*/
157162
private checkWorkspaceReset(props: AssessmentWorkspaceProps) {
158163
/* Don't reset workspace if assessment not fetched yet. */
@@ -168,12 +173,22 @@ class AssessmentWorkspace extends React.Component<
168173
this.props.storedAssessmentId !== assessmentId ||
169174
this.props.storedQuestionId !== questionId
170175
) {
171-
const chapter = this.props.assessment.questions[questionId].library.chapter
172-
const externalName = this.props.assessment.questions[questionId].library.externalLibraryName
173-
const externals = this.props.assessment.questions[questionId].library.externals
176+
const question = this.props.assessment.questions[questionId]
177+
const chapter = question.library.chapter
178+
const externalName = question.library.externalLibraryName
179+
const externals = question.library.externals
180+
const editorValue =
181+
question.type === QuestionTypes.programming
182+
? question.answer !== null
183+
? ((question as IProgrammingQuestion).answer as string)
184+
: (question as IProgrammingQuestion).solutionTemplate
185+
: null
174186
this.props.handleUpdateCurrentAssessmentId(assessmentId, questionId)
175187
this.props.handleResetWorkspace()
176188
this.props.handleClearContext(chapter, externals, externalName)
189+
if (editorValue) {
190+
this.props.handleEditorValueChange(editorValue)
191+
}
177192
}
178193
}
179194

@@ -223,6 +238,11 @@ class AssessmentWorkspace extends React.Component<
223238
onClickNext: () => history.push(assessmentWorkspacePath + `/${(questionId + 1).toString()}`),
224239
onClickPrevious: () =>
225240
history.push(assessmentWorkspacePath + `/${(questionId - 1).toString()}`),
241+
onClickSave: () =>
242+
this.props.handleSave(
243+
this.props.assessment!.questions[questionId].id,
244+
this.props.editorValue!
245+
),
226246
sourceChapter: this.props.assessment!.questions[questionId].library.chapter
227247
}
228248
}

src/components/assessment/__tests__/AssessmentWorkspace.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const defaultProps: AssessmentWorkspaceProps = {
88
activeTab: 0,
99
assessmentId: 0,
1010
closeDate: '2048-06-18T05:24:26.026Z',
11+
editorValue: null,
1112
editorWidth: '50%',
1213
handleAssessmentFetch: (assessmentId: number) => {},
1314
handleBrowseHistoryDown: () => {},
@@ -23,6 +24,7 @@ const defaultProps: AssessmentWorkspaceProps = {
2324
handleReplOutputClear: () => {},
2425
handleReplValueChange: (newValue: string) => {},
2526
handleResetWorkspace: () => {},
27+
handleSave: (id: number, answer: string | number) => {},
2628
handleSideContentHeightChange: (heightChange: number) => {},
2729
handleUpdateCurrentAssessmentId: (a: number, q: number) => {},
2830
isRunning: false,

src/components/assessment/__tests__/__snapshots__/AssessmentWorkspace.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ exports[`AssessmentWorkspace page with MCQ question renders correctly 1`] = `
1414
<Blueprint2.Button className=\\"assessment-briefing-button\\" onClick={[Function: onClick]} text=\\"Continue\\" />
1515
</Blueprint2.Card>
1616
</Blueprint2.Dialog>
17-
<Workspace controlBarProps={{...}} editorProps={{...}} editorWidth=\\"50%\\" handleEditorWidthChange={[Function: handleEditorWidthChange]} handleSideContentHeightChange={[Function: handleSideContentHeightChange]} mcq={{...}} sideContentHeight={[undefined]} sideContentProps={{...}} replProps={{...}} />
17+
<Workspace controlBarProps={{...}} editorProps={[undefined]} editorWidth=\\"50%\\" handleEditorWidthChange={[Function: handleEditorWidthChange]} handleSideContentHeightChange={[Function: handleSideContentHeightChange]} mcq={{...}} sideContentHeight={[undefined]} sideContentProps={{...}} replProps={{...}} />
1818
</div>"
1919
`;
2020

src/components/assessment/assessmentShape.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export interface IMCQQuestion extends IQuestion {
4545
}
4646

4747
export interface IQuestion {
48+
answer: string | number | null
4849
content: string
4950
id: number
5051
library: Library

0 commit comments

Comments
 (0)