github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/components/Lab.tsx (about) 1 import React, { useEffect } from 'react' 2 import { useParams } from 'react-router' 3 import { Assignment, Submission } from '../../proto/qf/types_pb' 4 import { hasReviews, isManuallyGraded } from '../Helpers' 5 import { useAppState, useActions } from '../overmind' 6 import CourseLinks from "./CourseLinks" 7 import LabResultTable from "./LabResultTable" 8 import ReviewResult from './ReviewResult' 9 10 interface MatchProps { 11 id: string 12 lab: string 13 } 14 15 /** Lab displays a submission based on the /course/:id/lab/:lab route if the user is a student. 16 * If the user is a teacher, Lab displays the currently selected submission. 17 */ 18 const Lab = (): JSX.Element => { 19 20 const state = useAppState() 21 const actions = useActions() 22 const { id, lab } = useParams<MatchProps>() 23 const courseID = id 24 const assignmentID = lab ? BigInt(lab) : BigInt(-1) 25 26 useEffect(() => { 27 if (!state.isTeacher) { 28 actions.setSelectedAssignmentID(Number(lab)) 29 } 30 }, [lab]) 31 32 const InternalLab = () => { 33 let submission: Submission | null 34 let assignment: Assignment | null 35 36 if (state.isTeacher) { 37 // If used for grading purposes, retrieve the currently selected submission 38 submission = state.selectedSubmission 39 assignment = state.assignments[courseID].find(a => a.ID === submission?.AssignmentID) ?? null 40 } else { 41 // Retrieve the student's submission 42 submission = state.submissions[courseID]?.find(s => s.AssignmentID === assignmentID) ?? null 43 assignment = state.assignments[courseID]?.find(a => a.ID === assignmentID) ?? null 44 } 45 46 if (assignment && submission) { 47 // Confirm both assignment and submission exists before attempting to render 48 const review = hasReviews(submission) ? submission.reviews : [] 49 let buildLog: JSX.Element[] = [] 50 const buildLogRaw = submission.BuildInfo?.BuildLog 51 if (buildLogRaw) { 52 buildLog = buildLogRaw.split("\n").map((x: string, i: number) => <span key={i} >{x}<br /></span>) 53 } 54 55 return ( 56 <div key={submission.ID.toString()} className="mb-4"> 57 <LabResultTable submission={submission} assignment={assignment} /> 58 59 {isManuallyGraded(assignment) && submission.released ? <ReviewResult review={review[0]} /> : null} 60 61 <div className="card bg-light"> 62 <code className="card-body" style={{ color: "#c7254e", wordBreak: "break-word" }}>{buildLog}</code> 63 </div> 64 </div> 65 ) 66 } 67 return ( 68 <div>No submission found</div> 69 ) 70 } 71 72 return ( 73 <div className={state.isTeacher ? "" : "row"}> 74 <div className={state.isTeacher ? "" : "col-md-9"}> 75 <InternalLab /> 76 </div> 77 {state.isTeacher ? null : <CourseLinks />} 78 </div> 79 ) 80 } 81 82 export default Lab