Spaces:
Sleeping
Sleeping
| import type { Dataset, DatasetMetadata, DataItem, Modality } from '../types'; | |
| /** | |
| * A helper function to handle API errors. | |
| */ | |
| const handleApiError = async (response: Response) => { | |
| if (!response.ok) { | |
| let errorMessage = `API error! status: ${response.status}`; | |
| try { | |
| // First, get the response text, as it might not be JSON. | |
| const text = await response.text(); | |
| try { | |
| // Try to parse it as JSON | |
| const errorData = JSON.parse(text); | |
| errorMessage = errorData.detail || JSON.stringify(errorData); | |
| } catch (e) { | |
| // If parsing fails, use the raw text. | |
| errorMessage = text || errorMessage; | |
| } | |
| } catch (e) { | |
| // Fallback if reading the body fails for some reason. | |
| // This is unlikely to be hit with the logic above. | |
| } | |
| throw new Error(errorMessage); | |
| } | |
| // Only call .json() on success to avoid "body already read" errors. | |
| return response.json(); | |
| }; | |
| /** | |
| * Returns the metadata for all available shared datasets by querying the backend. | |
| */ | |
| export const getSharedDatasetMetadata = async (): Promise<DatasetMetadata[]> => { | |
| try { | |
| const response = await fetch('/api/shared-dataset-metadata'); | |
| const metadataList = await handleApiError(response); | |
| // The backend returns strings for dates, convert them to Date objects. | |
| return metadataList.map((meta: any) => ({ | |
| ...meta, | |
| uploadDate: new Date(meta.uploadDate), | |
| })); | |
| } catch (error) { | |
| console.error("Failed to fetch shared dataset metadata:", error); | |
| // Re-throw the error so the UI layer can handle it. | |
| throw error; | |
| } | |
| }; | |
| /** | |
| * Returns the full data structure for a specific shared dataset from the backend. | |
| * The content for each item remains null, only the URLs are provided. | |
| */ | |
| export const getSharedDataset = async (id: string): Promise<Dataset | null> => { | |
| try { | |
| // NOTE: The backend API endpoint for fetching the full dataset is assumed to exist. | |
| // It should return the full Dataset object structure based on the scanned files. | |
| const response = await fetch(`/api/shared-dataset?id=${id}`); | |
| const dataset = await handleApiError(response); | |
| // Convert date string from API to Date object | |
| dataset.uploadDate = new Date(dataset.uploadDate); | |
| return dataset; | |
| } catch (error) { | |
| console.error(`Failed to fetch shared dataset with id ${id}:`, error); | |
| // Re-throw the error so the UI layer can handle it. | |
| throw error; | |
| } | |
| }; | |
| /** | |
| * Fetches the actual content of a single lazy-loaded item from the server's static files. | |
| * This function is used for text and mesh files. Images are loaded directly by the browser <img> tag. | |
| */ | |
| export const getItemContent = async (url: string): Promise<string | ArrayBuffer> => { | |
| const response = await fetch(url); | |
| if (!response.ok) { | |
| throw new Error(`Failed to fetch content from ${url}: ${response.statusText}`); | |
| } | |
| // Determine content type based on file extension | |
| if (url.endsWith('.txt')) { | |
| return response.text(); | |
| } else if (url.endsWith('.stl')) { | |
| return response.arrayBuffer(); | |
| } else { | |
| // This case is for completeness; images are usually handled by `<img>` src attribute. | |
| const blob = await response.blob(); | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.onloadend = () => resolve(reader.result as string); | |
| reader.onerror = reject; | |
| reader.readAsDataURL(blob); | |
| }); | |
| } | |
| }; | |