Make images draggable between products, add zoom

This commit is contained in:
2025-02-26 18:20:49 -05:00
parent 41f7f33746
commit e3361cf098
2 changed files with 747 additions and 152 deletions

View File

@@ -10,6 +10,113 @@ const fs = require('fs');
const uploadsDir = path.join('/var/www/html/inventory/uploads/products');
fs.mkdirSync(uploadsDir, { recursive: true });
// Create a Map to track image upload times and their scheduled deletion
const imageUploadMap = new Map();
// Function to schedule image deletion after 24 hours
const scheduleImageDeletion = (filename, filePath) => {
// Delete any existing timeout for this file
if (imageUploadMap.has(filename)) {
clearTimeout(imageUploadMap.get(filename).timeoutId);
}
// Schedule deletion after 24 hours (24 * 60 * 60 * 1000 ms)
const timeoutId = setTimeout(() => {
console.log(`Auto-deleting image after 24 hours: ${filename}`);
// Check if file exists before trying to delete
if (fs.existsSync(filePath)) {
try {
fs.unlinkSync(filePath);
console.log(`Successfully auto-deleted image: ${filename}`);
} catch (error) {
console.error(`Error auto-deleting image ${filename}:`, error);
}
} else {
console.log(`File already deleted: ${filename}`);
}
// Remove from tracking map
imageUploadMap.delete(filename);
}, 24 * 60 * 60 * 1000); // 24 hours
// Store upload time and timeout ID
imageUploadMap.set(filename, {
uploadTime: new Date(),
timeoutId: timeoutId,
filePath: filePath
});
};
// Function to clean up scheduled deletions on server restart
const cleanupImagesOnStartup = () => {
console.log('Checking for images to clean up...');
// Check if uploads directory exists
if (!fs.existsSync(uploadsDir)) {
console.log('Uploads directory does not exist');
return;
}
// Read all files in the directory
fs.readdir(uploadsDir, (err, files) => {
if (err) {
console.error('Error reading uploads directory:', err);
return;
}
const now = new Date();
let countDeleted = 0;
files.forEach(filename => {
const filePath = path.join(uploadsDir, filename);
// Get file stats
try {
const stats = fs.statSync(filePath);
const fileCreationTime = stats.birthtime || stats.ctime; // birthtime might not be available on all systems
const ageMs = now.getTime() - fileCreationTime.getTime();
// If file is older than 24 hours, delete it
if (ageMs > 24 * 60 * 60 * 1000) {
fs.unlinkSync(filePath);
countDeleted++;
console.log(`Deleted old image on startup: ${filename} (age: ${Math.round(ageMs / (60 * 60 * 1000))} hours)`);
} else {
// Schedule deletion for remaining time
const remainingMs = (24 * 60 * 60 * 1000) - ageMs;
console.log(`Scheduling deletion for ${filename} in ${Math.round(remainingMs / (60 * 60 * 1000))} hours`);
const timeoutId = setTimeout(() => {
if (fs.existsSync(filePath)) {
try {
fs.unlinkSync(filePath);
console.log(`Successfully auto-deleted scheduled image: ${filename}`);
} catch (error) {
console.error(`Error auto-deleting scheduled image ${filename}:`, error);
}
}
imageUploadMap.delete(filename);
}, remainingMs);
imageUploadMap.set(filename, {
uploadTime: fileCreationTime,
timeoutId: timeoutId,
filePath: filePath
});
}
} catch (error) {
console.error(`Error processing file ${filename}:`, error);
}
});
console.log(`Cleanup completed: ${countDeleted} old images deleted, ${imageUploadMap.size} images scheduled for deletion`);
});
};
// Run cleanup on server start
cleanupImagesOnStartup();
// Configure multer for file uploads
const storage = multer.diskStorage({
destination: function (req, file, cb) {
@@ -138,6 +245,9 @@ router.post('/upload-image', upload.single('image'), (req, res) => {
const baseUrl = 'https://inventory.acot.site';
const imageUrl = `${baseUrl}/uploads/products/${req.file.filename}`;
// Schedule this image for deletion in 24 hours
scheduleImageDeletion(req.file.filename, filePath);
// Return success response with image URL
res.status(200).json({
success: true,
@@ -145,7 +255,7 @@ router.post('/upload-image', upload.single('image'), (req, res) => {
fileName: req.file.filename,
mimetype: req.file.mimetype,
fullPath: filePath,
message: 'Image uploaded successfully'
message: 'Image uploaded successfully (will auto-delete after 24 hours)'
});
} catch (error) {
@@ -173,6 +283,12 @@ router.delete('/delete-image', (req, res) => {
// Delete the file
fs.unlinkSync(filePath);
// Clear any scheduled deletion for this file
if (imageUploadMap.has(filename)) {
clearTimeout(imageUploadMap.get(filename).timeoutId);
imageUploadMap.delete(filename);
}
// Return success response
res.status(200).json({
success: true,