Add sync functionality for prerequisite users in collection detail

This commit is contained in:
Ross
2025-10-13 14:14:17 +01:00
parent eeef34bffc
commit 2c30145d3a
5 changed files with 118 additions and 29 deletions
+62 -6
View File
@@ -2189,9 +2189,7 @@ def collection_take_start(request, pk, cid=None, passcode=None):
Returns:
_type_: _description_
"""
print(f"Collection take start: {pk}, cid: {cid}, passcode: {passcode}")
collection = get_object_or_404(CaseCollection, pk=pk)
print(f"Collection: {collection}")
try:
collection.check_user_can_take(cid, passcode, request.user)
@@ -2204,7 +2202,7 @@ def collection_take_start(request, pk, cid=None, passcode=None):
return render(
request,
'atlas/prerequisite_required.html',
{'message': str(e), 'prereq': prereq},
{'message': str(e), 'prereq': prereq, 'cid': cid, 'passcode': passcode},
)
@@ -2626,7 +2624,7 @@ def collection_take_overview(
collection.check_user_can_take(cid, passcode, request.user)
except PrerequisiteRequired as e:
prereq = getattr(e, 'prereq', None)
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq})
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq, 'cid': cid, 'passcode': passcode})
cid_user_exam = collection.get_or_create_cid_user_exam(
cid=cid, user_user=request.user
@@ -2703,7 +2701,7 @@ def collection_case_view_take_answers(
collection.check_user_can_take(cid, passcode, request.user)
except PrerequisiteRequired as e:
prereq = getattr(e, 'prereq', None)
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq})
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq, 'cid': cid, 'passcode': passcode})
case, case_count = collection.get_case_by_index(case_number, case_count=True)
@@ -2756,7 +2754,7 @@ def collection_case_view_take(
collection.check_user_can_take(cid, passcode, request.user)
except PrerequisiteRequired as e:
prereq = getattr(e, 'prereq', None)
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq})
return render(request, 'atlas/prerequisite_required.html', {'message': str(e), 'prereq': prereq, 'cid': cid, 'passcode': passcode})
case, case_count = collection.get_case_by_index(case_number, case_count=True)
@@ -3563,6 +3561,64 @@ def collection_question_schemas(request, exam_id: int):
)
@user_is_collection_author_or_atlas_editor
def collection_sync_prerequisite_users(request, pk: int):
"""Copy valid cid_users and user_users from all prerequisite collections into this collection.
This endpoint is intended to be called via HTMX from the collection detail page.
"""
if not request.htmx:
raise Http404("Invalid request")
collection = get_object_or_404(CaseCollection, pk=pk)
# Collect the closure of collections: the target collection and all prerequisites (recursively)
to_visit = [collection]
visited = {}
while to_visit:
col = to_visit.pop()
if col.pk in visited:
continue
visited[col.pk] = col
for p in col.prerequisites.all():
if p.pk not in visited:
to_visit.append(p)
collections = list(visited.values())
# Compute the union of all cid users and user users across the set
union_cid_users = set()
union_user_users = set()
for col in collections:
union_cid_users.update(list(col.valid_cid_users.all()))
union_user_users.update(list(col.valid_user_users.all()))
# Apply the union to each collection and count additions
total_added_cid = 0
total_added_user = 0
per_collection_added = []
for col in collections:
added_cid = 0
added_user = 0
for cid_user in union_cid_users:
if not col.valid_cid_users.filter(pk=cid_user.pk).exists():
col.valid_cid_users.add(cid_user)
added_cid += 1
for user in union_user_users:
if not col.valid_user_users.filter(pk=user.pk).exists():
col.valid_user_users.add(user)
added_user += 1
if added_cid or added_user:
col.save()
total_added_cid += added_cid
total_added_user += added_user
per_collection_added.append((col.pk, added_cid, added_user))
return HttpResponse(
f"Two-way sync complete — total added: {total_added_cid} cid(s), {total_added_user} user(s)."
)
def collection_reset_answers_user_list(request, exam_id: int):
if request.htmx:
collection = get_object_or_404(CaseCollection, pk=exam_id)