Skip to content

Commit 6226c5c

Browse files
authored
Merge pull request #225 from makeopensource/62-add-text-problem-modal
#62 - Implement adding text problem modal
2 parents ca64638 + 636ec9f commit 6226c5c

5 files changed

Lines changed: 125 additions & 41 deletions

File tree

devU-client/src/assets/global.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
color: var(--text-color);
117117
border: none;
118118
border-radius: 5px;
119+
cursor: pointer;
119120
}
120121

121122
button.modalAction {

devU-client/src/components/pages/forms/assignments/assignmentUpdatePage.tsx

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import DialogActions from '@mui/material/DialogActions';
1515
import DialogContent from '@mui/material/DialogContent';
1616
import { getCssVariables } from 'utils/theme.utils'
1717
import { Button as MuiButton, StyledEngineProvider } from '@mui/material'
18+
import TextProblemModal from './textProblemModal'
1819
/*import Dropdown, { Option } from 'components/shared/inputs/dropdown';*/
1920
//import Select from 'react-select/src/Select'
2021

@@ -218,32 +219,31 @@ setFiles;
218219
}
219220
}*/
220221

221-
const [addProblemModal, setAddProblemModal] = useState(false)
222-
const [addProblemForm, setAddProblemForm] = useState({
223-
assignmentId: currentAssignmentId,
224-
problemName: '',
225-
maxScore: 0,
226-
})
227-
const openAddProblemModal = () => {setAddProblemModal(true)}
228-
const handleCloseAddProblemModal = () => {setAddProblemModal(false)}
229-
230-
const handleAddProblemChange = (value: String, e: React.ChangeEvent<HTMLInputElement>) => {
231-
const key = e.target.id
232-
setAddProblemForm(prevState => ({ ...prevState, [key]: value }))
233-
}
234-
const handleAddProblem = () => {
235-
RequestService.post(`/api/course/${courseId}/assignment/${currentAssignmentId}/assignment-problems`, addProblemForm)
236-
.then(() => {
237-
setAlert({ autoDelete: true, type: 'success', message: 'Problem Added' })
238-
setAddProblemModal(false)
239-
setAddProblemForm({
240-
assignmentId: currentAssignmentId,
241-
problemName: '',
242-
maxScore: 0,
243-
})
244-
fetchAssignmentProblems()
245-
})
246-
}
222+
const [textModal, setTextModal] = useState(false)
223+
// const [addProblemForm, setAddProblemForm] = useState({
224+
// assignmentId: currentAssignmentId,
225+
// problemName: '',
226+
// maxScore: 0,
227+
// })
228+
const handleCloseTextModal = () => {setTextModal(false)}
229+
230+
// const handleAddProblemChange = (value: String, e: React.ChangeEvent<HTMLInputElement>) => {
231+
// const key = e.target.id
232+
// setAddProblemForm(prevState => ({ ...prevState, [key]: value }))
233+
// }
234+
// const handleAddProblem = () => {
235+
// RequestService.post(`/api/course/${courseId}/assignment/${currentAssignmentId}/assignment-problems`, addProblemForm)
236+
// .then(() => {
237+
// setAlert({ autoDelete: true, type: 'success', message: 'Problem Added' })
238+
// setAddProblemModal(false)
239+
// setAddProblemForm({
240+
// assignmentId: currentAssignmentId,
241+
// problemName: '',
242+
// maxScore: 0,
243+
// })
244+
// fetchAssignmentProblems()
245+
// })
246+
// }
247247

248248
const handleDeleteProblem = (problemId: number) => {
249249
RequestService.delete(`/api/course/${courseId}/assignment/${currentAssignmentId}/assignment-problems/${problemId}`)
@@ -269,17 +269,8 @@ setFiles;
269269
</DialogContent>
270270
</Dialog>
271271

272-
<Dialog open={addProblemModal} onClose={handleCloseAddProblemModal}>
273-
<DialogContent sx={{bgcolor:theme.listItemBackground}}>
274-
<h3 className={styles.header}>Add Problem</h3>
275-
<TextField id="problemName" label={'Problem Name'} onChange={handleAddProblemChange}/>
276-
<TextField id="maxScore" label={'Max Score'} onChange={handleAddProblemChange}/>
277-
<DialogActions>
278-
<Button onClick={handleAddProblem}>Add</Button>
279-
<Button onClick={handleCloseAddProblemModal}>Close</Button>
280-
</DialogActions>
281-
</DialogContent>
282-
</Dialog>
272+
<TextProblemModal open={textModal} onClose={handleCloseTextModal}/>
273+
283274
<div className={styles.pageHeader}>
284275
<h1 style={{gridColumnStart:2}}>Edit Assignment</h1>
285276
<Button className={`btnPrimary ${styles.backToCourse}`} onClick={() => {history.goBack()}}>back to course</Button>
@@ -381,7 +372,7 @@ setFiles;
381372
<h2 className={styles.header}>Add Problems</h2>
382373
<div className={styles.buttonContainer}>
383374
<Button onClick={() => setAlert({ autoDelete: true, type: 'error', message: 'Setup Code/File Input creation modal' })} className='btnSecondary'>Code/File Input</Button>
384-
<Button onClick={openAddProblemModal} className='btnSecondary'>Text Input</Button>
375+
<Button onClick={() => {setTextModal(true)}} className='btnSecondary'>Text Input</Button>
385376
<Button onClick={() => setAlert({ autoDelete: true, type: 'error', message: 'Setup Multiple Choice creation modal' })} className='btnSecondary'>Multiple Choice</Button>
386377
</div>
387378
<h2 className={styles.header}>Add Graders</h2>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React, { useState } from 'react'
2+
import { useParams } from 'react-router-dom'
3+
import { ExpressValidationError } from 'devu-shared-modules'
4+
import { SET_ALERT } from 'redux/types/active.types'
5+
import { useActionless } from 'redux/hooks'
6+
import RequestService from 'services/request.service'
7+
import Modal from 'components/shared/layouts/modal'
8+
9+
interface Props {
10+
open: boolean;
11+
onClose: () => void;
12+
}
13+
14+
const TextProblemModal = ({ open, onClose }: Props) => {
15+
const [setAlert] = useActionless(SET_ALERT)
16+
const { assignmentId } = useParams<{ assignmentId: string }>()
17+
const { courseId } = useParams<{ courseId: string }>()
18+
const [formData, setFormData] = useState({
19+
title: '',
20+
maxScore: '',
21+
correctAnswer: '',
22+
regex: false
23+
});
24+
25+
const handleSubmit = () => {
26+
// early return if form not fully filled out
27+
if (!formData.title || !formData.maxScore || !formData.correctAnswer) { return }
28+
29+
const problemFormData = {
30+
assignmentId: parseInt(assignmentId),
31+
problemName: formData.title,
32+
maxScore: parseInt(formData.maxScore),
33+
};
34+
35+
const graderFormData = {
36+
assignmentId: parseInt(assignmentId),
37+
question: formData.title,
38+
correctString: formData.correctAnswer,
39+
score: Number(formData.maxScore),
40+
isRegex: formData.regex,
41+
}
42+
43+
RequestService.post(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems`, problemFormData)
44+
.then(() => {
45+
console.log("PROBLEM CREATED")
46+
})
47+
.catch((err: ExpressValidationError[] | Error) => {
48+
const message = Array.isArray(err) ? err.map((e) => `${e.param} ${e.msg}`).join(', ') : err.message
49+
setAlert({ autoDelete: false, type: 'error', message })
50+
})
51+
52+
RequestService.post(`/api/course/${courseId}/assignment/${assignmentId}/non-container-auto-graders/`, graderFormData)
53+
.then(() => {
54+
console.log("GRADER CREATED")
55+
})
56+
.catch((err: ExpressValidationError[] | Error) => {
57+
const message = Array.isArray(err) ? err.map((e) => `${e.param} ${e.msg}`).join(', ') : err.message
58+
setAlert({ autoDelete: false, type: 'error', message })
59+
})
60+
61+
// close modal
62+
onClose();
63+
}
64+
65+
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
66+
const key = e.target.id
67+
const value = e.target.value
68+
69+
setFormData(prevState => ({ ...prevState, [key]: value }))
70+
}
71+
72+
return (
73+
<Modal title="Add Text Problem" buttonAction={handleSubmit} open={open} onClose={onClose}>
74+
<div className="input-group">
75+
<label htmlFor="title" className="input-label">Problem Title:</label>
76+
<input type="text" id="title" onChange={handleChange}
77+
placeholder='e.g. What is the time complexity of MergeSort?' />
78+
</div>
79+
<div className="input-group">
80+
<label htmlFor="correctAnswer" className="input-label">Correct Answer:</label>
81+
<input type="text" id="correctAnswer" onChange={handleChange}
82+
placeholder='e.g. O(nlogn)' />
83+
</div>
84+
<div className="input-group">
85+
<label htmlFor="maxScore" className="input-label">Maximum Score:</label>
86+
<input type="number" id="maxScore" onChange={handleChange}
87+
placeholder='e.g. 10' min="0" />
88+
</div>
89+
<label htmlFor="regex">Correct answer is regex <input type="checkbox" id="regex" /></label>
90+
</Modal>
91+
)
92+
}
93+
94+
export default TextProblemModal;

devU-client/src/components/pages/forms/courses/createCourseModal.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ const CreateCourseModal = ({ open, onClose }: Props) => {
5252
privateDate: formatDateForSubmission(endDate)
5353
};
5454

55-
console.log("HANDLE SUBMIT TRIGGERED")
56-
console.log("FORM DATA:", finalFormData)
57-
5855
RequestService.post('/api/courses/instructor', finalFormData)
5956
.then(() => {
6057
setAlert({ autoDelete: true, type: 'success', message: 'Course Added' });

devU-client/src/components/shared/layouts/modal.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const Modal = ({ title, children, buttonAction, open, onClose }: ModalProps) =>
2323
<Dialog open={open} onClose={onClose} className='modal'
2424
sx={{
2525
"& .MuiPaper-root": {
26+
minWidth: "350px",
2627
padding: "20px",
2728
display: "flex",
2829
flexDirection: "column",

0 commit comments

Comments
 (0)