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.
This commit is contained in:
parent
548a86678b
commit
de4a6d2db8
@ -1,6 +1,9 @@
|
|||||||
|
// TypeScript (ResultGrid.tsx snippet)
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { DataGrid, GridColDef } from '@mui/x-data-grid';
|
import { DataGrid, GridColDef } from '@mui/x-data-grid';
|
||||||
import { OpenAPI, SamplesService } from '../../openapi';
|
import { OpenAPI, SamplesService } from '../../openapi';
|
||||||
|
import './Sampleimage.css';
|
||||||
|
|
||||||
|
|
||||||
interface ImageInfo {
|
interface ImageInfo {
|
||||||
id: number;
|
id: number;
|
||||||
@ -22,14 +25,10 @@ interface ResultGridProps {
|
|||||||
|
|
||||||
const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
|
const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
|
||||||
const [rows, setRows] = useState<SampleResult[]>([]);
|
const [rows, setRows] = useState<SampleResult[]>([]);
|
||||||
const [basePath, setBasePath] = React.useState("");
|
const [basePath, setBasePath] = useState('');
|
||||||
const [hoveredImageUrl, setHoveredImageUrl] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Detect the current environment
|
|
||||||
const mode = import.meta.env.MODE;
|
const mode = import.meta.env.MODE;
|
||||||
|
|
||||||
// Dynamic resolution for OpenAPI.BASE
|
|
||||||
OpenAPI.BASE =
|
OpenAPI.BASE =
|
||||||
mode === 'test'
|
mode === 'test'
|
||||||
? import.meta.env.VITE_OPENAPI_BASE_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('Environment Mode:', mode);
|
||||||
console.log('Resolved OpenAPI.BASE:', OpenAPI.BASE);
|
console.log('Resolved OpenAPI.BASE:', OpenAPI.BASE);
|
||||||
|
|
||||||
// Set the base path for images dynamically
|
// Update the base path for images
|
||||||
setBasePath(`${OpenAPI.BASE}/`);
|
setBasePath(`${OpenAPI.BASE}/`);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -62,111 +61,82 @@ const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
|
|||||||
}, [activePgroup]);
|
}, [activePgroup]);
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
{ field: 'sample_id', headerName: 'ID', width: 70 },
|
{ field: 'sample_id', headerName: 'ID', width: 70 },
|
||||||
{ field: 'sample_name', headerName: 'Sample Name', width: 150 },
|
{ field: 'sample_name', headerName: 'Sample Name', width: 150 },
|
||||||
{ field: 'puck_name', headerName: 'Puck Name', width: 150 },
|
{ field: 'puck_name', headerName: 'Puck Name', width: 150 },
|
||||||
{ field: 'dewar_name', headerName: 'Dewar Name', width: 150 },
|
{ field: 'dewar_name', headerName: 'Dewar Name', width: 150 },
|
||||||
{
|
{
|
||||||
field: 'images',
|
field: 'images',
|
||||||
headerName: 'Images',
|
headerName: 'Images',
|
||||||
width: 300,
|
width: 300,
|
||||||
renderCell: (params) => {
|
renderCell: (params) => {
|
||||||
const imageList: ImageInfo[] = params.value;
|
const imageList: ImageInfo[] = params.value;
|
||||||
if (imageList && imageList.length) {
|
if (imageList && imageList.length) {
|
||||||
const primaryImage = imageList[0];
|
const primaryImage = imageList[0];
|
||||||
// Define the base path to your backend images directory
|
const imageUrl = basePath + primaryImage.filepath;
|
||||||
|
|
||||||
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 }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
console.log("Local relative path:", imageUrl);
|
</div>
|
||||||
|
|
||||||
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}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
}
|
return null;
|
||||||
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 (
|
return (
|
||||||
<div style={{ position: 'relative' }}>
|
<DataGrid
|
||||||
<div style={{ height: 600, width: '100%' }}>
|
rows={rows}
|
||||||
<DataGrid rows={gridRows} columns={columns} pageSize={10} />
|
columns={columns}
|
||||||
</div>
|
pageSize={10}
|
||||||
{hoveredImageUrl && (
|
getRowId={(row) => row.sample_id}
|
||||||
<div
|
sx={{
|
||||||
style={{
|
'& .MuiDataGrid-cell': {
|
||||||
position: 'fixed',
|
overflow: 'visible',
|
||||||
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>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default ResultGrid;
|
export default ResultGrid;
|
13
frontend/src/components/SampleImage.css
Normal file
13
frontend/src/components/SampleImage.css
Normal file
@ -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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user