kolibri icon indicating copy to clipboard operation
kolibri copied to clipboard

Exclude surveys from quiz resource import

Open rtibbles opened this issue 5 months ago • 0 comments

Observed behaviour

Going on the assumption that we do want users to be able to add free response questions in quizzes too, at this time it is possible to add them to a quiz, but it's not possible to save afterwards, with a 400 Bad Request error.

Image

Originally posted by @radinamatic in #13599

Expected behaviour

Because survey questions have no 'correct' answer, and in some cases have a 'correct answer' chosen at random for the sake of having one, we should not allow them to be included in quizzes.

Solution

Exclude survey exercises from quiz resource selection in both backend and frontend.

Backend Changes

File: kolibri/core/content/api.py

In the descendants_assessments action (line 931-952), exclude surveys from the assessment count:

from le_utils.constants import modalities

@action(detail=False)
def descendants_assessments(self, request):
    ids = self.request.query_params.get("ids", None)
    if not ids:
        return Response([])
    queryset = self.filter_queryset(self.get_queryset())
    data = list(
        queryset.annotate(
            num_assessments=SQSum(
                models.ContentNode.objects.filter(
                    tree_id=OuterRef("tree_id"),
                    lft__gte=OuterRef("lft"),
                    lft__lt=OuterRef("rght"),
                    kind=content_kinds.EXERCISE,
                    available=True,
                )
                .exclude(modality=modalities.SURVEY)  # Add this line
                .values_list(
                    "assessmentmetadata__number_of_assessments", flat=True
                ),
                field="number_of_assessments",
            )
        ).values("id", "num_assessments")
    )
    return Response(data)

This ensures topic descendant counts exclude surveys, so the UI shows accurate counts of selectable resources.

Frontend Changes

File: kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/sidePanels/QuizResourceSelection/index.vue

1. Add a filter function (around line 396, before isPracticeQuiz):

const isNotSurvey = item =>
  get(item, ['options', 'modality'], false) !== 'SURVEY';

2. Update the useResourceSelection configuration:

Bookmarks annotator (line 414):

bookmarks: {
  filters: { kind: ContentNodeKinds.EXERCISE },
  annotator: results => results.filter(isNotSurvey).filter(isPracticeQuiz),
},

Search (add annotator at line 446):

search: {
  filters: {
    kind: ContentNodeKinds.EXERCISE,
    contains_quiz: selectPracticeQuiz ? true : null,
  },
  annotator: results => results.filter(isNotSurvey),
},

Benefits

  • Backend: Topic descendant counts accurately reflect selectable resources (excluding surveys)
  • Frontend: Surveys are excluded from all quiz resource selection methods (bookmarks, topic tree, search)
  • Prevents 400 Bad Request error when trying to save quizzes with survey questions
  • Clear UX - incompatible resources are not shown as options

🤖 This issue was updated with resolution details by Claude Code, under supervision, review and final edits by @rtibbles 🤖

rtibbles avatar Aug 07 '25 20:08 rtibbles