Admin polish: section fallback, live-scoped coverage, dual source status
Per Codex audit: * Unknown ?section= values now clamp to Overview, so the page never renders the tabs with an empty body. * Summary/image coverage counts join through articles+scores and require accepted=1 AND duplicate_of IS NULL, so percentages stay ≤100% and honest as rejected/duplicate rows accrue summaries over time. * A source that's both resting and flagged now shows "⚠ resting · review" rather than hiding the review flag behind the resting state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,11 @@
|
|||||||
{ key: 'audience', label: 'Audience' },
|
{ key: 'audience', label: 'Audience' },
|
||||||
{ key: 'feedback', label: 'Feedback' },
|
{ key: 'feedback', label: 'Feedback' },
|
||||||
];
|
];
|
||||||
let section = $derived($page.url.searchParams.get('section') || 'overview');
|
const VALID_SECTIONS = new Set(TABS.map((t) => t.key));
|
||||||
|
// Unknown ?section= values fall back to Overview so the page never renders blank.
|
||||||
|
let section = $derived(
|
||||||
|
VALID_SECTIONS.has($page.url.searchParams.get('section')) ? $page.url.searchParams.get('section') : 'overview'
|
||||||
|
);
|
||||||
|
|
||||||
function fdate(s) {
|
function fdate(s) {
|
||||||
try { return new Date(s + 'Z').toLocaleDateString(undefined, { month: 'short', day: 'numeric' }); }
|
try { return new Date(s + 'Z').toLocaleDateString(undefined, { month: 'short', day: 'numeric' }); }
|
||||||
@@ -208,7 +212,7 @@
|
|||||||
<td class="dim">{fwhen(s.next_due_at)}</td>
|
<td class="dim">{fwhen(s.next_due_at)}</td>
|
||||||
<td class="num">{s.failures || ''}</td>
|
<td class="num">{s.failures || ''}</td>
|
||||||
<td class="status">
|
<td class="status">
|
||||||
{#if s.failures > 0}<span class="bad" title={s.last_error || ''}>⚠ resting</span>
|
{#if s.failures > 0}<span class="bad" title={s.last_error || ''}>⚠ resting{#if s.review_flag} · review{/if}</span>
|
||||||
{:else if s.review_flag}<span class="flagtxt">⚑ review</span>
|
{:else if s.review_flag}<span class="flagtxt">⚑ review</span>
|
||||||
{:else}<span class="good">✓ ok</span>{/if}
|
{:else}<span class="good">✓ ok</span>{/if}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
+8
-2
@@ -237,10 +237,16 @@ def content_stats(conn: sqlite3.Connection) -> dict:
|
|||||||
"SELECT COUNT(*) FROM article_scores s JOIN articles a ON a.id=s.article_id "
|
"SELECT COUNT(*) FROM article_scores s JOIN articles a ON a.id=s.article_id "
|
||||||
"WHERE s.accepted=1 AND a.duplicate_of IS NULL AND a.image_url IS NOT NULL AND a.image_url!=''"
|
"WHERE s.accepted=1 AND a.duplicate_of IS NULL AND a.image_url IS NOT NULL AND a.image_url!=''"
|
||||||
)
|
)
|
||||||
summaries = scalar("SELECT COUNT(*) FROM article_summaries")
|
# Coverage is scoped to LIVE articles (accepted, non-duplicate) so the
|
||||||
|
# percentages can't drift past 100% as rejected/duplicate rows accrue summaries.
|
||||||
|
summaries = scalar(
|
||||||
|
"SELECT COUNT(*) FROM article_summaries m JOIN articles a ON a.id=m.article_id "
|
||||||
|
"JOIN article_scores s ON s.article_id=a.id WHERE s.accepted=1 AND a.duplicate_of IS NULL"
|
||||||
|
)
|
||||||
summaries_with_image = scalar(
|
summaries_with_image = scalar(
|
||||||
"SELECT COUNT(*) FROM article_summaries m JOIN articles a ON a.id=m.article_id "
|
"SELECT COUNT(*) FROM article_summaries m JOIN articles a ON a.id=m.article_id "
|
||||||
"WHERE a.image_url IS NOT NULL AND a.image_url!=''"
|
"JOIN article_scores s ON s.article_id=a.id WHERE s.accepted=1 AND a.duplicate_of IS NULL "
|
||||||
|
"AND a.image_url IS NOT NULL AND a.image_url!=''"
|
||||||
)
|
)
|
||||||
brief_with_image = 0
|
brief_with_image = 0
|
||||||
if brief:
|
if brief:
|
||||||
|
|||||||
Reference in New Issue
Block a user