Skip to content

Commit

Permalink
enhance(apps/frontend-manage): add links from and to learning analyti…
Browse files Browse the repository at this point in the history
…cs pages behind feature flag (#4408)
  • Loading branch information
sjschlapbach authored Dec 22, 2024
1 parent 2041e65 commit c8e79fc
Show file tree
Hide file tree
Showing 31 changed files with 284 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function CircularPerformancePlot({
<H3 className={{ root: 'mt-4' }}>{title}</H3>
<div className="h-full w-full">
<ResponsiveContainer width="100%" height="100%">
<PieChart margin={{ top: -10, right: 0, bottom: 0, left: 0 }}>
<PieChart margin={{ top: -10, right: 15, bottom: 0, left: 15 }}>
<Pie
data={data}
cx="50%"
Expand All @@ -43,7 +43,7 @@ function CircularPerformancePlot({
return <Cell key={`cell-${index}`} fill={colorValues[index]} />
})}
</Pie>
{activeIndex !== undefined && (
{/* {activeIndex !== undefined && (
<text
x="50%"
y="48%"
Expand All @@ -53,7 +53,7 @@ function CircularPerformancePlot({
>
{data[activeIndex].name}
</text>
)}
)} */}
</PieChart>
</ResponsiveContainer>
</div>
Expand Down
16 changes: 10 additions & 6 deletions apps/frontend-manage/src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ function Header({ user }: HeaderProps): React.ReactElement {
active: router.pathname == '/courses',
cy: 'courses',
},
{
href: '/analytics',
label: t('manage.general.analytics'),
active: router.pathname == '/analytics',
cy: 'analytics',
},
...(user?.featurePreview
? [
{
href: '/analytics',
label: t('manage.general.analytics'),
active: router.pathname == '/analytics',
cy: 'analytics',
},
]
: []),
]

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMutation, useQuery } from '@apollo/client'
import { faHandPointer } from '@fortawesome/free-regular-svg-icons'
import { faPencil } from '@fortawesome/free-solid-svg-icons'
import { faChartPie, faPencil } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
Course,
Expand All @@ -11,6 +11,7 @@ import {
import { Button, Dropdown, H1, Toast } from '@uzh-bf/design-system'
import dayjs from 'dayjs'
import { useTranslations } from 'next-intl'
import { useRouter } from 'next/router'
import { useState } from 'react'
import CourseQRModal from '../liveQuiz/cockpit/CourseQRModal'
import { getLTIAccessLink } from './PracticeQuizElement'
Expand Down Expand Up @@ -41,14 +42,16 @@ function CourseOverviewHeader({
latestEndDate,
}: CourseOverviewHeaderProps) {
const t = useTranslations()
const [courseSettingsModal, setCourseSettingsModal] = useState(false)
const [updateCourseSettings] = useMutation(UpdateCourseSettingsDocument)
const router = useRouter()

const [courseSettingsModal, setCourseSettingsModal] = useState(false)
const [copyToast, setCopyToast] = useState(false)

const [updateCourseSettings] = useMutation(UpdateCourseSettingsDocument)
const { data: dataUser } = useQuery(UserProfileDocument, {
fetchPolicy: 'cache-only',
})
const user = dataUser?.userProfile

return (
<div className="flex flex-row flex-wrap items-center justify-between">
Expand Down Expand Up @@ -82,7 +85,21 @@ function CourseOverviewHeader({
dataModal={{ cy: 'course-join-modal' }}
dataCloseButton={{ cy: 'course-join-modal-close' }}
/>
{dataUser?.userProfile?.catalyst && (
{user?.featurePreview ? (
<Button
onClick={() => {
window.open(`/analytics/${course.id}/activity`, '_blank')
}}
className={{ root: 'bg-primary-80 gap-3 text-white' }}
data={{ cy: 'course-learning-analytics-link' }}
>
<Button.Icon>
<FontAwesomeIcon icon={faChartPie} />
</Button.Icon>
<Button.Label>{t('manage.course.learningAnalytics')}</Button.Label>
</Button>
) : null}
{user?.catalyst && (
<Dropdown
data={{ cy: `course-actions-${name}` }}
className={{
Expand All @@ -92,7 +109,7 @@ function CourseOverviewHeader({
}}
trigger={t('manage.course.otherActions')}
items={[
dataUser?.userProfile?.catalyst
user?.catalyst
? [
getLTIAccessLink({
href: `${process.env.NEXT_PUBLIC_PWA_URL}/course/${course.id}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { WizardMode } from '../activities/ElementCreation'
import CopyConfirmationToast from '../toasts/CopyConfirmationToast'
import { getAccessLink, getLTIAccessLink } from './PracticeQuizElement'
import StatusTag from './StatusTag'
import ActivityAnalyticsLink from './actions/ActivityAnalyticsLink'
import MicroLearningAccessLink from './actions/MicroLearningAccessLink'
import MicroLearningEvaluationLink from './actions/MicroLearningEvaluationLink'
import MicroLearningPreviewLink from './actions/MicroLearningPreviewLink'
Expand Down Expand Up @@ -68,6 +69,7 @@ function MicroLearningElement({
const { data: dataUser } = useQuery(UserProfileDocument, {
fetchPolicy: 'cache-only',
})
const user = dataUser?.userProfile

const href = `${process.env.NEXT_PUBLIC_PWA_URL}/course/${courseId}/microlearning/${microLearning.id}/`
const evaluationHref = `/microLearning/${microLearning.id}/evaluation`
Expand Down Expand Up @@ -176,7 +178,7 @@ function MicroLearningElement({
t,
name: microLearning.name,
}),
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -240,7 +242,7 @@ function MicroLearningElement({
}}
trigger={t('manage.course.otherActions')}
items={[
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -299,7 +301,7 @@ function MicroLearningElement({
}}
trigger={t('manage.course.otherActions')}
items={[
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -397,6 +399,17 @@ function MicroLearningElement({
},
]
: []),
user?.featurePreview
? {
label: (
<ActivityAnalyticsLink
courseId={courseId}
activityId={microLearning.id}
/>
),
onClick: () => null,
}
: [],
deletionElement,
].flat()}
triggerIcon={faHandPointer}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import React, { useState } from 'react'
import { WizardMode } from '../activities/ElementCreation'
import CopyConfirmationToast from '../toasts/CopyConfirmationToast'
import StatusTag from './StatusTag'
import ActivityAnalyticsLink from './actions/ActivityAnalyticsLink'
import PracticeQuizAccessLink from './actions/PracticeQuizAccessLink'
import PracticeQuizEvaluationLink from './actions/PracticeQuizEvaluationLink'
import PracticeQuizPreviewLink from './actions/PracticeQuizPreviewLink'
Expand Down Expand Up @@ -127,6 +128,7 @@ function PracticeQuizElement({
const { data: dataUser } = useQuery(UserProfileDocument, {
fetchPolicy: 'cache-only',
})
const user = dataUser?.userProfile

const [unpublishPracticeQuiz] = useMutation(UnpublishPracticeQuizDocument, {
variables: { id: practiceQuiz.id! },
Expand Down Expand Up @@ -231,7 +233,7 @@ function PracticeQuizElement({
t,
name: practiceQuiz.name,
}),
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -292,7 +294,7 @@ function PracticeQuizElement({
}}
trigger={t('manage.course.otherActions')}
items={[
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -349,7 +351,7 @@ function PracticeQuizElement({
}}
trigger={t('manage.course.otherActions')}
items={[
dataUser?.userProfile?.catalyst
user?.catalyst
? getLTIAccessLink({
href,
setCopyToast,
Expand Down Expand Up @@ -384,6 +386,17 @@ function PracticeQuizElement({
cy: `duplicate-practice-quiz-${practiceQuiz.name}`,
},
}),
user?.featurePreview
? {
label: (
<ActivityAnalyticsLink
courseId={courseId}
activityId={practiceQuiz.id}
/>
),
onClick: () => null,
}
: [],
deletionItem,
].flat()}
triggerIcon={faHandPointer}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { faChartPie } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useTranslations } from 'next-intl'
import Link from 'next/link'

interface ActivityAnalyticsLinkProps {
courseId: string
activityId: string
}

function ActivityAnalyticsLink({
courseId,
activityId,
}: ActivityAnalyticsLinkProps) {
const t = useTranslations()

return (
<Link
href={`/analytics/${courseId}/quizzes/${activityId}`}
target="_blank"
className="text-primary-100 flex flex-row items-center gap-1"
data-cy={`open-analytics-async-activity`}
>
<FontAwesomeIcon icon={faChartPie} size="sm" className="w-4" />
<div>{t('manage.courseList.activityAnalytics')}</div>
</Link>
)
}

export default ActivityAnalyticsLink
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export type ActivityEvaluationType = 'LiveQuiz' | 'Asynchronous'
export type ActiveStackType = number | 'feedbacks' | 'confusion' | 'leaderboard'

interface ActivityEvaluationProps {
courseId?: string | null
activityId: string
activityName: string
stacks: StackEvaluation[]
feedbacks?: Feedback[] | null
Expand All @@ -39,6 +41,8 @@ interface ActivityEvaluationProps {
}

function ActivityEvaluation({
courseId,
activityId,
activityName,
stacks,
feedbacks,
Expand Down Expand Up @@ -92,6 +96,8 @@ function ActivityEvaluation({
{router.query.hideControls !== 'true' && (
<div className="z-20 h-11 flex-none">
<EvaluationNavigation
courseId={courseId ?? ''}
activityId={activityId}
stacks={stacks}
stackInstanceMap={stackInstanceMap}
activeStack={activeStack}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { StackEvaluation } from '@klicker-uzh/graphql/dist/ops'
import { useQuery } from '@apollo/client'
import { faPieChart } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
CheckFeaturePreviewAvailableDocument,
StackEvaluation,
} from '@klicker-uzh/graphql/dist/ops'
import { Button } from '@uzh-bf/design-system'
import { useTranslations } from 'next-intl'
import { ActiveStackType, ActivityEvaluationType } from '../ActivityEvaluation'
import useInstanceArrowNavigation from '../hooks/useInstanceArrowNavigation'
import useStackInstanceUpdates from '../hooks/useStackInstanceUpdates'
import InstanceNavigation from './InstanceNavigation'
import StackNavigation from './StackNavigation'

interface EvaluationNavigationProps {
courseId: string
activityId: string
stacks: StackEvaluation[]
stackInstanceMap: Record<number, { label: string; value: number }[]>
activeStack: ActiveStackType
Expand All @@ -19,6 +29,8 @@ interface EvaluationNavigationProps {
}

function EvaluationNavigation({
courseId,
activityId,
stacks,
stackInstanceMap,
activeStack,
Expand All @@ -30,6 +42,10 @@ function EvaluationNavigation({
leaderboardAvailable,
feedbacksAvailable,
}: EvaluationNavigationProps) {
const t = useTranslations()

const { data, loading } = useQuery(CheckFeaturePreviewAvailableDocument)

// automatically switch the active stack based on the active instance
useStackInstanceUpdates({
activeInstance,
Expand Down Expand Up @@ -57,16 +73,35 @@ function EvaluationNavigation({
) : (
<div />
)}
<StackNavigation
stacks={stacks}
activeStack={activeStack}
setActiveStack={setActiveStack}
stackInstanceMap={stackInstanceMap}
setActiveInstance={setActiveInstance}
type={type}
leaderboardAvailable={leaderboardAvailable}
feedbacksAvailable={feedbacksAvailable}
/>
<div className="flex flex-row items-center gap-4">
{!loading &&
data?.checkFeaturePreviewAvailable &&
type === 'Asynchronous' ? (
<Button
className={{ root: 'flex h-8 flex-row gap-2' }}
onClick={() =>
window.open(
`/analytics/${courseId}/quizzes/${activityId}`,
'_blank'
)
}
data={{ cy: 'quiz-analytics' }}
>
<FontAwesomeIcon icon={faPieChart} />
<div>{t('manage.analytics.quizAnalytics')}</div>
</Button>
) : null}
<StackNavigation
stacks={stacks}
activeStack={activeStack}
setActiveStack={setActiveStack}
stackInstanceMap={stackInstanceMap}
setActiveInstance={setActiveInstance}
type={type}
leaderboardAvailable={leaderboardAvailable}
feedbacksAvailable={feedbacksAvailable}
/>
</div>
</div>
)
}
Expand Down
Loading

0 comments on commit c8e79fc

Please sign in to comment.