project-demo / frontend /services /sharedDatasetService.ts
Шатурный Алексей Давыдович
add files
0269f70
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);
});
}
};