From 3a63e5a6d8de38fd11e606a935ec04da213e6e0a Mon Sep 17 00:00:00 2001
From: GotthardG <51994228+GotthardG@users.noreply.github.com>
Date: Wed, 5 Mar 2025 13:39:04 +0100
Subject: [PATCH] Add image modal functionality to RunDetails component

Introduce a modal for zooming images in the RunDetails component, enhancing UX by allowing users to click and view images in detail. Adjust styling in SampleImage.css to disable zoom effects in the details panel and ensure proper image rendering. Update ResultGrid to pass the basePath prop to support dynamic image paths.
---
 frontend/src/components/ResultGrid.tsx  |  1 +
 frontend/src/components/RunDetails.tsx  | 69 ++++++++++++++++++++++---
 frontend/src/components/SampleImage.css |  9 +++-
 3 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/frontend/src/components/ResultGrid.tsx b/frontend/src/components/ResultGrid.tsx
index a3aa790..09ad8da 100644
--- a/frontend/src/components/ResultGrid.tsx
+++ b/frontend/src/components/ResultGrid.tsx
@@ -299,6 +299,7 @@ const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
             return (
                 <RunDetails
                     run={params.row}
+                    basePath={basePath}
                     onHeightChange={(height: number) => handleDetailPanelHeightChange(params.row.id, height)} // Pass callback for dynamic height
                 />
             );
diff --git a/frontend/src/components/RunDetails.tsx b/frontend/src/components/RunDetails.tsx
index 02cbf63..b0914a3 100644
--- a/frontend/src/components/RunDetails.tsx
+++ b/frontend/src/components/RunDetails.tsx
@@ -5,18 +5,23 @@ import {
     AccordionDetails,
     Typography,
     Grid,
+    Modal,
+    Box
 } from '@mui/material';
 import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
 import './SampleImage.css';
 
 interface RunDetailsProps {
     run: ExperimentParameters;
+    basePath: string;
     onHeightChange?: (height: number) => void; // Callback to notify the parent about height changes
 }
 
-const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange }) => {
+const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange, basePath }) => {
     const containerRef = useRef<HTMLDivElement | null>(null); // Ref to track component height
     const [currentHeight, setCurrentHeight] = useState<number>(0);
+    const [modalOpen, setModalOpen] = useState<boolean>(false); // For modal state
+    const [selectedImage, setSelectedImage] = useState<string | null>(null); // Tracks the selected image for the modal
 
     const { beamline_parameters, images } = run;
     const { synchrotron, beamline, detector } = beamline_parameters;
@@ -49,8 +54,20 @@ const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange }) => {
         };
     }, [containerRef]);
 
+    const handleImageClick = (imagePath: string) => {
+        setSelectedImage(imagePath);
+        setModalOpen(true); // Open the modal when the image is clicked
+    };
+
+    const closeModal = () => {
+        setSelectedImage(null); // Clear the current image
+        setModalOpen(false);
+    };
+
+
     return (
         <div
+            className="details-panel" // Add the class here
             ref={containerRef} // Attach the ref to the main container
             style={{
                 display: 'flex',
@@ -61,7 +78,8 @@ const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange }) => {
                 alignItems: 'flex-start',
             }}
         >
-            {/* Main Details Section */}
+
+        {/* Main Details Section */}
             <div style={{ flexGrow: 1 }}>
                 <Typography variant="h6" gutterBottom>
                     Run {run.run_number} Details
@@ -144,17 +162,23 @@ const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange }) => {
                     Associated Images
                 </Typography>
                 {images && images.length > 0 ? (
-                    <Grid container spacing={2}>
+                    <Grid container spacing={1}>
                         {images.map((img) => (
-                            <Grid item xs={6} key={img.id}>
-                                <div className="image-container">
+                            <Grid item xs={4} key={img.id}>
+                                <div
+                                    className="image-container"
+                                    onClick={() => handleImageClick(`${basePath || ''}${img.filepath}`)} // Open modal with image
+                                    style={{
+                                        cursor: 'pointer',
+                                    }}
+                                >
                                     <img
-                                        src={img.filepath}
+                                        src={`${basePath || ''}${img.filepath}`} // Ensure basePath
                                         alt={img.comment || 'Image'}
                                         className="zoom-image"
                                         style={{
-                                            width: '100%',
-                                            maxWidth: '100%',
+                                            width: '100%', // Ensure the image takes the full width of its container
+                                            maxWidth: '100%', // Prevent any overflow
                                             borderRadius: '4px',
                                         }}
                                     />
@@ -168,6 +192,35 @@ const RunDetails: React.FC<RunDetailsProps> = ({ run, onHeightChange }) => {
                     </Typography>
                 )}
             </div>
+
+            {/* Modal for Zoomed Image */}
+            <Modal open={modalOpen} onClose={closeModal}>
+                <Box
+                    style={{
+                        position: 'absolute',
+                        top: '50%',
+                        left: '50%',
+                        transform: 'translate(-50%, -50%)',
+                        backgroundColor: '#fff',
+                        boxShadow: 24,
+                        padding: 16,
+                        maxHeight: '90%',
+                        overflow: 'auto',
+                    }}
+                >
+                    {selectedImage && (
+                        <img
+                            src={selectedImage}
+                            alt="Zoomed"
+                            style={{
+                                maxWidth: '100%',
+                                height: 'auto',
+                                borderRadius: '4px',
+                            }}
+                        />
+                    )}
+                </Box>
+            </Modal>
         </div>
     );
 };
diff --git a/frontend/src/components/SampleImage.css b/frontend/src/components/SampleImage.css
index ba545b9..e42d575 100644
--- a/frontend/src/components/SampleImage.css
+++ b/frontend/src/components/SampleImage.css
@@ -13,4 +13,11 @@
 
 .image-container {
     overflow: visible; /* Ensures zoomed images are not cropped by the parent */
-}
\ No newline at end of file
+}
+
+/* Disable zoom effect specifically in the details panel */
+.details-panel .zoom-image:hover {
+    transform: none; /* Disable scaling */
+    z-index: 1; /* Reset any z-index adjustment */
+    border: none; /* Reset border effect */
+}
-- 
GitLab