feat: initial commit

This commit is contained in:
2026-03-05 22:12:38 +01:00
commit bce762a783
380 changed files with 51955 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
import api from './client'
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export interface CadObjects {
cad_file_id: string
original_name: string
processing_status: 'pending' | 'processing' | 'completed' | 'failed'
parsed_objects: Record<string, unknown> | null
}
export interface RegenerateThumbnailResponse {
cad_file_id: string
original_name: string
status: 'queued'
task_id: string | null
}
// ---------------------------------------------------------------------------
// API functions
// ---------------------------------------------------------------------------
/**
* Returns the URL to the thumbnail PNG for a CAD file.
* Use directly in <img src={getCadThumbnailUrl(id)} /> the browser will
* handle the authenticated request via the axios interceptor when called
* programmatically, or you can construct the URL for use in img tags when
* the auth token is set as a header.
*
* For use in <img> tags without auth headers, prefer fetching as a blob and
* creating an object URL (see fetchThumbnailBlob below).
*/
export function getCadThumbnailUrl(cadFileId: string): string {
return `/api/cad/${cadFileId}/thumbnail`
}
/**
* Fetch the thumbnail PNG as a Blob and return an object URL suitable for
* use in <img src=...> without needing explicit auth headers.
* Remember to call URL.revokeObjectURL() when the component unmounts.
*/
export async function fetchThumbnailBlob(cadFileId: string): Promise<string> {
const res = await api.get<Blob>(`/cad/${cadFileId}/thumbnail`, {
responseType: 'blob',
})
return URL.createObjectURL(res.data)
}
/**
* Fetch the glTF model file as a Blob and return an object URL.
* Remember to call URL.revokeObjectURL() when the consumer is done.
*/
export async function fetchModelBlob(cadFileId: string): Promise<string> {
const res = await api.get<Blob>(`/cad/${cadFileId}/model`, {
responseType: 'blob',
})
return URL.createObjectURL(res.data)
}
/**
* Return the parsed_objects JSON for a CAD file.
*/
export async function getCadObjects(cadFileId: string): Promise<CadObjects> {
const res = await api.get<CadObjects>(`/cad/${cadFileId}/objects`)
return res.data
}
/**
* Download the cached STL for a CAD file as a file-save dialog.
* quality: 'low' | 'high'
* The backend returns a human-readable filename, but we derive it client-side too.
*/
export async function downloadStl(cadFileId: string, quality: 'low' | 'high', suggestedName?: string): Promise<void> {
const res = await api.get<Blob>(`/cad/${cadFileId}/stl/${quality}`, {
responseType: 'blob',
})
const url = URL.createObjectURL(res.data)
const a = document.createElement('a')
a.href = url
a.download = suggestedName ? `${suggestedName}_${quality}.stl` : `model_${quality}.stl`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
}
export async function generateStl(cadFileId: string, quality: 'low' | 'high'): Promise<{ task_id: string }> {
const res = await api.post<{ task_id: string }>(`/cad/${cadFileId}/generate-stl/${quality}`)
return res.data
}
/**
* Ask the backend to re-queue STEP processing for a CAD file (admin only).
* Returns the Celery task_id (or null if the worker is not available).
*/
export async function regenerateThumbnail(
cadFileId: string,
): Promise<RegenerateThumbnailResponse> {
const res = await api.post<RegenerateThumbnailResponse>(
`/cad/${cadFileId}/regenerate-thumbnail`,
)
return res.data
}