feat: Update user messages inbox and collection user messages with enhanced acknowledgment statistics and navigation links
This commit is contained in:
@@ -45,6 +45,17 @@
|
|||||||
<span class="badge bg-danger">{{ row.stats.outstanding_total_count }} outstanding</span>
|
<span class="badge bg-danger">{{ row.stats.outstanding_total_count }} outstanding</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body pt-0">
|
<div class="card-body pt-0">
|
||||||
|
<div class="d-flex flex-wrap gap-2 mt-2 mb-2">
|
||||||
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:collection_detail' collection.id %}">
|
||||||
|
Collection
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:collection_case_view' pk=collection.id case_number=row.casedetail.sort_order %}">
|
||||||
|
Case In Collection
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% if target_user %}{% url 'atlas:collection_history_user' collection.id target_user.id %}{% else %}{% url 'atlas:collection_history_ciduser' collection.id target_cid %}{% endif %}#case-history-{{ row.casedetail.case.id }}">
|
||||||
|
User Answer In Context
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div hx-get="{{ row.thread_url }}{% if row.cid %}?cid={{ row.cid }}{% endif %}"
|
<div hx-get="{{ row.thread_url }}{% if row.cid %}?cid={{ row.cid }}{% endif %}"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
hx-target="this"
|
hx-target="this"
|
||||||
@@ -78,6 +89,17 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div id="history-collapse-{{ row.casedetail.case.id }}" class="accordion-collapse collapse" aria-labelledby="history-heading-{{ row.casedetail.case.id }}" data-bs-parent="#userMessageHistoryAccordion">
|
<div id="history-collapse-{{ row.casedetail.case.id }}" class="accordion-collapse collapse" aria-labelledby="history-heading-{{ row.casedetail.case.id }}" data-bs-parent="#userMessageHistoryAccordion">
|
||||||
<div class="accordion-body pt-0">
|
<div class="accordion-body pt-0">
|
||||||
|
<div class="d-flex flex-wrap gap-2 mt-2 mb-2">
|
||||||
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:collection_detail' collection.id %}">
|
||||||
|
Collection
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:collection_case_view' pk=collection.id case_number=row.casedetail.sort_order %}">
|
||||||
|
Case In Collection
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% if target_user %}{% url 'atlas:collection_history_user' collection.id target_user.id %}{% else %}{% url 'atlas:collection_history_ciduser' collection.id target_cid %}{% endif %}#case-history-{{ row.casedetail.case.id }}">
|
||||||
|
User Answer In Context
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div hx-get="{{ row.thread_url }}{% if row.cid %}?cid={{ row.cid }}{% endif %}"
|
<div hx-get="{{ row.thread_url }}{% if row.cid %}?cid={{ row.cid }}{% endif %}"
|
||||||
hx-trigger="revealed once"
|
hx-trigger="revealed once"
|
||||||
hx-target="this"
|
hx-target="this"
|
||||||
|
|||||||
@@ -9,7 +9,13 @@
|
|||||||
<div class="card border-secondary" style="min-width: 320px;">
|
<div class="card border-secondary" style="min-width: 320px;">
|
||||||
<div class="card-body py-2 px-3">
|
<div class="card-body py-2 px-3">
|
||||||
<div class="small text-muted">Pending acknowledgements</div>
|
<div class="small text-muted">Pending acknowledgements</div>
|
||||||
<div class="fw-semibold {% if total_outstanding %}text-danger{% endif %}">
|
<div class="fw-semibold {% if total_needs_your_ack %}text-danger{% endif %}">
|
||||||
|
{{ total_needs_your_ack }} need your acknowledgement
|
||||||
|
</div>
|
||||||
|
<div class="small mt-1 {% if total_waiting_on_other %}text-warning-emphasis{% else %}text-muted{% endif %}">
|
||||||
|
{{ total_waiting_on_other }} waiting on another user
|
||||||
|
</div>
|
||||||
|
<div class="small mt-1 text-muted">
|
||||||
{{ total_outstanding }} unacknowledged message{{ total_outstanding|pluralize }}
|
{{ total_outstanding }} unacknowledged message{{ total_outstanding|pluralize }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
@@ -38,11 +44,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-wrap gap-2 align-items-center">
|
<div class="d-flex flex-wrap gap-2 align-items-center">
|
||||||
{% if row.outstanding_count %}
|
<span class="badge {% if row.needs_your_ack_count %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||||
<span class="badge bg-danger">{{ row.outstanding_count }} unacknowledged</span>
|
{{ row.needs_your_ack_count }} need your ack
|
||||||
{% else %}
|
</span>
|
||||||
<span class="badge bg-secondary">No outstanding</span>
|
{% if row.waiting_on_other_count %}
|
||||||
|
<span class="badge text-bg-warning">{{ row.waiting_on_other_count }} waiting on other</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<span class="badge bg-dark-subtle text-dark-emphasis">{{ row.outstanding_count }} total unacknowledged</span>
|
||||||
<a class="btn btn-sm btn-outline-secondary" href="{{ row.detail_url }}">Open user message page</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{{ row.detail_url }}">Open user message page</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,7 +67,13 @@
|
|||||||
{% if row.collection.show_title_post %}
|
{% if row.collection.show_title_post %}
|
||||||
<span class="text-muted">{{ case_row.casedetail.case.title|default:case_row.casedetail.case.pk|truncatechars:90 }}</span>
|
<span class="text-muted">{{ case_row.casedetail.case.title|default:case_row.casedetail.case.pk|truncatechars:90 }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="badge bg-danger">{{ case_row.stats.outstanding_total_count }} unacknowledged</span>
|
<span class="badge {% if case_row.stats.needs_your_ack_count %}bg-danger{% else %}bg-secondary{% endif %}">
|
||||||
|
{{ case_row.stats.needs_your_ack_count }} need your ack
|
||||||
|
</span>
|
||||||
|
{% if case_row.stats.waiting_on_other_count %}
|
||||||
|
<span class="badge text-bg-warning">{{ case_row.stats.waiting_on_other_count }} waiting on other</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="badge bg-dark-subtle text-dark-emphasis">{{ case_row.stats.outstanding_total_count }} total</span>
|
||||||
</summary>
|
</summary>
|
||||||
{% if row.viewer_role == 'moderator' %}
|
{% if row.viewer_role == 'moderator' %}
|
||||||
<div class="d-flex flex-wrap gap-2 mt-2">
|
<div class="d-flex flex-wrap gap-2 mt-2">
|
||||||
@@ -114,6 +128,9 @@
|
|||||||
: {{ case_row.casedetail.case.title|default:case_row.casedetail.case.pk|truncatechars:90 }}
|
: {{ case_row.casedetail.case.title|default:case_row.casedetail.case.pk|truncatechars:90 }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="badge bg-secondary ms-2">{{ case_row.stats.message_count }} messages</span>
|
<span class="badge bg-secondary ms-2">{{ case_row.stats.message_count }} messages</span>
|
||||||
|
{% if case_row.stats.outstanding_total_count %}
|
||||||
|
<span class="badge bg-dark-subtle text-dark-emphasis ms-1">{{ case_row.stats.outstanding_total_count }} unacknowledged</span>
|
||||||
|
{% endif %}
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div id="history-collapse-{{ row.attempt.id }}-{{ case_row.casedetail.case.id }}" class="accordion-collapse collapse" aria-labelledby="history-heading-{{ row.attempt.id }}-{{ case_row.casedetail.case.id }}" data-bs-parent="#history-{{ row.attempt.id }}">
|
<div id="history-collapse-{{ row.attempt.id }}-{{ case_row.casedetail.case.id }}" class="accordion-collapse collapse" aria-labelledby="history-heading-{{ row.attempt.id }}-{{ case_row.casedetail.case.id }}" data-bs-parent="#history-{{ row.attempt.id }}">
|
||||||
|
|||||||
+39
-1
@@ -4500,6 +4500,8 @@ def user_messages_inbox(request):
|
|||||||
{
|
{
|
||||||
"inbox_rows": [],
|
"inbox_rows": [],
|
||||||
"total_outstanding": 0,
|
"total_outstanding": 0,
|
||||||
|
"total_needs_your_ack": 0,
|
||||||
|
"total_waiting_on_other": 0,
|
||||||
"show_all": request.GET.get("show") == "all",
|
"show_all": request.GET.get("show") == "all",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -4537,12 +4539,23 @@ def user_messages_inbox(request):
|
|||||||
acknowledged_at__isnull=True,
|
acknowledged_at__isnull=True,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
outstanding_query_count=Count(
|
||||||
|
"id",
|
||||||
|
filter=Q(
|
||||||
|
requires_acknowledgement=True,
|
||||||
|
acknowledged_at__isnull=True,
|
||||||
|
message_type=CaseReviewMessage.MessageType.QUERY,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
outstanding_total_count = row["outstanding_total_count"]
|
outstanding_total_count = row["outstanding_total_count"]
|
||||||
|
outstanding_query_count = row["outstanding_query_count"]
|
||||||
message_stats_by_attempt_case[row["cid_user_exam_id"]][row["case_id"]] = {
|
message_stats_by_attempt_case[row["cid_user_exam_id"]][row["case_id"]] = {
|
||||||
"message_count": row["message_count"],
|
"message_count": row["message_count"],
|
||||||
"outstanding_total_count": outstanding_total_count,
|
"outstanding_total_count": outstanding_total_count,
|
||||||
|
"outstanding_query_count": outstanding_query_count,
|
||||||
|
"outstanding_feedback_count": outstanding_total_count - outstanding_query_count,
|
||||||
"has_messages": row["message_count"] > 0,
|
"has_messages": row["message_count"] > 0,
|
||||||
"has_outstanding_any": outstanding_total_count > 0,
|
"has_outstanding_any": outstanding_total_count > 0,
|
||||||
}
|
}
|
||||||
@@ -4567,14 +4580,31 @@ def user_messages_inbox(request):
|
|||||||
{
|
{
|
||||||
"message_count": 0,
|
"message_count": 0,
|
||||||
"outstanding_total_count": 0,
|
"outstanding_total_count": 0,
|
||||||
|
"outstanding_query_count": 0,
|
||||||
|
"outstanding_feedback_count": 0,
|
||||||
"has_messages": False,
|
"has_messages": False,
|
||||||
"has_outstanding_any": False,
|
"has_outstanding_any": False,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
outstanding_query_count = stats.get("outstanding_query_count", 0)
|
||||||
|
outstanding_feedback_count = stats.get("outstanding_feedback_count", 0)
|
||||||
|
if viewer_role == "moderator":
|
||||||
|
needs_your_ack_count = outstanding_query_count
|
||||||
|
waiting_on_other_count = outstanding_feedback_count
|
||||||
|
else:
|
||||||
|
needs_your_ack_count = outstanding_feedback_count
|
||||||
|
waiting_on_other_count = outstanding_query_count
|
||||||
|
|
||||||
|
enriched_stats = {
|
||||||
|
**stats,
|
||||||
|
"needs_your_ack_count": needs_your_ack_count,
|
||||||
|
"waiting_on_other_count": waiting_on_other_count,
|
||||||
|
}
|
||||||
feedback_rows.append(
|
feedback_rows.append(
|
||||||
{
|
{
|
||||||
"casedetail": casedetail,
|
"casedetail": casedetail,
|
||||||
"stats": stats,
|
"stats": enriched_stats,
|
||||||
"thread_url": reverse(
|
"thread_url": reverse(
|
||||||
"atlas:collection_case_review_thread",
|
"atlas:collection_case_review_thread",
|
||||||
kwargs={
|
kwargs={
|
||||||
@@ -4610,6 +4640,8 @@ def user_messages_inbox(request):
|
|||||||
)
|
)
|
||||||
|
|
||||||
outstanding_count = sum(row["stats"].get("outstanding_total_count", 0) for row in feedback_rows)
|
outstanding_count = sum(row["stats"].get("outstanding_total_count", 0) for row in feedback_rows)
|
||||||
|
needs_your_ack_count = sum(row["stats"].get("needs_your_ack_count", 0) for row in feedback_rows)
|
||||||
|
waiting_on_other_count = sum(row["stats"].get("waiting_on_other_count", 0) for row in feedback_rows)
|
||||||
inbox_rows.append(
|
inbox_rows.append(
|
||||||
{
|
{
|
||||||
"collection": collection,
|
"collection": collection,
|
||||||
@@ -4620,6 +4652,8 @@ def user_messages_inbox(request):
|
|||||||
"outstanding_rows": outstanding_rows,
|
"outstanding_rows": outstanding_rows,
|
||||||
"history_rows": history_rows,
|
"history_rows": history_rows,
|
||||||
"outstanding_count": outstanding_count,
|
"outstanding_count": outstanding_count,
|
||||||
|
"needs_your_ack_count": needs_your_ack_count,
|
||||||
|
"waiting_on_other_count": waiting_on_other_count,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -4633,6 +4667,8 @@ def user_messages_inbox(request):
|
|||||||
)
|
)
|
||||||
|
|
||||||
total_outstanding = sum(row["outstanding_count"] for row in inbox_rows)
|
total_outstanding = sum(row["outstanding_count"] for row in inbox_rows)
|
||||||
|
total_needs_your_ack = sum(row["needs_your_ack_count"] for row in inbox_rows)
|
||||||
|
total_waiting_on_other = sum(row["waiting_on_other_count"] for row in inbox_rows)
|
||||||
show_all = request.GET.get("show") == "all"
|
show_all = request.GET.get("show") == "all"
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
@@ -4641,6 +4677,8 @@ def user_messages_inbox(request):
|
|||||||
{
|
{
|
||||||
"inbox_rows": inbox_rows,
|
"inbox_rows": inbox_rows,
|
||||||
"total_outstanding": total_outstanding,
|
"total_outstanding": total_outstanding,
|
||||||
|
"total_needs_your_ack": total_needs_your_ack,
|
||||||
|
"total_waiting_on_other": total_waiting_on_other,
|
||||||
"show_all": show_all,
|
"show_all": show_all,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user