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
11 changes: 11 additions & 0 deletions backend/reviews/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,21 @@ def get_recap_context(
)
}

# Count submissions per speaker for the current conference
speaker_submission_counts = {
str(speaker_id): count
for speaker_id, count in Submission.objects.for_conference(conference.id)
.non_cancelled()
.values("speaker_id")
.annotate(count=Count("id"))
.values_list("speaker_id", "count")
}

return dict(
admin_site.each_context(request),
items=items,
grants=grants,
speaker_submission_counts=speaker_submission_counts,
review_session_id=review_session.id,
audience_levels=conference.audience_levels.all(),
submission_types=conference.submission_types.all(),
Expand Down
20 changes: 20 additions & 0 deletions backend/reviews/templates/proposals-recap.html
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,18 @@
tr:nth-of-type(odd) {
background-color: var(--body-bg);
}

.speaker-multi-submission-badge {
display: inline-block;
background-color: #f0ad4e;
color: #fff;
font-size: 10px;
font-weight: bold;
padding: 2px 6px;
border-radius: 10px;
margin-left: 6px;
vertical-align: middle;
}
</style>

<script type="application/javascript">
Expand Down Expand Up @@ -650,6 +662,7 @@ <h3>Show proposals of type:</h3>
</thead>
<tbody>
{% for item in items %}
{% with speaker_id=item.speaker_id|stringformat:"i" %}
<script>
submissionsById[{{ item.id }}] = {
id: {{ item.id }},
Expand All @@ -661,8 +674,10 @@ <h3>Show proposals of type:</h3>
submissionType: "{{ item.type.name }}",
speakerName: "{{ item.speaker.fullname|escapejs }}",
speakerGender: "{{ item.speaker.gender|default:'unknown' }}",
speakerSubmissionCount: {{ speaker_submission_counts|get_item:speaker_id|default:1 }},
};
</script>
{% endwith %}
<tr class="proposal-item" id="submission-{{item.id}}" data-original-status="{{ item.current_or_pending_status }}">
<td>{{forloop.counter}}</td>
<td class="results-title">
Expand All @@ -676,6 +691,11 @@ <h3>Show proposals of type:</h3>
<li>
<strong>Speaker</strong>
<span class="speaker-name-link" onclick="filterBySpeakerName('{{ item.speaker.fullname|escapejs }}')">{{ item.speaker.fullname }}</span>
{% with submission_count=speaker_submission_counts|get_item:speaker_id %}
{% if submission_count and submission_count > 1 %}
<span class="speaker-multi-submission-badge" title="This speaker has {{ submission_count }} submissions">{{ submission_count }} talks</span>
{% endif %}
{% endwith %}
<button type="button" class="clear-filter-btn speaker-row-clear-btn" onclick="event.stopPropagation(); clearSpeakerFilter();" style="display: none;">Clear filter</button>
</li>
<li>
Expand Down
40 changes: 40 additions & 0 deletions backend/reviews/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,8 +833,48 @@ def test_proposals_review_get_recap_context(rf):
assert "review_session_id" in context
assert "audience_levels" in context
assert "all_statuses" in context
assert "speaker_submission_counts" in context
assert context["review_session_id"] == review_session.id
assert str(submission.speaker_id) in context["grants"]
# Verify speaker submission count is tracked
assert str(submission.speaker_id) in context["speaker_submission_counts"]
assert context["speaker_submission_counts"][str(submission.speaker_id)] == 1


def test_proposals_review_get_recap_context_with_multiple_submissions_per_speaker(rf):
user = UserFactory(is_staff=True, is_superuser=True)
conference = ConferenceFactory()

review_session = ReviewSessionFactory(
conference=conference,
session_type=ReviewSession.SessionType.PROPOSALS,
status=ReviewSession.Status.COMPLETED,
)
AvailableScoreOptionFactory(review_session=review_session, numeric_value=0)
AvailableScoreOptionFactory(review_session=review_session, numeric_value=1)

# Create a speaker with multiple submissions
speaker = UserFactory()
submission_1 = SubmissionFactory(conference=conference, speaker=speaker)
submission_2 = SubmissionFactory(conference=conference, speaker=speaker)
submission_3 = SubmissionFactory(conference=conference, speaker=speaker)

# Create another speaker with only one submission
single_speaker = UserFactory()
single_submission = SubmissionFactory(conference=conference, speaker=single_speaker)

request = rf.get("/")
request.user = user

adapter = get_review_adapter(review_session)
items = adapter.get_recap_items_queryset(review_session).all()
context = adapter.get_recap_context(request, review_session, items, AdminSite())

assert "speaker_submission_counts" in context
# Speaker with 3 submissions should have count of 3
assert context["speaker_submission_counts"][str(speaker.id)] == 3
# Speaker with 1 submission should have count of 1
assert context["speaker_submission_counts"][str(single_speaker.id)] == 1


def test_proposals_review_process_recap_post(rf):
Expand Down
Loading