feat(kb-ui): humanise provenance "Added by" via an injected resolver
ProvenancePanel/ObjectViewer gain an optional resolvePrincipal(p) prop so the
consumer can turn a {type,id} principal ref into a human label — the lib can't
know who "you" is. Falls back to the raw type·id when the resolver returns
undefined, so existing callers are unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
Tag,
|
||||
Trash2,
|
||||
} from "lucide-react";
|
||||
import type { ObjectOutline, ObjectSummary, OutlineSection, TextSlice } from "./types";
|
||||
import type { ObjectOutline, ObjectSummary, OutlineSection, PrincipalRef, TextSlice } from "./types";
|
||||
import {
|
||||
Badge,
|
||||
SensitivityBadge,
|
||||
@@ -160,11 +160,20 @@ export const CatalogCard: FC<{ outline: ObjectOutline; className?: string }> = (
|
||||
|
||||
// ---- ProvenancePanel ------------------------------------------------------
|
||||
|
||||
export const ProvenancePanel: FC<{ outline: ObjectOutline; className?: string }> = ({ outline, className }) => {
|
||||
export const ProvenancePanel: FC<{
|
||||
outline: ObjectOutline;
|
||||
/** Turn a principal ref into a human label ("You", an agent's name, …). The
|
||||
* lib can't know who "you" is, so the app supplies this; falls back to the
|
||||
* raw type·id when it returns undefined. */
|
||||
resolvePrincipal?: (p: string | PrincipalRef) => string | undefined;
|
||||
className?: string;
|
||||
}> = ({ outline, resolvePrincipal, className }) => {
|
||||
const p = outline.provenance;
|
||||
const addedBy =
|
||||
(p.created_by != null ? resolvePrincipal?.(p.created_by) : undefined) ?? formatPrincipal(p.created_by) ?? "—";
|
||||
const rows: [string, ReactNode][] = [
|
||||
["Source", p.source_ref ? `${p.source_type} · ${p.source_ref}` : p.source_type],
|
||||
["Added by", formatPrincipal(p.created_by) ?? "—"],
|
||||
["Added by", addedBy],
|
||||
["Added", formatDate(p.inserted_at)],
|
||||
["Effective", p.effective_at ? formatDate(p.effective_at) : "—"],
|
||||
["Last verified", p.verified_at ? formatDate(p.verified_at) : "Not confirmed"],
|
||||
@@ -499,6 +508,8 @@ export interface ObjectViewerProps {
|
||||
readText: TextReaderProps["readText"];
|
||||
/** Resolve a browser-openable blob URL (for images + download). */
|
||||
resolveBlobUrl?: () => Promise<string>;
|
||||
/** Humanise the "Added by" principal (see ProvenancePanel). */
|
||||
resolvePrincipal?: (p: string | PrincipalRef) => string | undefined;
|
||||
highlight?: { start: number; end: number };
|
||||
onOpenObject?: (objectId: string, span?: { start: number; end: number }) => void;
|
||||
actions?: ObjectActions;
|
||||
@@ -509,6 +520,7 @@ export const ObjectViewer: FC<ObjectViewerProps> = ({
|
||||
outline,
|
||||
readText,
|
||||
resolveBlobUrl,
|
||||
resolvePrincipal,
|
||||
highlight,
|
||||
onOpenObject,
|
||||
actions,
|
||||
@@ -602,7 +614,7 @@ export const ObjectViewer: FC<ObjectViewerProps> = ({
|
||||
<OutlineNav sections={outline.outline} activeId={activeSection} onSelect={(s) => setActiveSection(s.id)} />
|
||||
</div>
|
||||
)}
|
||||
<ProvenancePanel outline={outline} />
|
||||
<ProvenancePanel outline={outline} resolvePrincipal={resolvePrincipal} />
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user