Implement hiding and showing functionality for user exams and collections
This commit is contained in:
@@ -182,4 +182,103 @@ def test_people_page_and_user_search(client, create_users, create_cid_manager):
|
||||
assert b"No users found matching" in response_no_match.content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_hide_exams_and_collections(client, create_users):
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from physics.models import Exam as PhysicsExam
|
||||
from atlas.models import CaseCollection
|
||||
from generic.models import UserHiddenItem
|
||||
|
||||
user1, user2 = create_users
|
||||
|
||||
# 1. Create a PhysicsExam and associate with user1
|
||||
exam = PhysicsExam.objects.create(
|
||||
name="Test Physics Exam", exam_mode=True, active=True
|
||||
)
|
||||
user1.user_physics_exams.add(exam)
|
||||
|
||||
# 2. Create a CaseCollection and associate with user1
|
||||
collection = CaseCollection.objects.create(
|
||||
name="Test Case Collection", exam_mode=True, active=True
|
||||
)
|
||||
user1.user_casecollection_exams.add(collection)
|
||||
|
||||
# Log in as user1
|
||||
client.force_login(user1)
|
||||
|
||||
# Verify they are visible on user scores page initially
|
||||
response = client.get(reverse("user_scores"))
|
||||
assert response.status_code == 200
|
||||
assert b"Test Physics Exam" in response.content
|
||||
|
||||
# Load atlas collections partial
|
||||
response_cc = client.get(reverse("atlas:user_collections"))
|
||||
assert response_cc.status_code == 200
|
||||
assert b"Test Case Collection" in response_cc.content
|
||||
|
||||
# 3. Hide the PhysicsExam
|
||||
exam_ct = ContentType.objects.get_for_model(PhysicsExam)
|
||||
response_hide_exam = client.post(
|
||||
reverse("generic:toggle_hide_item"),
|
||||
{"content_type_id": exam_ct.id, "object_id": exam.id},
|
||||
)
|
||||
assert response_hide_exam.status_code == 200
|
||||
assert response_hide_exam.headers.get("HX-Refresh") == "true"
|
||||
|
||||
# Verify UserHiddenItem exists
|
||||
assert UserHiddenItem.objects.filter(
|
||||
user=user1, content_type=exam_ct, object_id=exam.id
|
||||
).exists()
|
||||
|
||||
# Verify exam is hidden now from standard user_scores
|
||||
response_hidden = client.get(reverse("user_scores"))
|
||||
assert response_hidden.status_code == 200
|
||||
assert b"Test Physics Exam" not in response_hidden.content
|
||||
|
||||
# But present when show_hidden=true is requested
|
||||
response_show_hidden = client.get(reverse("user_scores") + "?show_hidden=true")
|
||||
assert response_show_hidden.status_code == 200
|
||||
assert b"Test Physics Exam" in response_show_hidden.content
|
||||
assert b"Hidden" in response_show_hidden.content
|
||||
|
||||
# 4. Hide the CaseCollection
|
||||
cc_ct = ContentType.objects.get_for_model(CaseCollection)
|
||||
response_hide_cc = client.post(
|
||||
reverse("generic:toggle_hide_item"),
|
||||
{"content_type_id": cc_ct.id, "object_id": collection.pk},
|
||||
)
|
||||
assert response_hide_cc.status_code == 200
|
||||
assert response_hide_cc.headers.get("HX-Refresh") == "true"
|
||||
|
||||
assert UserHiddenItem.objects.filter(
|
||||
user=user1, content_type=cc_ct, object_id=collection.pk
|
||||
).exists()
|
||||
|
||||
# Verify collection is hidden from normal view
|
||||
response_cc_hidden = client.get(reverse("atlas:user_collections"))
|
||||
assert response_cc_hidden.status_code == 200
|
||||
assert b"Test Case Collection" not in response_cc_hidden.content
|
||||
|
||||
# Verify collection is visible in show_hidden view
|
||||
response_cc_show_hidden = client.get(reverse("atlas:user_collections") + "?show_hidden=true")
|
||||
assert response_cc_show_hidden.status_code == 200
|
||||
assert b"Test Case Collection" in response_cc_show_hidden.content
|
||||
assert b"Hidden" in response_cc_show_hidden.content
|
||||
|
||||
# 5. Unhide the PhysicsExam by toggling again
|
||||
response_unhide_exam = client.post(
|
||||
reverse("generic:toggle_hide_item"),
|
||||
{"content_type_id": exam_ct.id, "object_id": exam.id},
|
||||
)
|
||||
assert response_unhide_exam.status_code == 200
|
||||
assert not UserHiddenItem.objects.filter(
|
||||
user=user1, content_type=exam_ct, object_id=exam.id
|
||||
).exists()
|
||||
|
||||
response_unhidden = client.get(reverse("user_scores"))
|
||||
assert response_unhidden.status_code == 200
|
||||
assert b"Test Physics Exam" in response_unhidden.content
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+42
-12
@@ -706,39 +706,69 @@ def user_scores(request, user=None):
|
||||
user = request.user
|
||||
admin = False
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from generic.models import UserHiddenItem
|
||||
|
||||
show_hidden = request.GET.get("show_hidden") in ("true", "1")
|
||||
|
||||
# Fetch user's hidden items map: {content_type_id: {object_ids}}
|
||||
hidden_map = {}
|
||||
for ct_id, obj_id in UserHiddenItem.objects.filter(user=user).values_list("content_type_id", "object_id"):
|
||||
hidden_map.setdefault(ct_id, set()).add(obj_id)
|
||||
|
||||
# Filter Exam Results list (all_exams)
|
||||
exams = get_user_exams(user)
|
||||
filtered_exams = []
|
||||
for exam_type, exams_qs in exams:
|
||||
exam_model = exams_qs.model
|
||||
ct_id = ContentType.objects.get_for_model(exam_model).id
|
||||
hidden_ids = hidden_map.get(ct_id, set())
|
||||
|
||||
# case_collections = request.user.casecollection_exams.all()
|
||||
if not show_hidden:
|
||||
exams_qs = exams_qs.exclude(id__in=hidden_ids)
|
||||
|
||||
exams_list = list(exams_qs)
|
||||
for exam in exams_list:
|
||||
exam.is_hidden = exam.id in hidden_ids
|
||||
|
||||
if exams_list:
|
||||
filtered_exams.append((exam_type, exams_list))
|
||||
|
||||
# Filter Assigned Exams list (available_exams)
|
||||
available_exams = []
|
||||
|
||||
for n, t in USER_EXAM_TYPES:
|
||||
exam_rel = getattr(user, t)
|
||||
if exam_rel.exists():
|
||||
temp_exams = exam_rel.filter(exam_mode=True, archive=False).order_by("name")
|
||||
available_exams.append((n, temp_exams))
|
||||
exam_model = temp_exams.model
|
||||
ct_id = ContentType.objects.get_for_model(exam_model).id
|
||||
hidden_ids = hidden_map.get(ct_id, set())
|
||||
|
||||
# available_exams = request.user.get_cid_exams()
|
||||
if not show_hidden:
|
||||
temp_exams = temp_exams.exclude(id__in=hidden_ids)
|
||||
|
||||
temp_exams_list = list(temp_exams)
|
||||
for exam in temp_exams_list:
|
||||
exam.is_hidden = exam.id in hidden_ids
|
||||
|
||||
if temp_exams_list:
|
||||
available_exams.append((n, temp_exams_list))
|
||||
|
||||
return render(
|
||||
request,
|
||||
"user_scores.html",
|
||||
{
|
||||
# "physics_exams": physics_exams,
|
||||
# "anatomy_exams": anatomy_exams,
|
||||
# "rapid_exams": rapid_exams,
|
||||
# "longs_exams": longs_exams,
|
||||
# "sba_exams": sba_exams,
|
||||
"all_exams": exams,
|
||||
# "passcode": passcode,
|
||||
"all_exams": filtered_exams,
|
||||
"cid_user": user,
|
||||
"available_exams": available_exams,
|
||||
"case_collections": [], # case_collections,
|
||||
"case_collections": [],
|
||||
"admin": admin,
|
||||
"show_hidden": show_hidden,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@login_required
|
||||
def user_marking(request):
|
||||
"""Main page for user marking overview. Uses HTMX to fetch per-app partials."""
|
||||
|
||||
Reference in New Issue
Block a user