ETAXJ5YIOUH75V6ZKHUGQWTRWIRZVJAUG5LYXYZEJDS7SXPNEZSAC
YBJGFUTFTV4SBPUVC6LBETGMPMLS47LSQPL3OJAAPH7BROBQD7DQC
OBXY6BHNROIV7W4O3MMQ6GTQXU2XUKF5A4DCJYDLUEUHV72E7BNAC
ONSQYCF6NFUEA24ORB62W4P62LKUMV7C5PLYRZQULHFDNROEY2HQC
CF7JTOBNLOMGK36B5CXQP3FWA3RLBYAOCNGXNNLKCCO7TBWR65GQC
IUHUM6OZ5KYEAYQCIYNG5Q4QLQRAQNMBWKYGV2ZDJFNY5W4DOUNQC
RELTAIDEZ4Y2SC2WQROQ4IEJO5BVPULTVLLJ4BA23WE5FVT5QOQAC
GIAIXNFCQIP5ZHBFXWFWDTLDUGV35MDC3ARQCVAN6FEWIX7Q32GQC
Z3XA4BHNMZB6I34LZ626NQRUPHARWJ5UYHGT65IFQVSQ5B2TY6OQC
HBM7XFBGVMKW3P3VZFNQTJMINZ4DC3D4TZMT4TPTJRXC62HKZMMQC
M3JUJ2WWZGCVMBITKRM5FUJMHFYL2QRMXJUVRUE4AC2RF74AOL5AC
/**
* Protected API route to get file context information (dataset, location, cluster)
*
* @route GET /api/files/:fileId/context
* @authentication Required
* @param {string} fileId - File ID in URL path
* @returns {Object} Response containing:
* - data: Object with dataset, location, and cluster information
* @error 400 - If fileId is invalid
* @error 404 - If file not found
* @error 500 - If database operation fails
* @description Returns context information for breadcrumb display
*/
files.get("/:fileId/context", authenticate, async (c) => {
try {
const fileId = c.req.param("fileId");
// Validate file ID format
if (!isValidFileId(fileId)) {
return c.json({
error: "Invalid file ID format"
}, 400);
}
// Connect to database
const db = createDatabase(c.env);
// Query file with location, cluster, and dataset information
const result = await db
.select({
fileId: file.id,
fileName: file.fileName,
datasetId: dataset.id,
datasetName: dataset.name,
locationId: location.id,
locationName: location.name,
clusterId: cluster.id,
clusterName: cluster.name,
})
.from(file)
.leftJoin(location, eq(file.locationId, location.id))
.leftJoin(cluster, eq(file.clusterId, cluster.id))
.leftJoin(dataset, eq(location.datasetId, dataset.id))
.where(
sqlExpr`${file.id} = ${fileId} AND ${file.active} = true`
)
.limit(1);
if (result.length === 0) {
return c.json({
error: "File not found"
}, 404);
}
const fileContext = result[0];
return c.json({
data: {
dataset: {
id: fileContext.datasetId,
name: fileContext.datasetName
},
location: {
id: fileContext.locationId,
name: fileContext.locationName
},
cluster: {
id: fileContext.clusterId,
name: fileContext.clusterName
}
}
});
} catch (error) {
console.error("Error fetching file context:", error);
return c.json({
error: "Failed to fetch file context",
details: error instanceof Error ? error.message : String(error),
}, 500);
}
});
// Fetch file context data
const fetchFileContext = useCallback(async (fileId: string) => {
setState(prev => ({ ...prev, fileContextLoading: true }));
try {
const accessToken = await getAccessToken();
const response = await fetch(`/api/files/${fileId}/context`, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch file context: ${response.status}`);
}
const data = await response.json();
setState(prev => ({
...prev,
fileContext: data.data,
fileContextLoading: false
}));
} catch (error) {
console.error('Error fetching file context:', error);
setState(prev => ({
...prev,
fileContextLoading: false
}));
}
}, [getAccessToken]);
{datasetName && `Dataset: ${datasetName}`}
{datasetName && locationName && ' • '}
{locationName && `Location: ${locationName}`}
{(datasetName || locationName) && clusterName && ' • '}
{clusterName && `Cluster: ${clusterName}`}
{!datasetName && !locationName && !clusterName && 'Audio File'}
{state.fileContext ? (
<>
{state.fileContext.dataset && `Dataset: ${state.fileContext.dataset.name}`}
{state.fileContext.dataset && state.fileContext.location && ' • '}
{state.fileContext.location && `Location: ${state.fileContext.location.name}`}
{(state.fileContext.dataset || state.fileContext.location) && state.fileContext.cluster && ' • '}
{state.fileContext.cluster && `Cluster: ${state.fileContext.cluster.name}`}
</>
) : state.fileContextLoading ? (
'Loading context...'
) : (
'Audio File'
)}