-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add evaluation view for asynchronous activities (#4265)
- Loading branch information
1 parent
533be1b
commit 2ea3b69
Showing
56 changed files
with
7,137 additions
and
1,939 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
apps/frontend-manage/src/components/courses/actions/MicroLearningEvaluationLink.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { faExternalLink } from '@fortawesome/free-solid-svg-icons' | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
import { useTranslations } from 'next-intl' | ||
import Link from 'next/link' | ||
|
||
interface MicroLearningEvaluationLinkProps { | ||
quizName: string | ||
evaluationHref: string | ||
} | ||
|
||
function MicroLearningEvaluationLink({ | ||
quizName, | ||
evaluationHref, | ||
}: MicroLearningEvaluationLinkProps) { | ||
const t = useTranslations() | ||
|
||
return ( | ||
<Link | ||
href={evaluationHref} | ||
target="_blank" | ||
className="text-primary-100 flex flex-row items-center gap-1" | ||
data-cy={`evaluation-microlearning-${quizName}`} | ||
> | ||
<FontAwesomeIcon icon={faExternalLink} size="sm" className="w-4" /> | ||
<div>{t('manage.courseList.openEvaluation')}</div> | ||
</Link> | ||
) | ||
} | ||
|
||
export default MicroLearningEvaluationLink |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
apps/frontend-manage/src/components/courses/actions/PracticeQuizEvaluationLink.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { faExternalLink } from '@fortawesome/free-solid-svg-icons' | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
import { useTranslations } from 'next-intl' | ||
import Link from 'next/link' | ||
|
||
interface PracticeQuizEvaluationLinkProps { | ||
quizName: string | ||
evaluationHref: string | ||
} | ||
|
||
function PracticeQuizEvaluationLink({ | ||
quizName, | ||
evaluationHref, | ||
}: PracticeQuizEvaluationLinkProps) { | ||
const t = useTranslations() | ||
|
||
return ( | ||
<Link | ||
href={evaluationHref} | ||
target="_blank" | ||
className="text-primary-100 flex flex-row items-center gap-1" | ||
data-cy={`evaluation-practice-quiz-${quizName}`} | ||
> | ||
<FontAwesomeIcon icon={faExternalLink} size="sm" className="w-4" /> | ||
<div>{t('manage.courseList.openEvaluation')}</div> | ||
</Link> | ||
) | ||
} | ||
|
||
export default PracticeQuizEvaluationLink |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
apps/frontend-manage/src/components/evaluation/ActivityEvaluation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
import { | ||
sizeReducer, | ||
TextSizes, | ||
} from '@components/sessions/evaluation/constants' | ||
import { StackEvaluation } from '@klicker-uzh/graphql/dist/ops' | ||
import { ChartType } from '@klicker-uzh/shared-components/src/constants' | ||
import Head from 'next/head' | ||
import { useRouter } from 'next/router' | ||
import { useReducer, useState } from 'react' | ||
import { twMerge } from 'tailwind-merge' | ||
import ElementEvaluation from './ElementEvaluation' | ||
import EvaluationFooter from './EvaluationFooter' | ||
import useChartTypeUpdate from './hooks/useChartTypeUpdate' | ||
import useStackInstanceMap from './hooks/useStackInstanceMap' | ||
import EvaluationNavigation from './navigation/EvaluationNavigation' | ||
|
||
interface ActivityEvaluationProps { | ||
activityName: string | ||
stacks: StackEvaluation[] | ||
} | ||
|
||
export type ActiveStackType = number | 'feedbacks' | 'confusion' | 'leaderboard' | ||
|
||
function ActivityEvaluation({ activityName, stacks }: ActivityEvaluationProps) { | ||
const router = useRouter() | ||
const [activeStack, setActiveStack] = useState<ActiveStackType>(0) | ||
const [activeInstance, setActiveInstance] = useState<number>(0) | ||
const [showSolution, setShowSolution] = useState<boolean>(false) | ||
const [chartType, setChartType] = useState<ChartType>(ChartType.UNSET) | ||
const [textSize, setTextSize] = useReducer(sizeReducer, TextSizes['md']) | ||
|
||
const instanceResults = stacks.flatMap((stack) => stack.instances) | ||
|
||
// compute a map between stack and instance indices {stackIx: [instanceIx1, instanceIx2], ...} | ||
const stackInstanceMap = useStackInstanceMap({ stacks }) | ||
|
||
// update the chart type as soon as the active instance changes | ||
useChartTypeUpdate({ | ||
activeInstance, | ||
activeElementType: instanceResults[activeInstance].type, | ||
chartType, | ||
setChartType, | ||
}) | ||
|
||
return ( | ||
<> | ||
<Head> | ||
<title>{`KlickerUZH - Evaluation: ${activityName}`}</title> | ||
<meta | ||
name="description" | ||
content={`KlickerUZH - Evaluation: ${activityName}`} | ||
charSet="utf-8" | ||
></meta> | ||
</Head> | ||
|
||
{router.query.hideControls !== 'true' && ( | ||
<div className="z-20 h-11 flex-none"> | ||
<EvaluationNavigation | ||
stacks={stacks} | ||
stackInstanceMap={stackInstanceMap} | ||
activeStack={activeStack} | ||
setActiveStack={setActiveStack} | ||
activeInstance={activeInstance} | ||
setActiveInstance={setActiveInstance} | ||
numOfInstances={instanceResults.length} | ||
/> | ||
</div> | ||
)} | ||
|
||
<div className="flex min-h-0 flex-1 flex-col"> | ||
{typeof activeStack === 'number' && ( | ||
<ElementEvaluation | ||
currentInstance={instanceResults[activeInstance]} | ||
textSize={textSize} | ||
chartType={chartType} | ||
showSolution={ | ||
instanceResults[activeInstance].hasSampleSolution | ||
? showSolution | ||
: false | ||
} | ||
/> | ||
)} | ||
|
||
{/* {showLeaderboard && !showConfusion && !showFeedbacks && ( | ||
<div className="overflow-y-auto"> | ||
<div className="border-t p-4"> | ||
<div className="mx-auto max-w-2xl text-xl"> | ||
{data.sessionLeaderboard && | ||
data.sessionLeaderboard.length > 0 ? ( | ||
<Leaderboard | ||
leaderboard={data.sessionLeaderboard ?? []} | ||
podiumImgSrc={{ | ||
rank1: Rank1Img, | ||
rank2: Rank2Img, | ||
rank3: Rank3Img, | ||
}} | ||
/> | ||
) : ( | ||
<UserNotification | ||
className={{ message: 'text-lg' }} | ||
type="warning" | ||
message={t('manage.evaluation.noSignedInStudents')} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
)} */} | ||
|
||
{/* {!showLeaderboard && | ||
!showConfusion && | ||
showFeedbacks && | ||
data.sessionEvaluation && ( | ||
<div className="overflow-y-auto print:overflow-y-visible"> | ||
<div className="p-4"> | ||
<div className="mx-auto max-w-5xl text-xl"> | ||
{feedbacks && feedbacks.length > 0 ? ( | ||
<EvaluationFeedbacks | ||
feedbacks={feedbacks} | ||
sessionName={data.sessionEvaluation.displayName} | ||
/> | ||
) : ( | ||
<UserNotification | ||
className={{ message: 'text-lg' }} | ||
type="warning" | ||
message={t('manage.evaluation.noFeedbacksYet')} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
)} */} | ||
|
||
{/* {!showLeaderboard && showConfusion && !showFeedbacks && ( | ||
<div className="overflow-y-auto"> | ||
<div className="border-t p-4"> | ||
<div className="mx-auto max-w-5xl text-xl"> | ||
{confusionFeedbacks && confusionFeedbacks.length > 0 ? ( | ||
<EvaluationConfusion confusionTS={confusionFeedbacks} /> | ||
) : ( | ||
<UserNotification | ||
className={{ message: 'text-lg' }} | ||
type="warning" | ||
message={t('manage.evaluation.noConfusionFeedbacksYet')} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
)} */} | ||
</div> | ||
|
||
<div | ||
className={twMerge( | ||
'z-20 h-14 flex-none', | ||
(activeStack === 'feedbacks' || | ||
activeStack === 'confusion' || | ||
activeStack === 'leaderboard') && | ||
'h-18' | ||
)} | ||
> | ||
<EvaluationFooter | ||
activeStack={activeStack} | ||
textSize={textSize} | ||
setTextSize={setTextSize} | ||
showSolution={showSolution} | ||
setShowSolution={setShowSolution} | ||
chartType={chartType} | ||
setChartType={setChartType} | ||
currentInstance={instanceResults[activeInstance]} | ||
/> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
export default ActivityEvaluation |
66 changes: 66 additions & 0 deletions
66
apps/frontend-manage/src/components/evaluation/ElementChart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { | ||
ElementInstanceEvaluation, | ||
NumericalElementInstanceEvaluation, | ||
} from '@klicker-uzh/graphql/dist/ops' | ||
import { ChartType } from '@klicker-uzh/shared-components/src/constants' | ||
import { useTranslations } from 'next-intl' | ||
import React from 'react' | ||
import { TextSizeType } from '../sessions/evaluation/constants' | ||
import ElementBarChart from './charts/ElementBarChart' | ||
import ElementHistogram from './charts/ElementHistogram' | ||
import ElementTableChart from './charts/ElementTableChart' | ||
import ElementWordcloud from './charts/ElementWordcloud' | ||
|
||
interface ElementChartProps { | ||
chartType: string | ||
instanceEvaluation: ElementInstanceEvaluation | ||
showSolution: boolean | ||
textSize: TextSizeType | ||
} | ||
|
||
function ElementChart({ | ||
chartType, | ||
instanceEvaluation, | ||
showSolution, | ||
textSize, | ||
}: ElementChartProps): React.ReactElement { | ||
const t = useTranslations() | ||
|
||
if (chartType === ChartType.TABLE) { | ||
return ( | ||
<ElementTableChart | ||
instance={instanceEvaluation} | ||
showSolution={showSolution} | ||
textSize={textSize.textLg} | ||
/> | ||
) | ||
} else if (chartType === ChartType.HISTOGRAM) { | ||
return ( | ||
<ElementHistogram | ||
instance={instanceEvaluation as NumericalElementInstanceEvaluation} | ||
showSolution={{ general: showSolution }} | ||
textSize={textSize.text} | ||
/> | ||
) | ||
} else if (chartType === ChartType.WORD_CLOUD) { | ||
return ( | ||
<ElementWordcloud | ||
instance={instanceEvaluation} | ||
showSolution={showSolution} | ||
textSize={{ min: textSize.min, max: textSize.max }} | ||
/> | ||
) | ||
} else if (chartType === ChartType.BAR_CHART) { | ||
return ( | ||
<ElementBarChart | ||
instance={instanceEvaluation} | ||
showSolution={showSolution} | ||
textSize={textSize} | ||
/> | ||
) | ||
} else { | ||
return <div>{t('manage.evaluation.noChartsAvailable')}</div> | ||
} | ||
} | ||
|
||
export default ElementChart |
Oops, something went wrong.