diff --git a/README.md b/README.md index 8d89401..6b993ba 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This project extends the original [Image-Uploader by vallezw](https://github.com - Image grouping with descriptions - Random slideshow rotation - Keyboard navigation support -- Mobile-responsive design- Mobile-responsive design +- Mobile-responsive design ## Quick Start @@ -79,8 +79,6 @@ docker compose up -d - Backend: `http://localhost:5000` - Slideshow Mode: `http://localhost/slideshow` - - ### Multi-Image Upload 1. Visit `http://localhost` @@ -115,9 +113,8 @@ docker compose up -d - View group details (title, creator, description, image count) - Bulk moderation actions -- **Group Management**: Navigate to `http://localhost/groups` (requires authentication) +- **Group Management**: Navigate to `http://localhost/groups` - Overview of all approved slideshow collections - - Delete entire groups - Launch slideshow mode from any group - View group statistics and metadata @@ -230,22 +227,17 @@ Docker Volume (app-data) ## Configuration ### Environment Variables - - | Variable | Default | Description | |----------|---------|-------------| | `API_URL` | `http://localhost:5000` | Backend API endpoint | | `CLIENT_URL` | `http://localhost` | Frontend application URL | - ### Volume Configuration - **Data Persistence**: `/usr/src/app/src/upload` and `/usr/src/app/src/data` mounted to `app-data` - **Upload Limits**: 100MB maximum file size for batch uploads - **Supported Formats**: JPG, JPEG, PNG, GIF, WebP - - ### Custom Deployment For production deployment, modify the docker-compose configuration: @@ -263,17 +255,14 @@ environment: ### Backup & Restore #### Backup slideshow data ```sh -docker cp backend:/usr/src/app/src/data ./backup-data -docker cp backend:/usr/src/app/src/upload ./backup-images +docker cp backend:/usr/src/app/src/data/ ./backup-data ``` #### Restore slideshow data ```sh docker cp ./backup-data backend:/usr/src/app/src/data -docker cp ./backup-images backend:/usr/src/app/src/upload ``` - ## Contributing Contributions are welcome! This project extends the original work by [vallezw](https://github.com/vallezw/Image-Uploader). diff --git a/backend/src/constants.js b/backend/src/constants.js index 651d84d..0ed5141 100644 --- a/backend/src/constants.js +++ b/backend/src/constants.js @@ -8,9 +8,13 @@ const endpoints = { DELETE_GROUP: '/groups/:groupId' }; +// Filesystem directory (relative to backend/src) where uploaded images will be stored +// Use path.join(__dirname, '..', UPLOAD_FS_DIR, fileName) in code +const UPLOAD_FS_DIR = 'data/images'; + const time = { HOURS_24: 86400000, WEEK_1: 604800000 }; -module.exports = { endpoints, time }; \ No newline at end of file +module.exports = { endpoints, time, UPLOAD_FS_DIR }; \ No newline at end of file diff --git a/backend/src/database/DatabaseManager.js b/backend/src/database/DatabaseManager.js index a767fd3..6be73c9 100644 --- a/backend/src/database/DatabaseManager.js +++ b/backend/src/database/DatabaseManager.js @@ -5,7 +5,8 @@ const fs = require('fs'); class DatabaseManager { constructor() { this.db = null; - this.dbPath = path.join(__dirname, '../data/image_uploader.db'); // FIX: ../data statt ../../data + // Place database file under data/db + this.dbPath = path.join(__dirname, '../data/db/image_uploader.db'); this.schemaPath = path.join(__dirname, 'schema.sql'); } diff --git a/backend/src/routes/batchUpload.js b/backend/src/routes/batchUpload.js index fe9ec23..b794f9b 100644 --- a/backend/src/routes/batchUpload.js +++ b/backend/src/routes/batchUpload.js @@ -45,8 +45,10 @@ router.post(endpoints.UPLOAD_BATCH, async (req, res) => { const fileEnding = file.name.split(".").pop(); const fileName = generateId() + '.' + fileEnding; - // Speichere Datei - const uploadPath = `${__dirname}/..${endpoints.UPLOAD_STATIC_DIRECTORY}/${fileName}`; + // Speichere Datei unter data/images + const path = require('path'); + const { UPLOAD_FS_DIR } = require('../constants'); + const uploadPath = path.join(__dirname, '..', UPLOAD_FS_DIR, fileName); file.mv(uploadPath, (err) => { if (err) { console.error('Error saving file:', err); diff --git a/backend/src/routes/download.js b/backend/src/routes/download.js index eeba1c5..a7b042e 100644 --- a/backend/src/routes/download.js +++ b/backend/src/routes/download.js @@ -1,10 +1,12 @@ const { Router } = require('express'); -const { endpoints } = require('../constants'); +const { endpoints, UPLOAD_FS_DIR } = require('../constants'); +const path = require('path'); const router = Router(); router.get(endpoints.DOWNLOAD_FILE, (req, res) => { - res.download(`${__dirname}/..${endpoints.UPLOAD_STATIC_DIRECTORY}/${req.params.id}`); + const filePath = path.join(__dirname, '..', UPLOAD_FS_DIR, req.params.id); + res.download(filePath); }); module.exports = router; diff --git a/backend/src/routes/upload.js b/backend/src/routes/upload.js index ecda0d3..d4876be 100644 --- a/backend/src/routes/upload.js +++ b/backend/src/routes/upload.js @@ -1,11 +1,13 @@ const generateId = require("shortid"); const express = require('express'); const { Router } = require('express'); -const { endpoints } = require('../constants'); +const { endpoints, UPLOAD_FS_DIR } = require('../constants'); +const path = require('path'); const router = Router(); -router.use(endpoints.UPLOAD_STATIC_DIRECTORY, express.static( __dirname + endpoints.UPLOAD_STATIC_DIRECTORY)); +// Serve uploaded images via URL /upload but store files under data/images +router.use(endpoints.UPLOAD_STATIC_DIRECTORY, express.static( path.join(__dirname, '..', UPLOAD_FS_DIR) )); router.post(endpoints.UPLOAD_FILE, (req, res) => { if(req.files === null){ @@ -19,7 +21,8 @@ router.post(endpoints.UPLOAD_FILE, (req, res) => { fileEnding = fileEnding[fileEnding.length - 1] fileName = generateId() + '.' + fileEnding - file.mv(`${__dirname}/..` + endpoints.UPLOAD_STATIC_DIRECTORY + `/${fileName}`, err => { + const savePath = path.join(__dirname, '..', UPLOAD_FS_DIR, fileName); + file.mv(savePath, err => { if(err) { console.error(err); return res.status(500).send(err); diff --git a/backend/src/services/MigrationService.js b/backend/src/services/MigrationService.js index b106ce4..612dc03 100644 --- a/backend/src/services/MigrationService.js +++ b/backend/src/services/MigrationService.js @@ -5,8 +5,9 @@ const dbManager = require('../database/DatabaseManager'); class MigrationService { constructor() { - this.jsonDataPath = path.join(__dirname, '../data'); - this.backupPath = path.join(__dirname, '../data/backup'); + // JSON metadata and backups now live under data/db + this.jsonDataPath = path.join(__dirname, '../data/db'); + this.backupPath = path.join(__dirname, '../data/db/backup'); } // Hauptmigration von JSON zu SQLite diff --git a/backend/src/utils/groupStorage.js b/backend/src/utils/groupStorage.js index 4cc5fb8..3facd75 100644 --- a/backend/src/utils/groupStorage.js +++ b/backend/src/utils/groupStorage.js @@ -1,7 +1,8 @@ const fs = require('fs'); const path = require('path'); -const GROUPS_FILE = path.join(__dirname, '../data/upload-groups.json'); +// Store JSON metadata under data/db +const GROUPS_FILE = path.join(__dirname, '../data/db/upload-groups.json'); class GroupStorage { // Initialisiere die JSON-Datei falls sie nicht existiert diff --git a/backend/src/utils/initiate-resources.js b/backend/src/utils/initiate-resources.js index 398402b..c9fb87d 100644 --- a/backend/src/utils/initiate-resources.js +++ b/backend/src/utils/initiate-resources.js @@ -2,7 +2,8 @@ const { applyMiddlewares } = require('../middlewares'); const { renderRoutes } = require('../routes/index'); const removeImages = require('./remove-images'); const fs = require('fs'); -const { endpoints } = require('../constants'); +const path = require('path'); +const { endpoints, UPLOAD_FS_DIR } = require('../constants'); const initiateResources = (app) => { @@ -10,10 +11,16 @@ const initiateResources = (app) => { renderRoutes(app); - const dir = `${__dirname}/..` + endpoints.UPLOAD_STATIC_DIRECTORY + // Ensure upload images directory exists: backend/src/../data/images + const imagesDir = path.join(__dirname, '..', UPLOAD_FS_DIR); + if (!fs.existsSync(imagesDir)){ + fs.mkdirSync(imagesDir, { recursive: true }); + } - if (!fs.existsSync(dir)){ - fs.mkdirSync(dir); + // Ensure db directory exists: backend/src/../data/db + const dbDir = path.join(__dirname, '..', 'data', 'db'); + if (!fs.existsSync(dbDir)){ + fs.mkdirSync(dbDir, { recursive: true }); } if(process.env.REMOVE_IMAGES === 'true') { diff --git a/docker-compose.yml b/docker-compose.yml index 1a4f234..7513e24 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,8 +27,7 @@ services: networks: - image-uploader-internal volumes: - - app-data:/usr/src/app/src/upload - - app-data:/usr/src/app/src/data + - app-data:/usr/src/app/data volumes: app-data: diff --git a/prod.sh b/prod.sh index 848fbbe..4bb9b9b 100755 --- a/prod.sh +++ b/prod.sh @@ -109,11 +109,11 @@ case $choice in 12) echo -e "${GREEN}Upload-Verzeichnis Inhalt:${NC}" if docker compose ps -q image-uploader-backend > /dev/null 2>&1; then - echo -e "${BLUE}Hochgeladene Bilder:${NC}" - docker compose exec image-uploader-backend ls -la /usr/src/app/src/upload/ || echo "Upload-Verzeichnis ist leer" + echo -e "${BLUE}Hochgeladene Bilder (data/images):${NC}" + docker compose exec image-uploader-backend ls -la /usr/src/app/data/images/ || echo "Upload-Verzeichnis ist leer" echo - echo -e "${BLUE}JSON Metadaten:${NC}" - docker compose exec image-uploader-backend ls -la /usr/src/app/src/data/ || echo "Keine Metadaten vorhanden" + echo -e "${BLUE}JSON Metadaten (data/db):${NC}" + docker compose exec image-uploader-backend ls -la /usr/src/app/data/db/ || echo "Keine Metadaten vorhanden" else echo -e "${YELLOW}Backend Container ist nicht gestartet.${NC}" fi