We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Home page - The 'Continue learning on your own' section is not displayed
## Observed behavior
The 'Continue learning on your own' section is not displayed at the Home page even though I have completed all assigned class resources and have some non-class resources in progress.

## Expected behavior
The 'Continue learning on your own' section should be displayed as specified in [Notion](https://www.notion.so/Home-Page-QA-8ffb1011fa034e21bc1f52a2aad585ac).

## Steps to reproduce the issue
1. Install the following [build.](https://github.com/learningequality/kolibri/releases/tag/v0.15.0-beta2)
2. As a Coach create a new Learner user, enroll that user to a Class and assign a lesson with resources.
3. Sign in with the Learner user and complete the assigned resources.
4. Start looking at some non-classes resources so that those will get marked as being in progress.
5. Go back to the Home page and look for the 'Continue learning on your own' section

## Additional information

![2021-11-18_17-03-21](https://user-images.githubusercontent.com/79847249/142441864-88064d81-f972-49ee-8e13-5c33a6d5140e.png)

## Usage Details
 - OS: Windows 10
 - Browser: Chrome

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kolibri/plugins/learn/viewsets.py`
Content:
```
1 from django.db.models import Count
2 from django.db.models import OuterRef
3 from django.db.models import Q
4 from django.db.models import Subquery
5 from django.db.models import Sum
6 from django.db.models.fields import IntegerField
7 from rest_framework.permissions import IsAuthenticated
8 from rest_framework.response import Response
9 from rest_framework.views import APIView
10 
11 from kolibri.core.api import ReadOnlyValuesViewset
12 from kolibri.core.auth.api import KolibriAuthPermissionsFilter
13 from kolibri.core.auth.models import Classroom
14 from kolibri.core.auth.models import Facility
15 from kolibri.core.content.api import ContentNodeProgressViewset
16 from kolibri.core.content.api import ContentNodeViewset
17 from kolibri.core.content.api import UserContentNodeViewset
18 from kolibri.core.exams.models import Exam
19 from kolibri.core.lessons.models import Lesson
20 from kolibri.core.logger.models import AttemptLog
21 from kolibri.core.logger.models import MasteryLog
22 
23 
24 contentnode_progress_viewset = ContentNodeProgressViewset()
25 contentnode_viewset = ContentNodeViewset()
26 user_contentnode_viewset = UserContentNodeViewset()
27 
28 
29 class LearnStateView(APIView):
30     def get(self, request, format=None):
31         if request.user.is_anonymous():
32             default_facility = Facility.get_default_facility()
33             can_download_content = (
34                 default_facility.dataset.show_download_button_in_learn
35                 if default_facility
36                 else True
37             )
38             return Response(
39                 {
40                     "in_classes": False,
41                     "can_download_content": can_download_content,
42                 }
43             )
44         return Response(
45             {
46                 "in_classes": request.user.memberships.exists(),
47                 "can_download_content": request.user.dataset.show_download_button_in_learn,
48             }
49         )
50 
51 
52 class LearnerClassroomViewset(ReadOnlyValuesViewset):
53     """
54     Returns all Classrooms for which the requesting User is a member,
55     along with all associated assignments.
56     """
57 
58     filter_backends = (KolibriAuthPermissionsFilter,)
59     permission_classes = (IsAuthenticated,)
60 
61     values = ("id", "name")
62 
63     def get_queryset(self):
64         if self.request.user.is_anonymous():
65             return Classroom.objects.none()
66         return Classroom.objects.filter(membership__user=self.request.user)
67 
68     def consolidate(self, items, queryset):
69         if not items:
70             return items
71         lessons = (
72             Lesson.objects.filter(
73                 lesson_assignments__collection__membership__user=self.request.user,
74                 is_active=True,
75                 collection__in=(c["id"] for c in items),
76             )
77             .distinct()
78             .values(
79                 "description", "id", "is_active", "title", "resources", "collection"
80             )
81         )
82         lesson_contentnode_ids = set()
83         for lesson in lessons:
84             lesson_contentnode_ids |= {
85                 resource["contentnode_id"] for resource in lesson["resources"]
86             }
87 
88         contentnode_progress = contentnode_progress_viewset.serialize_list(
89             self.request, {"ids": lesson_contentnode_ids}
90         )
91 
92         contentnodes = contentnode_viewset.serialize_list(
93             self.request, {"ids": lesson_contentnode_ids}
94         )
95 
96         progress_map = {l["content_id"]: l["progress"] for l in contentnode_progress}
97 
98         contentnode_map = {c["id"]: c for c in contentnodes}
99 
100         for lesson in lessons:
101             lesson["progress"] = {
102                 "resource_progress": sum(
103                     (
104                         progress_map[resource["content_id"]]
105                         for resource in lesson["resources"]
106                         if resource["content_id"] in progress_map
107                     )
108                 ),
109                 "total_resources": len(lesson["resources"]),
110             }
111             for resource in lesson["resources"]:
112                 resource["progress"] = progress_map.get(resource["content_id"], 0)
113                 resource["contentnode"] = contentnode_map.get(
114                     resource["contentnode_id"], None
115                 )
116 
117         user_masterylog_content_ids = MasteryLog.objects.filter(
118             user=self.request.user
119         ).values("summarylog__content_id")
120 
121         exams = (
122             Exam.objects.filter(
123                 assignments__collection__membership__user=self.request.user,
124                 collection__in=(c["id"] for c in items),
125             )
126             .filter(Q(active=True) | Q(id__in=user_masterylog_content_ids))
127             .annotate(
128                 closed=Subquery(
129                     MasteryLog.objects.filter(
130                         summarylog__content_id=OuterRef("id"), user=self.request.user
131                     ).values("complete")[:1]
132                 ),
133                 score=Subquery(
134                     AttemptLog.objects.filter(
135                         sessionlog__content_id=OuterRef("id"), user=self.request.user
136                     )
137                     .order_by()
138                     .values_list("item")
139                     .distinct()
140                     .values("masterylog")
141                     .annotate(total_correct=Sum("correct"))
142                     .values("total_correct"),
143                     output_field=IntegerField(),
144                 ),
145                 answer_count=Subquery(
146                     AttemptLog.objects.filter(
147                         sessionlog__content_id=OuterRef("id"), user=self.request.user
148                     )
149                     .order_by()
150                     .values_list("item")
151                     .distinct()
152                     .values("masterylog")
153                     .annotate(total_complete=Count("id"))
154                     .values("total_complete"),
155                     output_field=IntegerField(),
156                 ),
157             )
158             .distinct()
159             .values(
160                 "collection",
161                 "active",
162                 "archive",
163                 "id",
164                 "question_count",
165                 "title",
166                 "closed",
167                 "answer_count",
168                 "score",
169             )
170         )
171 
172         for exam in exams:
173             closed = exam.pop("closed")
174             score = exam.pop("score")
175             answer_count = exam.pop("answer_count")
176             if closed is not None:
177                 exam["progress"] = {
178                     "closed": closed,
179                     "score": score,
180                     "answer_count": answer_count,
181                     "started": True,
182                 }
183             else:
184                 exam["progress"] = {
185                     "score": None,
186                     "answer_count": None,
187                     "closed": None,
188                     "started": False,
189                 }
190         out_items = []
191         for item in items:
192             item["assignments"] = {
193                 "exams": [exam for exam in exams if exam["collection"] == item["id"]],
194                 "lessons": [
195                     lesson for lesson in lessons if lesson["collection"] == item["id"]
196                 ],
197             }
198             out_items.append(item)
199         return out_items
200 
201 
202 learner_classroom_viewset = LearnerClassroomViewset()
203 
204 
205 def _resumable_resources(classrooms):
206     for classroom in classrooms:
207         for lesson in classroom["assignments"]["lessons"]:
208             for resource in lesson["resources"]:
209                 yield resource["progress"] > 0
210 
211 
212 class LearnHomePageHydrationView(APIView):
213     def get(self, request, format=None):
214         classrooms = []
215         resumable_resources = []
216         resumable_resources_progress = []
217         if not request.user.is_anonymous():
218             classrooms = learner_classroom_viewset.serialize_list(request)
219             if not classrooms or not any(_resumable_resources(classrooms)):
220                 resumable_resources = user_contentnode_viewset.serialize_list(
221                     request, {"resume": True, "max_results": 12}
222                 )
223                 resumable_resources_progress = (
224                     contentnode_progress_viewset.serialize_list(
225                         request, {"resume": True, "max_results": 12}
226                     )
227                 )
228 
229         return Response(
230             {
231                 "classrooms": classrooms,
232                 "resumable_resources": resumable_resources,
233                 "resumable_resources_progress": resumable_resources_progress,
234             }
235         )
236 
237 
238 def _map_lesson_classroom(item):
239     return {
240         "id": item.pop("collection__id"),
241         "name": item.pop("collection__name"),
242         "parent": item.pop("collection__parent_id"),
243     }
244 
245 
246 class LearnerLessonViewset(ReadOnlyValuesViewset):
247     """
248     Special Viewset for Learners to view Lessons to which they are assigned.
249     The core Lesson Viewset is locked down to Admin users only.
250     """
251 
252     permission_classes = (IsAuthenticated,)
253 
254     values = (
255         "id",
256         "title",
257         "description",
258         "resources",
259         "is_active",
260         "collection",
261         "collection__id",
262         "collection__name",
263         "collection__parent_id",
264     )
265 
266     field_map = {"classroom": _map_lesson_classroom}
267 
268     def get_queryset(self):
269         if self.request.user.is_anonymous():
270             return Lesson.objects.none()
271         return Lesson.objects.filter(
272             lesson_assignments__collection__membership__user=self.request.user,
273             is_active=True,
274         )
275
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kolibri/plugins/learn/viewsets.py b/kolibri/plugins/learn/viewsets.py
--- a/kolibri/plugins/learn/viewsets.py
+++ b/kolibri/plugins/learn/viewsets.py
@@ -85,12 +85,20 @@
                 resource["contentnode_id"] for resource in lesson["resources"]
             }
 
-        contentnode_progress = contentnode_progress_viewset.serialize_list(
-            self.request, {"ids": lesson_contentnode_ids}
+        contentnode_progress = (
+            contentnode_progress_viewset.serialize_list(
+                self.request, {"ids": lesson_contentnode_ids}
+            )
+            if lesson_contentnode_ids
+            else []
         )
 
-        contentnodes = contentnode_viewset.serialize_list(
-            self.request, {"ids": lesson_contentnode_ids}
+        contentnodes = (
+            contentnode_viewset.serialize_list(
+                self.request, {"ids": lesson_contentnode_ids}
+            )
+            if lesson_contentnode_ids
+            else []
         )
 
         progress_map = {l["content_id"]: l["progress"] for l in contentnode_progress}
@@ -206,7 +214,7 @@
     for classroom in classrooms:
         for lesson in classroom["assignments"]["lessons"]:
             for resource in lesson["resources"]:
-                yield resource["progress"] > 0
+                yield 0 < resource["progress"] < 1
 
 
 class LearnHomePageHydrationView(APIView):

{"golden_diff": "diff --git a/kolibri/plugins/learn/viewsets.py b/kolibri/plugins/learn/viewsets.py\n--- a/kolibri/plugins/learn/viewsets.py\n+++ b/kolibri/plugins/learn/viewsets.py\n@@ -85,12 +85,20 @@\n                 resource[\"contentnode_id\"] for resource in lesson[\"resources\"]\n             }\n \n-        contentnode_progress = contentnode_progress_viewset.serialize_list(\n-            self.request, {\"ids\": lesson_contentnode_ids}\n+        contentnode_progress = (\n+            contentnode_progress_viewset.serialize_list(\n+                self.request, {\"ids\": lesson_contentnode_ids}\n+            )\n+            if lesson_contentnode_ids\n+            else []\n         )\n \n-        contentnodes = contentnode_viewset.serialize_list(\n-            self.request, {\"ids\": lesson_contentnode_ids}\n+        contentnodes = (\n+            contentnode_viewset.serialize_list(\n+                self.request, {\"ids\": lesson_contentnode_ids}\n+            )\n+            if lesson_contentnode_ids\n+            else []\n         )\n \n         progress_map = {l[\"content_id\"]: l[\"progress\"] for l in contentnode_progress}\n@@ -206,7 +214,7 @@\n     for classroom in classrooms:\n         for lesson in classroom[\"assignments\"][\"lessons\"]:\n             for resource in lesson[\"resources\"]:\n-                yield resource[\"progress\"] > 0\n+                yield 0 < resource[\"progress\"] < 1\n \n \n class LearnHomePageHydrationView(APIView):\n", "issue": "Home page - The 'Continue learning on your own' section is not displayed\n## Observed behavior\r\nThe 'Continue learning on your own' section is not displayed at the Home page even though I have completed all assigned class resources and have some non-class resources in progress.\r\n\r\n## Expected behavior\r\nThe 'Continue learning on your own' section should be displayed as specified in [Notion](https://www.notion.so/Home-Page-QA-8ffb1011fa034e21bc1f52a2aad585ac).\r\n\r\n## Steps to reproduce the issue\r\n1. Install the following [build.](https://github.com/learningequality/kolibri/releases/tag/v0.15.0-beta2)\r\n2. As a Coach create a new Learner user, enroll that user to a Class and assign a lesson with resources.\r\n3. Sign in with the Learner user and complete the assigned resources.\r\n4. Start looking at some non-classes resources so that those will get marked as being in progress.\r\n5. Go back to the Home page and look for the 'Continue learning on your own' section\r\n\r\n## Additional information\r\n\r\n![2021-11-18_17-03-21](https://user-images.githubusercontent.com/79847249/142441864-88064d81-f972-49ee-8e13-5c33a6d5140e.png)\r\n\r\n## Usage Details\r\n - OS: Windows 10\r\n - Browser: Chrome\n", "before_files": [{"content": "from django.db.models import Count\nfrom django.db.models import OuterRef\nfrom django.db.models import Q\nfrom django.db.models import Subquery\nfrom django.db.models import Sum\nfrom django.db.models.fields import IntegerField\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nfrom kolibri.core.api import ReadOnlyValuesViewset\nfrom kolibri.core.auth.api import KolibriAuthPermissionsFilter\nfrom kolibri.core.auth.models import Classroom\nfrom kolibri.core.auth.models import Facility\nfrom kolibri.core.content.api import ContentNodeProgressViewset\nfrom kolibri.core.content.api import ContentNodeViewset\nfrom kolibri.core.content.api import UserContentNodeViewset\nfrom kolibri.core.exams.models import Exam\nfrom kolibri.core.lessons.models import Lesson\nfrom kolibri.core.logger.models import AttemptLog\nfrom kolibri.core.logger.models import MasteryLog\n\n\ncontentnode_progress_viewset = ContentNodeProgressViewset()\ncontentnode_viewset = ContentNodeViewset()\nuser_contentnode_viewset = UserContentNodeViewset()\n\n\nclass LearnStateView(APIView):\n    def get(self, request, format=None):\n        if request.user.is_anonymous():\n            default_facility = Facility.get_default_facility()\n            can_download_content = (\n                default_facility.dataset.show_download_button_in_learn\n                if default_facility\n                else True\n            )\n            return Response(\n                {\n                    \"in_classes\": False,\n                    \"can_download_content\": can_download_content,\n                }\n            )\n        return Response(\n            {\n                \"in_classes\": request.user.memberships.exists(),\n                \"can_download_content\": request.user.dataset.show_download_button_in_learn,\n            }\n        )\n\n\nclass LearnerClassroomViewset(ReadOnlyValuesViewset):\n    \"\"\"\n    Returns all Classrooms for which the requesting User is a member,\n    along with all associated assignments.\n    \"\"\"\n\n    filter_backends = (KolibriAuthPermissionsFilter,)\n    permission_classes = (IsAuthenticated,)\n\n    values = (\"id\", \"name\")\n\n    def get_queryset(self):\n        if self.request.user.is_anonymous():\n            return Classroom.objects.none()\n        return Classroom.objects.filter(membership__user=self.request.user)\n\n    def consolidate(self, items, queryset):\n        if not items:\n            return items\n        lessons = (\n            Lesson.objects.filter(\n                lesson_assignments__collection__membership__user=self.request.user,\n                is_active=True,\n                collection__in=(c[\"id\"] for c in items),\n            )\n            .distinct()\n            .values(\n                \"description\", \"id\", \"is_active\", \"title\", \"resources\", \"collection\"\n            )\n        )\n        lesson_contentnode_ids = set()\n        for lesson in lessons:\n            lesson_contentnode_ids |= {\n                resource[\"contentnode_id\"] for resource in lesson[\"resources\"]\n            }\n\n        contentnode_progress = contentnode_progress_viewset.serialize_list(\n            self.request, {\"ids\": lesson_contentnode_ids}\n        )\n\n        contentnodes = contentnode_viewset.serialize_list(\n            self.request, {\"ids\": lesson_contentnode_ids}\n        )\n\n        progress_map = {l[\"content_id\"]: l[\"progress\"] for l in contentnode_progress}\n\n        contentnode_map = {c[\"id\"]: c for c in contentnodes}\n\n        for lesson in lessons:\n            lesson[\"progress\"] = {\n                \"resource_progress\": sum(\n                    (\n                        progress_map[resource[\"content_id\"]]\n                        for resource in lesson[\"resources\"]\n                        if resource[\"content_id\"] in progress_map\n                    )\n                ),\n                \"total_resources\": len(lesson[\"resources\"]),\n            }\n            for resource in lesson[\"resources\"]:\n                resource[\"progress\"] = progress_map.get(resource[\"content_id\"], 0)\n                resource[\"contentnode\"] = contentnode_map.get(\n                    resource[\"contentnode_id\"], None\n                )\n\n        user_masterylog_content_ids = MasteryLog.objects.filter(\n            user=self.request.user\n        ).values(\"summarylog__content_id\")\n\n        exams = (\n            Exam.objects.filter(\n                assignments__collection__membership__user=self.request.user,\n                collection__in=(c[\"id\"] for c in items),\n            )\n            .filter(Q(active=True) | Q(id__in=user_masterylog_content_ids))\n            .annotate(\n                closed=Subquery(\n                    MasteryLog.objects.filter(\n                        summarylog__content_id=OuterRef(\"id\"), user=self.request.user\n                    ).values(\"complete\")[:1]\n                ),\n                score=Subquery(\n                    AttemptLog.objects.filter(\n                        sessionlog__content_id=OuterRef(\"id\"), user=self.request.user\n                    )\n                    .order_by()\n                    .values_list(\"item\")\n                    .distinct()\n                    .values(\"masterylog\")\n                    .annotate(total_correct=Sum(\"correct\"))\n                    .values(\"total_correct\"),\n                    output_field=IntegerField(),\n                ),\n                answer_count=Subquery(\n                    AttemptLog.objects.filter(\n                        sessionlog__content_id=OuterRef(\"id\"), user=self.request.user\n                    )\n                    .order_by()\n                    .values_list(\"item\")\n                    .distinct()\n                    .values(\"masterylog\")\n                    .annotate(total_complete=Count(\"id\"))\n                    .values(\"total_complete\"),\n                    output_field=IntegerField(),\n                ),\n            )\n            .distinct()\n            .values(\n                \"collection\",\n                \"active\",\n                \"archive\",\n                \"id\",\n                \"question_count\",\n                \"title\",\n                \"closed\",\n                \"answer_count\",\n                \"score\",\n            )\n        )\n\n        for exam in exams:\n            closed = exam.pop(\"closed\")\n            score = exam.pop(\"score\")\n            answer_count = exam.pop(\"answer_count\")\n            if closed is not None:\n                exam[\"progress\"] = {\n                    \"closed\": closed,\n                    \"score\": score,\n                    \"answer_count\": answer_count,\n                    \"started\": True,\n                }\n            else:\n                exam[\"progress\"] = {\n                    \"score\": None,\n                    \"answer_count\": None,\n                    \"closed\": None,\n                    \"started\": False,\n                }\n        out_items = []\n        for item in items:\n            item[\"assignments\"] = {\n                \"exams\": [exam for exam in exams if exam[\"collection\"] == item[\"id\"]],\n                \"lessons\": [\n                    lesson for lesson in lessons if lesson[\"collection\"] == item[\"id\"]\n                ],\n            }\n            out_items.append(item)\n        return out_items\n\n\nlearner_classroom_viewset = LearnerClassroomViewset()\n\n\ndef _resumable_resources(classrooms):\n    for classroom in classrooms:\n        for lesson in classroom[\"assignments\"][\"lessons\"]:\n            for resource in lesson[\"resources\"]:\n                yield resource[\"progress\"] > 0\n\n\nclass LearnHomePageHydrationView(APIView):\n    def get(self, request, format=None):\n        classrooms = []\n        resumable_resources = []\n        resumable_resources_progress = []\n        if not request.user.is_anonymous():\n            classrooms = learner_classroom_viewset.serialize_list(request)\n            if not classrooms or not any(_resumable_resources(classrooms)):\n                resumable_resources = user_contentnode_viewset.serialize_list(\n                    request, {\"resume\": True, \"max_results\": 12}\n                )\n                resumable_resources_progress = (\n                    contentnode_progress_viewset.serialize_list(\n                        request, {\"resume\": True, \"max_results\": 12}\n                    )\n                )\n\n        return Response(\n            {\n                \"classrooms\": classrooms,\n                \"resumable_resources\": resumable_resources,\n                \"resumable_resources_progress\": resumable_resources_progress,\n            }\n        )\n\n\ndef _map_lesson_classroom(item):\n    return {\n        \"id\": item.pop(\"collection__id\"),\n        \"name\": item.pop(\"collection__name\"),\n        \"parent\": item.pop(\"collection__parent_id\"),\n    }\n\n\nclass LearnerLessonViewset(ReadOnlyValuesViewset):\n    \"\"\"\n    Special Viewset for Learners to view Lessons to which they are assigned.\n    The core Lesson Viewset is locked down to Admin users only.\n    \"\"\"\n\n    permission_classes = (IsAuthenticated,)\n\n    values = (\n        \"id\",\n        \"title\",\n        \"description\",\n        \"resources\",\n        \"is_active\",\n        \"collection\",\n        \"collection__id\",\n        \"collection__name\",\n        \"collection__parent_id\",\n    )\n\n    field_map = {\"classroom\": _map_lesson_classroom}\n\n    def get_queryset(self):\n        if self.request.user.is_anonymous():\n            return Lesson.objects.none()\n        return Lesson.objects.filter(\n            lesson_assignments__collection__membership__user=self.request.user,\n            is_active=True,\n        )\n", "path": "kolibri/plugins/learn/viewsets.py"}], "after_files": [{"content": "from django.db.models import Count\nfrom django.db.models import OuterRef\nfrom django.db.models import Q\nfrom django.db.models import Subquery\nfrom django.db.models import Sum\nfrom django.db.models.fields import IntegerField\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nfrom kolibri.core.api import ReadOnlyValuesViewset\nfrom kolibri.core.auth.api import KolibriAuthPermissionsFilter\nfrom kolibri.core.auth.models import Classroom\nfrom kolibri.core.auth.models import Facility\nfrom kolibri.core.content.api import ContentNodeProgressViewset\nfrom kolibri.core.content.api import ContentNodeViewset\nfrom kolibri.core.content.api import UserContentNodeViewset\nfrom kolibri.core.exams.models import Exam\nfrom kolibri.core.lessons.models import Lesson\nfrom kolibri.core.logger.models import AttemptLog\nfrom kolibri.core.logger.models import MasteryLog\n\n\ncontentnode_progress_viewset = ContentNodeProgressViewset()\ncontentnode_viewset = ContentNodeViewset()\nuser_contentnode_viewset = UserContentNodeViewset()\n\n\nclass LearnStateView(APIView):\n    def get(self, request, format=None):\n        if request.user.is_anonymous():\n            default_facility = Facility.get_default_facility()\n            can_download_content = (\n                default_facility.dataset.show_download_button_in_learn\n                if default_facility\n                else True\n            )\n            return Response(\n                {\n                    \"in_classes\": False,\n                    \"can_download_content\": can_download_content,\n                }\n            )\n        return Response(\n            {\n                \"in_classes\": request.user.memberships.exists(),\n                \"can_download_content\": request.user.dataset.show_download_button_in_learn,\n            }\n        )\n\n\nclass LearnerClassroomViewset(ReadOnlyValuesViewset):\n    \"\"\"\n    Returns all Classrooms for which the requesting User is a member,\n    along with all associated assignments.\n    \"\"\"\n\n    filter_backends = (KolibriAuthPermissionsFilter,)\n    permission_classes = (IsAuthenticated,)\n\n    values = (\"id\", \"name\")\n\n    def get_queryset(self):\n        if self.request.user.is_anonymous():\n            return Classroom.objects.none()\n        return Classroom.objects.filter(membership__user=self.request.user)\n\n    def consolidate(self, items, queryset):\n        if not items:\n            return items\n        lessons = (\n            Lesson.objects.filter(\n                lesson_assignments__collection__membership__user=self.request.user,\n                is_active=True,\n                collection__in=(c[\"id\"] for c in items),\n            )\n            .distinct()\n            .values(\n                \"description\", \"id\", \"is_active\", \"title\", \"resources\", \"collection\"\n            )\n        )\n        lesson_contentnode_ids = set()\n        for lesson in lessons:\n            lesson_contentnode_ids |= {\n                resource[\"contentnode_id\"] for resource in lesson[\"resources\"]\n            }\n\n        contentnode_progress = (\n            contentnode_progress_viewset.serialize_list(\n                self.request, {\"ids\": lesson_contentnode_ids}\n            )\n            if lesson_contentnode_ids\n            else []\n        )\n\n        contentnodes = (\n            contentnode_viewset.serialize_list(\n                self.request, {\"ids\": lesson_contentnode_ids}\n            )\n            if lesson_contentnode_ids\n            else []\n        )\n\n        progress_map = {l[\"content_id\"]: l[\"progress\"] for l in contentnode_progress}\n\n        contentnode_map = {c[\"id\"]: c for c in contentnodes}\n\n        for lesson in lessons:\n            lesson[\"progress\"] = {\n                \"resource_progress\": sum(\n                    (\n                        progress_map[resource[\"content_id\"]]\n                        for resource in lesson[\"resources\"]\n                        if resource[\"content_id\"] in progress_map\n                    )\n                ),\n                \"total_resources\": len(lesson[\"resources\"]),\n            }\n            for resource in lesson[\"resources\"]:\n                resource[\"progress\"] = progress_map.get(resource[\"content_id\"], 0)\n                resource[\"contentnode\"] = contentnode_map.get(\n                    resource[\"contentnode_id\"], None\n                )\n\n        user_masterylog_content_ids = MasteryLog.objects.filter(\n            user=self.request.user\n        ).values(\"summarylog__content_id\")\n\n        exams = (\n            Exam.objects.filter(\n                assignments__collection__membership__user=self.request.user,\n                collection__in=(c[\"id\"] for c in items),\n            )\n            .filter(Q(active=True) | Q(id__in=user_masterylog_content_ids))\n            .annotate(\n                closed=Subquery(\n                    MasteryLog.objects.filter(\n                        summarylog__content_id=OuterRef(\"id\"), user=self.request.user\n                    ).values(\"complete\")[:1]\n                ),\n                score=Subquery(\n                    AttemptLog.objects.filter(\n                        sessionlog__content_id=OuterRef(\"id\"), user=self.request.user\n                    )\n                    .order_by()\n                    .values_list(\"item\")\n                    .distinct()\n                    .values(\"masterylog\")\n                    .annotate(total_correct=Sum(\"correct\"))\n                    .values(\"total_correct\"),\n                    output_field=IntegerField(),\n                ),\n                answer_count=Subquery(\n                    AttemptLog.objects.filter(\n                        sessionlog__content_id=OuterRef(\"id\"), user=self.request.user\n                    )\n                    .order_by()\n                    .values_list(\"item\")\n                    .distinct()\n                    .values(\"masterylog\")\n                    .annotate(total_complete=Count(\"id\"))\n                    .values(\"total_complete\"),\n                    output_field=IntegerField(),\n                ),\n            )\n            .distinct()\n            .values(\n                \"collection\",\n                \"active\",\n                \"archive\",\n                \"id\",\n                \"question_count\",\n                \"title\",\n                \"closed\",\n                \"answer_count\",\n                \"score\",\n            )\n        )\n\n        for exam in exams:\n            closed = exam.pop(\"closed\")\n            score = exam.pop(\"score\")\n            answer_count = exam.pop(\"answer_count\")\n            if closed is not None:\n                exam[\"progress\"] = {\n                    \"closed\": closed,\n                    \"score\": score,\n                    \"answer_count\": answer_count,\n                    \"started\": True,\n                }\n            else:\n                exam[\"progress\"] = {\n                    \"score\": None,\n                    \"answer_count\": None,\n                    \"closed\": None,\n                    \"started\": False,\n                }\n        out_items = []\n        for item in items:\n            item[\"assignments\"] = {\n                \"exams\": [exam for exam in exams if exam[\"collection\"] == item[\"id\"]],\n                \"lessons\": [\n                    lesson for lesson in lessons if lesson[\"collection\"] == item[\"id\"]\n                ],\n            }\n            out_items.append(item)\n        return out_items\n\n\nlearner_classroom_viewset = LearnerClassroomViewset()\n\n\ndef _resumable_resources(classrooms):\n    for classroom in classrooms:\n        for lesson in classroom[\"assignments\"][\"lessons\"]:\n            for resource in lesson[\"resources\"]:\n                yield 0 < resource[\"progress\"] < 1\n\n\nclass LearnHomePageHydrationView(APIView):\n    def get(self, request, format=None):\n        classrooms = []\n        resumable_resources = []\n        resumable_resources_progress = []\n        if not request.user.is_anonymous():\n            classrooms = learner_classroom_viewset.serialize_list(request)\n            if not classrooms or not any(_resumable_resources(classrooms)):\n                resumable_resources = user_contentnode_viewset.serialize_list(\n                    request, {\"resume\": True, \"max_results\": 12}\n                )\n                resumable_resources_progress = (\n                    contentnode_progress_viewset.serialize_list(\n                        request, {\"resume\": True, \"max_results\": 12}\n                    )\n                )\n\n        return Response(\n            {\n                \"classrooms\": classrooms,\n                \"resumable_resources\": resumable_resources,\n                \"resumable_resources_progress\": resumable_resources_progress,\n            }\n        )\n\n\ndef _map_lesson_classroom(item):\n    return {\n        \"id\": item.pop(\"collection__id\"),\n        \"name\": item.pop(\"collection__name\"),\n        \"parent\": item.pop(\"collection__parent_id\"),\n    }\n\n\nclass LearnerLessonViewset(ReadOnlyValuesViewset):\n    \"\"\"\n    Special Viewset for Learners to view Lessons to which they are assigned.\n    The core Lesson Viewset is locked down to Admin users only.\n    \"\"\"\n\n    permission_classes = (IsAuthenticated,)\n\n    values = (\n        \"id\",\n        \"title\",\n        \"description\",\n        \"resources\",\n        \"is_active\",\n        \"collection\",\n        \"collection__id\",\n        \"collection__name\",\n        \"collection__parent_id\",\n    )\n\n    field_map = {\"classroom\": _map_lesson_classroom}\n\n    def get_queryset(self):\n        if self.request.user.is_anonymous():\n            return Lesson.objects.none()\n        return Lesson.objects.filter(\n            lesson_assignments__collection__membership__user=self.request.user,\n            is_active=True,\n        )\n", "path": "kolibri/plugins/learn/viewsets.py"}]}