From de4a6d2db8efc028ff0e3fcdb360bbd4cf0205d6 Mon Sep 17 00:00:00 2001 From: GotthardG <51994228+GotthardG@users.noreply.github.com> Date: Thu, 27 Feb 2025 11:40:40 +0100 Subject: [PATCH] Refactor image rendering in ResultGrid with CSS enhancements Simplified image rendering logic in `ResultGrid` by removing hover state management within JavaScript. Added `SampleImage.css` to handle hover effects for images and tooltips with scalable zoom. Cleaned up unnecessary comments and improved code readability. --- frontend/src/components/ResultGrid.tsx | 184 ++++++++++-------------- frontend/src/components/SampleImage.css | 13 ++ 2 files changed, 90 insertions(+), 107 deletions(-) create mode 100644 frontend/src/components/SampleImage.css diff --git a/frontend/src/components/ResultGrid.tsx b/frontend/src/components/ResultGrid.tsx index 64760ae..809460a 100644 --- a/frontend/src/components/ResultGrid.tsx +++ b/frontend/src/components/ResultGrid.tsx @@ -1,6 +1,9 @@ +// TypeScript (ResultGrid.tsx snippet) import React, { useEffect, useState } from 'react'; import { DataGrid, GridColDef } from '@mui/x-data-grid'; import { OpenAPI, SamplesService } from '../../openapi'; +import './Sampleimage.css'; + interface ImageInfo { id: number; @@ -22,14 +25,10 @@ interface ResultGridProps { const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => { const [rows, setRows] = useState<SampleResult[]>([]); - const [basePath, setBasePath] = React.useState(""); - const [hoveredImageUrl, setHoveredImageUrl] = useState<string | null>(null); + const [basePath, setBasePath] = useState(''); useEffect(() => { - // Detect the current environment const mode = import.meta.env.MODE; - - // Dynamic resolution for OpenAPI.BASE OpenAPI.BASE = mode === 'test' ? import.meta.env.VITE_OPENAPI_BASE_TEST @@ -45,7 +44,7 @@ const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => { console.log('Environment Mode:', mode); console.log('Resolved OpenAPI.BASE:', OpenAPI.BASE); - // Set the base path for images dynamically + // Update the base path for images setBasePath(`${OpenAPI.BASE}/`); }, []); @@ -62,111 +61,82 @@ const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => { }, [activePgroup]); const columns: GridColDef[] = [ - { field: 'sample_id', headerName: 'ID', width: 70 }, - { field: 'sample_name', headerName: 'Sample Name', width: 150 }, - { field: 'puck_name', headerName: 'Puck Name', width: 150 }, - { field: 'dewar_name', headerName: 'Dewar Name', width: 150 }, - { - field: 'images', - headerName: 'Images', - width: 300, - renderCell: (params) => { - const imageList: ImageInfo[] = params.value; - if (imageList && imageList.length) { - const primaryImage = imageList[0]; - // Define the base path to your backend images directory - - const imageUrl = basePath + primaryImage.filepath; - - console.log("Local relative path:", imageUrl); - - console.log("Updated image URL:", imageUrl); - - return ( - <div style={{display: 'flex', alignItems: 'center', position: 'relative'}}> - <img - src={imageUrl} - alt="sample" - style={{ width: 50, height: 50, marginRight: 5, borderRadius: 4, cursor: 'pointer' }} - onMouseEnter={() => { - console.log("Mouse entered image"); - setHoveredImageUrl(imageUrl); - }} - onMouseLeave={() => { - console.log("Mouse left image"); - setHoveredImageUrl(null); - }} - /> - - {imageList.length > 1 && ( - <div className="tooltip" style={{position: 'relative', cursor: 'pointer'}}> - <span>+{imageList.length - 1}</span> - <div - className="tooltip-content" - style={{ - display: 'none', - position: 'absolute', - top: '60px', - left: 0, - background: '#fff', - padding: '5px', - boxShadow: '0 2px 8px rgba(0,0,0,0.15)', - zIndex: 100, - }} - > - {imageList.slice(1).map((img) => { - const tooltipImageUrl = basePath + img.filepath; - return ( - <img - key={img.id} - src={tooltipImageUrl} - alt="sample" - style={{width: 50, height: 50, margin: 2, borderRadius: 4}} - /> - ); - })} + { field: 'sample_id', headerName: 'ID', width: 70 }, + { field: 'sample_name', headerName: 'Sample Name', width: 150 }, + { field: 'puck_name', headerName: 'Puck Name', width: 150 }, + { field: 'dewar_name', headerName: 'Dewar Name', width: 150 }, + { + field: 'images', + headerName: 'Images', + width: 300, + renderCell: (params) => { + const imageList: ImageInfo[] = params.value; + if (imageList && imageList.length) { + const primaryImage = imageList[0]; + const imageUrl = basePath + primaryImage.filepath; + + return ( + <div style={{ display: 'flex', alignItems: 'center', position: 'relative' }}> + <img + src={imageUrl} + alt="sample" + className="zoom-image" + style={{ width: 40, height: 40, marginRight: 5, borderRadius: 4 }} + /> + {imageList.length > 1 && ( + <div className="tooltip" style={{ position: 'relative', cursor: 'pointer' }}> + <span>+{imageList.length - 1}</span> + <div + className="tooltip-content" + style={{ + display: 'none', + position: 'absolute', + top: '60px', + left: 0, + background: '#fff', + padding: '5px', + boxShadow: '0 2px 8px rgba(0,0,0,0.15)', + zIndex: 100, + }} + > + {imageList.slice(1).map((img) => { + const url = basePath + img.filepath; + return ( + <img + key={img.id} + src={url} + alt={img.comment || 'additional sample'} + className="zoom-image" + style={{ width: 40, height: 40, marginRight: 5, borderRadius: 4 }} + /> + ); + })} + + </div> </div> - </div> - )} - </div> - ); - } - return null; + )} + </div> + ); + } + return null; + }, }, - }, - ]; - - - // Map each row so that DataGrid can use a unique "id" prop; here we use sample_id. - const gridRows = rows.map((row) => ({ ...row, id: row.sample_id })); + ]; return ( - <div style={{ position: 'relative' }}> - <div style={{ height: 600, width: '100%' }}> - <DataGrid rows={gridRows} columns={columns} pageSize={10} /> - </div> - {hoveredImageUrl && ( - <div - style={{ - position: 'fixed', - top: '20%', - left: '50%', - transform: 'translate(-50%, -50%)', - zIndex: 2000, - border: '2px solid #ccc', - background: '#fff', - padding: '10px', - borderRadius: '4px', - pointerEvents: 'none', // Ensures hover stays on the image - }} - > - <img src={hoveredImageUrl} alt="large preview" style={{ maxWidth: '400px', maxHeight: '400px' }} /> - </div> - )} - </div> + <DataGrid + rows={rows} + columns={columns} + pageSize={10} + getRowId={(row) => row.sample_id} + sx={{ + '& .MuiDataGrid-cell': { + overflow: 'visible', + }, + }} + /> + ); }; - - -export default ResultGrid; +export default ResultGrid; \ No newline at end of file diff --git a/frontend/src/components/SampleImage.css b/frontend/src/components/SampleImage.css new file mode 100644 index 0000000..bd6f9b9 --- /dev/null +++ b/frontend/src/components/SampleImage.css @@ -0,0 +1,13 @@ +.zoom-image { + transition: transform 0.3s ease; + cursor: pointer; +} + +.zoom-image:hover { + transform: scale(10); /* Adjust the scale value as needed */ + z-index: 10; /* Bring it to front if overlapping */ +} + +.tooltip:hover .tooltip-content { + display: block !important; +} -- GitLab