fix(admin): add Atom feed URL, unify container width, update branding

- Atom feed URL shown in both list and table views (new Atom column)
- Remove container-wide toggle — both views now use max-width 1200px
- Update dashboard title and login title to kill-the-news

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Julien Herr
2026-05-22 18:21:49 +02:00
parent 41f70143d1
commit 780bf6c190
+50 -10
View File
@@ -159,7 +159,7 @@ app.get("/login", (c) => {
/> />
</svg> </svg>
</div> </div>
<h1 class="auth-title">Email to RSS Admin</h1> <h1 class="auth-title">kill-the-news</h1>
{errorMessage && ( {errorMessage && (
<div class="auth-error">{errorMessage}</div> <div class="auth-error">{errorMessage}</div>
)} )}
@@ -337,12 +337,10 @@ app.get("/", async (c) => {
return c.html( return c.html(
<Layout title="Dashboard"> <Layout title="Dashboard">
<div <div class="container fade-in">
class={`container ${view === "table" ? "container-wide" : ""} fade-in`}
>
<div class="header-with-actions"> <div class="header-with-actions">
<div class="header-title"> <div class="header-title">
<h1>Email to RSS Admin</h1> <h1>kill-the-news</h1>
<p>Manage your email newsletter feeds</p> <p>Manage your email newsletter feeds</p>
</div> </div>
<div class="header-actions"> <div class="header-actions">
@@ -469,11 +467,12 @@ app.get("/", async (c) => {
<table class="table table-feeds"> <table class="table table-feeds">
<colgroup> <colgroup>
<col data-col="select" style="width: 44px;" /> <col data-col="select" style="width: 44px;" />
<col data-col="title" style="width: 340px;" /> <col data-col="title" style="width: 280px;" />
<col data-col="feedId" style="width: 160px;" /> <col data-col="feedId" style="width: 150px;" />
<col data-col="email" style="width: 220px;" /> <col data-col="email" style="width: 200px;" />
<col data-col="rss" style="width: 220px;" /> <col data-col="rss" style="width: 190px;" />
<col data-col="actions" style="width: 200px;" /> <col data-col="atom" style="width: 190px;" />
<col data-col="actions" style="width: 170px;" />
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>
@@ -572,6 +571,24 @@ app.get("/", async (c) => {
title="Resize" title="Resize"
></div> ></div>
</th> </th>
<th class="th-resizable" data-sort-key="atom" aria-sort="none">
<button
type="button"
class="th-button"
data-sort-key="atom"
>
Atom
<span
class="sort-indicator"
aria-hidden="true"
></span>
</button>
<div
class="col-resizer"
data-col="atom"
title="Resize"
></div>
</th>
<th class="th-resizable"> <th class="th-resizable">
<span>Actions</span> <span>Actions</span>
<div <div
@@ -586,12 +603,14 @@ app.get("/", async (c) => {
{feedsWithConfig.map((feed) => { {feedsWithConfig.map((feed) => {
const emailAddress = `${feed.id}@${env.DOMAIN}`; const emailAddress = `${feed.id}@${env.DOMAIN}`;
const rssUrl = `https://${env.DOMAIN}/rss/${feed.id}`; const rssUrl = `https://${env.DOMAIN}/rss/${feed.id}`;
const atomUrl = `https://${env.DOMAIN}/atom/${feed.id}`;
const titleDisplay = clampText(feed.title, 160); const titleDisplay = clampText(feed.title, 160);
const titleHover = clampText(feed.title, 1000); const titleHover = clampText(feed.title, 1000);
const sortTitle = titleHover.toLowerCase(); const sortTitle = titleHover.toLowerCase();
const sortFeedId = feed.id.toLowerCase(); const sortFeedId = feed.id.toLowerCase();
const sortEmail = emailAddress.toLowerCase(); const sortEmail = emailAddress.toLowerCase();
const sortRss = rssUrl.toLowerCase(); const sortRss = rssUrl.toLowerCase();
const sortAtom = atomUrl.toLowerCase();
const descDisplay = clampText(feed.description || "", 220); const descDisplay = clampText(feed.description || "", 220);
const descHover = clampText(feed.description || "", 1000); const descHover = clampText(feed.description || "", 1000);
const searchHaystack = const searchHaystack =
@@ -606,6 +625,7 @@ app.get("/", async (c) => {
data-sort-feed-id={sortFeedId} data-sort-feed-id={sortFeedId}
data-sort-email={sortEmail} data-sort-email={sortEmail}
data-sort-rss={sortRss} data-sort-rss={sortRss}
data-sort-atom={sortAtom}
> >
<td> <td>
<input <input
@@ -639,6 +659,9 @@ app.get("/", async (c) => {
<td> <td>
<CopyFieldInline value={rssUrl} /> <CopyFieldInline value={rssUrl} />
</td> </td>
<td>
<CopyFieldInline value={atomUrl} />
</td>
<td> <td>
<div class="row-actions"> <div class="row-actions">
<a <a
@@ -691,6 +714,7 @@ app.get("/", async (c) => {
{feedsWithConfig.map((feed) => { {feedsWithConfig.map((feed) => {
const emailAddress = `${feed.id}@${env.DOMAIN}`; const emailAddress = `${feed.id}@${env.DOMAIN}`;
const rssUrl = `https://${env.DOMAIN}/rss/${feed.id}`; const rssUrl = `https://${env.DOMAIN}/rss/${feed.id}`;
const atomUrl = `https://${env.DOMAIN}/atom/${feed.id}`;
const titleDisplay = clampText(feed.title, 140); const titleDisplay = clampText(feed.title, 140);
const titleHover = clampText(feed.title, 1000); const titleHover = clampText(feed.title, 1000);
const descDisplay = clampText(feed.description || "", 240); const descDisplay = clampText(feed.description || "", 240);
@@ -748,6 +772,22 @@ app.get("/", async (c) => {
</div> </div>
</div> </div>
</div> </div>
<div class="copyable">
<span class="copyable-label">Atom Feed:</span>
<div class="copyable-content">
<span
class="copyable-value"
data-copy={atomUrl}
title={atomUrl}
>
{atomUrl}
</span>
<div class="copy-icon-container">
<CopyIcon />
<CheckIcon />
</div>
</div>
</div>
</div> </div>
<div class="feed-buttons"> <div class="feed-buttons">