Skip to content

Commit 5635bc2

Browse files
authored
Merge pull request #272 from makeopensource/112-pdf-comment-frontend
DEPLOYMENT FIX: added back functionality for adding file upload problems
2 parents cbacb60 + c6cbc17 commit 5635bc2

File tree

5 files changed

+99
-42
lines changed

5 files changed

+99
-42
lines changed

devU-client/src/components/listItems/assignmentProblemListItem.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ const AssignmentProblemListItem = ({problem, handleChange, disabled}: Props) =>
9292
</label>))}
9393
</div>)
9494
}
95+
96+
else if (type == "File") {
97+
return (
98+
<div key={problem.id} className={styles.problem}>
99+
<h4 className={styles.problem_header}>{problem.problemName}</h4>
100+
</div>
101+
)
102+
}
95103

96104
else {
97105
return(

devU-client/src/components/pages/assignments/assignmentDetailPage.tsx

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { SET_ALERT } from 'redux/types/active.types'
1111
//import Card from '@mui/material/Card'
1212
//import CardContent from '@mui/material/CardContent'
1313
//import {Accordion, AccordionDetails, TextField, Typography} from '@mui/material'
14+
import DragDropFile from 'components/utils/dragDropFile'
1415

1516

1617
//import Grid from '@mui/material/Unstable_Grid2'
@@ -38,6 +39,8 @@ const AssignmentDetailPage = () => {
3839
const [assignment, setAssignment] = useState<Assignment>()
3940
const [course, setCourse] = useState<Course>()
4041
const [notClickable, setNotClickable] = useState(true);
42+
const [hasFileProblem, setHasFileProblem] = useState(false);
43+
4144

4245

4346

@@ -61,7 +64,11 @@ const AssignmentDetailPage = () => {
6164
setCourse(courses)
6265

6366
const assignmentProblemsReq = await RequestService.get<AssignmentProblem[]>(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems/`)
64-
setAssignmentProblems(assignmentProblemsReq)
67+
const hasFile = assignmentProblemsReq.some(problem => problem.metadata.type === "File")
68+
setHasFileProblem(hasFile)
69+
70+
const filteredProblems = assignmentProblemsReq.filter(problem => problem.metadata.type !== "File")
71+
setAssignmentProblems(filteredProblems)
6572

6673
const submissionsReq = await RequestService.get<Submission[]>(`/api/course/${courseId}/assignment/${assignmentId}/submissions/`)
6774
submissionsReq.sort((a, b) => (Date.parse(b.createdAt ?? '') - Date.parse(a.createdAt ?? '')))
@@ -128,8 +135,8 @@ const AssignmentDetailPage = () => {
128135
};
129136

130137

131-
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
132-
setFile(e.target.files?.item(0))
138+
const handleFileChange = (file: File) => {
139+
setFile(file)
133140
}
134141

135142
const handleCheckboxChange = () => {
@@ -242,10 +249,15 @@ const AssignmentDetailPage = () => {
242249

243250
<div className={styles.problems_section}>
244251

245-
{/* <div className={styles.file_upload}>
246-
<h4 className={styles.problem_header}>File Upload:</h4>
247-
<DragDropFile handleFile={(e) => {console.log(e)}} />
248-
</div> */}
252+
{/* conditionally render file upload */}
253+
{hasFileProblem && (
254+
<div className={styles.file_upload}>
255+
<h4 className={styles.problem_header}>File Upload:</h4>
256+
<DragDropFile handleFile={handleFileChange} />
257+
<span style={{margin: '15px 0', marginRight: '10px'}}>{file?.name}</span>
258+
{file && (<button className="btnDelete" onClick={() => setFile(null)}>Remove Files</button>)}
259+
</div>
260+
)}
249261

250262
<div className={styles.problems_list}>
251263
<h2>Problems</h2>

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const AssignmentUpdatePage = () => {
3232
const [assignmentProblems, setAssignmentProblems] = useState<AssignmentProblem[]>([])
3333
const [nonContainerAutograders, setNonContainerAutograders] = useState<NonContainerAutoGrader[]>([])
3434
const [containerAutograders, setContainerAutograders] = useState<ContainerAutoGrader[]>([])
35+
const [fileProblemId, setFileProblemId] = useState<number>()
3536

3637

3738
const [mcqProblemId, setMcqProblemId] = useState<number>()
@@ -210,8 +211,11 @@ const AssignmentUpdatePage = () => {
210211
}
211212

212213

213-
214-
214+
const [fileEditModal, setFileEditModal] = useState(false);
215+
const handleCloseFileEditModal = async () => {
216+
setFileEditModal(false)
217+
fetchAssignmentProblems()
218+
}
215219

216220

217221
const handleDeleteProblem = async (problem: AssignmentProblem) => {
@@ -252,14 +256,16 @@ const AssignmentUpdatePage = () => {
252256
};
253257

254258
const openEditModal = (problem: AssignmentProblem) => {
255-
const type = JSON.parse(problem.metadata).type ?? ""
259+
const type = problem.metadata.type ?? ""
256260
if (type === "MCQ-mult" || type === "MCQ-single"){
257261
setMcqProblemId(problem.id)
258262
setMcqEditModal(true)
259263
} else if (type === "Match"){
260264
console.log("Implement Match MCQ")
261-
}
262-
else {
265+
} else if (type === "File") {
266+
setFileProblemId(problem.id)
267+
setFileEditModal(true)
268+
} else {
263269
setTextProblemId(problem.id)
264270
setTextEditModal(true)
265271
}
@@ -277,7 +283,8 @@ const AssignmentUpdatePage = () => {
277283
<ContainerAutoGraderModal open={containerAutoGraderModal} onClose={handleCloseContainerAutoGraderModal} />
278284
<TextProblemModal open={textModal} onClose={handleCloseTextModal} />
279285
<TextProblemModal open={textEditModal} onClose={handleCloseTextEditModal} edit problemId={textProblemId}/>
280-
<CodeProblemModal open={codeModal} onClose={handleCloseCodeModal}/>
286+
<CodeProblemModal open={codeModal} onClose={handleCloseCodeModal} />
287+
<CodeProblemModal open={fileEditModal} onClose={handleCloseFileEditModal} edit problemId={fileProblemId} />
281288
<MultipleChoiceModal open={mcqModal} onClose={handleCloseMcqModal} />
282289
<MultipleChoiceModal open={mcqEditModal} onClose={handleCloseEditMcqModal} edit problemId={mcqProblemId}/>
283290

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

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { useParams } from 'react-router-dom';
3-
import { ExpressValidationError } from 'devu-shared-modules';
3+
import { ExpressValidationError, AssignmentProblem } from 'devu-shared-modules';
44
import { SET_ALERT } from 'redux/types/active.types';
55
import { useActionless } from 'redux/hooks';
66
import RequestService from 'services/request.service';
@@ -9,9 +9,11 @@ import Modal from 'components/shared/layouts/modal';
99
interface Props {
1010
open: boolean;
1111
onClose: () => void;
12+
edit?: boolean;
13+
problemId?: number;
1214
}
1315

14-
const CodeProblemModal = ({ open, onClose }: Props) => {
16+
const CodeProblemModal = ({ open, onClose, edit, problemId }: Props) => {
1517
const [setAlert] = useActionless(SET_ALERT);
1618
const { assignmentId } = useParams<{ assignmentId: string }>();
1719
const { courseId } = useParams<{ courseId: string }>();
@@ -22,31 +24,56 @@ const CodeProblemModal = ({ open, onClose }: Props) => {
2224
maxScore: '',
2325
});
2426

27+
const setInitalFormData = async () => {
28+
if (!problemId) {
29+
return
30+
}
31+
32+
const assignmentProblemData = await RequestService.get<AssignmentProblem>(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems/${problemId}`);
33+
setFormData(({
34+
title: assignmentProblemData.problemName,
35+
maxScore: '' + assignmentProblemData.maxScore,
36+
}))
37+
}
38+
39+
useEffect(() => { setInitalFormData() }, [problemId])
2540

2641
const submittable = () => {
27-
if (!formData.title || !formData.maxScore) {return false}
28-
else {return true}
42+
if (!formData.title || !formData.maxScore) { return false }
43+
else { return true }
2944
}
3045

3146
const handleSubmit = () => {
3247
if (!submittable) return;
3348

34-
3549
const problemFormData = {
3650
assignmentId: parseInt(assignmentId),
3751
problemName: formData.title,
3852
maxScore: parseInt(formData.maxScore),
53+
metadata: {
54+
type: 'File'
55+
}
3956
};
4057

41-
RequestService.post(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems`, problemFormData)
42-
.then(() => {
43-
setAlert({ autoDelete: true, type: 'success', message: 'Problem Added' });
44-
})
45-
.catch((err: ExpressValidationError[] | Error) => {
46-
const message = Array.isArray(err) ? err.map((e) => `${e.param} ${e.msg}`).join(', ') : err.message;
47-
setAlert({ autoDelete: false, type: 'error', message });
48-
});
49-
58+
if (edit) {
59+
RequestService.put(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems/${problemId}`, problemFormData)
60+
.then(() => {
61+
setAlert({ autoDelete: true, type: 'success', message: 'Problem Added' });
62+
})
63+
.catch((err: ExpressValidationError[] | Error) => {
64+
const message = Array.isArray(err) ? err.map((e) => `${e.param} ${e.msg}`).join(', ') : err.message;
65+
setAlert({ autoDelete: false, type: 'error', message });
66+
});
67+
} else {
68+
RequestService.post(`/api/course/${courseId}/assignment/${assignmentId}/assignment-problems`, problemFormData)
69+
.then(() => {
70+
setAlert({ autoDelete: true, type: 'success', message: 'Problem Added' });
71+
})
72+
.catch((err: ExpressValidationError[] | Error) => {
73+
const message = Array.isArray(err) ? err.map((e) => `${e.param} ${e.msg}`).join(', ') : err.message;
74+
setAlert({ autoDelete: false, type: 'error', message });
75+
});
76+
}
5077

5178
closeModal();
5279
};
@@ -55,7 +82,7 @@ const CodeProblemModal = ({ open, onClose }: Props) => {
5582
setFormData({
5683
title: '',
5784
maxScore: ''
58-
})
85+
})
5986
onClose()
6087
}
6188

@@ -67,25 +94,27 @@ const CodeProblemModal = ({ open, onClose }: Props) => {
6794
};
6895

6996
return (
70-
<Modal title="Add Code/File Input Problem" buttonAction={handleSubmit} open={open} onClose={closeModal} isSubmittable={submittable}>
97+
<Modal title={edit ? "Edit File Upload Problem" : "Add File Upload Problem"} buttonAction={handleSubmit} open={open} onClose={closeModal} isSubmittable={submittable}>
7198
<div className="input-group">
7299
<label htmlFor="title" className="input-label">Problem Title:</label>
73-
<input
74-
type="text"
75-
id="title"
76-
placeholder="e.g. Application Objective 3"
77-
onChange={handleChange}
100+
<input
101+
type="text"
102+
id="title"
103+
placeholder="e.g. Application Objective 3"
104+
onChange={handleChange}
105+
value={formData.title}
78106
/>
79107
</div>
80-
108+
81109
<div className="input-group">
82110
<label htmlFor="maxScore" className="input-label">Maximum Score:</label>
83-
<input
84-
type="number"
85-
id="maxScore"
86-
placeholder="e.g. 10"
87-
min="0"
88-
onChange={handleChange}
111+
<input
112+
type="number"
113+
id="maxScore"
114+
placeholder="e.g. 10"
115+
min="0"
116+
onChange={handleChange}
117+
value={formData.maxScore}
89118
/>
90119
</div>
91120
</Modal>

devU-client/src/components/utils/pdfViewer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const PDFViewer: React.FC<PDFWithHighlightProps> = ({ file }) => {
156156
</div>
157157

158158
{/* annotation options */}
159+
{console.log("IS INSTRUCTOR:", role.isInstructor())}
159160
{role.isInstructor() && (<div className={styles.annotationOptions}>
160161
<button
161162
className="btnSecondary"

0 commit comments

Comments
 (0)