From 02a47fa0b2a5a2daf4005d36aa4fd25957b6333b Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Thu, 10 Jul 2025 11:58:44 +0200 Subject: [PATCH] added multiple pic viewer and additional fixes --- .../pages/AssetManagement/AssetManagement.css | 131 +++++++++++++++++- .../pages/AssetManagement/AssetManagement.js | 69 +++++++-- 2 files changed, 188 insertions(+), 12 deletions(-) diff --git a/public/js/pages/AssetManagement/AssetManagement.css b/public/js/pages/AssetManagement/AssetManagement.css index ca0bb14c6..d82dab01d 100644 --- a/public/js/pages/AssetManagement/AssetManagement.css +++ b/public/js/pages/AssetManagement/AssetManagement.css @@ -30,19 +30,20 @@ height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; + flex-direction: column; /* Allow content to stack */ justify-content: center; align-items: center; z-index: 9999; cursor: zoom-out; /* Indicate it's closable */ - /* Ensure it can receive keyboard events for 'esc' */ outline: none; } .tt-fullscreen-image { max-width: 90%; - max-height: 90%; + max-height: 80%; /* Give space for gallery */ object-fit: contain; cursor: default; /* Change cursor back to default when over the image */ + transition: all 0.3s ease-in-out; } .tt-fullscreen-close-btn { @@ -61,4 +62,130 @@ .tt-fullscreen-close-btn:hover { color: #f0f0f0; +} + +.tt-fullscreen-gallery-nav { + position: absolute; + bottom: 20px; /* Position at the bottom */ + width: 90%; /* Match image width */ + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + z-index: 10000; + background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background for readability */ + padding: 10px; + border-radius: 8px; +} + +.tt-fullscreen-gallery-nav .nav-arrow { + background: none; + border: none; + color: white; + font-size: 24px; + cursor: pointer; + padding: 0 10px; +} + +.tt-fullscreen-gallery-nav .nav-arrow:hover { + color: #f0f0f0; +} + +.tt-fullscreen-gallery-nav .gallery-thumbnails { + display: flex; + gap: 8px; + overflow-x: auto; /* Allow horizontal scrolling for many thumbnails */ + padding: 5px 0; + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} + +.tt-fullscreen-gallery-nav .gallery-thumbnails::-webkit-scrollbar { + display: none; /* Chrome, Safari, Opera */ +} + + +.tt-fullscreen-gallery-nav .thumbnail { + width: 70px; + height: 70px; + object-fit: cover; + border: 2px solid transparent; + border-radius: 4px; + cursor: pointer; + transition: border-color 0.2s ease, transform 0.2s ease; +} + +.tt-fullscreen-gallery-nav .thumbnail:hover { + border-color: #fff; + transform: scale(1.05); +} + +.tt-fullscreen-gallery-nav .thumbnail.active { + border-color: #3b82f6; /* Highlight active thumbnail */ + transform: scale(1.05); +} + +/* Modal gallery grid for uploaded images */ +.asset-gallery-upload-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); /* Responsive grid */ + gap: 15px; + padding: 10px 0; +} + +.asset-gallery-upload-grid .gallery-item { + position: relative; + border: 1px solid #eee; + border-radius: 5px; + overflow: hidden; + padding-bottom: 100%; /* Creates a square aspect ratio */ + background-color: #f8f8f8; +} + +.asset-gallery-upload-grid .gallery-item img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +.asset-gallery-upload-grid .gallery-item.is-main::before { + content: '\f005'; /* FontAwesome star icon */ + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + position: absolute; + top: 5px; + left: 5px; + color: gold; + background-color: rgba(0, 0, 0, 0.4); + border-radius: 3px; + padding: 2px 5px; + font-size: 14px; + z-index: 5; +} + +.asset-gallery-upload-grid .gallery-item-actions { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: space-around; + padding: 5px; + opacity: 0; + transition: opacity 0.2s ease-in-out; + z-index: 4; +} + +.asset-gallery-upload-grid .gallery-item:hover .gallery-item-actions { + opacity: 1; +} + +.asset-gallery-upload-grid .gallery-item-actions .btn { + color: white; + font-size: 1rem; + padding: .25rem .5rem; } \ No newline at end of file diff --git a/public/js/pages/AssetManagement/AssetManagement.js b/public/js/pages/AssetManagement/AssetManagement.js index b3ccbceeb..b31049d4c 100644 --- a/public/js/pages/AssetManagement/AssetManagement.js +++ b/public/js/pages/AssetManagement/AssetManagement.js @@ -36,11 +36,11 @@ Vue.component('asset-management', { @@ -103,15 +103,20 @@ Vue.component('asset-management', { Vue.component('tt-asset-image', { props: { imageId: Number, + allImageIds: { + type: Array, + default: () => [] + } }, data() { return { isFullScreen: false, + currentFullScreenImageId: null, }; }, template: `
- +
@@ -122,11 +127,29 @@ Vue.component('tt-asset-image', { @keydown.esc="closeFullScreen" tabindex="-1" ref="fullScreenOverlay"> - + @click.stop /> + + +
`, @@ -134,18 +157,42 @@ Vue.component('tt-asset-image', { onImageError(event) { event.target.src = 'https://placehold.co/60x60/eee/ccc?text=Error'; // Fallback placeholder }, - openFullScreen() { + openFullScreen(initialImageId) { if (this.imageId) { // Only open if an image exists this.isFullScreen = true; + this.currentFullScreenImageId = initialImageId; this.$nextTick(() => { if (this.$refs.fullScreenOverlay) { this.$refs.fullScreenOverlay.focus(); // Focus the overlay to capture keydown events } + document.addEventListener('keydown', this.handleKeyDown); }); } }, closeFullScreen() { this.isFullScreen = false; + this.currentFullScreenImageId = null; + document.removeEventListener('keydown', this.handleKeyDown); + }, + setFullScreenImage(imageId) { + this.currentFullScreenImageId = imageId; + }, + prevImage() { + const currentIndex = this.allImageIds.indexOf(this.currentFullScreenImageId); + const prevIndex = (currentIndex - 1 + this.allImageIds.length) % this.allImageIds.length; + this.currentFullScreenImageId = this.allImageIds[prevIndex]; + }, + nextImage() { + const currentIndex = this.allImageIds.indexOf(this.currentFullScreenImageId); + const nextIndex = (currentIndex + 1) % this.allImageIds.length; + this.currentFullScreenImageId = this.allImageIds[nextIndex]; + }, + handleKeyDown(event) { + if (event.key === 'ArrowLeft') { + this.prevImage(); + } else if (event.key === 'ArrowRight') { + this.nextImage(); + } } }, watch: { @@ -365,7 +412,7 @@ Vue.component('asset-management-modal', {
Noch keine Bilder hochgeladen.
-