Repository: uzh-bf/klicker-uzh
Pull request #4713: feat(apps/frontend-manage): add possibility to open answer collection edit modal directly from element edit modal
Author: login: sjschlapbach
Labels: name: feature
name: size:XL
description: This PR changes 500-999 lines, ignoring generated files.
Created: 2025-05-23T15:17:07Z | Merged: 2025-05-26T10:10:58Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enabled inline editing capabilities for answer collections within forms and selection components.
  - Added an inline edit button for answer collections, conditionally active based on permissions.
  - Enhanced modals and forms to support inline editing and automatic data refresh post-editing.

- **Improvements**
  - Improved handling of answer collection permissions, providing clear messages for insufficient rights.
  - Refined data fetching and state management for answer collections, decoupling from internal queries.
  - Introduced logic to mark shared and editor status for answer collections, preventing duplication.

- **Bug Fixes**
  - Removed logic that reset solutions when changing or removing case study items, simplifying reset behavior.

- **Localization**
  - Added new translation strings for collection selection prompts and permission error messages in English and German.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx b/apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
index 0eb563acf4..d7bebf1348 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
@@ -1,7 +1,9 @@
+import { useQuery } from '@apollo/client'
 import {
   ElementData,
   ElementStatus,
   ElementType,
+  GetAnswerCollectionsElementsDocument,
   ObjectType,
 } from '@klicker-uzh/graphql/dist/ops'
 import { Button, H3, Modal } from '@uzh-bf/design-system'
@@ -14,6 +16,7 @@ import {
 import { Form, Formik } from 'formik'
 import { useTranslations } from 'next-intl'
 import { Dispatch, SetStateAction, useState } from 'react'
+import AnswerCollectionEditModal from '../../resources/answerCollections/AnswerCollectionEditModal'
 import ActivityLog from '../../sharing/ActivityLog'
 import AutoSaveMonitor from './AutoSaveMonitor'
 import ElementContentInput from './ElementContentInput'
@@ -94,281 +97,329 @@ function ElementEditForm({
   const [elementDataTypename, setElementDataTypename] = useState<
     ElementData['__typename'] | undefined
   >()
+  const [collectionModal, setCollectionModal] = useState<{
+    open: boolean
+    id?: number
+  }>({ open: false, id: undefined })
 
   const questionManipulationSchema = useValidationSchema({
     numberOfAnswerOptions: answerCollectionEntries.length,
   })
 
+  const {
+    data,
+    loading: collectionsLoading,
+    refetch,
+  } = useQuery(GetAnswerCollectionsElementsDocument, {
+    variables: { templateId },
+    fetchPolicy: 'network-only',
+  })
+  const collections = data?.getAnswerCollectionsElements ?? []
+
   return (
-    <Formik
-      validateOnMount
-      enableReinitialize={!isTemplate}
-      initialValues={initialValues}
-      validationSchema={questionManipulationSchema}
-      onSubmit={async (values, { setSubmitting }) => {
-        setSubmitting(true)
-        const success = await onSubmitElement({
-          ...values,
-          status: elementStatus,
-        })
+    <>
+      <Formik
+        validateOnMount
+        enableReinitialize={!isTemplate}
+        initialValues={initialValues}
+        validationSchema={questionManipulationSchema}
+        onSubmit={async (values, { setSubmitting }) => {
+          setSubmitting(true)
+          const success = await onSubmitElement({
+            ...values,
+            status: elementStatus,
+          })
 
-        // close modal, set success toast
-        setSubmitting(false)
-        if (!success) {
-          setFailureToast(true)
-        } else {
-          onSuccess()
-        }
-      }}
-    >
-      {({
-        values,
-        errors,
-        isSubmitting,
-        isValid,
-        setFieldValue,
-        setFieldTouched,
-        validateForm,
-      }) => {
-        if (loading) {
-          return null
-        }
+          // close modal, set success toast
+          setSubmitting(false)
+          if (!success) {
+            setFailureToast(true)
+          } else {
+            onSuccess()
+          }
+        }}
+      >
+        {({
+          values,
+          errors,
+          isSubmitting,
+          isValid,
+          setFieldValue,
+          setFieldTouched,
+          validateForm,
+        }) => {
+          if (loading) {
+            return null
+          }
 
-        return (
-          <Modal
-            asPortal
-            fullScreen
-            title={t(`manage.elements.${mode}Title`)}
-            className={{
-              content: 'h-max max-h-full max-w-[1400px] text-sm md:text-base',
-              title: 'text-xl',
-            }}
-            open={open}
-            onClose={() => onClose()}
-            escapeDisabled={true}
-            onPrimaryAction={
-              !inputsDisabled ? (
-                <Button
-                  primary
-                  type="submit"
-                  loading={isSubmitting}
-                  disabled={!isValid}
-                  className={{ root: 'mt-2' }}
-                  form="question-manipulation-form"
-                  data={{ cy: 'save-new-question' }}
-                >
-                  <Button.Label>{t('shared.generic.save')}</Button.Label>
-                </Button>
-              ) : undefined
-            }
-            onSecondaryAction={
-              !isTemplate && !inputsDisabled ? (
-                <Button
-                  className={{ root: 'mt-2' }}
-                  onClick={() => onClose()}
-                  data={{ cy: 'close-element-modal' }}
-                >
-                  <Button.Label>{t('shared.generic.close')}</Button.Label>
-                </Button>
-              ) : undefined
-            }
-          >
-            {!inputsDisabled && (
-              <AutoSaveMonitor
-                values={values}
-                initialValuesString={JSON.stringify(initialValues)}
-                setAutoSavedElement={setAutoSavedElement}
+          return (
+            <Modal
+              asPortal
+              fullScreen
+              title={t(`manage.elements.${mode}Title`)}
+              className={{
+                content: 'h-max max-h-full max-w-[1400px] text-sm md:text-base',
+                title: 'text-xl',
+              }}
+              open={open}
+              onClose={() => onClose()}
+              escapeDisabled={true}
+              onPrimaryAction={
+                !inputsDisabled ? (
+                  <Button
+                    primary
+                    type="submit"
+                    loading={isSubmitting}
+                    disabled={!isValid}
+                    className={{ root: 'mt-2' }}
+                    form="question-manipulation-form"
+                    data={{ cy: 'save-new-question' }}
+                  >
+                    <Button.Label>{t('shared.generic.save')}</Button.Label>
+                  </Button>
+                ) : undefined
+              }
+              onSecondaryAction={
+                !isTemplate && !inputsDisabled ? (
+                  <Button
+                    className={{ root: 'mt-2' }}
+                    onClick={() => onClose()}
+                    data={{ cy: 'close-element-modal' }}
+                  >
+                    <Button.Label>{t('shared.generic.close')}</Button.Label>
+                  </Button>
+                ) : undefined
+              }
+            >
+              {!inputsDisabled && (
+                <AutoSaveMonitor
+                  values={values}
+                  initialValuesString={JSON.stringify(initialValues)}
+                  setAutoSavedElement={setAutoSavedElement}
+                />
+              )}
+              <ElementTypeMonitor
+                elementType={values.type ?? ElementType.Sc}
+                setElementDataTypename={setElementDataTypename}
+                validateForm={validateForm}
               />
-            )}
-            <ElementTypeMonitor
-              elementType={values.type ?? ElementType.Sc}
-              setElementDataTypename={setElementDataTypename}
-              validateForm={validateForm}
-            />
-            <div className="flex flex-row gap-12">
-              <div className="max-w-5xl flex-1">
-                <Form className="w-full" id="question-manipulation-form">
-                  <ElementInformationFields
-                    isTemplate={isTemplate}
-                    elementId={elementId}
-                    elementStatus={elementStatus}
-                    setElementStatus={setElementStatus}
-                    inputsDisabled={inputsDisabled}
-                    mode={mode}
-                    values={values}
-                    isSubmitting={isSubmitting}
-                  />
-                  <ElementContentInput
-                    disabled={inputsDisabled}
-                    values={values}
-                    setFieldValue={setFieldValue}
-                  />
-                  <ElementExplanationField
-                    disabled={inputsDisabled}
-                    values={values}
-                    setFieldValue={setFieldValue}
-                  />
-
-                  {/* scoring section */}
-                  {!isTemplate &&
-                    values.type !== ElementType.Content &&
-                    values.type !== ElementType.Flashcard && (
-                      <ElementformScoringSection
-                        isTemplate={isTemplate}
-                        disabled={inputsDisabled}
-                        values={values}
-                        setFieldValue={setFieldValue}
-                        isSubmitting={isSubmitting}
-                      />
-                    )}
-
-                  <div className="mt-4 flex flex-row gap-4">
-                    <OptionsLabel type={values.type} />
-                    <AnswerFeedbackSetting
-                      disabled={isTemplate || inputsDisabled}
+              <div className="flex flex-row gap-12">
+                <div className="max-w-5xl flex-1">
+                  <Form className="w-full" id="question-manipulation-form">
+                    <ElementInformationFields
+                      isTemplate={isTemplate}
+                      elementId={elementId}
+                      elementStatus={elementStatus}
+                      setElementStatus={setElementStatus}
+                      inputsDisabled={inputsDisabled}
+                      mode={mode}
                       values={values}
+                      isSubmitting={isSubmitting}
                     />
-                    <DisplayModeSetting
+                    <ElementContentInput
                       disabled={inputsDisabled}
-                      type={values.type}
-                    />
-                  </div>
-
-                  {values.type === ElementType.Sc ||
-                  values.type === ElementType.Mc ||
-                  values.type === ElementType.Kprim ? (
-                    <ChoicesOptions
-                      inputsDisabled={inputsDisabled}
                       values={values}
                       setFieldValue={setFieldValue}
                     />
-                  ) : null}
-
-                  {values.type === ElementType.Numerical && (
-                    <NumericalOptions
-                      inputsDisabled={inputsDisabled}
+                    <ElementExplanationField
+                      disabled={inputsDisabled}
                       values={values}
+                      setFieldValue={setFieldValue}
                     />
-                  )}
 
-                  {values.type === ElementType.FreeText && (
-                    <FreeTextOptions
-                      inputsDisabled={inputsDisabled}
-                      values={values}
-                    />
-                  )}
+                    {/* scoring section */}
+                    {!isTemplate &&
+                      values.type !== ElementType.Content &&
+                      values.type !== ElementType.Flashcard && (
+                        <ElementformScoringSection
+                          isTemplate={isTemplate}
+                          disabled={inputsDisabled}
+                          values={values}
+                          setFieldValue={setFieldValue}
+                          isSubmitting={isSubmitting}
+                        />
+                      )}
 
-                  {values.type === ElementType.Selection && (
-                    <SelectionOptions
-                      creationMode={
-                        mode === ElementEditMode.CREATE ||
-                        mode === ElementEditMode.DUPLICATE
-                      }
-                      templateId={templateId}
-                      isTemplate={isTemplate}
-                      inputsDisabled={inputsDisabled}
-                      values={values}
-                      setAnswerCollectionEntries={setAnswerCollectionEntries}
-                    />
-                  )}
+                    <div className="mt-4 flex flex-row gap-4">
+                      <OptionsLabel type={values.type} />
+                      <AnswerFeedbackSetting
+                        disabled={isTemplate || inputsDisabled}
+                        values={values}
+                      />
+                      <DisplayModeSetting
+                        disabled={inputsDisabled}
+                        type={values.type}
+                      />
+                    </div>
 
-                  {values.type === ElementType.CaseStudy && (
-                    <CaseStudyOptions
-                      creationMode={
-                        mode === ElementEditMode.CREATE ||
-                        mode === ElementEditMode.DUPLICATE
-                      }
-                      templateId={templateId}
-                      isTemplate={isTemplate}
-                      inputsDisabled={inputsDisabled}
-                      setFieldValue={setFieldValue}
-                      setFieldTouched={setFieldTouched}
-                      hasSampleSolution={values.options.hasSampleSolution}
-                      setAnswerCollectionEntries={setAnswerCollectionEntries}
-                    />
-                  )}
-                </Form>
+                    {values.type === ElementType.Sc ||
+                    values.type === ElementType.Mc ||
+                    values.type === ElementType.Kprim ? (
+                      <ChoicesOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                        setFieldValue={setFieldValue}
+                      />
+                    ) : null}
 
-                {Object.keys(errors).length !== 0 && (
-                  <ElementFormErrors errors={errors} />
-                )}
-              </div>
+                    {values.type === ElementType.Numerical && (
+                      <NumericalOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                      />
+                    )}
+
+                    {values.type === ElementType.FreeText && (
+                      <FreeTextOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                      />
+                    )}
+
+                    {values.type === ElementType.Selection && (
+                      <SelectionOptions
+                        creationMode={
+                          mode === ElementEditMode.CREATE ||
+                          mode === ElementEditMode.DUPLICATE
+                        }
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                        collections={collections}
+                        collectionsLoading={collectionsLoading}
+                        refetchCollections={async () => {
+                          await refetch()
+                        }}
+                        setAnswerCollectionEntries={setAnswerCollectionEntries}
+                        openAnswerCollectionEditModal={(
+                          collectionId: number
+                        ) => {
+                          setCollectionModal({ open: true, id: collectionId })
+                        }}
+                      />
+                    )}
+
+                    {values.type === ElementType.CaseStudy && (
+                      <CaseStudyOptions
+                        creationMode={
+                          mode === ElementEditMode.CREATE ||
+                          mode === ElementEditMode.DUPLICATE
+                        }
+                        inputsDisabled={inputsDisabled}
+                        setFieldValue={setFieldValue}
+                        setFieldTouched={setFieldTouched}
+                        hasSampleSolution={values.options.hasSampleSolution}
+                        collections={collections}
+                        collectionsLoading={collectionsLoading}
+                        refetchCollections={async () => {
+                          await refetch()
+                        }}
+                        setAnswerCollectionEntries={setAnswerCollectionEntries}
+                        openAnswerCollectionEditModal={(
+                          collectionId: number
+                        ) => {
+                          setCollectionModal({ open: true, id: collectionId })
+                        }}
+                      />
+                    )}
+                  </Form>
+
+                  {Object.keys(errors).length !== 0 && (
+                    <ElementFormErrors errors={errors} />
+                  )}
+                </div>
 
-              {mode === ElementEditMode.EDIT ? (
-                <Tabs
-                  defaultValue="preview"
-                  className="w-full max-w-sm"
-                  onValueChange={(value) => {
-                    setActiveTab(value)
-                  }}
-                >
-                  <TabsList className="w-full">
-                    <TabsTrigger
-                      value="preview"
-                      className="w-1/2 font-bold"
-                      data-cy="element-preview-tab"
-                    >
-                      {t('shared.generic.preview')}
-                    </TabsTrigger>
-                    <TabsTrigger
-                      value="activity"
-                      className="w-1/2 font-bold"
-                      data-cy="element-activity-tab"
-                    >
-                      {t('shared.generic.activity')}
-                    </TabsTrigger>
-                  </TabsList>
-                  <TabsContent value="preview">
+                {mode === ElementEditMode.EDIT ? (
+                  <Tabs
+                    defaultValue="preview"
+                    className="w-full max-w-sm"
+                    onValueChange={(value) => {
+                      setActiveTab(value)
+                    }}
+                  >
+                    <TabsList className="w-full">
+                      <TabsTrigger
+                        value="preview"
+                        className="w-1/2 font-bold"
+                        data-cy="element-preview-tab"
+                      >
+                        {t('shared.generic.preview')}
+                      </TabsTrigger>
+                      <TabsTrigger
+                        value="activity"
+                        className="w-1/2 font-bold"
+                        data-cy="element-activity-tab"
+                      >
+                        {t('shared.generic.activity')}
+                      </TabsTrigger>
+                    </TabsList>
+                    <TabsContent value="preview">
+                      <StudentElementPreview
+                        values={values}
+                        elementDataTypename={elementDataTypename}
+                        answerCollectionEntries={answerCollectionEntries}
+                      />
+                    </TabsContent>
+                    <TabsContent value="activity">
+                      <div className="w-sm w-full flex-1">
+                        <ActivityLog
+                          visible={activeTab === 'activity'}
+                          objectId={elementId || ''}
+                          objectType={ObjectType.Element}
+                        />
+                      </div>
+                    </TabsContent>
+                  </Tabs>
+                ) : (
+                  <div className="w-full max-w-sm">
+                    <H3>{t('shared.generic.preview')}</H3>
                     <StudentElementPreview
                       values={values}
                       elementDataTypename={elementDataTypename}
                       answerCollectionEntries={answerCollectionEntries}
                     />
-                  </TabsContent>
-                  <TabsContent value="activity">
-                    <div className="w-sm w-full flex-1">
-                      <ActivityLog
-                        visible={activeTab === 'activity'}
-                        objectId={elementId || ''}
-                        objectType={ObjectType.Element}
-                      />
-                    </div>
-                  </TabsContent>
-                </Tabs>
-              ) : (
-                <div className="w-full max-w-sm">
-                  <H3>{t('shared.generic.preview')}</H3>
-                  <StudentElementPreview
-                    values={values}
-                    elementDataTypename={elementDataTypename}
-                    answerCollectionEntries={answerCollectionEntries}
-                  />
-                </div>
-              )}
-            </div>
+                  </div>
+                )}
+              </div>
 
-            {mode === ElementEditMode.EDIT && elementId && !inputsDisabled && (
-              <InstanceUpdateSwitch
-                elementId={elementId}
-                hasSampleSolution={
-                  'options' in values && 'hasSampleSolution' in values.options
-                    ? values.options.hasSampleSolution
-                    : undefined
-                }
-                updateInstances={updateInstances}
-                setUpdateInstances={setUpdateInstances}
-                includeTemplateUpdates={includeTemplateUpdates}
-                setIncludeTemplateUpdates={setIncludeTemplateUpdates}
+              {mode === ElementEditMode.EDIT &&
+                elementId &&
+                !inputsDisabled && (
+                  <InstanceUpdateSwitch
+                    elementId={elementId}
+                    hasSampleSolution={
+                      'options' in values &&
+                      'hasSampleSolution' in values.options
+                        ? values.options.hasSampleSolution
+                        : undefined
+                    }
+                    updateInstances={updateInstances}
+                    setUpdateInstances={setUpdateInstances}
+                    includeTemplateUpdates={includeTemplateUpdates}
+                    setIncludeTemplateUpdates={setIncludeTemplateUpdates}
+                  />
+                )}
+              <ElementFailureToast
+                open={failureToast}
+                onClose={() => setFailureToast(false)}
               />
-            )}
-            <ElementFailureToast
-              open={failureToast}
-              onClose={() => setFailureToast(false)}
-            />
-          </Modal>
-        )
-      }}
-    </Formik>
+            </Modal>
+          )
+        }}
+      </Formik>
+
+      {collectionModal.open && typeof collectionModal.id !== 'undefined' ? (
+        <AnswerCollectionEditModal
+          inlineEditing
+          collectionId={collectionModal.id}
+          open={collectionModal.open}
+          onClose={() => setCollectionModal({ open: false, id: undefined })}
+          refetchAnswerCollections={async () => {
+            await refetch()
+          }}
+          className={{ overlay: 'z-30', content: 'z-30' }}
+        />
+      ) : null}
+    </>
   )
 }
 
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx
new file mode 100644
index 0000000000..21dcea133b
--- /dev/null
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx
@@ -0,0 +1,48 @@
+import { faPencil } from '@fortawesome/free-solid-svg-icons'
+import { Button, Tooltip } from '@uzh-bf/design-system'
+import { useTranslations } from 'next-intl'
+
+function AnswerCollectionInlineEditButton({
+  disabled = true,
+  selectedCollectionId,
+  openAnswerCollectionEditModal,
+}: {
+  disabled?: boolean
+  selectedCollectionId?: number
+  openAnswerCollectionEditModal: (selectedCollectionId: number) => void
+}) {
+  const t = useTranslations()
+
+  if (disabled || typeof selectedCollectionId === 'undefined') {
+    return (
+      <Tooltip
+        tooltip={t('manage.elements.notSufficientPermissionsEditCollection')}
+        className={{ tooltip: 'text-sm' }}
+      >
+        <Button
+          disabled
+          className={{ root: 'h-9 w-9' }}
+          data={{ cy: 'inline-edit-answer-collection' }}
+        >
+          <Button.Icon withoutLabel icon={faPencil} />
+        </Button>
+      </Tooltip>
+    )
+  }
+
+  return (
+    <Button
+      onClick={() => {
+        if (typeof selectedCollectionId !== 'undefined') {
+          openAnswerCollectionEditModal(selectedCollectionId)
+        }
+      }}
+      className={{ root: 'h-9 w-9' }}
+      data={{ cy: 'inline-edit-answer-collection' }}
+    >
+      <Button.Icon withoutLabel icon={faPencil} />
+    </Button>
+  )
+}
+
+export default AnswerCollectionInlineEditButton
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx
index fec898538b..73bf47ad2f 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx
@@ -9,39 +9,41 @@ import {
 import { useField } from 'formik'
 import { useTranslations } from 'next-intl'
 import Link from 'next/link'
-import { Dispatch, SetStateAction, useState } from 'react'
+import { Dispatch, SetStateAction, useMemo, useState } from 'react'
 import Select from 'react-select'
 import { twMerge } from 'tailwind-merge'
 import { ElementFormTypesCaseStudy } from '../types'
+import AnswerCollectionInlineEditButton from './AnswerCollectionInlineEditButton'
 import CaseStudyCollectionChangeModal from './CaseStudyCollectionChangeModal'
 import useAnswerCollectionChangeEffect from './useAnswerCollectionChangeEffect'
 import useSelectAnswerCollectionOptions from './useSelectAnswerCollectionOptions'
 import useSelectedAnswerEntry from './useSelectedAnswerEntry'
+import useSolutionsUpdateItemsChange from './useSolutionsUpdateItemsChange'
 
 function CaseStudyCollectionSelection({
   loading,
   disabled,
   creationMode,
-  isTemplate,
   collections,
+  refetchCollections,
   setSelectedItems,
   hasSampleSolution,
   setAnswerCollectionEntries,
   setItemSelectionMode,
-  refetchAnswerCollections,
+  openAnswerCollectionEditModal,
 }: {
   loading: boolean
   disabled: boolean
   creationMode: boolean
-  isTemplate: boolean
-  collections: Pick<AnswerCollection, 'id' | 'name' | 'entries'>[]
+  collections: Pick<AnswerCollection, 'id' | 'name' | 'isEditor' | 'entries'>[]
+  refetchCollections: () => Promise<any>
   setSelectedItems: Dispatch<SetStateAction<{ id: number; name: string }[]>>
   hasSampleSolution: boolean
   setAnswerCollectionEntries: Dispatch<
     SetStateAction<{ id: number; value: string }[]>
   >
   setItemSelectionMode: (newValue: 'existing' | 'new') => void
-  refetchAnswerCollections: () => Promise<any>
+  openAnswerCollectionEditModal: (collectionId: number) => void
 }) {
   const t = useTranslations()
   const [changeModalOpen, setChangeModalOpen] = useState(false)
@@ -78,6 +80,24 @@ function CaseStudyCollectionSelection({
     collectionAnswers,
   })
 
+  // update the solutions stored on the cases to be consistent with the selected items
+  useSolutionsUpdateItemsChange({
+    itemIds: itemsField.value ?? [],
+    cases: casesField.value,
+    casesHelpers,
+  })
+
+  // locally store the selected answer collection
+  const selectedCollection = useMemo(() => {
+    if (typeof collectionField.value === 'undefined') {
+      return undefined
+    }
+
+    return collections.find(
+      (collection) => collection.id === parseInt(collectionField.value!)
+    )
+  }, [collectionField.value, collections])
+
   if (collections.length === 0) {
     return (
       <UserNotification type="warning" className={{ root: 'text-sm' }}>
@@ -155,7 +175,7 @@ function CaseStudyCollectionSelection({
         />
         <Button
           disabled={disabled || loading}
-          onClick={async () => await refetchAnswerCollections()}
+          onClick={async () => await refetchCollections()}
           className={{ root: 'h-9 w-9' }}
           data={{ cy: 'refresh-answer-collections' }}
         >
@@ -165,6 +185,13 @@ function CaseStudyCollectionSelection({
             className={{ root: twMerge(loading ? 'animate-spin' : '') }}
           />
         </Button>
+        <AnswerCollectionInlineEditButton
+          disabled={!selectedCollection?.isEditor}
+          selectedCollectionId={
+            collectionField.value ? parseInt(collectionField.value) : undefined
+          }
+          openAnswerCollectionEditModal={openAnswerCollectionEditModal}
+        />
       </div>
       {creationMode && (
         <Button
@@ -217,44 +244,8 @@ function CaseStudyCollectionSelection({
               container: () => 'w-full',
             }}
             onChange={(newValue) => {
-              const prevItemIds = itemsField.value
-              const newItemIds = newValue.map((item) => item.value)
-
-              // check if an item has been removed and conditionally remove the solutions for this item
-              if (newItemIds.length < (prevItemIds ?? []).length) {
-                // identify the removed item
-                const removedItem = (prevItemIds ?? []).find(
-                  (itemId) => !newItemIds.includes(itemId)
-                )
-
-                // if an item has been removed, remove the corresponding key from the case solutions
-                if (removedItem) {
-                  const newCases = casesField.value?.map((caseItem) => {
-                    // if no solutions are set, skip this case
-                    if (!('solutions' in caseItem) || !caseItem.solutions) {
-                      return caseItem
-                    }
-
-                    // filter out all solution entries for the removed item
-                    const newSolutions = Object.fromEntries(
-                      Object.entries(caseItem.solutions).filter(
-                        ([itemIdString]) =>
-                          itemIdString !== `itemId-${removedItem}`
-                      )
-                    )
-
-                    return {
-                      ...caseItem,
-                      solutions: newSolutions,
-                    }
-                  })
-
-                  // update the cases field
-                  casesHelpers.setValue(newCases)
-                }
-              }
-
               // update the selected items
+              const newItemIds = newValue.map((item) => item.value)
               itemsHelpers.setValue(newItemIds)
             }}
             placeholder={t('manage.elements.selectCaseStudyItems')}
@@ -273,20 +264,6 @@ function CaseStudyCollectionSelection({
 
             // reset the selected items
             itemsHelpers.setValue([])
-
-            // reset all solutions inside the cases
-            casesHelpers.setValue(
-              casesField.value?.map((caseItem) => {
-                if ('solutions' in caseItem) {
-                  return {
-                    ...caseItem,
-                    solutions: undefined,
-                  }
-                }
-
-                return caseItem
-              })
-            )
           }}
         />
       </div>
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx
index 1ba7d94e4b..abe34433ad 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx
@@ -156,13 +156,6 @@ function CaseStudyManualItemCreation({
           // reset the manually created items
           manualItemsHelpers.setValue([])
 
-          // manually reset the sample solutions defined for the created cases
-          const newCases = casesField.value?.map((caseItem) => ({
-            ...caseItem,
-            solutions: undefined,
-          }))
-          casesHelpers.setValue(newCases)
-
           // switch to the selection mode for existing answer collections
           setItemSelectionMode('existing')
         }}
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx
index b5e2deebe7..f153b2ebde 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx
@@ -1,5 +1,4 @@
-import { useQuery } from '@apollo/client'
-import { GetAnswerCollectionsElementsDocument } from '@klicker-uzh/graphql/dist/ops'
+import { AnswerCollection } from '@klicker-uzh/graphql/dist/ops'
 import Loader from '@klicker-uzh/shared-components/src/Loader'
 import { useField } from 'formik'
 import { Dispatch, SetStateAction, useState } from 'react'
@@ -13,23 +12,27 @@ import CaseStudyManualItemCreation from './CaseStudyManualItemCreation'
 
 interface CaseStudyOptionsProps extends CaseStudySetterProps {
   creationMode: boolean
-  templateId?: string
-  isTemplate: boolean
   hasSampleSolution: boolean
+  collections: Omit<AnswerCollection, 'description'>[]
+  collectionsLoading: boolean
+  refetchCollections: () => Promise<any>
   setAnswerCollectionEntries: Dispatch<
     SetStateAction<{ id: number; value: string }[]>
   >
+  openAnswerCollectionEditModal: (collectionId: number) => void
 }
 
 function CaseStudyOptions({
   creationMode,
-  templateId,
-  isTemplate,
   inputsDisabled = false,
   setFieldValue,
   setFieldTouched,
   hasSampleSolution,
+  collections,
+  collectionsLoading,
+  refetchCollections,
   setAnswerCollectionEntries,
+  openAnswerCollectionEditModal,
 }: CaseStudyOptionsProps) {
   const [selectionMode, _, selectionModeHelpers] = useField<
     ElementFormTypesCaseStudy['options']['itemSelectionMode']
@@ -38,17 +41,8 @@ function CaseStudyOptions({
   const [selectedItems, setSelectedItems] = useState<
     { id: number; name: string }[]
   >([])
-  const {
-    data,
-    loading,
-    refetch: refetchAnswerCollections,
-  } = useQuery(GetAnswerCollectionsElementsDocument, {
-    variables: { templateId },
-    fetchPolicy: 'network-only',
-  })
-  const collections = data?.getAnswerCollectionsElements ?? []
 
-  if (loading) {
+  if (collectionsLoading) {
     return <Loader />
   }
 
@@ -57,10 +51,9 @@ function CaseStudyOptions({
       {(selectionMode.value === 'existing' ||
         typeof selectionMode.value === 'undefined') && (
         <CaseStudyCollectionSelection
-          loading={loading}
+          loading={collectionsLoading}
           disabled={inputsDisabled}
           creationMode={creationMode}
-          isTemplate={isTemplate}
           collections={collections}
           setSelectedItems={setSelectedItems}
           hasSampleSolution={hasSampleSolution}
@@ -68,9 +61,8 @@ function CaseStudyOptions({
           setItemSelectionMode={(newValue) =>
             selectionModeHelpers.setValue(newValue)
           }
-          refetchAnswerCollections={async () =>
-            await refetchAnswerCollections({ templateId })
-          }
+          refetchCollections={async () => await refetchCollections()}
+          openAnswerCollectionEditModal={openAnswerCollectionEditModal}
         />
       )}
       {creationMode && selectionMode.value === 'new' && (
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx
index c2b9f80d80..3b96fe58ac 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx
@@ -10,10 +10,11 @@ import {
 import { useField } from 'formik'
 import { useTranslations } from 'next-intl'
 import Link from 'next/link'
-import { Dispatch, SetStateAction } from 'react'
+import { Dispatch, SetStateAction, useMemo } from 'react'
 import Select from 'react-select'
 import { twMerge } from 'tailwind-merge'
 import { ElementFormTypesSelection } from '../types'
+import AnswerCollectionInlineEditButton from './AnswerCollectionInlineEditButton'
 import useAnswerCollectionChangeEffect from './useAnswerCollectionChangeEffect'
 import useSelectAnswerCollectionOptions from './useSelectAnswerCollectionOptions'
 import useSelectedAnswerEntry from './useSelectedAnswerEntry'
@@ -29,6 +30,7 @@ interface SelectionCollectionOptionsProps {
     SetStateAction<{ id: number; value: string }[]>
   >
   setItemSelectionMode: (newValue: 'existing' | 'new') => void
+  openAnswerCollectionEditModal: (collectionId: number) => void
 }
 
 function SelectionCollectionOptions({
@@ -40,12 +42,13 @@ function SelectionCollectionOptions({
   refetchCollections,
   setAnswerCollectionEntries,
   setItemSelectionMode,
+  openAnswerCollectionEditModal,
 }: SelectionCollectionOptionsProps) {
   const t = useTranslations()
   const [solutions, _, solutionHelpers] = useField<
     ElementFormTypesSelection['options']['correctAnswers']
   >('options.correctAnswers')
-  const [__, ____, collectionHelpers] = useField<
+  const [collectionField, ___, collectionHelpers] = useField<
     ElementFormTypesSelection['options']['answerCollection']
   >('options.answerCollection')
 
@@ -70,6 +73,17 @@ function SelectionCollectionOptions({
     collectionAnswers,
   })
 
+  // locally store the selected answer collection
+  const selectedCollection = useMemo(() => {
+    if (typeof collectionField.value === 'undefined') {
+      return undefined
+    }
+
+    return collections.find(
+      (collection) => collection.id === parseInt(collectionField.value!)
+    )
+  }, [collectionField.value, collections])
+
   if (collections.length === 0) {
     return (
       <UserNotification type="warning" className={{ root: 'text-sm' }}>
@@ -78,11 +92,14 @@ function SelectionCollectionOptions({
             <span
               className="cursor-pointer font-bold underline"
               onClick={() => {
-                // switch to the creation mode for new answer collection options
-                setItemSelectionMode('new')
+                // unsert any answer collection entries
+                setAnswerCollectionEntries([])
 
                 // reset the answer collection field to ensure that all fields update
                 collectionHelpers.setValue(undefined)
+
+                // switch to the creation mode for new answer collection options
+                setItemSelectionMode('new')
               }}
               data-cy="create-inline-answer-collection"
             >
@@ -148,6 +165,15 @@ function SelectionCollectionOptions({
               className={{ root: twMerge(loading ? 'animate-spin' : '') }}
             />
           </Button>
+          <AnswerCollectionInlineEditButton
+            disabled={!selectedCollection?.isEditor}
+            selectedCollectionId={
+              collectionField.value
+                ? parseInt(collectionField.value)
+                : undefined
+            }
+            openAnswerCollectionEditModal={openAnswerCollectionEditModal}
+          />
         </div>
 
         <FormikNumberField
@@ -173,11 +199,11 @@ function SelectionCollectionOptions({
             // reset the items selected as sample solutions
             solutionHelpers.setValue([])
 
-            // switch to the creation mode for new answer collection options
-            setItemSelectionMode('new')
-
             // reset the answer collection field to ensure that all fields update
             collectionHelpers.setValue(undefined)
+
+            // switch to the creation mode for new answer collection options
+            setItemSelectionMode('new')
           }}
           className={{
             root: 'text-primary-100 hover:text-primary-100 w-max px-0.5 py-1 text-sm hover:bg-transparent hover:underline',
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx b/apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx
index a155a1e911..30a386b8c5 100644
--- a/apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx
@@ -1,8 +1,6 @@
-import { useQuery } from '@apollo/client'
-import { GetAnswerCollectionsElementsDocument } from '@klicker-uzh/graphql/dist/ops'
+import { AnswerCollection } from '@klicker-uzh/graphql/dist/ops'
 import Loader from '@klicker-uzh/shared-components/src/Loader'
 import { useField } from 'formik'
-import { useTranslations } from 'next-intl'
 import { Dispatch, SetStateAction } from 'react'
 import { ElementFormTypesSelection } from '../types'
 import SelectionCollectionOptions from './SelectionCollectionOptions'
@@ -10,38 +8,32 @@ import SelectionManualItemCreation from './SelectionManualItemCreation'
 
 interface SelectionOptionsProps {
   creationMode: boolean
-  templateId?: string
-  isTemplate: boolean
   inputsDisabled?: boolean
   values: ElementFormTypesSelection
+  collections: Omit<AnswerCollection, 'description'>[]
+  collectionsLoading: boolean
+  refetchCollections: () => Promise<any>
   setAnswerCollectionEntries: Dispatch<
     SetStateAction<{ id: number; value: string }[]>
   >
+  openAnswerCollectionEditModal: (collectionId: number) => void
 }
 
 function SelectionOptions({
   creationMode,
-  templateId,
-  isTemplate,
   inputsDisabled,
   values,
+  collections,
+  collectionsLoading,
+  refetchCollections,
   setAnswerCollectionEntries,
+  openAnswerCollectionEditModal,
 }: SelectionOptionsProps) {
-  const t = useTranslations()
   const [selectionMode, _, selectionModeHelpers] = useField<
     ElementFormTypesSelection['options']['itemSelectionMode']
   >('options.itemSelectionMode')
 
-  const { data, loading, refetch } = useQuery(
-    GetAnswerCollectionsElementsDocument,
-    {
-      variables: { templateId },
-      fetchPolicy: 'network-only',
-    }
-  )
-  const collections = data?.getAnswerCollectionsElements ?? []
-
-  if (loading) {
+  if (collectionsLoading) {
     return <Loader />
   }
 
@@ -68,13 +60,14 @@ function SelectionOptions({
       creationMode={creationMode}
       inputsDisabled={inputsDisabled}
       collections={collections}
-      refetchCollections={refetch}
-      loading={loading}
+      refetchCollections={refetchCollections}
+      loading={collectionsLoading}
       values={values}
       setAnswerCollectionEntries={setAnswerCollectionEntries}
       setItemSelectionMode={(newValue) =>
         selectionModeHelpers.setValue(newValue)
       }
+      openAnswerCollectionEditModal={openAnswerCollectionEditModal}
     />
   )
 }
diff --git a/apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts b/apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts
new file mode 100644
index 0000000000..26d2ee8f29
--- /dev/null
+++ b/apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts
@@ -0,0 +1,44 @@
+import { FieldHelperProps } from 'formik'
+import { useEffect } from 'react'
+import { ElementFormTypesCaseStudy } from '../types'
+
+function useSolutionsUpdateItemsChange({
+  itemIds,
+  cases,
+  casesHelpers,
+}: {
+  itemIds: number[]
+  cases: ElementFormTypesCaseStudy['options']['cases']
+  casesHelpers: FieldHelperProps<ElementFormTypesCaseStudy['options']['cases']>
+}) {
+  useEffect(() => {
+    // map over the cases and remove any solutions that do not belong to one of the selected items
+    const newCases = cases?.map((caseItem) => {
+      // if no solutions are set, skip this case
+      if (!('solutions' in caseItem) || !caseItem.solutions) {
+        return caseItem
+      }
+
+      // filter out all solution entries that do not belong to one of the selected items
+      const newSolutions = Object.fromEntries(
+        Object.entries(caseItem.solutions).filter(([itemIdString]) =>
+          itemIds.includes(parseInt(itemIdString.split('-')[1]))
+        )
+      )
+
+      return {
+        ...caseItem,
+        solutions: newSolutions,
+      }
+    })
+
+    // update the cases field with the new cases
+    casesHelpers.setValue(newCases)
+
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [itemIds, casesHelpers])
+
+  return null
+}
+
+export default useSolutionsUpdateItemsChange
diff --git a/apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx b/apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx
index 79a48f1ecd..eacc99155a 100644
--- a/apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx
+++ b/apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx
@@ -20,6 +20,8 @@ function AddAnswerCollectionEntry({
   onTouched,
   onUntouched,
   onSuccess,
+  inlineEditing,
+  refetchAnswerCollections,
 }: {
   collectionId: number
   entries: AnswerCollectionEntry[]
@@ -27,6 +29,8 @@ function AddAnswerCollectionEntry({
   onTouched: () => void
   onUntouched: () => void
   onSuccess: () => void
+  inlineEditing: boolean
+  refetchAnswerCollections?: () => Promise<any>
 }) {
   const t = useTranslations()
   const [fieldOpen, setFieldOpen] = useState(false)
@@ -106,6 +110,12 @@ function AddAnswerCollectionEntry({
           },
           refetchQueries: [{ query: GetAnswerCollectionsInfoDocument }],
         })
+
+        // if the answer collection is edited inline (in a question context), refetch the selection
+        if (inlineEditing) {
+          await refetchAnswerCollections?.()
+        }
+
         setFieldOpen(false)
         setOptionsEditingDisabled(false)
         onSuccess()
diff --git a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx
index 294f0d82fd..c10e600a9c 100644
--- a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx
+++ b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx
@@ -16,6 +16,7 @@ import {
 import * as JsSearch from 'js-search'
 import { useTranslations } from 'next-intl'
 import { useMemo, useState } from 'react'
+import { twMerge } from 'tailwind-merge'
 import AddAnswerCollectionEntry from './AddAnswerCollectionEntry'
 import AnswerCollectionMetaForm from './AnswerCollectionMetaForm'
 import AnswerCollectionOption from './AnswerCollectionOption'
@@ -24,16 +25,22 @@ function AnswerCollectionEditModal({
   collectionId,
   open,
   onClose,
+  inlineEditing = false,
+  refetchAnswerCollections,
+  className,
 }: {
   collectionId: number
   open: boolean
   onClose: () => void
+  inlineEditing?: boolean
+  refetchAnswerCollections?: () => Promise<any>
+  className?: { overlay?: string; content?: string }
 }) {
   const t = useTranslations()
   const [successToast, setSuccessToast] = useState(false)
   const [optionsEditingDisabled, setOptionsEditingDisabled] = useState(false)
   const [accordionState, setAccordionState] = useState<'metadata' | 'options'>(
-    'metadata'
+    inlineEditing ? 'options' : 'metadata'
   )
   const [metadataTouched, setMetadataTouched] = useState(false)
   const [optionsTouched, setOptionsTouched] = useState(false)
@@ -86,12 +93,18 @@ function AnswerCollectionEditModal({
       }}
       title={t('manage.resources.answerCollection', { name: collection.name })}
       dataCloseButton={{ cy: 'close-answer-collection-edit-modal' }}
-      className={{ content: 'max-h-[calc(100vh-1.5rem)] overflow-y-auto' }}
+      className={{
+        content: twMerge(
+          'max-h-[calc(100vh-1.5rem)] overflow-y-auto',
+          className?.content
+        ),
+        overlay: className?.overlay,
+      }}
     >
       <Accordion
         collapsible
         type="single"
-        defaultValue="metadata"
+        defaultValue={'metadata'}
         value={accordionState}
         onValueChange={(newValue) => {
           if (metadataTouched || optionsTouched) {
@@ -119,6 +132,8 @@ function AnswerCollectionEditModal({
               }}
               metadataTouched={metadataTouched}
               setMetadataTouched={setMetadataTouched}
+              inlineEditing={inlineEditing}
+              refetchAnswerCollections={refetchAnswerCollections}
             />
           </AccordionContent>
         </AccordionItem>
@@ -176,6 +191,8 @@ function AnswerCollectionEditModal({
                       setOptionsTouched(false)
                       setSuccessToast(true)
                     }}
+                    inlineEditing={inlineEditing}
+                    refetchAnswerCollections={refetchAnswerCollections}
                   />
                 ))
               )}
@@ -194,6 +211,8 @@ function AnswerCollectionEditModal({
                 setOptionsTouched(false)
                 setSuccessToast(true)
               }}
+              inlineEditing={inlineEditing}
+              refetchAnswerCollections={refetchAnswerCollections}
             />
           </AccordionContent>
         </AccordionItem>
diff --git a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx
index cf0ac45338..6d05c0d8f2 100644
--- a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx
+++ b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx
@@ -17,11 +17,15 @@ function AnswerCollectionMetaForm({
   onSuccess,
   metadataTouched,
   setMetadataTouched,
+  inlineEditing,
+  refetchAnswerCollections,
 }: {
   collection: AnswerCollection
   onSuccess: () => void
   metadataTouched: boolean
   setMetadataTouched: Dispatch<SetStateAction<boolean>>
+  inlineEditing: boolean
+  refetchAnswerCollections?: () => Promise<any>
 }) {
   const t = useTranslations()
   const [modifyAnswerCollection] = useMutation(ModifyAnswerCollectionDocument)
@@ -45,6 +49,11 @@ function AnswerCollectionMetaForm({
         })
 
         if (data?.modifyAnswerCollection?.id) {
+          // if the answer collection is edited inline (in a question context), refetch the selection
+          if (inlineEditing) {
+            await refetchAnswerCollections?.()
+          }
+
           onSuccess()
           resetForm()
         }
diff --git a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx
index 32054be878..7d05986d86 100644
--- a/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx
+++ b/apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx
@@ -26,6 +26,8 @@ function AnswerCollectionOption({
   setEditDisabled,
   onTouched,
   onSuccess,
+  inlineEditing,
+  refetchAnswerCollections,
 }: {
   entry: AnswerCollectionEntry
   otherEntries: string[]
@@ -36,6 +38,8 @@ function AnswerCollectionOption({
   setEditDisabled: Dispatch<SetStateAction<boolean>>
   onTouched: () => void
   onSuccess: () => void
+  inlineEditing: boolean
+  refetchAnswerCollections?: () => Promise<any>
 }) {
   const t = useTranslations()
   const [editMode, setEditMode] = useState(false)
@@ -92,6 +96,11 @@ function AnswerCollectionOption({
             refetchQueries: [{ query: GetAnswerCollectionsInfoDocument }],
           })
 
+          // if the answer collection is edited inline (in a question context), refetch the selection
+          if (inlineEditing) {
+            await refetchAnswerCollections?.()
+          }
+
           onSuccess()
         }}
       >
diff --git a/packages/graphql/src/graphql/ops/QGetAnswerCollectionsElements.graphql b/packages/graphql/src/graphql/ops/QGetAnswerCollectionsElements.graphql
index aafb99fd51..9cc716babc 100644
--- a/packages/graphql/src/graphql/ops/QGetAnswerCollectionsElements.graphql
+++ b/packages/graphql/src/graphql/ops/QGetAnswerCollectionsElements.graphql
@@ -3,6 +3,7 @@ query GetAnswerCollectionsElements($templateId: String) {
     id
     name
     isShared
+    isEditor
 
     entries {
       id
diff --git a/packages/graphql/src/ops.ts b/packages/graphql/src/ops.ts
index 31e496b05f..1ffa1d068d 100644
--- a/packages/graphql/src/ops.ts
+++ b/packages/graphql/src/ops.ts
@@ -5574,7 +5574,7 @@ export type GetAnswerCollectionsElementsQueryVariables = Exact<{
 }>;
 
 
-export type GetAnswerCollectionsElementsQuery = { __typename?: 'Query', getAnswerCollectionsElements?: Array<{ __typename?: 'AnswerCollection', id: number, name: string, isShared?: boolean | null, entries?: Array<{ __typename?: 'AnswerCollectionEntry', id: number, value: string }> | null }> | null };
+export type GetAnswerCollectionsElementsQuery = { __typename?: 'Query', getAnswerCollectionsElements?: Array<{ __typename?: 'AnswerCollection', id: number, name: string, isShared?: boolean | null, isEditor?: boolean | null, entries?: Array<{ __typename?: 'AnswerCollectionEntry', id: number, value: string }> | null }> | null };
 
 export type GetAnswerCollectionsInfoQueryVariables = Exact<{ [key: string]: never; }>;
 
@@ -6420,7 +6420,7 @@ export const GetActiveUserCoursesDocument = {"kind":"Document","definitions":[{"
 export const GetActivityAnalyticsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActivityAnalytics"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"activityId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getActivityAnalytics"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"activityId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"activityId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"activityName"}},{"kind":"Field","name":{"kind":"Name","value":"activityType"}},{"kind":"Field","name":{"kind":"Name","value":"courseParticipants"}},{"kind":"Field","name":{"kind":"Name","value":"instanceQuizAnalytics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementName"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"Field","name":{"kind":"Name","value":"numberOfAnswers"}},{"kind":"Field","name":{"kind":"Name","value":"uniqueParticipants"}},{"kind":"Field","name":{"kind":"Name","value":"averageTimeSpent"}},{"kind":"Field","name":{"kind":"Name","value":"firstErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"firstPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"firstCorrectRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastCorrectRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalCorrectRate"}},{"kind":"Field","name":{"kind":"Name","value":"upvoteRate"}},{"kind":"Field","name":{"kind":"Name","value":"downvoteRate"}},{"kind":"Field","name":{"kind":"Name","value":"feedbackCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"activityQuizAnalytics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"numberOfAnswers"}},{"kind":"Field","name":{"kind":"Name","value":"averageTimeSpent"}},{"kind":"Field","name":{"kind":"Name","value":"firstErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"firstPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"firstCorrectRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"lastCorrectRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalErrorRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalPartialRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalCorrectRate"}}]}}]}}]}}]} as unknown as DocumentNode<GetActivityAnalyticsQuery, GetActivityAnalyticsQueryVariables>;
 export const GetActivityTemplateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActivityTemplate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getActivityTemplate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"templateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"activityType"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"instructions"}},{"kind":"Field","name":{"kind":"Name","value":"liveQuiz"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"isLiveQAEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isConfusionFeedbackEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isModerationEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"isGamificationEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"accessMode"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"defaultPoints"}},{"kind":"Field","name":{"kind":"Name","value":"defaultCorrectPoints"}},{"kind":"Field","name":{"kind":"Name","value":"maxBonusPoints"}},{"kind":"Field","name":{"kind":"Name","value":"timeToZeroBonus"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"blocks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"timeLimit"}},{"kind":"Field","name":{"kind":"Name","value":"elements"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ElementData"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"practiceQuiz"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"resetTimeDays"}},{"kind":"Field","name":{"kind":"Name","value":"orderType"}},{"kind":"Field","name":{"kind":"Name","value":"stacks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"elements"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ElementData"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"microLearning"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"scheduledStartAt"}},{"kind":"Field","name":{"kind":"Name","value":"scheduledEndAt"}},{"kind":"Field","name":{"kind":"Name","value":"stacks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"elements"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ElementData"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"groupActivity"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"scheduledStartAt"}},{"kind":"Field","name":{"kind":"Name","value":"scheduledEndAt"}},{"kind":"Field","name":{"kind":"Name","value":"clues"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"unit"}}]}},{"kind":"Field","name":{"kind":"Name","value":"stacks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"elements"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ElementData"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ElementData"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ElementInstance"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"elementData"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ChoicesElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"hasAnswerFeedbacks"}},{"kind":"Field","name":{"kind":"Name","value":"displayMode"}},{"kind":"Field","name":{"kind":"Name","value":"choices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ix"}},{"kind":"Field","name":{"kind":"Name","value":"correct"}},{"kind":"Field","name":{"kind":"Name","value":"feedback"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NumericalElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"accuracy"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"unit"}},{"kind":"Field","name":{"kind":"Name","value":"restrictions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}},{"kind":"Field","name":{"kind":"Name","value":"solutionRanges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exactSolutions"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FreeTextElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"restrictions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"maxLength"}}]}},{"kind":"Field","name":{"kind":"Name","value":"solutions"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SelectionElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"numberOfInputs"}},{"kind":"Field","name":{"kind":"Name","value":"answerCollection"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"entries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"answerCollectionSolutionIds"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CaseStudyElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"answerCollectionId"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}},{"kind":"Field","name":{"kind":"Name","value":"step"}},{"kind":"Field","name":{"kind":"Name","value":"unit"}},{"kind":"Field","name":{"kind":"Name","value":"labels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"mid"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"cases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"solutions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"itemId"}},{"kind":"Field","name":{"kind":"Name","value":"criteriaSolutions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"criterionId"}},{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}}]}}]}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FlashcardElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ContentElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}}]}}]}}]}}]} as unknown as DocumentNode<GetActivityTemplateQuery, GetActivityTemplateQueryVariables>;
 export const GetAnswerCollectionCatalogInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAnswerCollectionCatalogInfo"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"collectionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"catalogCollectionId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAnswerCollectionCatalogInfo"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"collectionId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"collectionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"catalogCollectionId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"catalogCollectionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"entries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]} as unknown as DocumentNode<GetAnswerCollectionCatalogInfoQuery, GetAnswerCollectionCatalogInfoQueryVariables>;
-export const GetAnswerCollectionsElementsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAnswerCollectionsElements"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAnswerCollectionsElements"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"templateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isShared"}},{"kind":"Field","name":{"kind":"Name","value":"entries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]} as unknown as DocumentNode<GetAnswerCollectionsElementsQuery, GetAnswerCollectionsElementsQueryVariables>;
+export const GetAnswerCollectionsElementsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAnswerCollectionsElements"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAnswerCollectionsElements"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"templateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"templateId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isShared"}},{"kind":"Field","name":{"kind":"Name","value":"isEditor"}},{"kind":"Field","name":{"kind":"Name","value":"entries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]} as unknown as DocumentNode<GetAnswerCollectionsElementsQuery, GetAnswerCollectionsElementsQueryVariables>;
 export const GetAnswerCollectionsInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAnswerCollectionsInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAnswerCollectionsInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"ownerShortname"}},{"kind":"Field","name":{"kind":"Name","value":"numSharedUsers"}},{"kind":"Field","name":{"kind":"Name","value":"numOfEntries"}},{"kind":"Field","name":{"kind":"Name","value":"permissionLevel"}},{"kind":"Field","name":{"kind":"Name","value":"isOwner"}},{"kind":"Field","name":{"kind":"Name","value":"isManager"}},{"kind":"Field","name":{"kind":"Name","value":"isEditor"}},{"kind":"Field","name":{"kind":"Name","value":"isImported"}},{"kind":"Field","name":{"kind":"Name","value":"isShared"}},{"kind":"Field","name":{"kind":"Name","value":"isDeletable"}},{"kind":"Field","name":{"kind":"Name","value":"isRemovable"}},{"kind":"Field","name":{"kind":"Name","value":"sharingType"}}]}}]}}]} as unknown as DocumentNode<GetAnswerCollectionsInfoQuery, GetAnswerCollectionsInfoQueryVariables>;
 export const GetArtificialInstanceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetArtificialInstance"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"elementId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"artificialInstance"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"elementId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"elementId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"elementType"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ElementData"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ElementData"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ElementInstance"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"elementData"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ChoicesElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"hasAnswerFeedbacks"}},{"kind":"Field","name":{"kind":"Name","value":"displayMode"}},{"kind":"Field","name":{"kind":"Name","value":"choices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ix"}},{"kind":"Field","name":{"kind":"Name","value":"correct"}},{"kind":"Field","name":{"kind":"Name","value":"feedback"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NumericalElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"accuracy"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"unit"}},{"kind":"Field","name":{"kind":"Name","value":"restrictions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}},{"kind":"Field","name":{"kind":"Name","value":"solutionRanges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exactSolutions"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FreeTextElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"restrictions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"maxLength"}}]}},{"kind":"Field","name":{"kind":"Name","value":"solutions"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SelectionElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"numberOfInputs"}},{"kind":"Field","name":{"kind":"Name","value":"answerCollection"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"entries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"answerCollectionSolutionIds"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CaseStudyElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasSampleSolution"}},{"kind":"Field","name":{"kind":"Name","value":"answerCollectionId"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}},{"kind":"Field","name":{"kind":"Name","value":"step"}},{"kind":"Field","name":{"kind":"Name","value":"unit"}},{"kind":"Field","name":{"kind":"Name","value":"labels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"mid"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"cases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"solutions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"itemId"}},{"kind":"Field","name":{"kind":"Name","value":"criteriaSolutions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"criterionId"}},{"kind":"Field","name":{"kind":"Name","value":"min"}},{"kind":"Field","name":{"kind":"Name","value":"max"}}]}}]}}]}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FlashcardElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ContentElementData"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"elementId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"explanation"}},{"kind":"Field","name":{"kind":"Name","value":"basePoints"}},{"kind":"Field","name":{"kind":"Name","value":"pointsMultiplier"}}]}}]}}]}}]} as unknown as DocumentNode<GetArtificialInstanceQuery, GetArtificialInstanceQueryVariables>;
 export const GetBasicCourseInformationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetBasicCourseInformation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"basicCourseInformation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"courseId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"owner"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shortname"}}]}}]}}]}}]} as unknown as DocumentNode<GetBasicCourseInformationQuery, GetBasicCourseInformationQueryVariables>;
diff --git a/packages/graphql/src/public/client.json b/packages/graphql/src/public/client.json
index f259fbddd7..8e71a5a304 100644
--- a/packages/graphql/src/public/client.json
+++ b/packages/graphql/src/public/client.json
@@ -160,7 +160,7 @@
    "GetActivityAnalytics": "bcbe895236bd0027e2db37d5884645cfa3230e90a7ce6de893783c5fdc54fa1b",
    "GetActivityTemplate": "76e5a05b34e721087d416156dd847e6b73ff89f8e81f4627cb8dea4a36d2fb00",
    "GetAnswerCollectionCatalogInfo": "c3c4b1990cc245dbf1c006da6cf8269c622981c251eac3a0392b47d87000bc46",
-   "GetAnswerCollectionsElements": "1a9fb168a01f68c233ab6c424b10b11ea0dbdb4071fb499aa1acdf6d03ee572c",
+   "GetAnswerCollectionsElements": "c0fb446d39dcf0abfa86bc00dbecb29dffa8716cbd5dca352c3d87140eb2f374",
    "GetAnswerCollectionsInfo": "7e5b5ab11e46dd1f8f4880a54df2a537a2a48c531d54e69ba718c9f87da8ce8b",
    "GetArtificialInstance": "89d6ac92566a3e58b1ded67069879270c412a70254acf111cb1458fa88bd832f",
    "GetBasicCourseInformation": "14169116abd9278adb08977b9c153403e6065ab0c3d02a6beb38017e1c8b19d6",
diff --git a/packages/graphql/src/public/server.json b/packages/graphql/src/public/server.json
index 1a6b2ef4dd..1de2520b42 100644
--- a/packages/graphql/src/public/server.json
+++ b/packages/graphql/src/public/server.json
@@ -160,7 +160,7 @@
    "bcbe895236bd0027e2db37d5884645cfa3230e90a7ce6de893783c5fdc54fa1b": "query GetActivityAnalytics($activityId: String!) {\n  getActivityAnalytics(activityId: $activityId) {\n    __typename\n    activityName\n    activityType\n    courseParticipants\n    instanceQuizAnalytics {\n      __typename\n      id\n      elementName\n      elementType\n      numberOfAnswers\n      uniqueParticipants\n      averageTimeSpent\n      firstErrorRate\n      firstPartialRate\n      firstCorrectRate\n      lastErrorRate\n      lastPartialRate\n      lastCorrectRate\n      totalErrorRate\n      totalPartialRate\n      totalCorrectRate\n      upvoteRate\n      downvoteRate\n      feedbackCount\n    }\n    activityQuizAnalytics {\n      __typename\n      id\n      numberOfAnswers\n      averageTimeSpent\n      firstErrorRate\n      firstPartialRate\n      firstCorrectRate\n      lastErrorRate\n      lastPartialRate\n      lastCorrectRate\n      totalErrorRate\n      totalPartialRate\n      totalCorrectRate\n    }\n  }\n}",
    "76e5a05b34e721087d416156dd847e6b73ff89f8e81f4627cb8dea4a36d2fb00": "fragment ElementData 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        hasSampleSolution\n        hasAnswerFeedbacks\n        displayMode\n        choices {\n          ix\n          correct\n          feedback\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        hasSampleSolution\n        accuracy\n        placeholder\n        unit\n        restrictions {\n          min\n          max\n          __typename\n        }\n        solutionRanges {\n          min\n          max\n          __typename\n        }\n        exactSolutions\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        hasSampleSolution\n        restrictions {\n          maxLength\n          __typename\n        }\n        solutions\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        hasSampleSolution\n        numberOfInputs\n        answerCollection {\n          id\n          entries {\n            id\n            value\n            __typename\n          }\n          __typename\n        }\n        answerCollectionSolutionIds\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        answerCollectionId\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          solutions {\n            itemId\n            criteriaSolutions {\n              criterionId\n              min\n              max\n              __typename\n            }\n            __typename\n          }\n          __typename\n        }\n        __typename\n      }\n    }\n    ... on FlashcardElementData {\n      __typename\n      id\n      elementId\n      name\n      type\n      content\n      explanation\n      basePoints\n      pointsMultiplier\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}\nquery GetActivityTemplate($templateId: String!) {\n  getActivityTemplate(templateId: $templateId) {\n    id\n    activityType\n    description\n    instructions\n    liveQuiz {\n      id\n      status\n      isLiveQAEnabled\n      isConfusionFeedbackEnabled\n      isModerationEnabled\n      isGamificationEnabled\n      accessMode\n      name\n      displayName\n      description\n      pointsMultiplier\n      defaultPoints\n      defaultCorrectPoints\n      maxBonusPoints\n      timeToZeroBonus\n      createdAt\n      blocks {\n        id\n        order\n        status\n        timeLimit\n        elements {\n          id\n          type\n          elementType\n          ...ElementData\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    practiceQuiz {\n      id\n      name\n      status\n      displayName\n      description\n      pointsMultiplier\n      resetTimeDays\n      orderType\n      stacks {\n        id\n        order\n        type\n        displayName\n        description\n        elements {\n          id\n          type\n          elementType\n          ...ElementData\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    microLearning {\n      id\n      name\n      status\n      displayName\n      description\n      pointsMultiplier\n      scheduledStartAt\n      scheduledEndAt\n      stacks {\n        id\n        order\n        type\n        displayName\n        description\n        elements {\n          id\n          type\n          elementType\n          ...ElementData\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    groupActivity {\n      id\n      name\n      displayName\n      description\n      pointsMultiplier\n      status\n      scheduledStartAt\n      scheduledEndAt\n      clues {\n        id\n        type\n        name\n        displayName\n        value\n        unit\n        __typename\n      }\n      stacks {\n        id\n        order\n        type\n        displayName\n        description\n        elements {\n          id\n          type\n          elementType\n          ...ElementData\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    __typename\n  }\n}",
    "c3c4b1990cc245dbf1c006da6cf8269c622981c251eac3a0392b47d87000bc46": "query GetAnswerCollectionCatalogInfo($collectionId: Int!, $catalogCollectionId: String) {\n  getAnswerCollectionCatalogInfo(\n    collectionId: $collectionId\n    catalogCollectionId: $catalogCollectionId\n  ) {\n    id\n    name\n    description\n    entries {\n      id\n      value\n      __typename\n    }\n    __typename\n  }\n}",
-   "1a9fb168a01f68c233ab6c424b10b11ea0dbdb4071fb499aa1acdf6d03ee572c": "query GetAnswerCollectionsElements($templateId: String) {\n  getAnswerCollectionsElements(templateId: $templateId) {\n    id\n    name\n    isShared\n    entries {\n      id\n      value\n      __typename\n    }\n    __typename\n  }\n}",
+   "c0fb446d39dcf0abfa86bc00dbecb29dffa8716cbd5dca352c3d87140eb2f374": "query GetAnswerCollectionsElements($templateId: String) {\n  getAnswerCollectionsElements(templateId: $templateId) {\n    id\n    name\n    isShared\n    isEditor\n    entries {\n      id\n      value\n      __typename\n    }\n    __typename\n  }\n}",
    "7e5b5ab11e46dd1f8f4880a54df2a537a2a48c531d54e69ba718c9f87da8ce8b": "query GetAnswerCollectionsInfo {\n  getAnswerCollectionsInfo {\n    id\n    name\n    description\n    ownerShortname\n    numSharedUsers\n    numOfEntries\n    permissionLevel\n    isOwner\n    isManager\n    isEditor\n    isImported\n    isShared\n    isDeletable\n    isRemovable\n    sharingType\n    __typename\n  }\n}",
    "89d6ac92566a3e58b1ded67069879270c412a70254acf111cb1458fa88bd832f": "fragment ElementData 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        hasSampleSolution\n        hasAnswerFeedbacks\n        displayMode\n        choices {\n          ix\n          correct\n          feedback\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        hasSampleSolution\n        accuracy\n        placeholder\n        unit\n        restrictions {\n          min\n          max\n          __typename\n        }\n        solutionRanges {\n          min\n          max\n          __typename\n        }\n        exactSolutions\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        hasSampleSolution\n        restrictions {\n          maxLength\n          __typename\n        }\n        solutions\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        hasSampleSolution\n        numberOfInputs\n        answerCollection {\n          id\n          entries {\n            id\n            value\n            __typename\n          }\n          __typename\n        }\n        answerCollectionSolutionIds\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        answerCollectionId\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          solutions {\n            itemId\n            criteriaSolutions {\n              criterionId\n              min\n              max\n              __typename\n            }\n            __typename\n          }\n          __typename\n        }\n        __typename\n      }\n    }\n    ... on FlashcardElementData {\n      __typename\n      id\n      elementId\n      name\n      type\n      content\n      explanation\n      basePoints\n      pointsMultiplier\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}\nquery GetArtificialInstance($elementId: Int!) {\n  artificialInstance(elementId: $elementId) {\n    id\n    type\n    elementType\n    ...ElementData\n    __typename\n  }\n}",
    "14169116abd9278adb08977b9c153403e6065ab0c3d02a6beb38017e1c8b19d6": "query GetBasicCourseInformation($courseId: String!) {\n  basicCourseInformation(courseId: $courseId) {\n    id\n    displayName\n    description\n    color\n    owner {\n      shortname\n      __typename\n    }\n    __typename\n  }\n}",
diff --git a/packages/graphql/src/services/resources.ts b/packages/graphql/src/services/resources.ts
index 235e151f5e..2499ac2eb9 100644
--- a/packages/graphql/src/services/resources.ts
+++ b/packages/graphql/src/services/resources.ts
@@ -190,19 +190,33 @@ export async function getAnswerCollectionsElements(
     }
   }
 
+  // get the ids of all answer collections that are shared with the user
+  const sharedAnswerCollectionIds = user.objects
+    .filter((object) => object.answerCollection)
+    .map((object) => object.answerCollection!.id)
+
   const combinedAnswerCollections = [
     ...user.objects.flatMap((object) =>
       object.answerCollection
         ? {
             ...object.answerCollection,
             isShared: object.permissionLevel !== DB.PermissionLevel.OWNER,
+            isEditor:
+              object.permissionLevel === DB.PermissionLevel.WRITE ||
+              object.permissionLevel === DB.PermissionLevel.ADMIN ||
+              object.permissionLevel === DB.PermissionLevel.OWNER,
           }
         : []
     ),
-    ...templateAnswerCollections.map((collection) => ({
-      ...collection,
-      isShared: false,
-    })),
+    ...templateAnswerCollections
+      .filter(
+        (collection) => !sharedAnswerCollectionIds.includes(collection.id)
+      )
+      .map((collection) => ({
+        ...collection,
+        isShared: false,
+        isEditor: false,
+      })),
   ]
 
   // return deduplicated list of answer collections (based on id)
diff --git a/packages/i18n/messages/de.ts b/packages/i18n/messages/de.ts
index 6d5663d497..467d4110cd 100644
--- a/packages/i18n/messages/de.ts
+++ b/packages/i18n/messages/de.ts
@@ -1238,6 +1238,8 @@ Da die KlickerUZH-App noch nicht im iOS-App-Store verfügbar ist, folgen Sie die
         'Zur Erstellung von Auswahl-Fragen benötigen Sie Zugriff auf eine Antwort-Sammlung oder können <link>die Auswahl-Möglichkeiten manuell eingeben</link>. Um eine Antwort-Sammlung zu verwenden, erstellen Sie entweder eine eigene unter <link2>Ressourcen → Antwort-Sammlungen</link2> oder importieren Sie bestehende Sammlungen anderer Nutzer über den <link3>Katalog</link3>.',
       selectCollection: 'Sammlung auswählen...',
       answerCollection: 'Antwort-Sammlung',
+      notSufficientPermissionsEditCollection:
+        'Ihre Berechtigungen für diese Antwort-Sammlung sind nicht ausreichend, um diese zu bearbeiten.',
       caseStudyAnswerCollectionTooltip:
         'Bitte wählen Sie eine Antwort-Sammlung, aus welcher Sie die in der Fallstudie zu bewertenden Elemente auswählen möchten.',
       numberOfInputs: 'Anzahl Eingabefelder',
diff --git a/packages/i18n/messages/en.ts b/packages/i18n/messages/en.ts
index 0ad23cb08f..bd4ca211bc 100644
--- a/packages/i18n/messages/en.ts
+++ b/packages/i18n/messages/en.ts
@@ -1235,10 +1235,12 @@ Since the KlickerUZH app is not yet available on the iOS App Store, follow these
         'To create a case study question, you need access to an answer collection or can choose to <link>enter the case study items manually</link>. To use an answer collection, you can either create one yourself under <link2>Resources → Answer Collections</link2> or import existing collections from other users through the <link3>Catalog</link3>.',
       SEAnswerCollectionRequired:
         'To create a case selection question, you need access to an answer collection or can choose to <link>enter the available options manually</link>. To use an answer collection, you can either create one yourself under <link2>Resources → Answer Collections</link2> or import existing collections from other users through the <link3>Catalog</link3>.',
+      selectCollection: 'Select collection...',
       answerCollection: 'Answer collection',
+      notSufficientPermissionsEditCollection:
+        'Your permissions for this answer collection are not sufficient to edit it.',
       caseStudyAnswerCollectionTooltip:
         'Please select an answer collection from which you want to select the elements to be evaluated in the case study.',
-      selectCollection: 'Select collection...',
       numberOfInputs: 'Number of inputs',
       correctAnswerOptions: 'Correct answer options',
       correctAnswerOptionsTooltip:


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx (1)</summary><blockquote>

`33-39`: **Remove redundant undefined check in onClick handler**

The check for `selectedCollectionId !== 'undefined'` is redundant since this code path is only reached when `selectedCollectionId` is already defined (due to the check on line 16).


```diff
 return (
   <Button
-    onClick={() => {
-      if (typeof selectedCollectionId !== 'undefined') {
-        openAnswerCollectionEditModal(selectedCollectionId)
-      }
-    }}
+    onClick={() => openAnswerCollectionEditModal(selectedCollectionId)}
     className={{ root: 'h-9 w-9' }}
     data={{ cy: 'inline-edit-answer-collection' }}
   >
```

</blockquote></details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx (2)</summary><blockquote>

`109-117`: **Consider using a more cache-friendly fetch policy.**

The `fetchPolicy: 'network-only'` bypasses Apollo's cache entirely, which could impact performance with frequent refetches. Consider using `cache-and-network` to benefit from caching while still fetching fresh data.

```diff
  } = useQuery(GetAnswerCollectionsElementsDocument, {
    variables: { templateId },
-   fetchPolicy: 'network-only',
+   fetchPolicy: 'cache-and-network',
  })
```

---

`289-291`: **Simplify the refetch callbacks.**

The `async` wrapper is unnecessary since `refetch()` already returns a Promise.

```diff
-refetchCollections={async () => {
-  await refetch()
-}}
+refetchCollections={() => refetch()}
```

Apply the same simplification to all three occurrences.


Also applies to: 313-315, 415-417

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7133692f845bf11d27b8a6c9008c9530f843641d and 534984de7747ea5f43bf90db4c701d0010010df9.

</details>

<details>
<summary>⛔ Files ignored due to path filters (4)</summary>

* `packages/graphql/src/graphql/ops/QGetAnswerCollectionsElements.graphql` is excluded by `!**/**/graphql/ops/**`
* `packages/graphql/src/ops.ts` is excluded by `!**/**/ops.ts`
* `packages/graphql/src/public/client.json` is excluded by `!**/**/public/**`
* `packages/graphql/src/public/server.json` is excluded by `!**/**/public/**`

</details>

<details>
<summary>📒 Files selected for processing (15)</summary>

* `apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx` (3 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx` (1 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx` (5 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx` (0 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx` (4 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx` (7 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx` (2 hunks)
* `apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts` (1 hunks)
* `apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx` (2 hunks)
* `apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx` (6 hunks)
* `apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx` (2 hunks)
* `apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx` (3 hunks)
* `packages/graphql/src/services/resources.ts` (1 hunks)
* `packages/i18n/messages/de.ts` (1 hunks)
* `packages/i18n/messages/en.ts` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx (1)</summary>

```
Learnt from: sjschlapbach
PR: uzh-bf/klicker-uzh#4498
File: apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx:32-32
Timestamp: 2025-02-05T15:07:43.967Z
Learning: The codebase uses two distinct GraphQL queries for answer collections:
1. `GetAnswerCollectionsInfoDocument`: A lightweight query designed for overview pages, fetching minimal information
2. `GetAnswerCollectionsDocument`: A detailed query used in dropdowns and interactive components requiring complete collection data
```

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: GitGuardian Security Checks
* GitHub Check: SonarCloud

</details>

<details>
<summary>🔇 Additional comments (21)</summary><blockquote>

<details>
<summary>packages/i18n/messages/de.ts (1)</summary>

`1241-1242`: **LGTM! Clean addition of German localization for permission error message.**

This change properly adds a new translation string for insufficient permissions when editing answer collections. The German translation is grammatically correct and professionally worded. The placement in the `shared` section is appropriate for a general permission message, and it follows the established naming conventions and syntax patterns used throughout the file.

</details>
<details>
<summary>packages/i18n/messages/en.ts (3)</summary>

`1238-1238`: **LGTM! Clear placeholder text for collection selection.**

The `selectCollection` key provides appropriate placeholder text for dropdown selection of answer collections, following standard UI conventions and existing patterns in the codebase.

---

`1240-1241`: **LGTM! Clear and informative permission error message.**

The `notSufficientPermissionsEditCollection` key provides a clear, user-friendly error message that appropriately informs users when they lack permissions to edit an answer collection. The message follows standard error messaging patterns and is well-formatted.

---

`1238-1241`: **Note potential inconsistency with AI summary.**

The AI summary mentions that `selectCollection` was added in two places (SEAnswerCollectionRequired and answerCollection sections), but only one instance is visible in the annotated code. This doesn't affect the review of the visible changes, but you may want to verify all intended localization keys were included.

</details>
<details>
<summary>apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx (1)</summary>

`20-29`: **LGTM! Well-implemented inline editing support.**

The refetch logic is properly integrated:
- Props are correctly typed with `refetchAnswerCollections` being optional
- The refetch is appropriately triggered only after a successful mutation
- Proper use of optional chaining and async/await pattern




Also applies to: 52-56

</details>
<details>
<summary>packages/graphql/src/services/resources.ts (1)</summary>

`193-220`: **Excellent permission handling and deduplication logic!**

The implementation correctly:
- Prevents duplicate answer collections by filtering template collections against shared ones
- Properly computes `isEditor` based on permission levels (WRITE, ADMIN, OWNER)
- Ensures template-only collections have appropriate default permissions (`isShared: false`, `isEditor: false`)

</details>
<details>
<summary>apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx (1)</summary>

`23-24`: **Consistent implementation of inline editing support!**

The refetch logic maintains consistency with `AnswerCollectionMetaForm`:
- Same prop signature and optional typing
- Identical conditional refetch pattern after mutation
- Proper async/await handling




Also applies to: 32-33, 114-118

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx (1)</summary>

`1-49`: **Well-structured component implementation**

The component is properly typed, uses internationalization correctly, and handles the disabled state gracefully with appropriate user feedback via tooltips.

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts (1)</summary>

`38-39`: **Verify the intentional exclusion of 'cases' from dependencies**

Excluding `cases` from the dependency array could lead to stale data if cases are updated externally. Please ensure this is the intended behavior and that cases are always fresh when `itemIds` change.


Could you confirm that the `cases` data is always synchronized with `itemIds` changes through the parent component's state management? This would help ensure the effect operates on fresh data despite the dependency exclusion.

</details>
<details>
<summary>apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx (1)</summary>

`24-102`: **Well-implemented inline editing support**

The addition of `inlineEditing` mode and `refetchAnswerCollections` callback is cleanly implemented. Good use of tailwind-merge for className handling and proper prop drilling to child components.

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx (1)</summary>

`1-31`: **Clean refactoring with improved separation of concerns!**

The refactoring to lift data fetching to the parent component is well-executed. This change enables better data flow control and supports the inline editing feature while maintaining backward compatibility.

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx (1)</summary>

`409-421`: **Well-implemented inline editing modal!**

The conditional rendering logic and modal configuration are properly implemented. The z-index ensures proper layering above the parent modal.

</details>
<details>
<summary>apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx (1)</summary>

`99-103`: **Clean implementation of conditional refetch logic!**

The conditional refetch after deletion is well-implemented with proper null safety using optional chaining. This ensures the UI stays synchronized during inline editing.

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx (1)</summary>

`1-93`: **Good architectural refactoring!**

The refactoring to lift data fetching up to the parent component improves separation of concerns and makes the component more testable and reusable. This pattern is consistently applied across related components.

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx (3)</summary>

`76-86`: **Efficient use of useMemo for permission checking.**

Good implementation for deriving the selected collection. The memoization prevents unnecessary recalculations when other props change.

---

`168-176`: **Well-implemented inline edit button with proper permission handling.**

The button correctly checks edit permissions and provides a clean interface for inline editing answer collections.

---

`95-103`: **Clear state management with explicit mode switching.**

Good addition of explicit mode switching after resets. This improves UX by ensuring the interface properly reflects the state change.



Also applies to: 205-206

</details>
<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx (4)</summary>

`83-88`: **Good addition for maintaining data consistency.**

The `useSolutionsUpdateItemsChange` hook ensures solutions stay synchronized with selected items, preventing inconsistent state.

---

`90-100`: **Consistent implementation pattern.**

Good use of the same memoization pattern as in `SelectionCollectionOptions.tsx` for deriving the selected collection.

---

`188-194`: **Consistent inline editing implementation.**

The inline edit button follows the same pattern as in `SelectionCollectionOptions.tsx`, maintaining UI consistency.

---

`247-250`: **Clean simplification of onChange handler.**

Good simplification - the logic for handling removed items is now properly delegated to the `useSolutionsUpdateItemsChange` hook.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-26T08:21:50Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 534984de7747ea5f43bf90db4c701d0010010df9 and 6e30689cdda1b701c2197bad84c1390d9a844725.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx` (3 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Analyze (javascript)
* GitHub Check: SonarCloud
* GitHub Check: cypress-run
* GitHub Check: check
* GitHub Check: build
* GitHub Check: build

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-26T08:56:58Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx (1)</summary><blockquote>

`109-117`: **Address the missing skip option for better query optimization.**

The GraphQL query lacks the `skip` option that was recommended in previous reviews to prevent unnecessary network requests when `templateId` is undefined.



Apply this fix to optimize the query execution:

```diff
 const {
   data,
   loading: collectionsLoading,
   refetch,
 } = useQuery(GetAnswerCollectionsElementsDocument, {
   variables: { templateId },
   fetchPolicy: 'network-only',
+  skip: !templateId,
 })
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx (1)</summary><blockquote>

`119-423`: **Consider error handling for the GraphQL query.**

While the integration looks solid, there's no error handling for the `useQuery` hook. Consider adding error state management to provide user feedback if the collections query fails.



Add error handling to the query:

```diff
 const {
   data,
   loading: collectionsLoading,
   refetch,
+  error: collectionsError,
 } = useQuery(GetAnswerCollectionsElementsDocument, {
   variables: { templateId },
   fetchPolicy: 'network-only',
   skip: !templateId,
 })
```

Then display an error message or fallback UI when `collectionsError` is present.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6e30689cdda1b701c2197bad84c1390d9a844725 and 23e2353ca13d83a78268a8ba018e53602995ba1f.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx` (3 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (5)</summary>

* GitHub Check: SonarCloud
* GitHub Check: Analyze (javascript)
* GitHub Check: format
* GitHub Check: cypress-run
* GitHub Check: build

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx (5)</summary>

`1-1`: **LGTM: Import additions support the new functionality.**

The new imports are appropriate for the inline answer collection editing feature:
- `useQuery` for GraphQL data fetching
- `GetAnswerCollectionsElementsDocument` for the collections query
- `AnswerCollectionEditModal` for the inline editing modal




Also applies to: 6-6, 19-19

---

`100-103`: **LGTM: Well-structured state management for collection modal.**

The collection modal state properly tracks both visibility and the selected collection ID, which is essential for controlling the inline editing modal.

---

`279-299`: **LGTM: Proper integration of collection data with SelectionOptions.**

The component correctly passes the fetched collections data, loading state, refetch function, and modal opening handler to `SelectionOptions`. This enables seamless inline editing functionality.

---

`301-323`: **LGTM: Consistent collection data integration with CaseStudyOptions.**

The `CaseStudyOptions` component receives the same collection-related props as `SelectionOptions`, ensuring consistent inline editing behavior across different element types.

---

`410-422`: **LGTM: Modal open prop issue has been resolved.**

The `AnswerCollectionEditModal` now correctly uses `collectionModal.open` for the `open` prop, fixing the issue identified in previous reviews. The modal integration includes proper styling with high z-index values to ensure it appears above the parent modal.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-26T09:07:58Z

Review comments:
diff_hunk: @@ -0,0 +1,44 @@
+import { FieldHelperProps } from 'formik'
+import { useEffect } from 'react'
+import { ElementFormTypesCaseStudy } from '../types'
+
+function useSolutionsUpdateItemsChange({
+  itemIds,
+  cases,
+  casesHelpers,
+}: {
+  itemIds: number[]
+  cases: ElementFormTypesCaseStudy['options']['cases']
+  casesHelpers: FieldHelperProps<ElementFormTypesCaseStudy['options']['cases']>
+}) {
+  useEffect(() => {
+    // map over the cases and remove any solutions that do not belong to one of the selected items
+    const newCases = cases?.map((caseItem) => {
+      // if no solutions are set, skip this case
+      if (!('solutions' in caseItem) || !caseItem.solutions) {
+        return caseItem
+      }
+
+      // filter out all solution entries that do not belong to one of the selected items
+      const newSolutions = Object.fromEntries(
+        Object.entries(caseItem.solutions).filter(([itemIdString]) =>
+          itemIds.includes(parseInt(itemIdString.split('-')[1]))
+        )
+      )
path: apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Add error handling for solution key parsing**

The code assumes that `itemIdString` contains a hyphen and has a valid number after it. This could cause runtime errors if the format is unexpected.


```diff
 // filter out all solution entries that do not belong to one of the selected items
 const newSolutions = Object.fromEntries(
-  Object.entries(caseItem.solutions).filter(([itemIdString]) =>
-    itemIds.includes(parseInt(itemIdString.split('-')[1]))
-  )
+  Object.entries(caseItem.solutions).filter(([itemIdString]) => {
+    const parts = itemIdString.split('-')
+    if (parts.length < 2) return false
+    const itemId = parseInt(parts[1])
+    return !isNaN(itemId) && itemIds.includes(itemId)
+  })
 )
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      // filter out all solution entries that do not belong to one of the selected items
      const newSolutions = Object.fromEntries(
        Object.entries(caseItem.solutions).filter(([itemIdString]) => {
          const parts = itemIdString.split('-')
          if (parts.length < 2) return false
          const itemId = parseInt(parts[1])
          return !isNaN(itemId) && itemIds.includes(itemId)
        })
      )
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In
apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts
lines 22 to 27, the code assumes that itemIdString contains a hyphen and a valid
number after it, which could lead to runtime errors if the format is unexpected.
Add error handling or validation before parsing the number to ensure the string
format is correct, preventing potential exceptions during execution.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T08:21:49Z
author_association: NONE
diff_hunk: @@ -86,12 +93,18 @@ function AnswerCollectionEditModal({
       }}
       title={t('manage.resources.answerCollection', { name: collection.name })}
       dataCloseButton={{ cy: 'close-answer-collection-edit-modal' }}
-      className={{ content: 'max-h-[calc(100vh-1.5rem)] overflow-y-auto' }}
+      className={{
+        content: twMerge(
+          'max-h-[calc(100vh-1.5rem)] overflow-y-auto',
+          className?.content
+        ),
+        overlay: className?.overlay,
+      }}
     >
       <Accordion
         collapsible
         type="single"
-        defaultValue="metadata"
+        defaultValue={'metadata'}
         value={accordionState}
         onValueChange={(newValue) => {
path: apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix accordion defaultValue inconsistency**

The `defaultValue` is hardcoded to `'metadata'` but the initial `value` state depends on `inlineEditing`. Since this is a controlled component (with `value` prop), the `defaultValue` prop is unnecessary and could cause confusion.


```diff
 <Accordion
   collapsible
   type="single"
-  defaultValue={'metadata'}
   value={accordionState}
   onValueChange={(newValue) => {
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      <Accordion
        collapsible
        type="single"
        value={accordionState}
        onValueChange={(newValue) => {
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In
apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx
around lines 104 to 109, the Accordion component has a hardcoded defaultValue of
'metadata' while its value is controlled by the accordionState variable. Since
the component is controlled via the value prop, the defaultValue is redundant
and can cause confusion. Remove the defaultValue prop to ensure consistent
controlled behavior.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T08:21:49Z
author_association: NONE
diff_hunk: @@ -94,281 +97,329 @@ function ElementEditForm({
   const [elementDataTypename, setElementDataTypename] = useState<
     ElementData['__typename'] | undefined
   >()
+  const [collectionModal, setCollectionModal] = useState<{
+    open: boolean
+    id?: number
+  }>({ open: false, id: undefined })
 
   const questionManipulationSchema = useValidationSchema({
     numberOfAnswerOptions: answerCollectionEntries.length,
   })
 
+  const {
+    data,
+    loading: collectionsLoading,
+    refetch,
+  } = useQuery(GetAnswerCollectionsElementsDocument, {
+    variables: { templateId },
+    fetchPolicy: 'network-only',
+  })
+  const collections = data?.getAnswerCollectionsElements ?? []
+
   return (
-    <Formik
-      validateOnMount
-      enableReinitialize={!isTemplate}
-      initialValues={initialValues}
-      validationSchema={questionManipulationSchema}
-      onSubmit={async (values, { setSubmitting }) => {
-        setSubmitting(true)
-        const success = await onSubmitElement({
-          ...values,
-          status: elementStatus,
-        })
+    <>
+      <Formik
+        validateOnMount
+        enableReinitialize={!isTemplate}
+        initialValues={initialValues}
+        validationSchema={questionManipulationSchema}
+        onSubmit={async (values, { setSubmitting }) => {
+          setSubmitting(true)
+          const success = await onSubmitElement({
+            ...values,
+            status: elementStatus,
+          })
 
-        // close modal, set success toast
-        setSubmitting(false)
-        if (!success) {
-          setFailureToast(true)
-        } else {
-          onSuccess()
-        }
-      }}
-    >
-      {({
-        values,
-        errors,
-        isSubmitting,
-        isValid,
-        setFieldValue,
-        setFieldTouched,
-        validateForm,
-      }) => {
-        if (loading) {
-          return null
-        }
+          // close modal, set success toast
+          setSubmitting(false)
+          if (!success) {
+            setFailureToast(true)
+          } else {
+            onSuccess()
+          }
+        }}
+      >
+        {({
+          values,
+          errors,
+          isSubmitting,
+          isValid,
+          setFieldValue,
+          setFieldTouched,
+          validateForm,
+        }) => {
+          if (loading) {
+            return null
+          }
 
-        return (
-          <Modal
-            asPortal
-            fullScreen
-            title={t(`manage.elements.${mode}Title`)}
-            className={{
-              content: 'h-max max-h-full max-w-[1400px] text-sm md:text-base',
-              title: 'text-xl',
-            }}
-            open={open}
-            onClose={() => onClose()}
-            escapeDisabled={true}
-            onPrimaryAction={
-              !inputsDisabled ? (
-                <Button
-                  primary
-                  type="submit"
-                  loading={isSubmitting}
-                  disabled={!isValid}
-                  className={{ root: 'mt-2' }}
-                  form="question-manipulation-form"
-                  data={{ cy: 'save-new-question' }}
-                >
-                  <Button.Label>{t('shared.generic.save')}</Button.Label>
-                </Button>
-              ) : undefined
-            }
-            onSecondaryAction={
-              !isTemplate && !inputsDisabled ? (
-                <Button
-                  className={{ root: 'mt-2' }}
-                  onClick={() => onClose()}
-                  data={{ cy: 'close-element-modal' }}
-                >
-                  <Button.Label>{t('shared.generic.close')}</Button.Label>
-                </Button>
-              ) : undefined
-            }
-          >
-            {!inputsDisabled && (
-              <AutoSaveMonitor
-                values={values}
-                initialValuesString={JSON.stringify(initialValues)}
-                setAutoSavedElement={setAutoSavedElement}
+          return (
+            <Modal
+              asPortal
+              fullScreen
+              title={t(`manage.elements.${mode}Title`)}
+              className={{
+                content: 'h-max max-h-full max-w-[1400px] text-sm md:text-base',
+                title: 'text-xl',
+              }}
+              open={open}
+              onClose={() => onClose()}
+              escapeDisabled={true}
+              onPrimaryAction={
+                !inputsDisabled ? (
+                  <Button
+                    primary
+                    type="submit"
+                    loading={isSubmitting}
+                    disabled={!isValid}
+                    className={{ root: 'mt-2' }}
+                    form="question-manipulation-form"
+                    data={{ cy: 'save-new-question' }}
+                  >
+                    <Button.Label>{t('shared.generic.save')}</Button.Label>
+                  </Button>
+                ) : undefined
+              }
+              onSecondaryAction={
+                !isTemplate && !inputsDisabled ? (
+                  <Button
+                    className={{ root: 'mt-2' }}
+                    onClick={() => onClose()}
+                    data={{ cy: 'close-element-modal' }}
+                  >
+                    <Button.Label>{t('shared.generic.close')}</Button.Label>
+                  </Button>
+                ) : undefined
+              }
+            >
+              {!inputsDisabled && (
+                <AutoSaveMonitor
+                  values={values}
+                  initialValuesString={JSON.stringify(initialValues)}
+                  setAutoSavedElement={setAutoSavedElement}
+                />
+              )}
+              <ElementTypeMonitor
+                elementType={values.type ?? ElementType.Sc}
+                setElementDataTypename={setElementDataTypename}
+                validateForm={validateForm}
               />
-            )}
-            <ElementTypeMonitor
-              elementType={values.type ?? ElementType.Sc}
-              setElementDataTypename={setElementDataTypename}
-              validateForm={validateForm}
-            />
-            <div className="flex flex-row gap-12">
-              <div className="max-w-5xl flex-1">
-                <Form className="w-full" id="question-manipulation-form">
-                  <ElementInformationFields
-                    isTemplate={isTemplate}
-                    elementId={elementId}
-                    elementStatus={elementStatus}
-                    setElementStatus={setElementStatus}
-                    inputsDisabled={inputsDisabled}
-                    mode={mode}
-                    values={values}
-                    isSubmitting={isSubmitting}
-                  />
-                  <ElementContentInput
-                    disabled={inputsDisabled}
-                    values={values}
-                    setFieldValue={setFieldValue}
-                  />
-                  <ElementExplanationField
-                    disabled={inputsDisabled}
-                    values={values}
-                    setFieldValue={setFieldValue}
-                  />
-
-                  {/* scoring section */}
-                  {!isTemplate &&
-                    values.type !== ElementType.Content &&
-                    values.type !== ElementType.Flashcard && (
-                      <ElementformScoringSection
-                        isTemplate={isTemplate}
-                        disabled={inputsDisabled}
-                        values={values}
-                        setFieldValue={setFieldValue}
-                        isSubmitting={isSubmitting}
-                      />
-                    )}
-
-                  <div className="mt-4 flex flex-row gap-4">
-                    <OptionsLabel type={values.type} />
-                    <AnswerFeedbackSetting
-                      disabled={isTemplate || inputsDisabled}
+              <div className="flex flex-row gap-12">
+                <div className="max-w-5xl flex-1">
+                  <Form className="w-full" id="question-manipulation-form">
+                    <ElementInformationFields
+                      isTemplate={isTemplate}
+                      elementId={elementId}
+                      elementStatus={elementStatus}
+                      setElementStatus={setElementStatus}
+                      inputsDisabled={inputsDisabled}
+                      mode={mode}
                       values={values}
+                      isSubmitting={isSubmitting}
                     />
-                    <DisplayModeSetting
+                    <ElementContentInput
                       disabled={inputsDisabled}
-                      type={values.type}
-                    />
-                  </div>
-
-                  {values.type === ElementType.Sc ||
-                  values.type === ElementType.Mc ||
-                  values.type === ElementType.Kprim ? (
-                    <ChoicesOptions
-                      inputsDisabled={inputsDisabled}
                       values={values}
                       setFieldValue={setFieldValue}
                     />
-                  ) : null}
-
-                  {values.type === ElementType.Numerical && (
-                    <NumericalOptions
-                      inputsDisabled={inputsDisabled}
+                    <ElementExplanationField
+                      disabled={inputsDisabled}
                       values={values}
+                      setFieldValue={setFieldValue}
                     />
-                  )}
 
-                  {values.type === ElementType.FreeText && (
-                    <FreeTextOptions
-                      inputsDisabled={inputsDisabled}
-                      values={values}
-                    />
-                  )}
+                    {/* scoring section */}
+                    {!isTemplate &&
+                      values.type !== ElementType.Content &&
+                      values.type !== ElementType.Flashcard && (
+                        <ElementformScoringSection
+                          isTemplate={isTemplate}
+                          disabled={inputsDisabled}
+                          values={values}
+                          setFieldValue={setFieldValue}
+                          isSubmitting={isSubmitting}
+                        />
+                      )}
 
-                  {values.type === ElementType.Selection && (
-                    <SelectionOptions
-                      creationMode={
-                        mode === ElementEditMode.CREATE ||
-                        mode === ElementEditMode.DUPLICATE
-                      }
-                      templateId={templateId}
-                      isTemplate={isTemplate}
-                      inputsDisabled={inputsDisabled}
-                      values={values}
-                      setAnswerCollectionEntries={setAnswerCollectionEntries}
-                    />
-                  )}
+                    <div className="mt-4 flex flex-row gap-4">
+                      <OptionsLabel type={values.type} />
+                      <AnswerFeedbackSetting
+                        disabled={isTemplate || inputsDisabled}
+                        values={values}
+                      />
+                      <DisplayModeSetting
+                        disabled={inputsDisabled}
+                        type={values.type}
+                      />
+                    </div>
 
-                  {values.type === ElementType.CaseStudy && (
-                    <CaseStudyOptions
-                      creationMode={
-                        mode === ElementEditMode.CREATE ||
-                        mode === ElementEditMode.DUPLICATE
-                      }
-                      templateId={templateId}
-                      isTemplate={isTemplate}
-                      inputsDisabled={inputsDisabled}
-                      setFieldValue={setFieldValue}
-                      setFieldTouched={setFieldTouched}
-                      hasSampleSolution={values.options.hasSampleSolution}
-                      setAnswerCollectionEntries={setAnswerCollectionEntries}
-                    />
-                  )}
-                </Form>
+                    {values.type === ElementType.Sc ||
+                    values.type === ElementType.Mc ||
+                    values.type === ElementType.Kprim ? (
+                      <ChoicesOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                        setFieldValue={setFieldValue}
+                      />
+                    ) : null}
 
-                {Object.keys(errors).length !== 0 && (
-                  <ElementFormErrors errors={errors} />
-                )}
-              </div>
+                    {values.type === ElementType.Numerical && (
+                      <NumericalOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                      />
+                    )}
+
+                    {values.type === ElementType.FreeText && (
+                      <FreeTextOptions
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                      />
+                    )}
+
+                    {values.type === ElementType.Selection && (
+                      <SelectionOptions
+                        creationMode={
+                          mode === ElementEditMode.CREATE ||
+                          mode === ElementEditMode.DUPLICATE
+                        }
+                        inputsDisabled={inputsDisabled}
+                        values={values}
+                        collections={collections}
+                        collectionsLoading={collectionsLoading}
+                        refetchCollections={async () => {
+                          await refetch()
+                        }}
+                        setAnswerCollectionEntries={setAnswerCollectionEntries}
+                        openAnswerCollectionEditModal={(
+                          collectionId: number
+                        ) => {
+                          setCollectionModal({ open: true, id: collectionId })
+                        }}
+                      />
+                    )}
+
+                    {values.type === ElementType.CaseStudy && (
+                      <CaseStudyOptions
+                        creationMode={
+                          mode === ElementEditMode.CREATE ||
+                          mode === ElementEditMode.DUPLICATE
+                        }
+                        inputsDisabled={inputsDisabled}
+                        setFieldValue={setFieldValue}
+                        setFieldTouched={setFieldTouched}
+                        hasSampleSolution={values.options.hasSampleSolution}
+                        collections={collections}
+                        collectionsLoading={collectionsLoading}
+                        refetchCollections={async () => {
+                          await refetch()
+                        }}
+                        setAnswerCollectionEntries={setAnswerCollectionEntries}
+                        openAnswerCollectionEditModal={(
+                          collectionId: number
+                        ) => {
+                          setCollectionModal({ open: true, id: collectionId })
+                        }}
+                      />
+                    )}
+                  </Form>
+
+                  {Object.keys(errors).length !== 0 && (
+                    <ElementFormErrors errors={errors} />
+                  )}
+                </div>
 
-              {mode === ElementEditMode.EDIT ? (
-                <Tabs
-                  defaultValue="preview"
-                  className="w-full max-w-sm"
-                  onValueChange={(value) => {
-                    setActiveTab(value)
-                  }}
-                >
-                  <TabsList className="w-full">
-                    <TabsTrigger
-                      value="preview"
-                      className="w-1/2 font-bold"
-                      data-cy="element-preview-tab"
-                    >
-                      {t('shared.generic.preview')}
-                    </TabsTrigger>
-                    <TabsTrigger
-                      value="activity"
-                      className="w-1/2 font-bold"
-                      data-cy="element-activity-tab"
-                    >
-                      {t('shared.generic.activity')}
-                    </TabsTrigger>
-                  </TabsList>
-                  <TabsContent value="preview">
+                {mode === ElementEditMode.EDIT ? (
+                  <Tabs
+                    defaultValue="preview"
+                    className="w-full max-w-sm"
+                    onValueChange={(value) => {
+                      setActiveTab(value)
+                    }}
+                  >
+                    <TabsList className="w-full">
+                      <TabsTrigger
+                        value="preview"
+                        className="w-1/2 font-bold"
+                        data-cy="element-preview-tab"
+                      >
+                        {t('shared.generic.preview')}
+                      </TabsTrigger>
+                      <TabsTrigger
+                        value="activity"
+                        className="w-1/2 font-bold"
+                        data-cy="element-activity-tab"
+                      >
+                        {t('shared.generic.activity')}
+                      </TabsTrigger>
+                    </TabsList>
+                    <TabsContent value="preview">
+                      <StudentElementPreview
+                        values={values}
+                        elementDataTypename={elementDataTypename}
+                        answerCollectionEntries={answerCollectionEntries}
+                      />
+                    </TabsContent>
+                    <TabsContent value="activity">
+                      <div className="w-sm w-full flex-1">
+                        <ActivityLog
+                          visible={activeTab === 'activity'}
+                          objectId={elementId || ''}
+                          objectType={ObjectType.Element}
+                        />
+                      </div>
+                    </TabsContent>
+                  </Tabs>
+                ) : (
+                  <div className="w-full max-w-sm">
+                    <H3>{t('shared.generic.preview')}</H3>
                     <StudentElementPreview
                       values={values}
                       elementDataTypename={elementDataTypename}
                       answerCollectionEntries={answerCollectionEntries}
                     />
-                  </TabsContent>
-                  <TabsContent value="activity">
-                    <div className="w-sm w-full flex-1">
-                      <ActivityLog
-                        visible={activeTab === 'activity'}
-                        objectId={elementId || ''}
-                        objectType={ObjectType.Element}
-                      />
-                    </div>
-                  </TabsContent>
-                </Tabs>
-              ) : (
-                <div className="w-full max-w-sm">
-                  <H3>{t('shared.generic.preview')}</H3>
-                  <StudentElementPreview
-                    values={values}
-                    elementDataTypename={elementDataTypename}
-                    answerCollectionEntries={answerCollectionEntries}
-                  />
-                </div>
-              )}
-            </div>
+                  </div>
+                )}
+              </div>
 
-            {mode === ElementEditMode.EDIT && elementId && !inputsDisabled && (
-              <InstanceUpdateSwitch
-                elementId={elementId}
-                hasSampleSolution={
-                  'options' in values && 'hasSampleSolution' in values.options
-                    ? values.options.hasSampleSolution
-                    : undefined
-                }
-                updateInstances={updateInstances}
-                setUpdateInstances={setUpdateInstances}
-                includeTemplateUpdates={includeTemplateUpdates}
-                setIncludeTemplateUpdates={setIncludeTemplateUpdates}
+              {mode === ElementEditMode.EDIT &&
+                elementId &&
+                !inputsDisabled && (
+                  <InstanceUpdateSwitch
+                    elementId={elementId}
+                    hasSampleSolution={
+                      'options' in values &&
+                      'hasSampleSolution' in values.options
+                        ? values.options.hasSampleSolution
+                        : undefined
+                    }
+                    updateInstances={updateInstances}
+                    setUpdateInstances={setUpdateInstances}
+                    includeTemplateUpdates={includeTemplateUpdates}
+                    setIncludeTemplateUpdates={setIncludeTemplateUpdates}
+                  />
+                )}
+              <ElementFailureToast
+                open={failureToast}
+                onClose={() => setFailureToast(false)}
               />
-            )}
-            <ElementFailureToast
-              open={failureToast}
-              onClose={() => setFailureToast(false)}
-            />
-          </Modal>
-        )
-      }}
-    </Formik>
+            </Modal>
+          )
+        }}
+      </Formik>
+
+      {collectionModal.open && typeof collectionModal.id !== 'undefined' ? (
+        <AnswerCollectionEditModal
+          inlineEditing
+          collectionId={collectionModal.id}
+          open={open}
+          onClose={() => setCollectionModal({ open: false, id: undefined })}
+          refetchAnswerCollections={async () => {
+            await refetch()
+          }}
+          className={{ overlay: 'z-30', content: 'z-30' }}
+        />
+      ) : null}
+    </>
path: apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix the modal's open prop to use the correct state.**

The `AnswerCollectionEditModal` is using the parent modal's `open` state instead of `collectionModal.open`, which will cause incorrect behavior.


Apply this fix to use the correct open state:

```diff
       {collectionModal.open && typeof collectionModal.id !== 'undefined' ? (
         <AnswerCollectionEditModal
           inlineEditing
           collectionId={collectionModal.id}
-          open={open}
+          open={collectionModal.open}
           onClose={() => setCollectionModal({ open: false, id: undefined })}
           refetchAnswerCollections={async () => {
             await refetch()
           }}
           className={{ overlay: 'z-30', content: 'z-30' }}
         />
       ) : null}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      {collectionModal.open && typeof collectionModal.id !== 'undefined' ? (
        <AnswerCollectionEditModal
          inlineEditing
          collectionId={collectionModal.id}
          open={collectionModal.open}
          onClose={() => setCollectionModal({ open: false, id: undefined })}
          refetchAnswerCollections={async () => {
            await refetch()
          }}
          className={{ overlay: 'z-30', content: 'z-30' }}
        />
      ) : null}
    </>
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In
apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
around lines 410 to 422, the AnswerCollectionEditModal component's open prop is
set to a variable named open, which is likely a parent modal state, instead of
using collectionModal.open. This causes the modal to open or close incorrectly.
Fix this by setting the open prop to collectionModal.open to ensure the modal's
visibility is controlled by the correct state.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T08:56:56Z
author_association: NONE
diff_hunk: @@ -94,281 +97,329 @@
   const [elementDataTypename, setElementDataTypename] = useState<
     ElementData['__typename'] | undefined
   >()
+  const [collectionModal, setCollectionModal] = useState<{
+    open: boolean
+    id?: number
+  }>({ open: false, id: undefined })
 
   const questionManipulationSchema = useValidationSchema({
     numberOfAnswerOptions: answerCollectionEntries.length,
   })
 
+  const {
+    data,
+    loading: collectionsLoading,
+    refetch,
+  } = useQuery(GetAnswerCollectionsElementsDocument, {
+    variables: { templateId },
+    fetchPolicy: 'network-only',
+  })
+  const collections = data?.getAnswerCollectionsElements ?? []
+
path: apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Consider skipping the query when templateId is undefined.**

The query is executed even when `templateId` is undefined, which may cause unnecessary network requests or GraphQL errors if the query expects a non-null value.


Add the `skip` option to prevent unnecessary query execution:

```diff
 const {
   data,
   loading: collectionsLoading,
   refetch,
 } = useQuery(GetAnswerCollectionsElementsDocument, {
   variables: { templateId },
   fetchPolicy: 'network-only',
+  skip: !templateId,
 })
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
  const {
    data,
    loading: collectionsLoading,
    refetch,
  } = useQuery(GetAnswerCollectionsElementsDocument, {
    variables: { templateId },
    fetchPolicy: 'network-only',
    skip: !templateId,
  })
  const collections = data?.getAnswerCollectionsElements ?? []
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In
apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx
around lines 109 to 118, the useQuery hook executes even when templateId is
undefined, leading to unnecessary network requests or errors. Fix this by adding
a skip option that disables the query when templateId is undefined, ensuring the
query only runs when templateId has a valid value.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T08:56:56Z
author_association: NONE

PR comments:
user: login: aviator-app[bot]
created_at: 2025-05-23T15:17:11Z
body: # Current Aviator status
> Aviator will automatically update this comment as the status of the PR changes.
> Comment `/aviator refresh` to force Aviator to re-examine your PR (or [learn about other `/aviator` commands](https://docs.aviator.co/reference/slash-commands)).


This PR was merged manually (without Aviator). Merging manually can negatively impact the performance of the queue. Consider using Aviator next time.

---
<div id="aviator-app-message">
  See the real-time status of this PR on the
  <a class="promote-aviator-app" href="https://app.aviator.co/repo/uzh-bf/klicker-uzh/pull/4713" target="_blank">Aviator webapp</a>.
</div>

<div id="chrome-ext-message">
  Use the <a href="https://chrome.google.com/webstore/detail/inoabloekooadaolcncfmpgafkgbgnif" target='_blank'>Aviator Chrome Extension</a>
  to see the status of your PR within GitHub.
</div>
author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-23T15:17:14Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

<details>
<summary>📝 Walkthrough</summary>

## Walkthrough

This change enhances answer collection editing by adding inline editing capabilities, refactoring collection data fetching to be managed externally, and integrating modal controls. It updates permission handling, refetch logic, and component interactions to support inline workflows.

## Changes

| File(s)                                                                                                    | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apps/frontend-manage/src/components/questions/manipulation/ElementEditForm.tsx                             | Fetches answer collections via `useQuery`, manages modal state for inline editing, and passes collection data and handlers to child components.                                                                                                                                                                                                                                                                                                                               |
| apps/frontend-manage/src/components/questions/manipulation/options/AnswerCollectionInlineEditButton.tsx     | Adds a button component for inline editing of answer collections, conditionally enabled with tooltip feedback.                                                                                                                                                                                                                                                                                                                                                  |
| apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx         | Adds inline edit button, optimizes selected collection lookup, and decouples solution resets from item selection changes.                                                                                                                                                                                                                                                                                                                                 |
| apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyManualItemCreation.tsx          | Removes logic that resets solutions when reverting manual item creation, simplifying reset behavior.                                                                                                                                                                                                                                                                                                                                                     |
| apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyOptions.tsx                    | Refactors to accept externally managed collections, loading state, and refetch function, removing internal data fetching logic.                                                                                                                                                                                                                                                                                                                         |
| apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx           | Adds inline edit button, optimizes selected collection lookup, and updates reset/change handlers to reset states and switch modes explicitly.                                                                                                                                                                                                                                                                                                               |
| apps/frontend-manage/src/components/questions/manipulation/options/SelectionOptions.tsx                     | Accepts external collections, loading state, refetch function, and modal handler props, removing internal query logic.                                                                                                                                                                                                                                                                                                                                  |
| apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts         | Implements a hook to synchronize solutions in cases based on selected item IDs, filtering solutions accordingly.                                                                                                                                                                                                                                                                                                                                       |
| apps/frontend-manage/src/components/resources/answerCollections/AddAnswerCollectionEntry.tsx                | Adds `inlineEditing` and optional `refetchAnswerCollections` props to trigger refetch after adding in inline mode.                                                                                                                                                                                                                                                                                                                                   |
| apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionEditModal.tsx               | Adds `inlineEditing`, `refetchAnswerCollections`, and `className` props; passes them to children; updates modal styling and accordion state logic.                                                                                                                                                                                                                                                                                                     |
| apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionMetaForm.tsx                | Adds `inlineEditing` and optional `refetchAnswerCollections` props; refetches collections after mutation if in inline mode.                                                                                                                                                                                                                                                                                                                          |
| apps/frontend-manage/src/components/resources/answerCollections/AnswerCollectionOption.tsx                  | Adds `inlineEditing` and optional `refetchAnswerCollections` props; conditionally refetches after deletion in inline mode.                                                                                                                                                                                                                                                                                                                                  |
| packages/graphql/src/services/resources.ts                            | Enhances permission logic to mark answer collections as shared or not, and as editor or not, avoiding duplication and clarifying access rights.                                                                                                                                                                                                                                                                                                                         |
| packages/i18n/messages/de.ts                                                                                | Adds German translation string for insufficient permissions to edit answer collections.                                                                                                                                                                                                                                                                                                                                                                                          |
| packages/i18n/messages/en.ts                                                                                | Adds English strings for "Select collection..." and insufficient permission message for editing collections.                                                                                                                                                                                                                                                                                                                                                     |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant ElementEditForm
    participant AnswerCollectionEditModal
    participant AnswerCollectionComponents
    participant GraphQL_API

    User->>ElementEditForm: Opens question edit form
    ElementEditForm->>GraphQL_API: Fetch answer collections (useQuery)
    GraphQL_API-->>ElementEditForm: Returns collections data

    User->>ElementEditForm: Clicks inline edit button for a collection
    ElementEditForm->>AnswerCollectionEditModal: Open modal with collectionId

    AnswerCollectionEditModal->>AnswerCollectionComponents: Render collection edit UI

    User->>AnswerCollectionEditModal: Edits collection (meta/options)
    AnswerCollectionEditModal->>GraphQL_API: Submit changes (mutation)
    GraphQL_API-->>AnswerCollectionEditModal: Mutation success

    AnswerCollectionEditModal->>ElementEditForm: Trigger refetchCollections
    ElementEditForm->>GraphQL_API: Refetch answer collections
    GraphQL_API-->>ElementEditForm: Updated collections data

    AnswerCollectionEditModal->>ElementEditForm: Close modal
    ElementEditForm->>User: Updated collections reflected in UI
```

## Possibly related PRs

- [#4711](https://github.com/uzh-bf/klicker-uzh/pull/4711): Fixes for inline answer collection definition and handling in case study/selection questions.
- [#4498](https://github.com/uzh-bf/klicker-uzh/pull/4498): Refactors answer collection query logic and cache handling, related to data fetching and management.
- [#4532](https://github.com/uzh-bf/klicker-uzh/pull/4532): Implements answer collection access revocation, related to permission and sharing logic.

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=uzh-bf/klicker-uzh&utm_content=4713):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: cypress[bot]
created_at: 2025-05-23T16:24:58Z
body: 
<h3>
  <a href="https://cloud.cypress.io/projects/y436dx?utm_source=github&utm_medium=PASSED&utm_campaign=project">klicker-uzh</a>&nbsp;
  <img src="https://assets.cypress.io/github-pr-comment-icons/chevron.svg" alt="" height="14" width="14" />&nbsp;
  <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?utm_source=github&utm_medium=PASSED&utm_campaign=run%20number">Run #5278</a>
</h3>

<details>
  <summary>
    <strong>Run Properties:</strong>&nbsp;
    <code><img src="https://assets.cypress.io/github-pr-comment-icons/passed.svg" alt="status check passed" height="10" width="10" />&nbsp;Passed&nbsp;<a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?utm_source=github&utm_medium=PASSED&utm_campaign=run%20number">#5278</a></code> &nbsp;&bull;&nbsp;
    <code><img src="https://assets.cypress.io/github-pr-comment-icons/git-commit.svg" alt="git commit" width="10" height="10" /> <a href="https://github.com/uzh-bf/klicker-uzh/commit/f6daca87e9821795fee085bc3034a71dfbc1335e">f6daca87e9 <span style="cursor:help;" title="Your CI provider generated this commit by merging this branch into the target branch.">ℹ️</span></a>: Merge 23e2353ca13d83a78268a8ba018e53602995ba1f into 7133692f845bf11d27b8a6c9008c...</code>
  </summary><br />

  <table width="744">
    <tbody>
      <tr />
      <tr height="48">
        <td width="224">
          <strong>Project</strong>
        </td>
        <td width="520">
          <code><a href="https://cloud.cypress.io/projects/y436dx?utm_source=github&utm_medium=PASSED&utm_campaign=project">klicker-uzh</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td width="224">
          <strong>Branch Review</strong>
        </th>
        <td>
          <code><a href="https://cloud.cypress.io/projects/y436dx/branches/edit-answer-collections-element-edit-modal/review?utm_source=github&utm_medium=PASSED&utm_campaign=review%20changes&changeRequest=4713">edit-answer-collections-element-edit-modal</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Run status</strong></td>
        <td>
          <code><img src="https://assets.cypress.io/github-pr-comment-icons/passed.svg" alt="status check passed" height="10" width="10" />&nbsp;Passed&nbsp;<a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?utm_source=github&utm_medium=PASSED&utm_campaign=run%20number">#5278</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Run duration</strong></td>
        <td><code>59m 21s</code></td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Commit</strong></td>
        <td>
          <code><img src="https://assets.cypress.io/github-pr-comment-icons/git-commit.svg" alt="git commit" width="10" height="10" /> <a href="https://github.com/uzh-bf/klicker-uzh/commit/f6daca87e9821795fee085bc3034a71dfbc1335e">f6daca87e9 <span style="cursor:help;" title="Your CI provider generated this commit by merging this branch into the target branch.">ℹ️</span></a>: Merge 23e2353ca13d83a78268a8ba018e53602995ba1f into 7133692f845bf11d27b8a6c9008c...</code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Committer</strong></td>
        <td><code>Julius Schlapbach</code></td>
      </tr>
    </tbody>
    <tfoot>
      <tr />
      <tr height="48">
        <td colspan="2">
          <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/properties?utm_source=github&utm_medium=PASSED&utm_campaign=properties">View all properties for this run ↗︎</a>
        </td>
      </tr>
    </tfoot>
  </table>
  <hr />
</details>

<table width="744">
  <thead>
    <tr />
    <tr height="48">
      <th colspan="2" align="left" width="744">Test results</th>
    </tr>
  </thead>
  <tbody>
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/failed.svg" alt="Tests that failed" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?reviewViewBy=FAILED&utm_source=github&utm_medium=PASSED&utm_campaign=failed%20tests">
          <strong>Failures</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/flaky-v3.svg" alt="Tests that were flaky" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?reviewViewBy=FLAKY&utm_source=github&utm_medium=PASSED&utm_campaign=flaky%20tests">
          <strong>Flaky</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/pending.svg" alt="Tests that did not run due to a developer annotating a test with .skip" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/test-results?utm_source=github&utm_medium=PASSED&utm_campaign=pending%20tests&statuses=%5B%7B%22value%22%3A%22PENDING%22%2C%22label%22%3A%22PENDING%22%7D%5D">
          <strong>Pending</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/skipped-v3.svg" alt="Tests that did not run due to a failure in a mocha hook" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/test-results?utm_source=github&utm_medium=PASSED&utm_campaign=skipped%20tests&statuses=%5B%7B%22value%22%3A%22SKIPPED%22%2C%22label%22%3A%22SKIPPED%22%7D%5D">
          <strong>Skipped</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/passed.svg" alt="Tests that passed" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5278/overview?utm_source=github&utm_medium=PASSED&utm_campaign=passed%20tests">
          <strong>Passing</strong>
        </a>
      </td>
      <td>
        <code><strong>804</strong></code>
      </td>
    </tr><tfoot>
    <tr><td colspan="2"><b>⚠️ You've recorded test results over your free plan limit.<br /><a href="https://cloud.cypress.io/organizations/1a5729a2-8fed-493d-8ac1-0fcf1628e4fa/billing?utm_source=github&utm_medium=PASSED&utm_campaign=upgrade%20plan">Upgrade your plan to view test results</a>.</b></td></tr>
    <tr />
    <tr height="48"><td colspan="2"><a href="https://cloud.cypress.io/projects/y436dx/branches/edit-answer-collections-element-edit-modal/review?utm_source=github&utm_medium=PASSED&utm_campaign=review%20changes&changeRequest=4713">View all changes introduced in this branch ↗︎</a></td></tr></tfoot>
  </tbody>
</table>






author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-26T09:06:50Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=uzh-bf_klicker-uzh&pullRequest=4713) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [9.1% Duplication on New Code](https://sonarcloud.io/component_measures?id=uzh-bf_klicker-uzh&pullRequest=4713&metric=new_duplicated_lines_density&view=list) (required ≤ 3%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=uzh-bf_klicker-uzh&pullRequest=4713)


author_association: NONE
user: login: cypress[bot]
created_at: 2025-05-26T11:18:50Z
body: 
<h3>
  <a href="https://cloud.cypress.io/projects/y436dx?utm_source=github&utm_medium=failed&utm_campaign=project">klicker-uzh</a>&nbsp;
  <img src="https://assets.cypress.io/github-pr-comment-icons/chevron.svg" alt="" height="14" width="14" />&nbsp;
  <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?utm_source=github&utm_medium=failed&utm_campaign=run%20number">Run #5279</a>
</h3>

<details>
  <summary>
    <strong>Run Properties:</strong>&nbsp;
    <code><img src="https://assets.cypress.io/github-pr-comment-icons/failed.svg" alt="status check failed" height="10" width="10" />&nbsp;Failed&nbsp;<a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?utm_source=github&utm_medium=failed&utm_campaign=run%20number">#5279</a></code> &nbsp;&bull;&nbsp;
    <code><img src="https://assets.cypress.io/github-pr-comment-icons/git-commit.svg" alt="git commit" width="10" height="10" /> <a href="https://github.com/uzh-bf/klicker-uzh/commit/96b9377121940d1fe587ec1f0d96bb0fb0fb8389">96b9377121</a>: feat(apps/frontend-manage): add possibility to open answer collection edit modal...</code>
  </summary><br />

  <table width="744">
    <tbody>
      <tr />
      <tr height="48">
        <td width="224">
          <strong>Project</strong>
        </td>
        <td width="520">
          <code><a href="https://cloud.cypress.io/projects/y436dx?utm_source=github&utm_medium=failed&utm_campaign=project">klicker-uzh</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td width="224">
          <strong>Branch Review</strong>
        </th>
        <td>
          <code><a href="https://cloud.cypress.io/projects/y436dx/branches/v3/review?utm_source=github&utm_medium=failed&utm_campaign=review%20changes&changeRequest=4713">v3</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Run status</strong></td>
        <td>
          <code><img src="https://assets.cypress.io/github-pr-comment-icons/failed.svg" alt="status check failed" height="10" width="10" />&nbsp;Failed&nbsp;<a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?utm_source=github&utm_medium=failed&utm_campaign=run%20number">#5279</a></code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Run duration</strong></td>
        <td><code>00m 51s</code></td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Commit</strong></td>
        <td>
          <code><img src="https://assets.cypress.io/github-pr-comment-icons/git-commit.svg" alt="git commit" width="10" height="10" /> <a href="https://github.com/uzh-bf/klicker-uzh/commit/96b9377121940d1fe587ec1f0d96bb0fb0fb8389">96b9377121</a>: feat(apps/frontend-manage): add possibility to open answer collection edit modal...</code>
        </td>
      </tr>
      <tr />
      <tr height="48">
        <td><strong>Committer</strong></td>
        <td><code>Julius Schlapbach</code></td>
      </tr>
    </tbody>
    <tfoot>
      <tr />
      <tr height="48">
        <td colspan="2">
          <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/properties?utm_source=github&utm_medium=failed&utm_campaign=properties">View all properties for this run ↗︎</a>
        </td>
      </tr>
    </tfoot>
  </table>
  <hr />
</details>

<table width="744">
  <thead>
    <tr />
    <tr height="48">
      <th colspan="2" align="left" width="744">Test results</th>
    </tr>
  </thead>
  <tbody>
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/failed.svg" alt="Tests that failed" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?reviewViewBy=FAILED&utm_source=github&utm_medium=failed&utm_campaign=failed%20tests">
          <strong>Failures</strong>
        </a>
      </td>
      <td>
        <code><strong>1</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/flaky-v3.svg" alt="Tests that were flaky" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?reviewViewBy=FLAKY&utm_source=github&utm_medium=failed&utm_campaign=flaky%20tests">
          <strong>Flaky</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/pending.svg" alt="Tests that did not run due to a developer annotating a test with .skip" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/test-results?utm_source=github&utm_medium=failed&utm_campaign=pending%20tests&statuses=%5B%7B%22value%22%3A%22PENDING%22%2C%22label%22%3A%22PENDING%22%7D%5D">
          <strong>Pending</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/skipped-v3.svg" alt="Tests that did not run due to a failure in a mocha hook" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/test-results?utm_source=github&utm_medium=failed&utm_campaign=skipped%20tests&statuses=%5B%7B%22value%22%3A%22SKIPPED%22%2C%22label%22%3A%22SKIPPED%22%7D%5D">
          <strong>Skipped</strong>
        </a>
      </td>
      <td>
        <code><strong>0</strong></code>
      </td>
    </tr>
    <tr />
    <tr height="48">
      <td width="224">
        <img src="https://assets.cypress.io/github-pr-comment-icons/passed.svg" alt="Tests that passed" width="10" height="10" />&nbsp;
        <a href="https://cloud.cypress.io/projects/y436dx/runs/5279/overview?utm_source=github&utm_medium=failed&utm_campaign=passed%20tests">
          <strong>Passing</strong>
        </a>
      </td>
      <td>
        <code><strong>803</strong></code>
      </td>
    </tr><tfoot>
    <tr><td colspan="2"><b>⚠️ You've recorded test results over your free plan limit.<br /><a href="https://cloud.cypress.io/organizations/1a5729a2-8fed-493d-8ac1-0fcf1628e4fa/billing?utm_source=github&utm_medium=failed&utm_campaign=upgrade%20plan">Upgrade your plan to view test results</a>.</b></td></tr>
    <tr />
    <tr height="48"><td colspan="2"><a href="https://cloud.cypress.io/projects/y436dx/branches/v3/review?utm_source=github&utm_medium=failed&utm_campaign=review%20changes&changeRequest=4713">View all changes introduced in this branch ↗︎</a></td></tr></tfoot>
  </tbody>
</table>


<hr></hr>
<h3>
  Tests for review
</h3>



author_association: NONE