import type { IssueRelatedWorkItem, IssueRelatedWorkSummary } from "@paperclipai/shared"; import { IssueReferencePill } from "./IssueReferencePill"; import { ExternalObjectPill } from "./ExternalObjectPill"; import type { IssueExternalObjectGroup } from "../hooks/useIssueExternalObjects"; import { externalObjectToneSeverity } from "../lib/external-objects"; import { Badge } from "@/components/ui/badge"; type GroupedSource = { label: string; count: number; sampleMatchedText: string | null; }; function groupSourcesByLabel(sources: IssueRelatedWorkItem["sources"]): GroupedSource[] { const groups = new Map(); for (const source of sources) { const existing = groups.get(source.label); if (existing) { existing.count += 1; } else { groups.set(source.label, { label: source.label, count: 1, sampleMatchedText: source.matchedText ?? null, }); } } return Array.from(groups.values()); } function Section({ title, description, items, emptyLabel, }: { title: string; description: string; items: IssueRelatedWorkItem[]; emptyLabel: string; }) { return (

{title}

{description}

{items.length === 0 ? (

{emptyLabel}

) : ( )}
); } function ExternalObjectsSection({ groups, isLoading, isError, onRetry, }: { groups: IssueExternalObjectGroup[]; isLoading: boolean; isError: boolean; onRetry?: () => void; }) { // Severity-first sort with most-recently-changed as the secondary sort. const sorted = [...groups].sort((a, b) => { const aTone = externalObjectToneSeverity(a.pill.statusCategory ? a.group.object?.statusTone ?? null : null); const bTone = externalObjectToneSeverity(b.pill.statusCategory ? b.group.object?.statusTone ?? null : null); if (aTone !== bTone) return bTone - aTone; const aChanged = a.group.object?.lastChangedAt ?? a.group.object?.lastResolvedAt ?? ""; const bChanged = b.group.object?.lastChangedAt ?? b.group.object?.lastResolvedAt ?? ""; return aChanged < bChanged ? 1 : aChanged > bChanged ? -1 : 0; }); return (

External objects

Remote work referenced from this issue — pull requests, deployments, tickets in other systems, and more.

{isError ? (

Couldn't load external objects.{" "} {onRetry ? ( ) : null}

) : isLoading ? (

Loading external objects…

) : sorted.length === 0 ? (

This issue does not reference any external objects yet.

) : ( )}
); } export function IssueRelatedWorkPanel({ relatedWork, externalObjectsEnabled = true, externalObjects, externalObjectsLoading, externalObjectsError, onRetryExternalObjects, }: { relatedWork?: IssueRelatedWorkSummary | null; externalObjectsEnabled?: boolean; externalObjects?: IssueExternalObjectGroup[]; externalObjectsLoading?: boolean; externalObjectsError?: boolean; onRetryExternalObjects?: () => void; }) { const outbound = relatedWork?.outbound ?? []; const inbound = relatedWork?.inbound ?? []; return (
{externalObjectsEnabled ? ( ) : null}
); }