diff --git a/ui/src/components/InlineEditor.tsx b/ui/src/components/InlineEditor.tsx index 192e8260d8e..094566243a1 100644 --- a/ui/src/components/InlineEditor.tsx +++ b/ui/src/components/InlineEditor.tsx @@ -1,6 +1,6 @@ import { useState, useRef, useEffect, useCallback } from "react"; import { cn } from "../lib/utils"; -import { MarkdownBody } from "./MarkdownBody"; +import { MarkdownBody, type MarkdownExternalReferenceMap } from "./MarkdownBody"; import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor"; import { useAutosaveIndicator } from "../hooks/useAutosaveIndicator"; import { FoldCurtain } from "./FoldCurtain"; @@ -19,6 +19,11 @@ interface InlineEditorProps { nullable?: boolean; /** When true, long display-mode markdown is clipped with a fade curtain that expands on click. */ foldable?: boolean; + /** + * Optional host-resolved external object metadata. Forwarded to the read-mode + * `MarkdownBody` so resolved URLs render with the inline status icon prefix. + */ + externalReferences?: MarkdownExternalReferenceMap; } /** Shared padding so display and edit modes occupy the exact same box. */ @@ -55,6 +60,7 @@ export function InlineEditor({ onDropFile, mentions, foldable = false, + externalReferences, }: InlineEditorProps) { const [editing, setEditing] = useState(false); const [multilineEditing, setMultilineEditing] = useState(false); @@ -288,12 +294,18 @@ export function InlineEditor({ > {foldable ? ( - + {previewValue} ) : ( - + {previewValue} )} diff --git a/ui/src/components/IssueFiltersPopover.tsx b/ui/src/components/IssueFiltersPopover.tsx index 19a844ad2c3..473689fb6d5 100644 --- a/ui/src/components/IssueFiltersPopover.tsx +++ b/ui/src/components/IssueFiltersPopover.tsx @@ -9,6 +9,8 @@ import { PriorityIcon } from "./PriorityIcon"; import { StatusIcon } from "./StatusIcon"; import { defaultIssueFilterState, + externalObjectFilterLabel, + externalObjectFilterOrder, issueFilterArraysEqual, issueFilterLabel, issuePriorityOrder, @@ -17,6 +19,8 @@ import { toggleIssueFilterValue, type IssueFilterState, } from "../lib/issue-filters"; +import { externalObjectIconForCategory } from "../lib/external-objects"; +import { externalObjectStatusIcon } from "../lib/status-colors"; import { formatAssigneeUserLabel } from "../lib/assignees"; type AgentOption = { @@ -344,6 +348,37 @@ export function IssueFiltersPopover({ ) : null} +
+ External object status +
+ {externalObjectFilterOrder.map((value) => { + const iconCategory = value === "failed" ? "failed" + : value === "waiting" ? "waiting" + : value === "running" ? "running" + : value === "auth_required" ? "auth_required" + : value === "unreachable" ? "unreachable" + : value === "stale" ? "unknown" + : "closed"; + const Icon = externalObjectIconForCategory(iconCategory); + const tone = externalObjectStatusIcon[iconCategory] ?? ""; + const textTone = tone.split(" ").filter((c) => c.startsWith("text-")).join(" "); + return ( + + ); + })} +
+
+
Visibility