From 8f623bc319d6385bbaedd1bf8fb70ec59bd8bd48 Mon Sep 17 00:00:00 2001
From: pitoi
Date: Sun, 24 May 2026 17:17:33 +0000
Subject: [PATCH] Generated with Hive: Display publish date as relative time on
feed cards and node detail panel
---
src/components/feed/feed-card.tsx | 2 +-
src/components/layout/node-preview-panel.tsx | 20 +++++++++-------
src/lib/__tests__/node-preview-panel.test.tsx | 23 +++++++++++++------
3 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/src/components/feed/feed-card.tsx b/src/components/feed/feed-card.tsx
index 7ca1663..6e7e753 100644
--- a/src/components/feed/feed-card.tsx
+++ b/src/components/feed/feed-card.tsx
@@ -38,7 +38,7 @@ export function FeedCard({ node, schemas, selected, onSelect, onHover }: FeedCar
const avatar = pickString(p, "image_url") || thumb
const handle = pickString(p, "twitter_handle")
const type = node.node_type ?? "Unknown"
- const when = timeAgo(typeof p.date === "number" ? p.date : node.date_added_to_graph)
+ const when = timeAgo(p.date ?? p.published_date)
return (
{title}
+ {/* Publish / air date — omitted when no date field is present */}
+ {(props.date != null || props.published_date != null) && (
+ (() => {
+ const rel = formatDateRelative(props.date ?? props.published_date)
+ return rel ? (
+ {rel}
+ ) : null
+ })()
+ )}
+
{/* Description (suppressed when a rich widget already renders this field) */}
{description && !widgetCoversDescription && (
{description}
@@ -1290,15 +1300,12 @@ export function NodePreviewPanel({ node, onBack, schemas }: NodePreviewPanelProp
{/* Core properties row */}
{(() => {
const statusBadge = getStatusBadge(fp.status)
- const dateStr = typeof fp.date_added_to_graph === "string" && fp.date_added_to_graph
- ? new Date(fp.date_added_to_graph).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
- : null
const sats = typeof fp.boost === "number" && fp.boost > 0
? fp.boost
: typeof fp.num_boost === "number" && fp.num_boost > 0
? fp.num_boost
: null
- if (!statusBadge && !dateStr && sats === null) return null
+ if (!statusBadge && sats === null) return null
return (
{statusBadge && (
@@ -1306,9 +1313,6 @@ export function NodePreviewPanel({ node, onBack, schemas }: NodePreviewPanelProp
{statusBadge.label}
)}
- {dateStr && (
-
{dateStr}
- )}
{sats !== null && (
diff --git a/src/lib/__tests__/node-preview-panel.test.tsx b/src/lib/__tests__/node-preview-panel.test.tsx
index 48b2023..baf0d9c 100644
--- a/src/lib/__tests__/node-preview-panel.test.tsx
+++ b/src/lib/__tests__/node-preview-panel.test.tsx
@@ -156,6 +156,12 @@ function makeGraphData(node: GraphNode) {
return { nodes: [node], edges: [] }
}
+// jsdom doesn't implement Element.prototype.scrollTo — stub it so navigation
+// tests that trigger handleNavigate don't throw uncaught exceptions.
+if (typeof Element.prototype.scrollTo !== "function") {
+ Element.prototype.scrollTo = () => undefined
+}
+
// Reset graph store mocks before each test so history navigation tests don't bleed
beforeEach(() => {
mockGraphNodes = []
@@ -399,15 +405,18 @@ describe("NodePreviewPanel – core property rendering", () => {
})
})
- it("shows formatted date when date_added_to_graph is present", async () => {
- const node = makeUnlockedNode({ date_added_to_graph: "2025-04-18" })
- mockApiGet.mockResolvedValue(makeGraphData(node))
+ it("shows publish date when date property is present", () => {
+ const node: GraphNode = {
+ ...BASE_NODE,
+ properties: { ...BASE_NODE.properties, date: 1745020800 },
+ }
+ render()
+ expect(screen.getByText(/ago/i)).toBeInTheDocument()
+ })
+ it("shows no date when neither date nor published_date is present", () => {
render()
-
- await waitFor(() => {
- expect(screen.getByText("Apr 18, 2025")).toBeInTheDocument()
- })
+ expect(screen.queryByText(/ago/i)).not.toBeInTheDocument()
})
it("shows sats counter when boost is a positive number", async () => {