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