Verified Commit 7f39d199 authored by Marek Veselý's avatar Marek Veselý
Browse files

feat: implement all submission showcase in analyst

parent 0ba88e6d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ const Questionnaire: FC<QuestionnaireProps> = ({
          <p>
            {maxAttempts === undefined
              ? 'Unlimited attempts: submit is available until all answers are correct'
              : `Remaining attempts: ${maxAttempts - submissionCount} out of ${maxAttempts}`}
              : `Remaining attempts: ${maxAttempts - submissionCount} of ${maxAttempts}`}
          </p>
        )}
      </div>
+123 −40
Original line number Diff line number Diff line
import { Section, SectionCard } from '@blueprintjs/core'
import { Button, Section, SectionCard } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { Questionnaire, TeamQuestionnaireState } from '@inject/graphql'
import type { NavigateOptions } from '@tanstack/react-router'
import { type FC } from 'react'
import { useEffect, useRef, useState, type FC } from 'react'
import InstructorQuestionnaire from '.'
import Status from './Status'
import { canBeReviewed } from './utils'

// TODO: add individual submissions
import { canBeReviewed, parseMaxAttempts } from './utils'

const objectiveClass = css`
  flex-shrink: 0;
@@ -35,7 +33,30 @@ export const InstructorQuestionnaireCard: FC<
  hideReview,
  getFileLink,
  initialOpen = true,
}) => (
}) => {
  const submissionCount = teamState.submissions.length
  const [submissionIndex, setSubmissionIndex] = useState(
    submissionCount > 0 ? submissionCount - 1 : undefined
  )
  const teamIdRef = useRef(teamId)
  const submissionCountRef = useRef(submissionCount)
  useEffect(() => {
    if (teamIdRef.current === teamId) {
      if (submissionCountRef.current < submissionCount) {
        setSubmissionIndex(submissionCount - 1)
        return
      }
      return
    }

    setSubmissionIndex(submissionCount > 0 ? submissionCount - 1 : undefined)
    teamIdRef.current = teamId
  }, [submissionCount, teamId])

  const answersAccepted = teamState.acceptedAnswers.length !== 0
  const maxAttempts = parseMaxAttempts(questionnaire.repeatable?.maxAttempts)

  return (
    <Section
      key={questionnaire.id}
      title={questionnaire.displayName}
@@ -51,6 +72,61 @@ export const InstructorQuestionnaireCard: FC<
        defaultIsOpen: initialOpen,
      }}
    >
      <SectionCard
        className={css`
          display: flex;
          flex-direction: column;
          gap: 0.5rem;
          align-items: center;
          justify-content: space-between;
        `}
      >
        <div>
          {maxAttempts === undefined
            ? 'Unlimited attempts: submit is available until all answers are correct'
            : `Remaining attempts: ${maxAttempts - submissionCount} of ${maxAttempts}`}
        </div>
        <div>
          {answersAccepted ? 'Answers accepted' : 'Answers not accepted'}
        </div>
        <div
          className={css`
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 0.5rem;
          `}
        >
          <Button
            minimal
            icon='chevron-left'
            disabled={submissionIndex === undefined || submissionIndex === 0}
            onClick={() => {
              if (submissionIndex !== undefined) {
                setSubmissionIndex(submissionIndex - 1)
              }
            }}
          />
          {submissionIndex === undefined
            ? 'No answers submitted yet'
            : `Answer submission: ${
                submissionIndex !== undefined ? submissionIndex + 1 : 'N/A'
              } of ${teamState.submissions.length}`}
          <Button
            minimal
            icon='chevron-right'
            disabled={
              submissionIndex === undefined ||
              submissionIndex === teamState.submissions.length - 1
            }
            onClick={() => {
              if (submissionIndex !== undefined) {
                setSubmissionIndex(submissionIndex + 1)
              }
            }}
          />
        </div>
      </SectionCard>
      <SectionCard padded>
        <InstructorQuestionnaire
          getFileLink={getFileLink}
@@ -61,13 +137,20 @@ export const InstructorQuestionnaireCard: FC<
          status={teamState.status}
          content={questionnaire.content}
          questions={questionnaire.questions}
        teamAnswers={teamState.acceptedAnswers}
          teamAnswers={
            submissionIndex !== undefined &&
            // can be bigger if the teamId changes
            submissionIndex < teamState.submissions.length
              ? teamState.submissions[submissionIndex].answers
              : []
          }
          relatedMilestones={teamState.relatedMilestones}
          hideReview={hideReview}
        submissionCount={teamState.submissions.length}
          submissionCount={submissionCount}
          maxAttempts={questionnaire.repeatable?.maxAttempts}
        answersAccepted={teamState.acceptedAnswers.length !== 0}
          answersAccepted={answersAccepted}
        />
      </SectionCard>
    </Section>
  )
}
+4 −0
Original line number Diff line number Diff line
@@ -1083,6 +1083,10 @@ export const TeamQuestionnaireState = graphql(
      submissions {
        id
        attempt
        accepted
        answers {
          ...QuestionnaireAnswer
        }
      }
      relatedMilestones {
        ...QuestionRelatedMilestones
+15 −15

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Diff line number Diff line
@@ -740,6 +740,13 @@ const cache: Exchange = offlineExchange<GraphCacheConfig>({
                { exerciseId: args.exerciseId as string },
                reverse(newArr)
              )

              if (actionLog.type === 'FORM_SUBMISSION') {
                cache.invalidate('Query', 'teamQuestionnaireState', {
                  teamId: actionLog.team.id,
                })
              }

              commitActionLogToCache(cache, actionLog)
            }
            break