Beta-2.1 - The clearer, the faster #22
@ -18,7 +18,16 @@
|
||||
<button id="remove-all-hero" class="up-btn">🗑 Delete all</button>
|
||||
</div>
|
||||
<input type="file" id="upload-hero" accept=".png,.jpg,.jpeg,.webp" multiple hidden>
|
||||
<span id="hero-count" class="photo-count"></span>
|
||||
<div id="hero"></div>
|
||||
<input type="file" id="upload-hero-bottom" accept=".png,.jpg,.jpeg,.webp" multiple hidden>
|
||||
<div id="bottom-hero-upload" class="upload-actions-row bottom-action-row">
|
||||
<span id="hero-count-bottom" class="photo-count"></span>
|
||||
<label for="upload-hero-bottom" class="up-btn">
|
||||
📸 Upload photos
|
||||
</label>
|
||||
<button id="remove-all-hero-bottom" class="up-btn bottom-remove-btn">🗑 Delete all</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gallery Upload Section -->
|
||||
@ -31,8 +40,17 @@
|
||||
</label>
|
||||
<button id="remove-all-gallery" class="up-btn">🗑 Delete all</button>
|
||||
</div>
|
||||
<span id="gallery-count" class="photo-count"></span>
|
||||
<input type="file" id="upload-gallery" accept=".png,.jpg,.jpeg,.webp" multiple hidden>
|
||||
<div id="gallery"></div>
|
||||
<input type="file" id="upload-gallery-bottom" accept=".png,.jpg,.jpeg,.webp" multiple hidden>
|
||||
<div id="bottom-gallery-upload" class="upload-actions-row bottom-action-row">
|
||||
<span id="gallery-count-bottom" class="photo-count"></span>
|
||||
<label for="upload-gallery-bottom" class="up-btn">
|
||||
📸 Upload photos
|
||||
</label>
|
||||
<button id="remove-all-gallery-bottom" class="up-btn bottom-remove-btn">🗑 Delete all</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
|
@ -54,11 +54,35 @@ function renderGallery() {
|
||||
renderTags(i, img.tags || []);
|
||||
});
|
||||
|
||||
// Show/hide Remove All button
|
||||
// Update gallery count (top)
|
||||
const galleryCount = document.getElementById('gallery-count');
|
||||
if (galleryCount) {
|
||||
galleryCount.innerHTML = `<p>${galleryImages.length} photos</p>`;
|
||||
}
|
||||
|
||||
// Update gallery count (bottom)
|
||||
const galleryCountBottom = document.getElementById('gallery-count-bottom');
|
||||
if (galleryCountBottom) {
|
||||
galleryCountBottom.innerHTML = `<p>${galleryImages.length} photos</p>`;
|
||||
}
|
||||
|
||||
// Show/hide Remove All button (top)
|
||||
const removeAllBtn = document.getElementById('remove-all-gallery');
|
||||
if (removeAllBtn) {
|
||||
removeAllBtn.style.display = galleryImages.length > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
// Show/hide bottom upload row
|
||||
const bottomGalleryUpload = document.getElementById('bottom-gallery-upload');
|
||||
if (bottomGalleryUpload) {
|
||||
bottomGalleryUpload.style.display = galleryImages.length > 0 ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
// Show/hide Remove All button (bottom)
|
||||
const removeAllBtnBottom = document.getElementById('remove-all-gallery-bottom');
|
||||
if (removeAllBtnBottom) {
|
||||
removeAllBtnBottom.style.display = galleryImages.length > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// --- Render tags for a single image ---
|
||||
@ -244,11 +268,35 @@ function renderHero() {
|
||||
container.appendChild(div);
|
||||
});
|
||||
|
||||
// Show/hide Remove All button
|
||||
// Update hero count (top)
|
||||
const heroCount = document.getElementById('hero-count');
|
||||
if (heroCount) {
|
||||
heroCount.innerHTML = `<p>${heroImages.length} photos</p>`;
|
||||
}
|
||||
|
||||
// Update hero count (bottom)
|
||||
const heroCountBottom = document.getElementById('hero-count-bottom');
|
||||
if (heroCountBottom) {
|
||||
heroCountBottom.innerHTML = `<p>${heroImages.length} photos</p>`;
|
||||
}
|
||||
|
||||
// Show/hide Remove All button (top)
|
||||
const removeAllBtn = document.getElementById('remove-all-hero');
|
||||
if (removeAllBtn) {
|
||||
removeAllBtn.style.display = heroImages.length > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
// Show/hide bottom upload row
|
||||
const bottomHeroUpload = document.getElementById('bottom-hero-upload');
|
||||
if (bottomHeroUpload) {
|
||||
bottomHeroUpload.style.display = heroImages.length > 0 ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
// Show/hide Remove All button (bottom)
|
||||
const removeAllBtnBottom = document.getElementById('remove-all-hero-bottom');
|
||||
if (removeAllBtnBottom) {
|
||||
removeAllBtnBottom.style.display = heroImages.length > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// --- Save gallery to server ---
|
||||
@ -429,9 +477,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// Bulk delete buttons
|
||||
const removeAllGalleryBtn = document.getElementById('remove-all-gallery');
|
||||
const removeAllGalleryBtnBottom = document.getElementById('remove-all-gallery-bottom');
|
||||
const removeAllHeroBtn = document.getElementById('remove-all-hero');
|
||||
const removeAllHeroBtnBottom = document.getElementById('remove-all-hero-bottom');
|
||||
if (removeAllGalleryBtn) removeAllGalleryBtn.onclick = () => showDeleteModal('gallery-all');
|
||||
if (removeAllGalleryBtnBottom) removeAllGalleryBtnBottom.onclick = () => showDeleteModal('gallery-all');
|
||||
if (removeAllHeroBtn) removeAllHeroBtn.onclick = () => showDeleteModal('hero-all');
|
||||
if (removeAllHeroBtnBottom) removeAllHeroBtnBottom.onclick = () => showDeleteModal('hero-all');
|
||||
});
|
||||
|
||||
// --- Initialize ---
|
||||
|
@ -11,6 +11,7 @@ function hideLoader() {
|
||||
if (loader) loader.classList.remove("active");
|
||||
}
|
||||
|
||||
|
||||
// --- Upload gallery images ---
|
||||
const galleryInput = document.getElementById('upload-gallery');
|
||||
if (galleryInput) {
|
||||
@ -62,3 +63,55 @@ if (heroInput) {
|
||||
} finally { e.target.value = ''; }
|
||||
});
|
||||
}
|
||||
|
||||
// --- Upload gallery images (bottom button) ---
|
||||
const galleryInputBottom = document.getElementById('upload-gallery-bottom');
|
||||
if (galleryInputBottom) {
|
||||
galleryInputBottom.addEventListener('change', async (e) => {
|
||||
const files = e.target.files;
|
||||
if (!files.length) return;
|
||||
showLoader("Uploading photos...");
|
||||
const formData = new FormData();
|
||||
for (const file of files) formData.append('files', file);
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/gallery/upload', { method: 'POST', body: formData });
|
||||
const data = await res.json();
|
||||
hideLoader();
|
||||
if (res.ok) {
|
||||
showToast(`✅ ${data.uploaded.length} gallery image(s) uploaded!`, "success");
|
||||
if (typeof refreshGallery === "function") refreshGallery();
|
||||
} else showToast('Error: ' + data.error, "error");
|
||||
} catch(err) {
|
||||
hideLoader();
|
||||
console.error(err);
|
||||
showToast('Server error!', "error");
|
||||
} finally { e.target.value = ''; }
|
||||
});
|
||||
}
|
||||
|
||||
// --- Upload hero images (bottom button) ---
|
||||
const heroInputBottom = document.getElementById('upload-hero-bottom');
|
||||
if (heroInputBottom) {
|
||||
heroInputBottom.addEventListener('change', async (e) => {
|
||||
const files = e.target.files;
|
||||
if (!files.length) return;
|
||||
showLoader("Uploading hero photos...");
|
||||
const formData = new FormData();
|
||||
for (const file of files) formData.append('files', file);
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/hero/upload', { method: 'POST', body: formData });
|
||||
const data = await res.json();
|
||||
hideLoader();
|
||||
if (res.ok) {
|
||||
showToast(`✅ ${data.uploaded.length} hero image(s) uploaded!`, "success");
|
||||
if (typeof refreshHero === "function") refreshHero();
|
||||
} else showToast('Error: ' + data.error, "error");
|
||||
} catch(err) {
|
||||
hideLoader();
|
||||
console.error(err);
|
||||
showToast('Server error!', "error");
|
||||
} finally { e.target.value = ''; }
|
||||
});
|
||||
}
|
@ -241,7 +241,7 @@ h2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
gap: 15px;
|
||||
margin-top: 30px;
|
||||
margin: 30px 0 0 0;
|
||||
}
|
||||
|
||||
/* --- Photo Card --- */
|
||||
@ -521,18 +521,23 @@ h2 {
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* --- Remove All Buttons --- */
|
||||
#remove-all-hero, #remove-all-gallery {
|
||||
#remove-all-hero, #remove-all-gallery, .bottom-remove-btn {
|
||||
background: #2d2d2d;
|
||||
color: white;
|
||||
display: none;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.bottom-remove-btn {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
#remove-all-gallery:hover,
|
||||
#remove-all-hero:hover {
|
||||
#remove-all-hero:hover, .bottom-remove-btn:hover {
|
||||
background: rgb(121, 26, 19);
|
||||
}
|
||||
|
||||
@ -541,6 +546,7 @@ h2 {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1037,3 +1043,11 @@ justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
#hero-count-bottom, #gallery-count-bottom {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.bottom-action-row {
|
||||
margin-top: 30px;
|
||||
}
|
Reference in New Issue
Block a user