Feb 02 2026: implement issue unfollow badge on issue list

This commit is contained in:
2026-03-01 21:40:41 -05:00
parent 91ef97d853
commit 68b180c2e4
2 changed files with 51 additions and 7 deletions
+16 -2
View File
@@ -56,10 +56,20 @@ def index():
q = q.filter(Issue.status == status_filter) q = q.filter(Issue.status == status_filter)
issues = q.paginate(page=page, per_page=25, error_out=False) issues = q.paginate(page=page, per_page=25, error_out=False)
# Build a set of issue IDs the current user is following so the template
# can render the following badge and inline unfollow button without an
# additional query per row.
followed_ids = {
f.issue_id
for f in IssueFollower.query.filter_by(user_id=current_user.id).all()
}
return render_template('issues/list.html', return render_template('issues/list.html',
issues=issues, issues=issues,
severity_filter=severity_filter, severity_filter=severity_filter,
status_filter=status_filter) status_filter=status_filter,
followed_ids=followed_ids)
# ── View / Update ───────────────────────────────────────────────────────────── # ── View / Update ─────────────────────────────────────────────────────────────
@@ -276,7 +286,11 @@ def unfollow(issue_id):
flash('You have unfollowed this issue.', 'info') flash('You have unfollowed this issue.', 'info')
else: else:
flash('You are not following this issue.', 'info') flash('You are not following this issue.', 'info')
return redirect(url_for('issues.view', issue_id=issue_id))
# Respect an explicit next URL (e.g. return to the list page).
# Fall back to the issue view if none is provided.
next_url = request.form.get('next') or url_for('issues.view', issue_id=issue_id)
return redirect(next_url)
# ── Standalone create ───────────────────────────────────────────────────────── # ── Standalone create ─────────────────────────────────────────────────────────
+35 -5
View File
@@ -45,11 +45,19 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover mb-0"> <table class="table table-hover mb-0">
<thead class="table-light"> <thead class="table-light">
<tr><th>Reported</th><th>Severity</th><th>Facility / Area</th> <tr>
<th>Description</th><th>Status</th><th>Assigned</th><th></th></tr> <th>Reported</th>
<th>Severity</th>
<th>Facility / Area</th>
<th>Description</th>
<th>Status</th>
<th>Assigned</th>
<th></th>
</tr>
</thead> </thead>
<tbody> <tbody>
{% for issue in issues.items %} {% for issue in issues.items %}
{% set is_following = issue.id in followed_ids %}
<tr> <tr>
<td><small>{{ issue.reported_at.strftime('%Y-%m-%d %H:%M') }}</small></td> <td><small>{{ issue.reported_at.strftime('%Y-%m-%d %H:%M') }}</small></td>
<td> <td>
@@ -71,8 +79,27 @@
{% if issue.assigned_user %}{{ issue.assigned_user.username }} {% if issue.assigned_user %}{{ issue.assigned_user.username }}
{% else %}<span class="text-muted"></span>{% endif %} {% else %}<span class="text-muted"></span>{% endif %}
</td> </td>
<td> <td class="text-nowrap">
<a href="{{ url_for('issues.view', issue_id=issue.id) }}" class="btn btn-sm btn-outline-secondary"> {# Following badge + inline unfollow #}
{% if is_following %}
<span class="badge bg-primary me-1" title="You are following this issue">
<i class="bi bi-bell-fill"></i> Following
</span>
<form method="post"
action="{{ url_for('issues.unfollow', issue_id=issue.id) }}"
class="d-inline"
title="Unfollow this issue">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="next" value="{{ url_for('issues.index', page=issues.page, severity=severity_filter, status=status_filter) }}">
<button type="submit" class="btn btn-sm btn-outline-primary p-0 px-1 me-1"
title="Unfollow">
<i class="bi bi-bell-slash" style="font-size:.75rem;"></i>
</button>
</form>
{% endif %}
<a href="{{ url_for('issues.view', issue_id=issue.id) }}"
class="btn btn-sm btn-outline-secondary">
{% if current_user.role in ['admin','supervisor'] or issue.assigned_to == current_user.id %} {% if current_user.role in ['admin','supervisor'] or issue.assigned_to == current_user.id %}
<i class="bi bi-pencil"></i> Edit <i class="bi bi-pencil"></i> Edit
{% else %} {% else %}
@@ -85,19 +112,22 @@
</tbody> </tbody>
</table> </table>
</div> </div>
{% if issues.pages > 1 %} {% if issues.pages > 1 %}
<div class="d-flex justify-content-center py-3"> <div class="d-flex justify-content-center py-3">
<nav><ul class="pagination pagination-sm mb-0"> <nav><ul class="pagination pagination-sm mb-0">
{% for p in issues.iter_pages(left_edge=1,right_edge=1,left_current=2,right_current=2) %} {% for p in issues.iter_pages(left_edge=1,right_edge=1,left_current=2,right_current=2) %}
{% if p %} {% if p %}
<li class="page-item {{ 'active' if p == issues.page }}"> <li class="page-item {{ 'active' if p == issues.page }}">
<a class="page-link" href="{{ url_for('issues.index', page=p, severity=severity_filter, status=status_filter) }}">{{ p }}</a> <a class="page-link"
href="{{ url_for('issues.index', page=p, severity=severity_filter, status=status_filter) }}">{{ p }}</a>
</li> </li>
{% else %}<li class="page-item disabled"><span class="page-link"></span></li>{% endif %} {% else %}<li class="page-item disabled"><span class="page-link"></span></li>{% endif %}
{% endfor %} {% endfor %}
</ul></nav> </ul></nav>
</div> </div>
{% endif %} {% endif %}
{% else %} {% else %}
<div class="alert alert-info m-3"><i class="bi bi-info-circle"></i> No issues found.</div> <div class="alert alert-info m-3"><i class="bi bi-info-circle"></i> No issues found.</div>
{% endif %} {% endif %}