refactor: align views with upstream @indiekit/frontend patterns

- Extract ~560 lines of inline CSS to external assets/styles.css
- Create intermediate layout (layouts/blogroll.njk) for CSS loading
- Use section(), badge(), button(), prose() macros instead of raw HTML
- Remove custom page headers (document.njk heading() handles via title/parent)
- Add parent breadcrumb navigation to all sub-pages
- Add consumeFlashMessage() to dashboard and sources controllers
- Rename CSS class prefix from br-* to blogroll-* for clarity
- Use upstream CSS custom properties without fallback values
- Fix Microsub orphan detection (soft-delete unsubscribed blogs)
- Fix upsert to conditionally set microsub fields (avoid path conflicts)
- Skip soft-deleted blogs during clear-and-resync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-12 18:42:27 +01:00
parent 87851bade2
commit 4ad4c13bbc
14 changed files with 722 additions and 925 deletions

View File

@@ -38,6 +38,9 @@ async function get(request, response) {
const errorBlogs = await getBlogs(application, { includeHidden: true, limit: 100 });
const blogsWithErrors = errorBlogs.filter((b) => b.status === "error");
// Extract flash messages for native Indiekit notification banner
const flash = consumeFlashMessage(request);
response.render("blogroll-dashboard", {
title: request.__("blogroll.title"),
sources,
@@ -51,6 +54,7 @@ async function get(request, response) {
syncStatus,
blogsWithErrors: blogsWithErrors.slice(0, 5),
baseUrl: request.baseUrl,
...flash,
});
} catch (error) {
console.error("[Blogroll] Dashboard error:", error);
@@ -151,6 +155,21 @@ async function status(request, response) {
}
}
/**
* Extract and clear flash messages from session
* Returns { success, error } for Indiekit's native notificationBanner
*/
function consumeFlashMessage(request) {
const result = {};
if (request.session?.messages?.length) {
const msg = request.session.messages[0];
if (msg.type === "success") result.success = msg.content;
else if (msg.type === "error" || msg.type === "warning") result.error = msg.content;
request.session.messages = null;
}
return result;
}
export const dashboardController = {
get,
sync,