Skip to content

Commit 88060ff

Browse files
committed
fix(trpc): show modal detail query failures
1 parent 748fb4e commit 88060ff

6 files changed

Lines changed: 378 additions & 256 deletions

File tree

apps/frontend-control/src/components/liveQuizzes/EmbeddingModal.tsx

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { faClipboard } from '@fortawesome/free-solid-svg-icons'
22
import { trpc } from '@lib/trpc'
3-
import { Button, H2, Modal } from '@uzh-bf/design-system'
3+
import { Button, H2, Modal, UserNotification } from '@uzh-bf/design-system'
44
import { useTranslations } from 'next-intl'
55
import Link from 'next/link'
66

@@ -49,49 +49,68 @@ function EmbeddingModal({
4949
quizId: string
5050
}) {
5151
const t = useTranslations()
52-
const { data, isLoading: loading } = trpc.liveQuiz.embeddingInfo.useQuery(
52+
const {
53+
data,
54+
error,
55+
isLoading: loading,
56+
} = trpc.liveQuiz.embeddingInfo.useQuery(
5357
{ id: quizId },
5458
{ enabled: !!quizId }
5559
)
5660
const embeddingInfo = data?.embeddingInfo
61+
const initialLoading = loading && !embeddingInfo
62+
const embeddingUnavailable = Boolean((error || !loading) && !embeddingInfo)
5763

5864
return (
5965
<Modal
6066
open
6167
hideCloseButton
62-
loading={loading}
68+
loading={initialLoading}
6369
onClose={onClose}
6470
onSecondaryAction={onClose}
6571
secondaryLabel={t('shared.generic.close')}
6672
dataSecondaryAction={{ cy: 'close-embedding-modal' }}
6773
>
6874
<H2>{t('control.course.pptEmbedding')}</H2>
69-
<div className="flex flex-col gap-3">
70-
{embeddingInfo?.instances.map((instance, ix) => {
71-
return (
72-
<div key={instance.id}>
73-
<div className="line-clamp-1 w-full font-bold">{`${ix + 1}. ${
74-
instance.name
75-
}`}</div>
76-
<HMACLink
77-
quizId={quizId}
78-
hmac={embeddingInfo.hmac}
79-
params={`questionIx=${ix}&hideControls=true`}
80-
identifier={`question-${ix}`}
81-
/>
82-
</div>
83-
)
84-
})}
85-
</div>
86-
<div className="mt-3">
87-
<div className="w-30 font-bold">{t('shared.generic.leaderboard')}:</div>
88-
<HMACLink
89-
quizId={quizId}
90-
hmac={embeddingInfo?.hmac ?? ''}
91-
params={`leaderboard=true&hideControls=true`}
92-
identifier={`leaderboard`}
75+
{embeddingUnavailable ? (
76+
<UserNotification
77+
type="error"
78+
message={t('shared.generic.systemError')}
9379
/>
94-
</div>
80+
) : null}
81+
82+
{embeddingInfo ? (
83+
<>
84+
<div className="flex flex-col gap-3">
85+
{embeddingInfo.instances.map((instance, ix) => {
86+
return (
87+
<div key={instance.id}>
88+
<div className="line-clamp-1 w-full font-bold">{`${ix + 1}. ${
89+
instance.name
90+
}`}</div>
91+
<HMACLink
92+
quizId={quizId}
93+
hmac={embeddingInfo.hmac}
94+
params={`questionIx=${ix}&hideControls=true`}
95+
identifier={`question-${ix}`}
96+
/>
97+
</div>
98+
)
99+
})}
100+
</div>
101+
<div className="mt-3">
102+
<div className="w-30 font-bold">
103+
{t('shared.generic.leaderboard')}:
104+
</div>
105+
<HMACLink
106+
quizId={quizId}
107+
hmac={embeddingInfo.hmac}
108+
params={`leaderboard=true&hideControls=true`}
109+
identifier={`leaderboard`}
110+
/>
111+
</div>
112+
</>
113+
) : null}
95114
</Modal>
96115
)
97116
}

apps/frontend-manage/src/components/elements/manipulation/ElementDeletionModal.tsx

Lines changed: 96 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { UserNotification } from '@uzh-bf/design-system'
12
import { useTranslations } from 'next-intl'
23
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
34
import { trpc } from '../../../lib/trpc'
@@ -28,17 +29,20 @@ function ElementDeletionModal({
2829
})
2930

3031
// fetch element information
31-
const { data, isLoading: queryLoading } = trpc.element.summary.useQuery(
32-
{ id: elementId },
33-
{ enabled: !!elementId }
32+
const {
33+
data,
34+
error: summaryError,
35+
isLoading: queryLoading,
36+
} = trpc.element.summary.useQuery({ id: elementId }, { enabled: !!elementId })
37+
const summary = data?.elementSummary
38+
const initialSummaryLoading = queryLoading && !summary
39+
const summaryUnavailable = Boolean(
40+
(summaryError || !queryLoading) && !summary
3441
)
3542

36-
const notApplicableShared =
37-
!!data?.elementSummary && !data.elementSummary.sharedElementActivityUse
38-
const notApplicableDerived =
39-
!!data?.elementSummary && !data.elementSummary.retainsDerivedAccess
40-
const notApplicableResources =
41-
!!data?.elementSummary && !data.elementSummary.derivedAccessToResources
43+
const notApplicableShared = !!summary && !summary.sharedElementActivityUse
44+
const notApplicableDerived = !!summary && !summary.retainsDerivedAccess
45+
const notApplicableResources = !!summary && !summary.derivedAccessToResources
4246

4347
// on modal opening, reset the confirmation state
4448
useEffect(() => {
@@ -62,7 +66,7 @@ function ElementDeletionModal({
6266
confirmationType="delete"
6367
onClose={() => setModalOpen(false)}
6468
title={t('manage.questionPool.deleteElement')}
65-
loading={queryLoading}
69+
loading={initialSummaryLoading}
6670
message={t.rich('manage.questionPool.confirmDeletion', {
6771
name: title,
6872
b: (content) => <b>{content}</b>,
@@ -77,79 +81,90 @@ function ElementDeletionModal({
7781
setModalOpen(false)
7882
}}
7983
submitting={deleteElement.isLoading}
80-
confirmations={confirmations}
81-
confirmationsInitializing={false}
84+
confirmations={summary ? confirmations : { summaryLoaded: false }}
85+
confirmationsInitializing={initialSummaryLoading}
8286
>
83-
<div className="flex flex-col gap-2">
84-
<ConfirmationItem
85-
confirmationType="delete"
86-
label={t('manage.questionPool.elementDeletionFinal')}
87-
onClick={() => {
88-
setConfirmations((prev) => ({
89-
...prev,
90-
actionFinal: true,
91-
}))
92-
}}
93-
confirmed={confirmations.actionFinal}
94-
notApplicable={false}
95-
data={{ cy: 'confirm-deletion-final' }}
87+
{summaryUnavailable ? (
88+
<UserNotification
89+
type="error"
90+
message={t('shared.generic.systemError')}
9691
/>
97-
<ConfirmationItem
98-
confirmationType="delete"
99-
label={
100-
notApplicableShared
101-
? t('manage.questionPool.elementDeletionOtherUsersNotApplicable')
102-
: t('manage.questionPool.elementDeletionOtherUsers')
103-
}
104-
onClick={() => {
105-
setConfirmations((prev) => ({
106-
...prev,
107-
otherUsersAccess: true,
108-
}))
109-
}}
110-
confirmed={confirmations.otherUsersAccess}
111-
notApplicable={notApplicableShared}
112-
data={{ cy: 'confirm-other-users-access' }}
113-
/>
114-
<ConfirmationItem
115-
confirmationType="delete"
116-
label={
117-
notApplicableDerived
118-
? t(
119-
'manage.questionPool.elementDeletionDerivedAccessNotApplicable'
120-
)
121-
: t('manage.questionPool.elementDeletionDerivedAccessHint')
122-
}
123-
onClick={() => {
124-
setConfirmations((prev) => ({
125-
...prev,
126-
derivedAccessHint: true,
127-
}))
128-
}}
129-
confirmed={confirmations.derivedAccessHint}
130-
notApplicable={notApplicableDerived}
131-
data={{ cy: 'confirm-derived-access' }}
132-
/>
133-
<ConfirmationItem
134-
confirmationType="delete"
135-
label={
136-
notApplicableResources
137-
? t(
138-
'manage.questionPool.elementDeletionDependencyAccessNotApplicable'
139-
)
140-
: t('manage.questionPool.elementDeletionDependencyAccess')
141-
}
142-
onClick={() => {
143-
setConfirmations((prev) => ({
144-
...prev,
145-
dependencyAccess: true,
146-
}))
147-
}}
148-
confirmed={confirmations.dependencyAccess}
149-
notApplicable={notApplicableResources}
150-
data={{ cy: 'confirm-dependency-access' }}
151-
/>
152-
</div>
92+
) : null}
93+
94+
{summary ? (
95+
<div className="flex flex-col gap-2">
96+
<ConfirmationItem
97+
confirmationType="delete"
98+
label={t('manage.questionPool.elementDeletionFinal')}
99+
onClick={() => {
100+
setConfirmations((prev) => ({
101+
...prev,
102+
actionFinal: true,
103+
}))
104+
}}
105+
confirmed={confirmations.actionFinal}
106+
notApplicable={false}
107+
data={{ cy: 'confirm-deletion-final' }}
108+
/>
109+
<ConfirmationItem
110+
confirmationType="delete"
111+
label={
112+
notApplicableShared
113+
? t(
114+
'manage.questionPool.elementDeletionOtherUsersNotApplicable'
115+
)
116+
: t('manage.questionPool.elementDeletionOtherUsers')
117+
}
118+
onClick={() => {
119+
setConfirmations((prev) => ({
120+
...prev,
121+
otherUsersAccess: true,
122+
}))
123+
}}
124+
confirmed={confirmations.otherUsersAccess}
125+
notApplicable={notApplicableShared}
126+
data={{ cy: 'confirm-other-users-access' }}
127+
/>
128+
<ConfirmationItem
129+
confirmationType="delete"
130+
label={
131+
notApplicableDerived
132+
? t(
133+
'manage.questionPool.elementDeletionDerivedAccessNotApplicable'
134+
)
135+
: t('manage.questionPool.elementDeletionDerivedAccessHint')
136+
}
137+
onClick={() => {
138+
setConfirmations((prev) => ({
139+
...prev,
140+
derivedAccessHint: true,
141+
}))
142+
}}
143+
confirmed={confirmations.derivedAccessHint}
144+
notApplicable={notApplicableDerived}
145+
data={{ cy: 'confirm-derived-access' }}
146+
/>
147+
<ConfirmationItem
148+
confirmationType="delete"
149+
label={
150+
notApplicableResources
151+
? t(
152+
'manage.questionPool.elementDeletionDependencyAccessNotApplicable'
153+
)
154+
: t('manage.questionPool.elementDeletionDependencyAccess')
155+
}
156+
onClick={() => {
157+
setConfirmations((prev) => ({
158+
...prev,
159+
dependencyAccess: true,
160+
}))
161+
}}
162+
confirmed={confirmations.dependencyAccess}
163+
notApplicable={notApplicableResources}
164+
data={{ cy: 'confirm-dependency-access' }}
165+
/>
166+
</div>
167+
) : null}
153168
</ActivityConfirmationModal>
154169
)
155170
}

0 commit comments

Comments
 (0)