From 44f35e9e81b36055b8eb381c0db455d9ee2f89d4 Mon Sep 17 00:00:00 2001 From: nicocayo Date: Mon, 29 Jun 2026 16:56:45 +0000 Subject: [PATCH] Generated with Hive: Render image preview for image_url changes in node review proposed changes --- src/components/admin/review-row.tsx | 25 ++++++++- src/lib/__tests__/reviews.test.tsx | 81 +++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/components/admin/review-row.tsx b/src/components/admin/review-row.tsx index e8a3d8c..b923dbd 100644 --- a/src/components/admin/review-row.tsx +++ b/src/components/admin/review-row.tsx @@ -18,6 +18,29 @@ import { Checkbox } from "@/components/ui/checkbox" import type { SchemaNode } from "@/lib/schema-types" import { DISPLAY_KEY_FALLBACKS, pickString } from "@/lib/node-display" import { useUserStore } from "@/stores/user-store" + +const IMAGE_FIELD_KEY = "image_url" + +function ProposedChangeValue({ fieldKey, value }: { fieldKey: string; value: unknown }) { + const [imgError, setImgError] = useState(false) + const strValue = String(value) + + if (fieldKey === IMAGE_FIELD_KEY && typeof value === "string" && value.length > 0 && !imgError) { + return ( +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + image preview setImgError(true)} + /> +
+ ) + } + + return {strValue} +} import { useGraphStore } from "@/stores/graph-store" // ── Status badge ────────────────────────────────────────────────────────────── @@ -1001,7 +1024,7 @@ export function ReviewRow({ {changedEntries.map(([k, v]) => ( <> {k} - {String(v)} + ))} diff --git a/src/lib/__tests__/reviews.test.tsx b/src/lib/__tests__/reviews.test.tsx index 83117a1..fcc72b8 100644 --- a/src/lib/__tests__/reviews.test.tsx +++ b/src/lib/__tests__/reviews.test.tsx @@ -761,6 +761,87 @@ describe("ReviewRow", () => { expect(getByText("Node Being Edited")).toBeTruthy() }) + // ── edit_node image_url preview ─────────────────────────────────────────── + + it("edit_node image_url change renders an img with the proposed URL as src", async () => { + const user = userEvent.setup() + const imgUrl = "https://example.com/photo.jpg" + const { getByText, container } = render( + + ) + await user.click(getByText("Edit Alice")) + const img = container.querySelector("img[alt='image preview']") as HTMLImageElement + expect(img).toBeTruthy() + expect(img.src).toBe(imgUrl) + }) + + it("edit_node non-image properties still render as plain text", async () => { + const user = userEvent.setup() + const { getByText } = render( + + ) + await user.click(getByText("Edit Bob")) + expect(getByText("Bob Updated")).toBeTruthy() + }) + + it("edit_node image_url falls back to URL string on image load error", async () => { + const user = userEvent.setup() + const brokenUrl = "https://example.invalid/content-c5-broken.jpg" + const { getByText, container } = render( + + ) + await user.click(getByText("Edit Charlie")) + // Trigger the error handler + const img = container.querySelector("img[alt='image preview']") as HTMLImageElement + expect(img).toBeTruthy() + fireEvent.error(img) + // After error, the img should be replaced by the raw URL string + expect(getByText(brokenUrl)).toBeTruthy() + expect(container.querySelector("img[alt='image preview']")).toBeNull() + }) + // ── add_schema_node_type ────────────────────────────────────────────────── it("renders add_schema_node_type row without crashing with valid payload", () => {