diff --git a/data/media/audio.mp3 b/data/media/audio.mp3 new file mode 100644 index 0000000..3f2741d Binary files /dev/null and b/data/media/audio.mp3 differ diff --git a/data/media/example.pdf b/data/media/example.pdf new file mode 100644 index 0000000..299531c Binary files /dev/null and b/data/media/example.pdf differ diff --git a/data/media/image.jpg b/data/media/image.jpg new file mode 100644 index 0000000..685e5a4 Binary files /dev/null and b/data/media/image.jpg differ diff --git a/data/media/table.parquet b/data/media/table.parquet new file mode 100644 index 0000000..8326840 Binary files /dev/null and b/data/media/table.parquet differ diff --git a/data/media/video.mp4 b/data/media/video.mp4 new file mode 100644 index 0000000..d9ae00b Binary files /dev/null and b/data/media/video.mp4 differ diff --git a/docs/media-urls.md b/docs/media-urls.md index e11d392..025d11d 100644 --- a/docs/media-urls.md +++ b/docs/media-urls.md @@ -62,6 +62,26 @@ For **every cell in every row**: [useProcessedRowData.ts](../smoosense-gui/src/lib/hooks/useProcessedRowData.ts) - Returns the processed data with all media URLs resolved +## Query Tab Processing + +The Query tab also processes media URLs in query results: + +**Location**: `SqlQueryPanel.tsx` @ [SqlQueryPanel.tsx](../smoosense-gui/src/components/sql/SqlQueryPanel.tsx) + +**Process**: +1. Execute SQL query via `/api/query` endpoint +2. Receive results as `{column_names, rows}` +3. Transform rows using `_.zipObject(column_names, rows)` +4. **Process media URLs** using same logic as Samples tab: + - For each cell, check `needToResolveMediaUrl(value)` + - If true, call `resolveAssetUrl(value, tablePath, baseUrl)` +5. Render in `BasicAGTable` with auto-detected cell renderers + +**Media Rendering**: +- Images displayed in `ImageCellRenderer` +- Videos displayed in `VideoCellRenderer` +- Audio displayed in `AudioCellRenderer` +- Cell renderers auto-detected via `inferRenderTypeFromData()` ## Backend Integration diff --git a/smoosense-gui/src/components/common/BasicAGTable.tsx b/smoosense-gui/src/components/common/BasicAGTable.tsx index 573bc82..701036a 100644 --- a/smoosense-gui/src/components/common/BasicAGTable.tsx +++ b/smoosense-gui/src/components/common/BasicAGTable.tsx @@ -27,13 +27,12 @@ export default function BasicAGTable({ data, className = '', onGridReady, colDef const baseColumnDefs = inferColumnDefinitions(data) // Apply overrides if provided - const columnDefs = colDefOverrides - ? baseColumnDefs.map(colDef => { - const fieldName = colDef.field - const overrides = fieldName ? colDefOverrides[fieldName] : undefined - return overrides ? { ...colDef, ...overrides } : colDef - }) - : baseColumnDefs + const columnDefs = baseColumnDefs.map(colDef => { + const fieldName = colDef.field + const overrides = colDefOverrides && fieldName ? colDefOverrides[fieldName] : undefined + + return overrides ? { ...colDef, ...overrides } : colDef + }) // Construct final grid options const finalGridOptions: GridOptions = { diff --git a/smoosense-gui/src/components/common/ImageBlock.tsx b/smoosense-gui/src/components/common/ImageBlock.tsx index 5ed31ac..aae35b4 100644 --- a/smoosense-gui/src/components/common/ImageBlock.tsx +++ b/smoosense-gui/src/components/common/ImageBlock.tsx @@ -1,7 +1,6 @@ 'use client' import { useAppSelector } from '@/lib/hooks' -import { proxyedUrl } from '@/lib/utils/urlUtils' interface ImageBlockProps { src: string @@ -19,7 +18,6 @@ export default function ImageBlock({ neverFitCover = false }: ImageBlockProps) { const cropMediaToFitCover = useAppSelector((state) => state.ui.cropMediaToFitCover) - const imageUrl = proxyedUrl(src) const finalClassName = `${className} ${(cropMediaToFitCover && !neverFitCover) ? 'object-cover' : 'object-contain'}`.trim() @@ -31,7 +29,7 @@ export default function ImageBlock({ return ( {alt} state.ui.autoPlayAllVideos) const cropMediaToFitCover = useAppSelector((state) => state.ui.cropMediaToFitCover) - const videoUrl = proxyedUrl(src) - // Apply crop fit logic - always take full width and height const finalClassName = cropMediaToFitCover ? `w-full h-full object-cover ${className || ''}`.trim() @@ -108,7 +105,7 @@ const VideoPlayer = memo(function VideoPlayer({ >