added image support
This commit is contained in:
parent
65ed1548a7
commit
15fc3944b4
8 changed files with 255 additions and 187 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1 +1,3 @@
|
|||
node_modules
|
||||
env
|
||||
.env
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -4513,9 +4513,9 @@
|
|||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
|
||||
"version": "16.4.7",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
|
||||
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="
|
||||
},
|
||||
"dotenv-expand": {
|
||||
"version": "5.1.0",
|
||||
|
|
@ -10368,6 +10368,13 @@
|
|||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-manifest-plugin": "^4.0.2",
|
||||
"workbox-webpack-plugin": "^6.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"read-cache": {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"dotenv": "^16.4.7",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1"
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ function App() {
|
|||
setSelectedProjectId(null);
|
||||
};
|
||||
|
||||
const selectedProject = selectedProjectId
|
||||
? projects.find(p => p.id === selectedProjectId)
|
||||
: null;
|
||||
const selectedProject = selectedProjectId ? projects.find(p => p.id === selectedProjectId) : null;
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
|
|
|
|||
|
|
@ -2,44 +2,63 @@ import React, { useState, useEffect } from 'react';
|
|||
|
||||
const ImageCarousel = ({ projectId }) => {
|
||||
const [images, setImages] = useState([]);
|
||||
const [highResImages, setHighResImages] = useState([]);
|
||||
const [fileIds, setFileIds] = useState([]);
|
||||
const [currentImageIndex, setCurrentImageIndex] = useState(0);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [viewMode, setViewMode] = useState('thumbnail');
|
||||
|
||||
const getDirectDownloadUrl = (fileId) => {
|
||||
return `https://lh3.google.com/u/0/d/${fileId}`
|
||||
};
|
||||
|
||||
const getThumbnailUrl = (fileId) => {
|
||||
return `https://drive.google.com/thumbnail?id=${fileId}&sz=w300`;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const loadImages = async () => {
|
||||
try {
|
||||
const apiKey = process.env.REACT_APP_GOOGLE_API_KEY;
|
||||
|
||||
const importAll = (r) => r.keys().map(r);
|
||||
|
||||
let imageContext = null;
|
||||
|
||||
try {
|
||||
switch(projectId){
|
||||
case "mycology-lab":
|
||||
imageContext = require.context(`../assets/mycology-lab`, false, /\.(png|jpe?g|svg)$/);
|
||||
break
|
||||
case "loanterra":
|
||||
imageContext = require.context(`../assets/loanterra`, false, /\.(png|jpe?g|svg)$/);
|
||||
break
|
||||
case "orchard-market":
|
||||
imageContext = require.context(`../assets/orchard-market`, false, /\.(png|jpe?g|svg)$/);
|
||||
break
|
||||
case "fecal-vision-model":
|
||||
imageContext = require.context(`../assets/fecal-vision-model`, false, /\.(png|jpe?g|svg)$/);
|
||||
break
|
||||
default:
|
||||
imageContext = require.context(`../assets/mycology-lab`, false, /\.(png|jpe?g|svg)$/);
|
||||
if (!apiKey) {
|
||||
throw new Error("Google API key not found in environment variables");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Error", e);
|
||||
|
||||
let folderId = "1kLdnnm47c7GkmKgiyIbv2QXh7sqFZ6p4";
|
||||
|
||||
let query = encodeURIComponent(`'${folderId}' in parents and trashed=false`);
|
||||
|
||||
let driveResponse = await fetch(
|
||||
`https://www.googleapis.com/drive/v3/files?q=${query}&fields=files(id,name,mimeType)&key=${apiKey}`
|
||||
);
|
||||
|
||||
if (!driveResponse.ok) {
|
||||
throw new Error(`Google Drive API error: ${driveResponse.status}`);
|
||||
}
|
||||
if(imageContext){
|
||||
const imageFiles = importAll(imageContext);
|
||||
setImages(imageFiles);
|
||||
|
||||
const folderData = await driveResponse.json();
|
||||
let foundFolder = folderData.files.filter(file => file.mimeType.startsWith('application/')).find(item => item.name === projectId);
|
||||
|
||||
if (foundFolder) {
|
||||
folderId = foundFolder.id;
|
||||
query = encodeURIComponent(`'${folderId}' in parents and trashed=false`);
|
||||
driveResponse = await fetch(
|
||||
`https://www.googleapis.com/drive/v3/files?q=${query}&fields=files(id,name,mimeType)&key=${apiKey}`
|
||||
);
|
||||
|
||||
const fileData = await driveResponse.json();
|
||||
const ids = fileData.files
|
||||
.filter(file => file.mimeType.startsWith('image/'))
|
||||
.map(file => file.id);
|
||||
|
||||
setFileIds(ids);
|
||||
const thumbnailUrls = ids.map(id => getThumbnailUrl(id));
|
||||
setImages(thumbnailUrls);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading images:", error);
|
||||
|
||||
setImages([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
|
@ -47,17 +66,40 @@ const ImageCarousel = ({ projectId }) => {
|
|||
};
|
||||
|
||||
loadImages();
|
||||
|
||||
setCurrentImageIndex(0);
|
||||
setViewMode('thumbnail');
|
||||
}, [projectId]);
|
||||
|
||||
const toggleViewMode = () => {
|
||||
if (viewMode === 'thumbnail') {
|
||||
setViewMode('highres');
|
||||
setHighResImages([]);
|
||||
setLoading(true);
|
||||
const highResUrls = fileIds.map(id => getDirectDownloadUrl(id));
|
||||
setHighResImages(highResUrls);
|
||||
setLoading(false);
|
||||
} else {
|
||||
setViewMode('thumbnail');
|
||||
|
||||
setImages([]);
|
||||
setLoading(true);
|
||||
const thumbnailUrls = fileIds.map(id => getThumbnailUrl(id));
|
||||
setImages(thumbnailUrls);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const nextImage = () => {
|
||||
if(viewMode === 'highres')
|
||||
toggleViewMode();
|
||||
setCurrentImageIndex((prevIndex) =>
|
||||
prevIndex === images.length - 1 ? 0 : prevIndex + 1
|
||||
);
|
||||
};
|
||||
|
||||
const prevImage = () => {
|
||||
if(viewMode === 'highres')
|
||||
toggleViewMode();
|
||||
setCurrentImageIndex((prevIndex) =>
|
||||
prevIndex === 0 ? images.length - 1 : prevIndex - 1
|
||||
);
|
||||
|
|
@ -70,7 +112,10 @@ const ImageCarousel = ({ projectId }) => {
|
|||
if (images.length === 0) {
|
||||
return <div className="carousel-empty">No images available</div>;
|
||||
}
|
||||
|
||||
const addDefaultImg = ev => {
|
||||
// ev.target.src = images[currentImageIndex]
|
||||
ev.target.src = 'https://upload.wikimedia.org/wikipedia/commons/1/14/No_Image_Available.jpg'
|
||||
}
|
||||
return (
|
||||
<div className="carousel">
|
||||
<button
|
||||
|
|
@ -83,12 +128,25 @@ const ImageCarousel = ({ projectId }) => {
|
|||
|
||||
<div className="carousel-image-container">
|
||||
<img
|
||||
src={images[currentImageIndex]}
|
||||
src={viewMode === "thumbnail" ? images[currentImageIndex] : highResImages[currentImageIndex]}
|
||||
alt={`Project ${projectId} - ${currentImageIndex + 1}`}
|
||||
className="carousel-image"
|
||||
onClick={toggleViewMode}
|
||||
onError={(e) => addDefaultImg}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 'auto'
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="carousel-counter">
|
||||
{currentImageIndex + 1} / {images.length}
|
||||
{viewMode === 'thumbnail' && (
|
||||
<span className="image-quality-indicator"> [SD](Click Image for HD)</span>
|
||||
)}
|
||||
{viewMode === 'highres' && (
|
||||
<span className="image-quality-indicator"> [HD](Click Image for SD)</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -103,4 +161,6 @@ const ImageCarousel = ({ projectId }) => {
|
|||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default ImageCarousel;
|
||||
Loading…
Reference in a new issue