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