Admin: tabbed operator console (Overview/Content/Sources/Audience/Feedback)
Reshape the long single-page dashboard into a sectioned console (one route, ?section= tabs, sticky subnav) focused on "what needs my attention" first. * Overview: an "Attention Needed" strip (soft amber/blue, never alarming red) derived from the same data — sources resting/flagged, image coverage <70%, thin brief, recent feedback — plus at-a-glance pulse cards. * Content: corpus health + image/summary coverage (with_image, summaries_with_ image, brief image coverage, 24h image misses) + top opened / topics / tags. * Sources: filterable table (All/Healthy/Resting/Flagged) — served, last success, next poll, failure streak, status — instead of a card pile. * Audience: visitors, retention, accounts, funnel, sharing, daily trend. * Feedback: inbox with category filter, newest first, quick mailto reply. Backend: content_stats gains added_7d + image-coverage fields; source_health gains review_flag; admin_stats adds attention[] + feedback_7d. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,3 +47,28 @@ def test_source_health_orders_failing_first_and_computes_next_due(tmp_path):
|
||||
assert flaky["next_due_at"] is not None
|
||||
good = next(s for s in sh if s["name"] == "Good")
|
||||
assert good["served"] == 1 and good["next_due_at"] is None # never attempted → due now
|
||||
|
||||
|
||||
def test_attention_flags_resting_flagged_and_brief():
|
||||
from goodnews import queries
|
||||
content = {"served": 100, "with_image": 90, "latest_brief_size": 5}
|
||||
sources = [
|
||||
{"failures": 3, "review_flag": 0},
|
||||
{"failures": 0, "review_flag": 1},
|
||||
{"failures": 0, "review_flag": 0},
|
||||
]
|
||||
items = queries._attention(content, sources, feedback_7d=2)
|
||||
texts = " | ".join(i["text"] for i in items)
|
||||
assert "1 source backing off" in texts # one resting
|
||||
assert "1 source flagged" in texts # one flagged
|
||||
assert "brief has only 5" in texts # brief < 7
|
||||
assert "2 feedback" in texts # recent feedback
|
||||
# 90/100 = 90% image coverage → no coverage warning
|
||||
assert "Image coverage" not in texts
|
||||
|
||||
|
||||
def test_attention_clear_when_healthy():
|
||||
from goodnews import queries
|
||||
content = {"served": 100, "with_image": 95, "latest_brief_size": 7}
|
||||
sources = [{"failures": 0, "review_flag": 0}]
|
||||
assert queries._attention(content, sources, feedback_7d=0) == []
|
||||
|
||||
Reference in New Issue
Block a user