diff --git a/frontend/src/features/store/api.test.ts b/frontend/src/features/store/api.test.ts new file mode 100644 index 0000000..72b84f7 --- /dev/null +++ b/frontend/src/features/store/api.test.ts @@ -0,0 +1,57 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { fetchStores, fetchStoreDocuments, removeDocumentFromStore, queryStore } from './api' + +vi.mock('../../shared/api/http', () => ({ + apiFetch: vi.fn(), +})) + +import { apiFetch } from '../../shared/api/http' + +describe('store API', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('fetchStores calls GET /api/stores', async () => { + const stores = [{ name: 'my-store', type: 'opensearch', connected: true }] + apiFetch.mockResolvedValue(stores) + + const result = await fetchStores() + + expect(apiFetch).toHaveBeenCalledWith('/api/stores') + expect(result).toEqual(stores) + }) + + it('fetchStoreDocuments calls GET /api/stores/:store/documents', async () => { + const docs = [{ docId: 'doc-1', filename: 'test.pdf', state: 'Ingested', chunkCount: 12 }] + apiFetch.mockResolvedValue(docs) + + const result = await fetchStoreDocuments('my-store') + + expect(apiFetch).toHaveBeenCalledWith('/api/stores/my-store/documents') + expect(result).toEqual(docs) + }) + + it('removeDocumentFromStore calls DELETE /api/stores/:store/documents/:docId', async () => { + apiFetch.mockResolvedValue(undefined) + + await removeDocumentFromStore('my-store', 'doc-1') + + expect(apiFetch).toHaveBeenCalledWith('/api/stores/my-store/documents/doc-1', { + method: 'DELETE', + }) + }) + + it('queryStore calls POST /api/stores/:store/query with body', async () => { + const results = [{ chunkId: 'c1', docId: 'd1', filename: 'a.pdf', text: 'hi', score: 0.9 }] + apiFetch.mockResolvedValue(results) + + const result = await queryStore('my-store', 'what is X?', 3) + + expect(apiFetch).toHaveBeenCalledWith('/api/stores/my-store/query', { + method: 'POST', + body: JSON.stringify({ query: 'what is X?', top_k: 3 }), + }) + expect(result).toEqual(results) + }) +}) diff --git a/frontend/src/features/store/api.ts b/frontend/src/features/store/api.ts new file mode 100644 index 0000000..ff21ce5 --- /dev/null +++ b/frontend/src/features/store/api.ts @@ -0,0 +1,50 @@ +import { apiFetch } from '../../shared/api/http' +import type { DocumentLifecycleState } from '../../shared/types' + +export interface StoreInfo { + name: string + type: string + connected: boolean + documentCount: number + chunkCount: number + errorMessage?: string +} + +export interface StoreDocEntry { + docId: string + filename: string + state: DocumentLifecycleState + chunkCount: number + pushedAt: string +} + +export interface QueryResult { + chunkId: string + docId: string + filename: string + text: string + score: number + pageRange?: [number, number] +} + +export function fetchStores(): Promise { + return apiFetch('/api/stores') +} + +export function fetchStoreDocuments(store: string): Promise { + return apiFetch(`/api/stores/${encodeURIComponent(store)}/documents`) +} + +export function removeDocumentFromStore(store: string, docId: string): Promise { + return apiFetch( + `/api/stores/${encodeURIComponent(store)}/documents/${encodeURIComponent(docId)}`, + { method: 'DELETE' }, + ) +} + +export function queryStore(store: string, query: string, topK = 5): Promise { + return apiFetch(`/api/stores/${encodeURIComponent(store)}/query`, { + method: 'POST', + body: JSON.stringify({ query, top_k: topK }), + }) +} diff --git a/frontend/src/features/store/index.ts b/frontend/src/features/store/index.ts new file mode 100644 index 0000000..3318fdb --- /dev/null +++ b/frontend/src/features/store/index.ts @@ -0,0 +1 @@ +export * from './api' diff --git a/frontend/src/pages/StoreDetailPage.vue b/frontend/src/pages/StoreDetailPage.vue index c8cdae2..5024395 100644 --- a/frontend/src/pages/StoreDetailPage.vue +++ b/frontend/src/pages/StoreDetailPage.vue @@ -1,20 +1,468 @@ + + diff --git a/frontend/src/pages/StoreQueryPage.vue b/frontend/src/pages/StoreQueryPage.vue index dcfa6ad..04d846e 100644 --- a/frontend/src/pages/StoreQueryPage.vue +++ b/frontend/src/pages/StoreQueryPage.vue @@ -1,20 +1,389 @@