-
-
-
- {% if group_by == 'user' %}
- | Collection |
- {% else %}
- Learner |
- {% endif %}
- Started |
- Ended |
- Status |
- Progress |
- |
-
-
-
- {% for attempt, collection in attempt_rows %}
-
- {% if group_by == 'user' %}
- |
- {% if collection %}
- {{ collection.name }}
- {% else %}
- Unknown
- {% endif %}
- |
- {% else %}
-
- {% if attempt.user_user %}
- {{ attempt.user_user.get_full_name|default:attempt.user_user.username }}
- {% if attempt.user_user.email %}
- {{ attempt.user_user.email }}
- {% endif %}
- {% elif attempt.cid_user %}
- CID {{ attempt.cid_user.cid }}
- {% if attempt.cid_user.name %} {{ attempt.cid_user.name }}{% endif %}
- {% else %}
- Unknown
- {% endif %}
- |
- {% endif %}
- {{ attempt.start_time|default:"-" }} |
- {{ attempt.end_time|default:"-" }} |
-
- {% if attempt.completed %}
- Completed
- {% else %}
- In progress
- {% endif %}
- |
-
- {% if attempt.user_user_id %}
-
- View attempt
-
- {% else %}
-
- View attempt
-
- {% endif %}
- |
-
- {% endfor %}
-
-
+ {# ---- Filter / group toolbar ---- #}
+
+
+ {# ---- Grouped results ---- #}
+ {% if groups %}
+ {% for group_label, attempt_rows in groups %}
+
+
+ {% if group_by == 'user' %}
+
+ {% else %}
+
+ {% endif %}
+ {{ group_label }}
+ {{ attempt_rows|length }} attempt{{ attempt_rows|length|pluralize }}
+
+
+
+
+
+ {% if group_by == 'user' %}
+ | Collection |
+ {% else %}
+ Learner |
+ {% endif %}
+ Started |
+ Ended |
+ Status |
+ |
+
+
+
+ {% for attempt, collection in attempt_rows %}
+
+ {% if group_by == 'user' %}
+ |
+ {% if collection %}{{ collection.name }}{% else %}Unknown{% endif %}
+ |
+ {% else %}
+
+ {% if attempt.user_user %}
+ {{ attempt.user_user.get_full_name|default:attempt.user_user.username }}
+ {% if attempt.user_user.email %}
+ {{ attempt.user_user.email }}
+ {% endif %}
+ {% elif attempt.cid_user %}
+ CID {{ attempt.cid_user.cid }}
+ {% if attempt.cid_user.name %} {{ attempt.cid_user.name }}{% endif %}
+ {% else %}
+ Unknown
+ {% endif %}
+ |
+ {% endif %}
+ {{ attempt.start_time|default:"-" }} |
+ {{ attempt.end_time|default:"-" }} |
+
+ {% if attempt.completed %}
+ Completed
+ {% else %}
+ In progress
+ {% endif %}
+ |
+
+ {% if attempt.user_user_id and collection %}
+
+ View attempt
+
+ {% else %}
+
+ View attempt
+
+ {% endif %}
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endfor %}
+ {% else %}
+
+ No collection attempts found. Try adjusting the filters.
+
+ {% endif %}
{% endblock %}
diff --git a/atlas/views.py b/atlas/views.py
index d1613cbc..4ff06c84 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -5844,72 +5844,9 @@ def collection_exam_user_search(request, pk):
@login_required
def collection_shared_with_me(request):
- """Full page listing all collection attempts that have been shared with the current user.
+ """Legacy redirect — the shared-with-me page is now part of the supervision page."""
+ return redirect(reverse("atlas:collection_supervision"))
- Includes attempts where the user is:
- - An author or marker of the collection
- - A supervisor of the attempt owner (share_with_supervisor=True or exam results_supervisor_visible)
- - Manually listed in CidUserExam.shared_with_users
-
- The user's own attempts are excluded.
- """
- collection_ct = ContentType.objects.get_for_model(CaseCollection)
-
- # Manual shares
- manual_qs = CidUserExam.objects.filter(
- shared_with_users=request.user,
- content_type=collection_ct,
- ).exclude(user_user=request.user)
-
- # Author or marker of the collection
- managed_collection_ids = list(
- CaseCollection.objects.filter(
- Q(author=request.user) | Q(markers=request.user)
- ).values_list("pk", flat=True)
- )
- authored_qs = CidUserExam.objects.filter(
- content_type=collection_ct,
- object_id__in=managed_collection_ids,
- ).exclude(user_user=request.user)
-
- # Supervisor (per-attempt flag)
- supervisor_qs = CidUserExam.objects.none()
- supervisor_exam_qs = CidUserExam.objects.none()
- try:
- supervisor = request.user.supervisor
- trainee_users = User.objects.filter(userprofile__supervisor=supervisor)
- trainee_cid_users = CidUser.objects.filter(supervisor=supervisor)
- supervisor_qs = CidUserExam.objects.filter(
- content_type=collection_ct,
- share_with_supervisor=True,
- ).filter(
- Q(user_user__in=trainee_users) | Q(cid_user__in=trainee_cid_users)
- ).exclude(user_user=request.user)
-
- # Exam-level supervisor visibility
- visible_collection_ids = list(
- CaseCollection.objects.filter(results_supervisor_visible=True).values_list("pk", flat=True)
- )
- supervisor_exam_qs = CidUserExam.objects.filter(
- content_type=collection_ct,
- object_id__in=visible_collection_ids,
- ).filter(
- Q(user_user__in=trainee_users) | Q(cid_user__in=trainee_cid_users)
- ).exclude(user_user=request.user)
- except Exception:
- pass
-
- all_attempts = (
- manual_qs | authored_qs | supervisor_qs | supervisor_exam_qs
- ).distinct().select_related("user_user", "cid_user").order_by("-start_time")
-
- attempt_list = [(attempt, attempt.exam) for attempt in all_attempts]
-
- return render(
- request,
- "atlas/shared_with_me.html",
- {"attempt_list": attempt_list},
- )
@login_required
@@ -5993,13 +5930,31 @@ def collection_supervision(request):
- GET param ``group_by``: ``user`` (default) or ``collection``
- GET params ``date_from`` / ``date_to``: ISO date strings to filter by
attempt start_time (inclusive).
+ - GET param ``q``: free-text search over learner name / username / email.
+ - GET param ``supervisor_only``: ``1`` to restrict to attempts where the current
+ user is the assigned supervisor (only shown when the user is a supervisor).
"""
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
+ from django.utils.dateparse import parse_date
collection_ct = ContentType.objects.get_for_model(CaseCollection)
- # ---- build base queryset of accessible attempts ----
+ # ---- determine supervisor status ----
+ is_supervisor = False
+ trainee_users = User.objects.none()
+ trainee_cid_users = CidUser.objects.none()
+ try:
+ supervisor = request.user.supervisor
+ is_supervisor = True
+ trainee_users = User.objects.filter(userprofile__supervisor=supervisor)
+ trainee_cid_users = CidUser.objects.filter(supervisor=supervisor)
+ except Exception:
+ pass
+
+ supervisor_only = request.GET.get("supervisor_only", "") == "1" and is_supervisor
+
+ # ---- build base querysets of accessible attempts ----
manual_qs = CidUserExam.objects.filter(
shared_with_users=request.user,
content_type=collection_ct,
@@ -6017,10 +5972,7 @@ def collection_supervision(request):
supervisor_qs = CidUserExam.objects.none()
supervisor_exam_qs = CidUserExam.objects.none()
- try:
- supervisor = request.user.supervisor
- trainee_users = User.objects.filter(userprofile__supervisor=supervisor)
- trainee_cid_users = CidUser.objects.filter(supervisor=supervisor)
+ if is_supervisor:
supervisor_qs = CidUserExam.objects.filter(
content_type=collection_ct,
share_with_supervisor=True,
@@ -6037,21 +5989,21 @@ def collection_supervision(request):
).filter(
Q(user_user__in=trainee_users) | Q(cid_user__in=trainee_cid_users)
).exclude(user_user=request.user)
- except Exception:
- pass
- all_attempts = (
- manual_qs | authored_qs | supervisor_qs | supervisor_exam_qs
- ).distinct().select_related("user_user", "cid_user")
+ if supervisor_only:
+ all_attempts = (supervisor_qs | supervisor_exam_qs).distinct()
+ else:
+ all_attempts = (
+ manual_qs | authored_qs | supervisor_qs | supervisor_exam_qs
+ ).distinct()
+
+ all_attempts = all_attempts.select_related("user_user", "cid_user")
# ---- date filter ----
date_from_raw = request.GET.get("date_from", "").strip()
date_to_raw = request.GET.get("date_to", "").strip()
- date_from = None
- date_to = None
try:
if date_from_raw:
- from django.utils.dateparse import parse_date
date_from = parse_date(date_from_raw)
if date_from:
all_attempts = all_attempts.filter(start_time__date__gte=date_from)
@@ -6059,13 +6011,24 @@ def collection_supervision(request):
pass
try:
if date_to_raw:
- from django.utils.dateparse import parse_date
date_to = parse_date(date_to_raw)
if date_to:
all_attempts = all_attempts.filter(start_time__date__lte=date_to)
except Exception:
pass
+ # ---- user / learner search ----
+ q = request.GET.get("q", "").strip()
+ if q:
+ all_attempts = all_attempts.filter(
+ Q(user_user__first_name__icontains=q)
+ | Q(user_user__last_name__icontains=q)
+ | Q(user_user__username__icontains=q)
+ | Q(user_user__email__icontains=q)
+ | Q(cid_user__name__icontains=q)
+ | Q(cid_user__email__icontains=q)
+ )
+
all_attempts = all_attempts.order_by("-start_time")
# ---- grouping ----
@@ -6094,7 +6057,6 @@ def collection_supervision(request):
key = (key_id, key_label)
grouped.setdefault(key, []).append((attempt, collection_obj))
- # Convert to sorted list of (key_label, [(attempt, collection), ...])
groups = sorted(grouped.items(), key=lambda x: str(x[0][1]).lower())
groups = [(label, rows) for (_, label), rows in groups]
@@ -6106,6 +6068,9 @@ def collection_supervision(request):
"group_by": group_by,
"date_from": date_from_raw,
"date_to": date_to_raw,
+ "q": q,
+ "is_supervisor": is_supervisor,
+ "supervisor_only": supervisor_only,
"total_attempts": all_attempts.count(),
},
)
diff --git a/templates/base.html b/templates/base.html
index a87a665e..db192389 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -214,9 +214,6 @@
Supervision
-
- Shared with me
-