feat(07-uat): admin AI panel UX enhancements + DocumentCard status indicators

- GET /api/admin/ai-config/models — fetch model list from provider's /models endpoint
- POST /api/admin/ai-config/test-connection — replaced GET; accepts unsaved form
  values (api_key, base_url, model_name) so admins can test before saving
- TestConnectionRequest Pydantic model with provider_id validation
- SearchableModelSelect.vue — new reusable combobox; Teleport to body avoids
  overflow:hidden clipping; shows all models on open, filters only on typing;
  static "Enter manually" item always pinned at bottom; caches per provider
- AdminAiConfigTab: model name input replaced with SearchableModelSelect;
  testingProvider ref + spinner added to Test Connection button
- DocumentCard: processing spinner + "Classifying…", pending "Queued" badge,
  classification_failed badge; topics section only shown when status=ready
- FileManagerView: onUnmounted imported (polling wiring pending next session)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-06-05 09:26:02 +02:00
co-authored by Claude Sonnet 4.6
parent ac2dded35b
commit 3b11b9a596
6 changed files with 457 additions and 29 deletions
@@ -16,8 +16,8 @@
<p class="font-medium text-gray-900 text-sm truncate">{{ doc.original_name }}</p>
<p class="text-xs text-gray-400 mt-0.5">{{ formatDate(doc.created_at) }} · {{ formatSize(doc.size_bytes) }}</p>
<!-- Topics -->
<div class="flex flex-wrap gap-1 mt-2">
<!-- Topics (only when classified) -->
<div v-if="doc.status === 'ready'" class="flex flex-wrap gap-1 mt-2">
<TopicBadge
v-for="topicName in doc.topics"
:key="topicName"
@@ -27,6 +27,17 @@
<span v-if="!doc.topics?.length" class="text-xs text-gray-300 italic">unclassified</span>
</div>
<!-- Processing indicator -->
<div v-else-if="doc.status === 'processing'" class="flex items-center gap-1.5 mt-2">
<span class="animate-spin rounded-full border-2 border-indigo-400 border-t-transparent w-3 h-3 shrink-0"></span>
<span class="text-xs text-indigo-500 font-medium">Classifying</span>
</div>
<!-- Pending / queued indicator -->
<div v-else-if="doc.status === 'pending'" class="mt-2">
<span class="bg-gray-100 text-gray-500 text-xs font-medium px-2 py-1 rounded-full">Queued</span>
</div>
<!-- Shared indicator pill -->
<div v-if="doc.is_shared" class="mt-2">
<span class="bg-indigo-50 text-indigo-600 text-xs font-medium px-2 py-1 rounded-full">Shared</span>