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:
parent
91aebae473
commit
3a63e5a6d8
@ -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
|
||||
/>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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 */
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user