mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 21:21:11 +00:00
[AZ-486] F7 endpoint builders + STC-ARCH-02 (cycle 1 close)
Single source of truth for every /api/<service>/... URL the UI talks to: src/api/endpoints.ts (25 typed builders) re-exported via the F4 barrel. Migrates 13 production callsites in admin / annotations / flights / settings / dataset / auth / api-client / FlightContext / DetectionClasses to endpoints.* . Adds the STC-ARCH-02 static gate (--mode=api-literals in scripts/check-arch-imports.mjs, wired into scripts/run-tests.sh) that fails any new hardcoded /api/<service>/ literal in src/ outside endpoints.ts and *.test.tsx? files. Tests: +36 contract assertions in src/api/endpoints.test.ts (every builder, character-identical), +6 STC-ARCH-02 architecture cases in tests/architecture_imports.test.ts (single / double / template literal fail paths, *.test.* exemption, line-comment skip, migrated codebase pass). Fast profile 167 -> 209 PASS / 13 SKIP / 0 FAIL, +42 new, 0 regressions. Static profile 31 / 31 PASS. Closes architecture baseline finding F7. Cycle 1 of Phase B closed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDropzone } from 'react-dropzone'
|
||||
import { useFlight, ConfirmDialog } from '../../components'
|
||||
import { api } from '../../api'
|
||||
import { api, endpoints } from '../../api'
|
||||
import { useDebounce } from '../../hooks'
|
||||
import { MediaType } from '../../types'
|
||||
import type { Media, PaginatedResponse, AnnotationListItem } from '../../types'
|
||||
@@ -27,7 +27,7 @@ export default function MediaList({ selectedMedia, onSelect, onAnnotationsLoaded
|
||||
if (selectedFlight) params.set('flightId', selectedFlight.id)
|
||||
if (debouncedFilter) params.set('name', debouncedFilter)
|
||||
try {
|
||||
const res = await api.get<PaginatedResponse<Media>>(`/api/annotations/media?${params}`)
|
||||
const res = await api.get<PaginatedResponse<Media>>(endpoints.annotations.media(params.toString()))
|
||||
setMedia(prev => {
|
||||
// Keep local-only (blob URL) entries, merge with backend entries
|
||||
const local = prev.filter(m => m.path.startsWith('blob:'))
|
||||
@@ -55,7 +55,7 @@ export default function MediaList({ selectedMedia, onSelect, onAnnotationsLoaded
|
||||
}
|
||||
try {
|
||||
const res = await api.get<PaginatedResponse<AnnotationListItem>>(
|
||||
`/api/annotations/annotations?mediaId=${m.id}&pageSize=1000`
|
||||
endpoints.annotations.annotationsByMedia(m.id),
|
||||
)
|
||||
onAnnotationsLoaded(res.items)
|
||||
} catch {
|
||||
@@ -72,7 +72,7 @@ export default function MediaList({ selectedMedia, onSelect, onAnnotationsLoaded
|
||||
setDeleteId(null)
|
||||
return
|
||||
}
|
||||
try { await api.delete(`/api/annotations/media/${deleteId}`) } catch {}
|
||||
try { await api.delete(endpoints.annotations.mediaItem(deleteId)) } catch {}
|
||||
setDeleteId(null)
|
||||
fetchMedia()
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export default function MediaList({ selectedMedia, onSelect, onAnnotationsLoaded
|
||||
const form = new FormData()
|
||||
form.append('waypointId', '')
|
||||
for (const file of arr) form.append('files', file)
|
||||
await api.upload('/api/annotations/media/batch', form)
|
||||
await api.upload(endpoints.annotations.mediaBatch(), form)
|
||||
fetchMedia()
|
||||
return
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user