Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions zeeguu/api/endpoints/teacher_dashboard/article_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ def cohort_text_overview(cohort_id):
"only_classroom_texts": bool(cohort.only_classroom_texts),
},
"texts": CohortArticleMap.get_articles_info_for_cohort(cohort),
# Nothing stops a text in another language being shared with a
# class, and its students then never see it -- they only ever get
# the texts in the language they are learning. The teacher is the
# one who can fix that, so the counts go to them.
"texts_by_language": cohort.text_counts_by_language(),
"student_count": len(cohort.get_students()),
}
)
Expand Down
6 changes: 5 additions & 1 deletion zeeguu/api/endpoints/teacher_dashboard/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ def get_cohort_info(id):
except sqlalchemy.orm.exc.NoResultFound:
language_name = "None"
dictionary = {
"id": str(id),
# An int, like every other cohort id we emit (Article's
# `shared_with`, the classroom's `from_classes`). It used to be
# stringified here alone, so the same class arrived with two
# different identifiers depending on which endpoint you asked.
"id": c.id,
"name": name,
"inv_code": inv_code,
"max_students": max_students,
Expand Down
42 changes: 31 additions & 11 deletions zeeguu/core/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,25 +551,45 @@ def add_user_to_cohort(self, cohort, session):
session.commit()

def cohort_articles_for_user(self):
"""The class texts this student can see, each tagged with its class.

A student in more than one class gets one merged list, so each text
says which class it came from -- otherwise the list is a pile with no
provenance. The tag is only useful to a student with several classes;
the client drops it for everyone else.
"""
from zeeguu.core.model import Cohort, CohortArticleMap, UserArticle

all_articles = []
classes_by_article = {}
try:
# Filter articles by the user's learned language: a student only
# ever reads in the language they are currently learning, so a
# class taught in another one has nothing to show them.
user_language_id = (
self.learned_language_id if self.learned_language else None
)

for c in self.cohorts:
cohort = Cohort.find(c.cohort_id)
# Get all articles from this cohort
cohort_articles = CohortArticleMap.get_articles_for_cohort(cohort)

# Filter articles by the user's learned language
user_language_id = (
self.learned_language_id if self.learned_language else None
)
for article in cohort_articles:
if article.language_id == user_language_id:
for article in CohortArticleMap.get_articles_for_cohort(cohort):
if article.language_id != user_language_id:
continue
# A text shared with two of this student's classes appears
# once, tagged with both.
if article.id not in classes_by_article:
all_articles.append(article)
classes_by_article[article.id] = []
classes_by_article[article.id].append(
{"id": cohort.id, "name": cohort.name}
)

# Use the standard helper for proper cache handling
return UserArticle.article_infos(self, all_articles, select_appropriate=False)
infos = UserArticle.article_infos(
self, all_articles, select_appropriate=False
)
for info in infos:
info["from_classes"] = classes_by_article.get(info["id"], [])
return infos
except NoResultFound as e:
return []

Expand Down
67 changes: 67 additions & 0 deletions zeeguu/core/test/test_cohort_article_attribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from unittest import TestCase

import zeeguu.core
from zeeguu.core.model.cohort_article_map import CohortArticleMap
from zeeguu.core.test.model_test_mixin import ModelTestMixIn
from zeeguu.core.test.rules.article_rule import ArticleRule
from zeeguu.core.test.rules.cohort_rule import CohortRule
from zeeguu.core.test.rules.language_rule import LanguageRule
from zeeguu.core.test.rules.user_rule import UserRule

db_session = zeeguu.core.model.db.session


class CohortArticleAttributionTest(ModelTestMixIn, TestCase):
"""cohort_articles_for_user says which class each text came from.

A student in several classes gets one merged list; without the tag it is a
pile of texts with no way to tell whose lesson is whose.
"""

def setUp(self):
super().setUp()
self.danish = LanguageRule().da
self.german = LanguageRule().de
self.student = UserRule().user
self.student.set_learned_language(self.danish.code, session=db_session)

def _class_with(self, *articles):
cohort = CohortRule().cohort
for article in articles:
db_session.add(CohortArticleMap(cohort, article, None))
self.student.add_user_to_cohort(cohort, db_session)
db_session.commit()
return cohort

def _article_in(self, language):
article = ArticleRule().article
article.language = language
db_session.add(article)
db_session.commit()
return article

def test_each_text_names_its_class(self):
cohort = self._class_with(self._article_in(self.danish))

infos = self.student.cohort_articles_for_user()

self.assertEqual(1, len(infos))
self.assertEqual([{"id": cohort.id, "name": cohort.name}], infos[0]["from_classes"])

def test_a_text_in_two_classes_appears_once_naming_both(self):
shared = self._article_in(self.danish)
first = self._class_with(shared)
second = self._class_with(shared)

infos = self.student.cohort_articles_for_user()

self.assertEqual(1, len(infos))
self.assertEqual(
{first.id, second.id},
{each["id"] for each in infos[0]["from_classes"]},
)

def test_off_language_texts_are_still_left_out(self):
self._class_with(self._article_in(self.german))

self.assertEqual([], self.student.cohort_articles_for_user())
Loading