/**
* PDF / HTML locator comments. Port of app.js:10835-10897.
*/
import { currentId } from "../stores/session";
import { api, apiErrorText } from "../features/artifacts/api";
import { artUrl } from "../features/artifacts/cache";
import type { ArtifactRow } from "../features/artifacts/types";
import { hint } from "../features/sessions/chrome";
import { el } from "./dom";
import { translate } from "./host";
import { loadAnnotations } from "./annot";
type PdfPage = { page?: number; text?: string };
export function renderLocatorComments(
container: HTMLElement,
a: ArtifactRow,
kind: string,
viewer?: HTMLIFrameElement | null,
): void {
const box = el("div", "wb-locator");
box.appendChild(el("div", "wb-locator-title", translate("wb.locator.title")));
const quote = el("textarea", "wb-locator-quote");
quote.placeholder = translate("wb.locator.quote");
const selector = el("input", "wb-locator-selector");
selector.placeholder = translate("wb.locator.selector");
const comment = el("textarea", "wb-locator-body");
comment.placeholder = translate("wb.locator.body");
const save = el("button", "solid-btn small", translate("common.save"));
const preview = el("pre", "wb-locator-preview");
let pdfPage: HTMLInputElement | null = null;
let pdfPages: PdfPage[] = [];
const selectPdfPage = (value: unknown): number => {
if (!pdfPage) return 1;
const page = Math.max(1, Math.floor(Number(value) || 1));
pdfPage.value = String(page);
if (viewer && viewer.dataset.currentPage !== String(page)) {
const base = String(viewer.src || artUrl(a)).split("#", 1)[0];
viewer.dataset.currentPage = String(page);
viewer.src = base + "#page=" + encodeURIComponent(String(page));
}
const extracted = pdfPages.find((item) => Number(item && item.page) === page);
preview.textContent = extracted ? String(extracted.text || "").slice(0, 4000) : "";
return page;
};
if (kind === "pdf") {
const pageControls = el("div", "wb-pdf-page-controls");
const label = el("label", "wb-pdf-page-label", translate("wb.locator.pdfPage"));
pdfPage = el("input", "wb-pdf-page");
pdfPage.type = "number";
pdfPage.min = "1";
pdfPage.step = "1";
pdfPage.value = "1";
label.appendChild(pdfPage);
pageControls.appendChild(label);
const previous = el("button", "outline-btn small", translate("wb.locator.pdfPrev"));
previous.type = "button";
const next = el("button", "outline-btn small", translate("wb.locator.pdfNext"));
next.type = "button";
previous.onclick = () => selectPdfPage(Number(pdfPage && pdfPage.value) - 1);
next.onclick = () => selectPdfPage(Number(pdfPage && pdfPage.value) + 1);
pdfPage.onchange = () => selectPdfPage(pdfPage && pdfPage.value);
pageControls.appendChild(previous);
pageControls.appendChild(next);
box.appendChild(pageControls);
}
if (kind === "html") box.appendChild(selector);
box.appendChild(quote);
box.appendChild(comment);
box.appendChild(save);
box.appendChild(preview);
container.appendChild(box);
const endpoint = kind === "pdf" ? "pdf-text" : "html-outline";
api(`/artifacts/${encodeURIComponent(a.id)}/${endpoint}`)
.then((payload) => {
const rec = payload && typeof payload === "object" ? (payload as Record) : {};
if (kind === "pdf") {
pdfPages = Array.isArray(rec.pages) ? (rec.pages as PdfPage[]) : [];
selectPdfPage(pdfPage && pdfPage.value);
} else {
const elements = Array.isArray(rec.elements) ? (rec.elements as Array>) : [];
preview.textContent = elements
.map((item) => (item.selector || item.tag) + " " + (item.text || ""))
.join("\n")
.slice(0, 4000);
}
})
.catch(() => {
preview.textContent = "";
});
save.onclick = async () => {
if (!currentId.value || !String(comment.value || "").trim()) return;
save.disabled = true;
try {
await api(`/frames/${currentId.value}/annotations`, {
method: "POST",
body: JSON.stringify({
artifact_id: a.id,
artifact_name: a.filename,
kind,
body: comment.value,
locator:
kind === "pdf"
? { page: selectPdfPage(pdfPage && pdfPage.value), quote: quote.value }
: { selector: selector.value, quote: quote.value },
}),
});
comment.value = "";
hint(translate("wb.locator.saved"));
if (currentId.value) void loadAnnotations(currentId.value);
} catch (error) {
hint(translate("wb.locator.err", apiErrorText(error)), true);
}
save.disabled = false;
};
}