From de02646dd2863071652b0cb816e3e004520a046f Mon Sep 17 00:00:00 2001 From: Kevin Zhong Date: Tue, 12 Nov 2024 10:49:50 -0500 Subject: [PATCH 1/3] Added a page to view pdf submissions Added a page to view pdf submissions for students --- .../src/fileUpload/fileUpload.controller.ts | 1 + devU-client/package.json | 1 + .../src/components/authenticatedRouter.tsx | 2 + .../submissions/submissionDetailPage.tsx | 3 + .../pages/submissions/submissionFileView.tsx | 113 ++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 devU-client/src/components/pages/submissions/submissionFileView.tsx diff --git a/devU-api/src/fileUpload/fileUpload.controller.ts b/devU-api/src/fileUpload/fileUpload.controller.ts index 0c30911..89a6734 100644 --- a/devU-api/src/fileUpload/fileUpload.controller.ts +++ b/devU-api/src/fileUpload/fileUpload.controller.ts @@ -23,6 +23,7 @@ export async function detail(req: Request, res: Response, next: NextFunction) { const bucketName = req.params.bucketName const fileName = req.params.fileName const file: Buffer = await FileUploadService.retrieve(bucketName, fileName) + console.log(file) if (!file) return res.status(404).json(NotFound) diff --git a/devU-client/package.json b/devU-client/package.json index af413ff..df47652 100644 --- a/devU-client/package.json +++ b/devU-client/package.json @@ -41,6 +41,7 @@ "react": "^17.0.2", "react-datepicker": "^4.1.1", "react-dom": "^17.0.1", + "react-pdf": "^9.1.1", "react-redux": "^7.2.4", "react-router-breadcrumbs-hoc": "^4.1.0", "react-router-dom": "^5.2.0", diff --git a/devU-client/src/components/authenticatedRouter.tsx b/devU-client/src/components/authenticatedRouter.tsx index a8016a4..65e87ed 100644 --- a/devU-client/src/components/authenticatedRouter.tsx +++ b/devU-client/src/components/authenticatedRouter.tsx @@ -20,6 +20,7 @@ import CoursePreviewPage from './pages/courses/coursePreviewPage' import CoursesListPage from "./pages/listPages/courses/coursesListPage"; import AssignmentProblemFormPage from './pages/forms/assignments/assignmentProblemFormPage' import InstructorSubmissionspage from "./pages/submissions/InstructorSubmissionspage"; +import SubmissionFileView from './pages/submissions/submissionFileView' import WebhookURLForm from './pages/webhookURLForm' @@ -53,6 +54,7 @@ const AuthenticatedRouter = () => ( component={InstructorSubmissionspage}/> + // TBD, undecided where webhooks should be placed {/**/} diff --git a/devU-client/src/components/pages/submissions/submissionDetailPage.tsx b/devU-client/src/components/pages/submissions/submissionDetailPage.tsx index 3e80558..52f6b9d 100644 --- a/devU-client/src/components/pages/submissions/submissionDetailPage.tsx +++ b/devU-client/src/components/pages/submissions/submissionDetailPage.tsx @@ -18,6 +18,7 @@ import {prettyPrintDateTime} from "../../../utils/date.utils"; //import React, { useState } from 'react'; //import { Document, Page } from 'react-pdf'; //import StickyNote from 'react-sticky-notes'; +import { useHistory } from 'react-router-dom' const SubmissionDetailPage = () => { @@ -25,6 +26,7 @@ const SubmissionDetailPage = () => { const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [setAlert] = useActionless(SET_ALERT) + const history = useHistory() const { submissionId, assignmentId, courseId } = useParams<{submissionId: string, assignmentId: string, courseId: string}>() const [submissionScore, setSubmissionScore] = useState(null) @@ -208,6 +210,7 @@ const SubmissionDetailPage = () => {

Content

+
{selectedSubmission.content}
diff --git a/devU-client/src/components/pages/submissions/submissionFileView.tsx b/devU-client/src/components/pages/submissions/submissionFileView.tsx new file mode 100644 index 0000000..cc32257 --- /dev/null +++ b/devU-client/src/components/pages/submissions/submissionFileView.tsx @@ -0,0 +1,113 @@ +import React, { useEffect, useState } from 'react' +import { useParams } from 'react-router-dom' +import RequestService from 'services/request.service' +import { Submission } from 'devu-shared-modules' +import {Document, Page} from 'react-pdf' +import { pdfjs } from 'react-pdf' +import PageWrapper from 'components/shared/layouts/pageWrapper' +import { getToken } from 'utils/authentication.utils' + +import config from '../../../config' +const proxiedUrls = { + '/api': `${config.apiUrl}`, +} + +function _replaceUrl(userUrl: string) { + const proxy: string | undefined = Object.keys(proxiedUrls).find((key) => { + if (userUrl.startsWith(key)) return true + return false + }) + + if (!proxy) return userUrl + + return userUrl.replace(proxy, proxiedUrls[proxy as keyof typeof proxiedUrls]) + } + + +pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`; + +const SubmissionFileView = () => { + const { courseId, assignmentId, submissionId } = useParams<{ courseId: string, assignmentId: string, submissionId: string }>() + const [bucket, setBucket] = useState('') + const [filename, setFilename] = useState('') + const authToken = getToken() + + const [file, setFile] = useState(null) + const [numPages, setNumPages] = useState(0) + + useEffect(() => { + fetchData() + }, []) + + useEffect(() => { + console.log(filename) + if (bucket && filename) { + fetchFile() + } + }, [bucket, filename]) + + const fetchData = async () => { + try { + await RequestService.get(`/api/course/${courseId}/assignment/${assignmentId}/submissions/${submissionId}`) + .then((data) => { + const submissionFiles = JSON.parse(data.content) + const [tempbucket,tempfilename] = submissionFiles.filepaths[0].split('/') + setBucket(tempbucket) + setFilename(tempfilename) + + + }) + } catch (e) { + console.error(e) + } + } + + const fetchFile = async () => { + try { + const url = _replaceUrl(`/api/course/${courseId}/file-upload/${bucket}/${filename}`) + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/pdf', + 'Authorization': `Bearer ${authToken}`, + }, + }) + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const arrayBuffer = await response.arrayBuffer(); + const blob = new Blob([arrayBuffer], { type: 'application/pdf' }); + const file = new File([blob], filename, { type: 'application/pdf' }); + + setFile(file); + } catch (e) { + console.error(e) + } + } + + const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { + setNumPages(numPages) + } + + return ( + +
+ {file && + + {[...Array(numPages)].map((_, index) => ( +
+ +
+ ))} +
+ } +
+
+ +
+ ) + +} + +export default SubmissionFileView \ No newline at end of file From 8dc951ec35edb57f8cbbcebba03aec3833a036ff Mon Sep 17 00:00:00 2001 From: Kevin Zhong Date: Tue, 12 Nov 2024 13:00:32 -0500 Subject: [PATCH 2/3] Updated button text Updated button text on submission detail page for redirect to viewing uploaded file. --- .../src/components/pages/submissions/submissionDetailPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devU-client/src/components/pages/submissions/submissionDetailPage.tsx b/devU-client/src/components/pages/submissions/submissionDetailPage.tsx index 52f6b9d..fe979ed 100644 --- a/devU-client/src/components/pages/submissions/submissionDetailPage.tsx +++ b/devU-client/src/components/pages/submissions/submissionDetailPage.tsx @@ -210,7 +210,7 @@ const SubmissionDetailPage = () => {

Content

- +
{selectedSubmission.content}
From 1f67e6466a78d5d6d2763d35f34f82473abbcd7f Mon Sep 17 00:00:00 2001 From: Kevin Zhong Date: Tue, 12 Nov 2024 13:07:28 -0500 Subject: [PATCH 3/3] Removed extra console.log() Removed extra console.log() from files for cleanup. --- devU-api/src/fileUpload/fileUpload.controller.ts | 1 - .../src/components/pages/submissions/submissionFileView.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/devU-api/src/fileUpload/fileUpload.controller.ts b/devU-api/src/fileUpload/fileUpload.controller.ts index 89a6734..0c30911 100644 --- a/devU-api/src/fileUpload/fileUpload.controller.ts +++ b/devU-api/src/fileUpload/fileUpload.controller.ts @@ -23,7 +23,6 @@ export async function detail(req: Request, res: Response, next: NextFunction) { const bucketName = req.params.bucketName const fileName = req.params.fileName const file: Buffer = await FileUploadService.retrieve(bucketName, fileName) - console.log(file) if (!file) return res.status(404).json(NotFound) diff --git a/devU-client/src/components/pages/submissions/submissionFileView.tsx b/devU-client/src/components/pages/submissions/submissionFileView.tsx index cc32257..8a31cd7 100644 --- a/devU-client/src/components/pages/submissions/submissionFileView.tsx +++ b/devU-client/src/components/pages/submissions/submissionFileView.tsx @@ -40,7 +40,6 @@ const SubmissionFileView = () => { }, []) useEffect(() => { - console.log(filename) if (bucket && filename) { fetchFile() }