Skip to content

Commit f1d4d52

Browse files
committed
feat(frontend): show quarantine tool count on servers list page
Add QuarantineStats interface and quarantine field to Server type so the ServerCard displays how many tools are pending approval without requiring users to click into each server's detail page. The badge appears in the Tools stat area with a warning icon when pending_count or changed_count is non-zero. Also updates v-memo keys in Servers.vue so cards re-render when quarantine stats change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0293953 commit f1d4d52

3 files changed

Lines changed: 26 additions & 4 deletions

File tree

frontend/src/components/ServerCard.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@
2929
<div class="stat bg-base-200 rounded-lg p-3">
3030
<div class="stat-title text-xs">Tools</div>
3131
<div class="stat-value text-lg">{{ server.tool_count }}</div>
32-
<div v-if="server.tool_list_token_size" class="stat-desc text-xs">
32+
<div v-if="quarantineToolCount > 0" class="stat-desc text-xs text-warning flex items-center gap-1">
33+
<svg class="w-3 h-3 inline-block flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
34+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
35+
</svg>
36+
{{ quarantineToolCount }} pending approval
37+
</div>
38+
<div v-else-if="server.tool_list_token_size" class="stat-desc text-xs">
3339
{{ server.tool_list_token_size.toLocaleString() }} tokens
3440
</div>
3541
</div>
@@ -269,6 +275,13 @@ const healthAction = computed(() => {
269275
return props.server.health?.action || ''
270276
})
271277
278+
// Tool-level quarantine count (pending + changed)
279+
const quarantineToolCount = computed(() => {
280+
const q = props.server.quarantine
281+
if (!q) return 0
282+
return (q.pending_count ?? 0) + (q.changed_count ?? 0)
283+
})
284+
272285
// Determine if error message should be shown (FR-018, FR-019)
273286
// Suppress verbose last_error when health.action already conveys the issue
274287
const shouldShowError = computed(() => {
@@ -484,4 +497,4 @@ async function confirmDelete() {
484497
loading.value = false
485498
}
486499
}
487-
</script>
500+
</script>

frontend/src/types/api.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export {
2020
// Import HealthStatus for use in this file
2121
import type { HealthStatus } from './contracts'
2222

23+
// Quarantine stats for tool-level quarantine (Spec 032)
24+
export interface QuarantineStats {
25+
pending_count: number
26+
changed_count: number
27+
}
28+
2329
// Server types
2430
export interface Server {
2531
name: string
@@ -43,6 +49,7 @@ export interface Server {
4349
token_expires_at?: string
4450
user_logged_out?: boolean // True if user explicitly logged out (prevents auto-reconnection)
4551
health?: HealthStatus // Unified health status calculated by the backend
52+
quarantine?: QuarantineStats // Tool-level quarantine stats (Spec 032)
4653
}
4754

4855
// Tool Annotation types

frontend/src/views/Servers.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@
139139
server.quarantined,
140140
server.tool_count,
141141
server.last_error,
142-
server.authenticated
142+
server.authenticated,
143+
server.quarantine?.pending_count,
144+
server.quarantine?.changed_count
143145
]"
144146
/>
145147
</TransitionGroup>
@@ -273,4 +275,4 @@ const serversHints = computed<Hint[]>(() => {
273275
}
274276
]
275277
})
276-
</script>
278+
</script>

0 commit comments

Comments
 (0)