Files
OmniRoute/src/shared/components/JsonTreeExpandControls.tsx
Markus Hartung 5684589ce7 feat(dashboard): collapsible JSON tree viewer for request/response payloads (#11703)
Resynced onto the release tip. Two fixes applied during boarding: (1) the branch forked before the recent optionalDependencies placement of @huggingface/transformers and onnxruntime-node — its own diff re-added both into "dependencies" as duplicates alongside the real new dependency (react18-json-view); removed the duplicates, ran npm install to sync the lockfile. (2) config/quality/dependency-allowlist.json referenced the wrong package name (react-json-view-lite, an earlier iteration per the PR body) — the code actually imports react18-json-view; fixed the allowlist entry to match. RequestLoggerDetail.tsx crossed its frozen file-size cap (1018->1111); rebaselined with a note — the PR does split out the new logic (RequestLoggerDetail.sections.tsx, JsonTreeExpandControls.tsx, useTimestampTitles.ts, jsonTreeExpandStore.ts, all well under cap), the growth here is irreducible wiring. typecheck:core, check:dashboard-typecheck, check:file-size, check-deps all green after resync; 8/8 vitest + 11/11 native tests pass. Nice, well-structured 6-commit feature with full i18n and good test coverage. Thanks!
2026-08-30 04:26:15 -03:00

70 lines
2.4 KiB
TypeScript

"use client";
import { useTranslations } from "next-intl";
import useJsonTreeExpandStore, { useJsonTreeExpandLevel } from "@/store/jsonTreeExpandStore";
interface JsonTreeExpandControlsProps {
/** Stable, locale-independent identifier for this box (e.g. "openaiRequest",
* "providerEventStream") -- NOT the translated title. Each sectionId tracks
* its own expand level, shared across different log entries but independent
* from every other section on the page, since different payload/stream
* boxes carry "interesting" data at different nesting depths. */
sectionId: string;
}
export function JsonTreeExpandControls({ sectionId }: JsonTreeExpandControlsProps) {
const t = useTranslations("requestLogger.detail");
const level = useJsonTreeExpandLevel(sectionId);
const { collapseAll, collapseOneLevel, expandOneLevel, expandAll } = useJsonTreeExpandStore();
const buttonClass =
"p-1 rounded hover:bg-bg-subtle text-text-muted hover:text-text-primary transition-colors";
return (
<div className="flex items-center gap-0.5">
<button
type="button"
onClick={() => collapseAll(sectionId)}
title={t("collapseAllLevels")}
aria-label={t("collapseAllLevels")}
className={buttonClass}
>
<span className="material-symbols-outlined text-[16px]">collapse_all</span>
</button>
<button
type="button"
onClick={() => collapseOneLevel(sectionId)}
title={t("collapseOneLevel")}
aria-label={t("collapseOneLevel")}
className={buttonClass}
>
<span className="material-symbols-outlined text-[16px]">remove</span>
</button>
<span
className="min-w-[1.5em] text-center text-[11px] font-mono text-text-muted tabular-nums"
title={t("currentExpandLevel")}
>
{level}
</span>
<button
type="button"
onClick={() => expandOneLevel(sectionId)}
title={t("expandOneLevel")}
aria-label={t("expandOneLevel")}
className={buttonClass}
>
<span className="material-symbols-outlined text-[16px]">add</span>
</button>
<button
type="button"
onClick={() => expandAll(sectionId)}
title={t("expandAllLevels")}
aria-label={t("expandAllLevels")}
className={buttonClass}
>
<span className="material-symbols-outlined text-[16px]">expand_all</span>
</button>
</div>
);
}