+
+
+
+ Todos from the site
+
+
{openCount} open
+
+
+
+
+
+
+ {projects.length > 1 && (
+
+ {[["", openCount] as [string, number], ...projects].map(([name, count]) => (
+
+ ))}
+
+ )}
+
+ {error && (
+
+ Couldn't load todos: {error}
+
+ )}
+
+ {visible.length === 0 ? (
+
+
+
+ {loading ? "Loading…" : todos.length === 0 ? "No todos yet" : "Nothing matches"}
+
+ {todos.length === 0 && !loading && (
+
+ Press Alt+Shift+T on a page running otel-rum.js to file one.
+
+ )}
+
+ ) : (
+
+ {visible.map((t) => (
+ void setDone(todo, done)} />
+ ))}
+
+ )}
+
+ )
+}
+
+export default TodosVisualizer
diff --git a/otel-ui/src/components/layout/IconRail.tsx b/otel-ui/src/components/layout/IconRail.tsx
index d5643a6..5a95fdc 100644
--- a/otel-ui/src/components/layout/IconRail.tsx
+++ b/otel-ui/src/components/layout/IconRail.tsx
@@ -7,6 +7,7 @@ import {
GitBranch,
Globe,
LineChart,
+ ListTodo,
Radar,
ScrollText,
TrendingUp,
@@ -64,6 +65,7 @@ export const IconRail: React.FC = () => {
{ tab: "tab2", label: "Metrics & APM", Icon: LineChart },
{ tab: "tab7", label: "RUM sessions", Icon: Globe },
{ tab: "tab10", label: "Source IPs", Icon: Fingerprint },
+ { tab: "tab11", label: "Todos from the site", Icon: ListTodo },
...(statsAvailable ? [{ tab: "tab5", label: "Historical trends", Icon: TrendingUp }] : []),
{ tab: "tab6", label: "Archive & trap", Icon: Radar },
]
diff --git a/otel-ui/src/hooks/useIssues.ts b/otel-ui/src/hooks/useIssues.ts
index 86f515e..1ee043d 100644
--- a/otel-ui/src/hooks/useIssues.ts
+++ b/otel-ui/src/hooks/useIssues.ts
@@ -28,6 +28,13 @@ export function useIssues() {
},
)
const refresh = useCallback(() => mutate(), [mutate])
+ // Optimistic local edit so a triage click shows immediately; the next
+ // refresh replaces it with the server's truth.
+ const patch = useCallback(
+ (id: string, changes: Partial