This commit is contained in:
dgtlmoon
2026-01-06 17:52:21 +01:00
parent 237f08b8ed
commit 286da3b810
4 changed files with 103 additions and 16 deletions
@@ -22,25 +22,40 @@ def construct_blueprint():
get_retry_config
)
# Get filter parameter from query string
filter_status = request.args.get('filter', '').lower()
valid_filters = ['delivered', 'queued', 'retrying', 'failed']
# Validate filter
if filter_status and filter_status not in valid_filters:
filter_status = ''
# Get all notification events (delivered, queued, retrying, failed)
events = get_all_notification_events(limit=100)
all_events = get_all_notification_events(limit=100)
# Get retry configuration for display
retry_config = get_retry_config()
# Count by status for summary
# Count by status for summary (always show all counts)
status_counts = {
'delivered': sum(1 for e in events if e['status'] == 'delivered'),
'queued': sum(1 for e in events if e['status'] == 'queued'),
'retrying': sum(1 for e in events if e['status'] == 'retrying'),
'failed': sum(1 for e in events if e['status'] == 'failed')
'delivered': sum(1 for e in all_events if e['status'] == 'delivered'),
'queued': sum(1 for e in all_events if e['status'] == 'queued'),
'retrying': sum(1 for e in all_events if e['status'] == 'retrying'),
'failed': sum(1 for e in all_events if e['status'] == 'failed')
}
# Filter events if a filter is active
if filter_status:
events = [e for e in all_events if e['status'] == filter_status]
else:
events = all_events
return render_template(
'notification-dashboard.html',
events=events,
retry_config=retry_config,
status_counts=status_counts
status_counts=status_counts,
active_filter=filter_status
)
@notification_dashboard.route("/log/<task_id>", methods=['GET'])
@@ -8,18 +8,36 @@
<!-- Summary Stats -->
<div class="event-summary">
<span class="stat-item">
<a href="{{ url_for('notification_dashboard.dashboard', filter='delivered') }}"
class="stat-item stat-filter-link {% if active_filter == 'delivered' %}stat-filter-active{% endif %}"
title="Show only delivered notifications">
<span class="stat-badge stat-delivered">{{ status_counts.delivered }}</span> Delivered
</span>
<span class="stat-item">
</a>
<a href="{{ url_for('notification_dashboard.dashboard', filter='queued') }}"
class="stat-item stat-filter-link {% if active_filter == 'queued' %}stat-filter-active{% endif %}"
title="Show only queued notifications">
<span class="stat-badge stat-queued">{{ status_counts.queued }}</span> Queued
</span>
<span class="stat-item">
</a>
<a href="{{ url_for('notification_dashboard.dashboard', filter='retrying') }}"
class="stat-item stat-filter-link {% if active_filter == 'retrying' %}stat-filter-active{% endif %}"
title="Show only retrying notifications">
<span class="stat-badge stat-retrying">{{ status_counts.retrying }}</span> Retrying
</span>
<span class="stat-item">
</a>
<a href="{{ url_for('notification_dashboard.dashboard', filter='failed') }}"
class="stat-item stat-filter-link {% if active_filter == 'failed' %}stat-filter-active{% endif %}"
title="Show only failed notifications">
<span class="stat-badge stat-failed">{{ status_counts.failed }}</span> Failed
</span>
</a>
{% if active_filter %}
<a href="{{ url_for('notification_dashboard.dashboard') }}"
class="stat-item stat-clear-filter"
title="Clear filter and show all notifications">
<svg width="14" height="14" viewBox="0 0 16 16" style="vertical-align: middle; margin-right: 4px;">
<path d="M4 4l8 8m0-8l-8 8" stroke="currentColor" stroke-width="2"/>
</svg>
Clear Filter
</a>
{% endif %}
</div>
<!-- Action Buttons -->
@@ -658,6 +658,60 @@
}
}
}
// Clickable filter links
.stat-filter-link {
text-decoration: none;
cursor: pointer;
padding: 6px 12px;
border-radius: 8px;
transition: all 0.15s ease;
&:hover {
background: rgba(0, 120, 231, 0.08);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
// Active filter state
&.stat-filter-active {
background: rgba(0, 120, 231, 0.15);
border: 2px solid #0078e7;
padding: 4px 10px; // Adjust for border
.stat-badge {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}
}
}
// Clear filter link
.stat-clear-filter {
display: flex;
align-items: center;
gap: 6px;
text-decoration: none;
padding: 6px 12px;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
color: var(--color-link);
background: rgba(108, 117, 125, 0.1);
transition: all 0.15s ease;
&:hover {
background: rgba(108, 117, 125, 0.2);
transform: translateY(-1px);
}
svg {
width: 14px;
height: 14px;
}
}
}
// Action buttons
File diff suppressed because one or more lines are too long