v52: simplify feed row: status, count, path, title inline

This commit is contained in:
primal
2026-01-30 16:49:38 -05:00
parent 6c9702eebc
commit 442e010672
3 changed files with 28 additions and 17 deletions
+7 -2
View File
@@ -137,6 +137,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
PublishStatus string `json:"publish_status,omitempty"` PublishStatus string `json:"publish_status,omitempty"`
Language string `json:"language,omitempty"` Language string `json:"language,omitempty"`
ItemCount int `json:"item_count,omitempty"`
} }
type DomainInfo struct { type DomainInfo struct {
@@ -165,7 +166,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
// Now get feeds for these domains // Now get feeds for these domains
if len(hosts) > 0 { if len(hosts) > 0 {
feedRows, err := c.db.Query(` feedRows, err := c.db.Query(`
SELECT source_host, url, title, type, status, publish_status, language SELECT source_host, url, title, type, status, publish_status, language, item_count
FROM feeds FROM feeds
WHERE source_host = ANY($1) WHERE source_host = ANY($1)
ORDER BY source_host, url ORDER BY source_host, url
@@ -177,7 +178,8 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
var host string var host string
var f FeedInfo var f FeedInfo
var title, feedType, status, publishStatus, language *string var title, feedType, status, publishStatus, language *string
if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus, &language); err != nil { var itemCount *int
if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus, &language, &itemCount); err != nil {
continue continue
} }
f.Title = StringValue(title) f.Title = StringValue(title)
@@ -185,6 +187,9 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
f.Status = StringValue(status) f.Status = StringValue(status)
f.PublishStatus = StringValue(publishStatus) f.PublishStatus = StringValue(publishStatus)
f.Language = StringValue(language) f.Language = StringValue(language)
if itemCount != nil {
f.ItemCount = *itemCount
}
feedsByHost[host] = append(feedsByHost[host], f) feedsByHost[host] = append(feedsByHost[host], f)
} }
// Attach feeds to domains // Attach feeds to domains
+20 -14
View File
@@ -132,43 +132,49 @@ function initDashboard() {
html += '</div>'; html += '</div>';
// Feeds under this domain (hidden by default, toggled by clicking domain name) // Feeds under this domain (hidden by default, toggled by clicking spacer)
if (d.feeds && d.feeds.length > 0) { if (d.feeds && d.feeds.length > 0) {
html += '<div class="domain-feeds" style="display: none; margin-left: 20px; border-left: 2px solid #333; padding-left: 10px;">'; html += '<div class="domain-feeds" style="display: none; margin-left: 20px; border-left: 2px solid #333; padding-left: 10px;">';
d.feeds.forEach(f => { d.feeds.forEach(f => {
const feedStatus = f.publish_status || 'hold'; const feedStatus = f.publish_status || 'hold';
const feedHasError = f.status === 'error' || f.status === 'dead';
html += `<div class="inline-feed-block" data-url="${escapeHtml(f.url)}" data-status="${feedStatus}">`; html += `<div class="inline-feed-block" data-url="${escapeHtml(f.url)}" data-status="${feedStatus}">`;
html += `<div class="feed-row" style="display: flex; align-items: center; padding: 4px 0; font-size: 12px;">`; html += `<div class="feed-row" style="display: flex; align-items: center; padding: 4px 0; font-size: 12px;">`;
// Language indicator (fixed width) // Language indicator (fixed width)
const lang = f.language || ''; const lang = f.language || '';
html += `<span style="display: inline-block; width: 32px; margin-right: 6px; color: #666; font-size: 10px; font-family: monospace; text-align: center;">${escapeHtml(lang)}</span>`; html += `<span style="display: inline-block; width: 32px; margin-right: 6px; color: #666; font-size: 10px; font-family: monospace; text-align: center;">${escapeHtml(lang)}</span>`;
// Feed status buttons // Feed publish status buttons (pass/hold/skip)
html += renderStatusBtns(feedStatus, 'feed', f.url, f.status); html += renderStatusBtns(feedStatus, 'feed', f.url, f.status);
// Feed path + title // Feed crawl status (active/error/dead)
const statusColor = f.status === 'active' ? '#484' : f.status === 'error' ? '#a66' : '#666';
html += `<span style="color: ${statusColor}; font-size: 10px; font-family: monospace; width: 40px; margin-right: 6px;">${escapeHtml(f.status || 'active')}</span>`;
// Item count if > 0
if (f.item_count > 0) {
html += `<span style="color: #888; font-size: 10px; font-family: monospace; width: 50px; margin-right: 6px; text-align: right;">${commaFormat(f.item_count)}</span>`;
} else {
html += `<span style="width: 50px; margin-right: 6px;"></span>`;
}
// Feed path (URL without domain)
let feedPath = f.url; let feedPath = f.url;
try { try {
const urlObj = new URL(f.url.startsWith('http') ? f.url : 'https://' + f.url); const urlObj = new URL(f.url.startsWith('http') ? f.url : 'https://' + f.url);
feedPath = urlObj.pathname + urlObj.search; feedPath = urlObj.pathname + urlObj.search;
} catch (e) {} } catch (e) {}
const displayText = f.title ? `${feedPath} - ${f.title}` : feedPath; html += `<span style="color: #0af; font-size: 11px; margin-right: 8px; white-space: nowrap;" title="${escapeHtml(f.url)}">${escapeHtml(feedPath)}</span>`;
html += `<span class="feed-title" style="color: #fff; cursor: pointer; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="${escapeHtml(f.url)}">${escapeHtml(displayText)}</span>`;
// Feed type // Feed title
if (f.type) { if (f.title) {
html += `<span style="color: #555; margin-left: 8px; font-size: 10px;">${escapeHtml(f.type)}</span>`; html += `<span style="color: #fff; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${escapeHtml(f.title)}</span>`;
} else {
html += '<span style="flex: 1;"></span>';
} }
html += '</div>'; html += '</div>';
// Collapsible detail section
html += '<div class="feed-detail" style="display: none; padding: 8px 0 8px 10px; border-left: 2px solid #444; margin-left: 10px; background: #0a0a0a;"></div>';
html += '</div>'; html += '</div>';
}); });
html += '</div>'; html += '</div>';
+1 -1
View File
@@ -534,7 +534,7 @@ const dashboardHTML = `<!DOCTYPE html>
<div id="output"></div> <div id="output"></div>
</div> </div>
<div style="color: #333; font-size: 11px; margin-top: 10px;">v51</div> <div style="color: #333; font-size: 11px; margin-top: 10px;">v52</div>
<div class="updated" id="updatedAt">Last updated: {{.UpdatedAt.Format "2006-01-02 15:04:05"}}</div> <div class="updated" id="updatedAt">Last updated: {{.UpdatedAt.Format "2006-01-02 15:04:05"}}</div>
</body> </body>