Skip to content

Commit 696a43a

Browse files
authored
enhance: add subscriptions for live quiz q&a channel and confusion feedback setting changes (#4742)
1 parent 9c17c58 commit 696a43a

12 files changed

Lines changed: 190 additions & 6 deletions

File tree

apps/frontend-pwa/src/components/liveQuiz/AllQuestionsAnsweredMessage.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { UserNotification } from '@uzh-bf/design-system'
22
import { useTranslations } from 'next-intl'
3+
import dynamic from 'next/dynamic'
34
import { useEffect, useState } from 'react'
4-
import ConfettiExplosion from 'react-confetti-explosion'
5+
6+
// load confetti explosion dynamically to avoid SSR issues
7+
const ConfettiExplosion = dynamic(() => import('react-confetti-explosion'), {
8+
ssr: false,
9+
})
510

611
function AllQuestionsAnsweredMessage({
712
gamificationEnabled,

apps/frontend-pwa/src/components/liveQuiz/LiveQuizSubscriber.tsx

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { SubscribeToMoreOptions } from '@apollo/client'
22
import {
33
ElementBlock,
44
LiveQuiz,
5+
LiveQuizSettingsChangedDocument,
6+
LiveQuizStudentSettings,
57
RunningLiveQuizUpdatedDocument,
68
} from '@klicker-uzh/graphql/dist/ops'
79
import { useEffect } from 'react'
@@ -14,11 +16,10 @@ function LiveQuizSubscriber({
1416
subscribeToMore: (doc: SubscribeToMoreOptions) => any
1517
}) {
1618
useEffect(() => {
17-
subscribeToMore({
19+
// update the active block on the student view through a subscription on block start / end
20+
const activeBlockChanged = subscribeToMore({
1821
document: RunningLiveQuizUpdatedDocument,
19-
variables: {
20-
quizId: id,
21-
},
22+
variables: { quizId: id },
2223
updateQuery: (
2324
prev: { studentLiveQuiz: LiveQuiz },
2425
{
@@ -36,6 +37,39 @@ function LiveQuizSubscriber({
3637
})
3738
},
3839
})
40+
41+
// live quiz student settings changed (Q&A channel or confusion feedback enabled / disabled)
42+
const liveQuizSettingsChanged = subscribeToMore({
43+
document: LiveQuizSettingsChangedDocument,
44+
variables: { quizId: id },
45+
updateQuery: (
46+
prev: { studentLiveQuiz: LiveQuiz },
47+
{
48+
subscriptionData,
49+
}: {
50+
subscriptionData: {
51+
data: { liveQuizSettingsChanged: LiveQuizStudentSettings }
52+
}
53+
}
54+
) => {
55+
if (!subscriptionData.data) return prev
56+
return Object.assign({}, prev, {
57+
studentLiveQuiz: {
58+
...prev.studentLiveQuiz,
59+
isLiveQAEnabled:
60+
subscriptionData.data.liveQuizSettingsChanged.isLiveQAEnabled,
61+
isConfusionFeedbackEnabled:
62+
subscriptionData.data.liveQuizSettingsChanged
63+
.isConfusionFeedbackEnabled,
64+
},
65+
})
66+
},
67+
})
68+
69+
return () => {
70+
activeBlockChanged && activeBlockChanged()
71+
liveQuizSettingsChanged && liveQuizSettingsChanged()
72+
}
3973
}, [id, subscribeToMore])
4074

4175
return <div />
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
subscription LiveQuizSettingsChanged($quizId: String!) {
2+
liveQuizSettingsChanged(quizId: $quizId) {
3+
isLiveQAEnabled
4+
isConfusionFeedbackEnabled
5+
}
6+
}

packages/graphql/src/graphql/ops/SRunningSessionUpdated.graphql renamed to packages/graphql/src/graphql/ops/SRunningLiveQuizUpdated.graphql

File renamed without changes.

packages/graphql/src/ops.schema.json

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16612,6 +16612,50 @@
1661216612
"enumValues": null,
1661316613
"possibleTypes": null
1661416614
},
16615+
{
16616+
"kind": "OBJECT",
16617+
"name": "LiveQuizStudentSettings",
16618+
"description": null,
16619+
"isOneOf": null,
16620+
"fields": [
16621+
{
16622+
"name": "isConfusionFeedbackEnabled",
16623+
"description": null,
16624+
"args": [],
16625+
"type": {
16626+
"kind": "NON_NULL",
16627+
"name": null,
16628+
"ofType": {
16629+
"kind": "SCALAR",
16630+
"name": "Boolean",
16631+
"ofType": null
16632+
}
16633+
},
16634+
"isDeprecated": false,
16635+
"deprecationReason": null
16636+
},
16637+
{
16638+
"name": "isLiveQAEnabled",
16639+
"description": null,
16640+
"args": [],
16641+
"type": {
16642+
"kind": "NON_NULL",
16643+
"name": null,
16644+
"ofType": {
16645+
"kind": "SCALAR",
16646+
"name": "Boolean",
16647+
"ofType": null
16648+
}
16649+
},
16650+
"isDeprecated": false,
16651+
"deprecationReason": null
16652+
}
16653+
],
16654+
"inputFields": null,
16655+
"interfaces": [],
16656+
"enumValues": null,
16657+
"possibleTypes": null
16658+
},
1661516659
{
1661616660
"kind": "OBJECT",
1661716661
"name": "LiveQuizSummary",
@@ -36091,6 +36135,35 @@
3609136135
"isDeprecated": false,
3609236136
"deprecationReason": null
3609336137
},
36138+
{
36139+
"name": "liveQuizSettingsChanged",
36140+
"description": null,
36141+
"args": [
36142+
{
36143+
"name": "quizId",
36144+
"description": null,
36145+
"type": {
36146+
"kind": "NON_NULL",
36147+
"name": null,
36148+
"ofType": {
36149+
"kind": "SCALAR",
36150+
"name": "String",
36151+
"ofType": null
36152+
}
36153+
},
36154+
"defaultValue": null,
36155+
"isDeprecated": false,
36156+
"deprecationReason": null
36157+
}
36158+
],
36159+
"type": {
36160+
"kind": "OBJECT",
36161+
"name": "LiveQuizStudentSettings",
36162+
"ofType": null
36163+
},
36164+
"isDeprecated": false,
36165+
"deprecationReason": null
36166+
},
3609436167
{
3609536168
"name": "microLearningEnded",
3609636169
"description": null,

packages/graphql/src/ops.ts

Lines changed: 20 additions & 0 deletions
Large diffs are not rendered by default.

packages/graphql/src/public/client.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@
262262
"FeedbackUpdated": "ff471e7074f90a5f5d884e8a80d4c711b25aa69cd18d79faa9df8aed1334ef97",
263263
"GroupActivityEnded": "0ad24543da1344f7c15139865c767cfdd51952a6a1630f3e080a14e577852b2f",
264264
"GroupActivityStarted": "68ba757fcf30a19c49cfdb2d47e803a0a4f0ed3ecf60a30e0b7ea3390ae0cf20",
265+
"LiveQuizSettingsChanged": "212af644b03fa955abc0a3c907b9543c9831e9432d5dcb0cdf6708a927b5886c",
265266
"MicroLearningEnded": "b296f5b68bb5cccea3da7f8947ee13a88ce78307e694e4caef561b3b5b8766cb",
266267
"RunningLiveQuizUpdated": "dc785e725af616e684230791a7e901ab0ee9ae8a20424f96c2b8e912e116d99f",
267268
"SingleGroupActivityEnded": "3b5bbe5b53ba4977f839f3bf2fd60f6776d1fea15166e1b151e6cddf3f0a814e",

packages/graphql/src/public/schema.graphql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,11 @@ type LiveQuizMeta {
14591459
status: PublicationStatus!
14601460
}
14611461

1462+
type LiveQuizStudentSettings {
1463+
isConfusionFeedbackEnabled: Boolean!
1464+
isLiveQAEnabled: Boolean!
1465+
}
1466+
14621467
type LiveQuizSummary {
14631468
numOfConfusionFeedbacks: Int!
14641469
numOfFeedbacks: Int!
@@ -2401,6 +2406,7 @@ type Subscription {
24012406
feedbackUpdated(quizId: String!): Feedback!
24022407
groupActivityEnded(courseId: String!): GroupActivity!
24032408
groupActivityStarted(courseId: String!): GroupActivity!
2409+
liveQuizSettingsChanged(quizId: String!): LiveQuizStudentSettings
24042410
microLearningEnded(activityId: String!): MicroLearning!
24052411
runningLiveQuizUpdated(quizId: String!): ElementBlock
24062412
singleGroupActivityEnded(activityId: String!): GroupActivity!

packages/graphql/src/public/server.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@
262262
"ff471e7074f90a5f5d884e8a80d4c711b25aa69cd18d79faa9df8aed1334ef97": "subscription FeedbackUpdated($quizId: String!) {\n feedbackUpdated(quizId: $quizId) {\n id\n isPublished\n isPinned\n isResolved\n content\n votes\n resolvedAt\n createdAt\n responses {\n id\n content\n positiveReactions\n negativeReactions\n __typename\n }\n __typename\n }\n}",
263263
"0ad24543da1344f7c15139865c767cfdd51952a6a1630f3e080a14e577852b2f": "subscription GroupActivityEnded($courseId: String!) {\n groupActivityEnded(courseId: $courseId) {\n id\n displayName\n status\n description\n scheduledStartAt\n scheduledEndAt\n __typename\n }\n}",
264264
"68ba757fcf30a19c49cfdb2d47e803a0a4f0ed3ecf60a30e0b7ea3390ae0cf20": "subscription GroupActivityStarted($courseId: String!) {\n groupActivityStarted(courseId: $courseId) {\n id\n displayName\n status\n description\n scheduledStartAt\n scheduledEndAt\n __typename\n }\n}",
265+
"212af644b03fa955abc0a3c907b9543c9831e9432d5dcb0cdf6708a927b5886c": "subscription LiveQuizSettingsChanged($quizId: String!) {\n liveQuizSettingsChanged(quizId: $quizId) {\n isLiveQAEnabled\n isConfusionFeedbackEnabled\n __typename\n }\n}",
265266
"b296f5b68bb5cccea3da7f8947ee13a88ce78307e694e4caef561b3b5b8766cb": "subscription MicroLearningEnded($activityId: String!) {\n microLearningEnded(activityId: $activityId) {\n id\n displayName\n scheduledStartAt\n scheduledEndAt\n __typename\n }\n}",
266267
"dc785e725af616e684230791a7e901ab0ee9ae8a20424f96c2b8e912e116d99f": "fragment ElementDataWithoutSolutions on ElementInstance {\n elementData {\n ... on ChoicesElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n options {\n displayMode\n choices {\n ix\n value\n __typename\n }\n __typename\n }\n }\n ... on NumericalElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n options {\n accuracy\n placeholder\n unit\n restrictions {\n min\n max\n __typename\n }\n __typename\n }\n }\n ... on FreeTextElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n options {\n restrictions {\n maxLength\n __typename\n }\n __typename\n }\n }\n ... on SelectionElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n options {\n numberOfInputs\n answerCollection {\n id\n entries {\n id\n value\n __typename\n }\n __typename\n }\n __typename\n }\n }\n ... on CaseStudyElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n options {\n hasSampleSolution\n items {\n id\n value\n __typename\n }\n criteria {\n id\n name\n min\n max\n step\n unit\n labels {\n min\n mid\n max\n __typename\n }\n __typename\n }\n cases {\n id\n title\n description\n __typename\n }\n __typename\n }\n }\n ... on FlashcardElementData {\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n __typename\n }\n ... on ContentElementData {\n __typename\n id\n elementId\n name\n type\n content\n explanation\n basePoints\n pointsMultiplier\n }\n __typename\n }\n __typename\n}\nsubscription RunningLiveQuizUpdated($quizId: String!) {\n runningLiveQuizUpdated(quizId: $quizId) {\n id\n status\n expiresAt\n timeLimit\n randomSelection\n execution\n elements {\n id\n ...ElementDataWithoutSolutions\n __typename\n }\n __typename\n }\n}",
267268
"3b5bbe5b53ba4977f839f3bf2fd60f6776d1fea15166e1b151e6cddf3f0a814e": "subscription SingleGroupActivityEnded($activityId: String!) {\n singleGroupActivityEnded(activityId: $activityId) {\n id\n displayName\n status\n description\n scheduledStartAt\n scheduledEndAt\n __typename\n }\n}",

packages/graphql/src/schema/liveQuiz.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,19 @@ export const ElementBlock = ElementBlockRef.implement({
207207
}),
208208
})
209209

210+
export interface ILiveQuizStudentSettings {
211+
isLiveQAEnabled: boolean
212+
isConfusionFeedbackEnabled: boolean
213+
}
214+
export const LiveQuizStudentSettingsRef =
215+
builder.objectRef<ILiveQuizStudentSettings>('LiveQuizStudentSettings')
216+
export const LiveQuizStudentSettings = LiveQuizStudentSettingsRef.implement({
217+
fields: (t) => ({
218+
isLiveQAEnabled: t.exposeBoolean('isLiveQAEnabled'),
219+
isConfusionFeedbackEnabled: t.exposeBoolean('isConfusionFeedbackEnabled'),
220+
}),
221+
})
222+
210223
export interface ILiveQuizSummary {
211224
numOfResponses: number
212225
numOfFeedbacks: number

0 commit comments

Comments
 (0)