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.
This commit is contained in:
GotthardG 2025-03-05 13:39:04 +01:00
parent 91aebae473
commit 3a63e5a6d8
3 changed files with 70 additions and 9 deletions

View File

@ -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
/>
);

View File

@ -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>
);
};

View File

@ -13,4 +13,11 @@
.image-container {
overflow: visible; /* Ensures zoomed images are not cropped by the parent */
}
}
/* 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 */
}