From ee6fda8f06eed300a2ddf53a60cdcac08e2b3de0 Mon Sep 17 00:00:00 2001 From: x Date: Fri, 23 Jan 2026 20:52:49 +0100 Subject: [PATCH] new modal for deleting tags and items --- public/s/css/f0ck.css | 66 ++++++++++++++++++++++++++++++++++++++ public/s/js/admin.js | 41 +++++++++++++++++++---- public/s/js/f0ck.js | 60 +++++++++++++++++++++++++++++++--- views/snippets/footer.html | 40 +++++++++++++++++------ 4 files changed, 186 insertions(+), 21 deletions(-) diff --git a/public/s/css/f0ck.css b/public/s/css/f0ck.css index 6e38113..135b80f 100644 --- a/public/s/css/f0ck.css +++ b/public/s/css/f0ck.css @@ -3178,3 +3178,69 @@ input#s_avatar { #search-close:hover { opacity: 1; } + +/* Delete Tag Modal */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.85); + backdrop-filter: blur(5px); + z-index: 10001; + display: flex; + align-items: center; + justify-content: center; +} + +.modal-content { + background: var(--dropdown-bg); + border: 1px solid var(--nav-border-color); + padding: 30px; + border-radius: 10px; + text-align: center; + box-shadow: 0 10px 30px rgba(0,0,0,0.5); + min-width: 300px; +} + +.modal-content h3 { + margin-top: 0; + color: var(--white); +} + +.modal-content p { + color: #ccc; + margin: 20px 0; +} + +.modal-actions { + display: flex; + justify-content: center; + gap: 15px; +} + +.modal-actions button { + padding: 10px 20px; + border: none; + border-radius: 5px; + cursor: pointer; + font-weight: bold; + font-family: var(--font); +} + +.btn-danger { + background: #e74c3c; + color: white; +} +.btn-danger:hover { + background: #c0392b; +} + +.btn-secondary { + background: #555; + color: white; +} +.btn-secondary:hover { + background: #666; +} diff --git a/public/s/js/admin.js b/public/s/js/admin.js index 2482e40..1d61cd3 100644 --- a/public/s/js/admin.js +++ b/public/s/js/admin.js @@ -184,13 +184,40 @@ if (!ctx) return; const { postid, poster } = ctx; - if (!confirm(`Reason for deleting f0ckpost ${postid} by ${poster} (Weihnachten™)`)) - return; - const res = await post("/api/v2/admin/deletepost", { - postid: postid - }); - if (!res.success) { - alert(res.msg); + const modal = document.getElementById('delete-item-modal'); + const idEl = document.getElementById('delete-item-id'); + const posterEl = document.getElementById('delete-item-poster'); + const confirmBtn = document.getElementById('delete-item-confirm'); + const cancelBtn = document.getElementById('delete-item-cancel'); + + if (modal) { + idEl.textContent = postid; + posterEl.textContent = poster || 'unknown'; + modal.style.display = 'flex'; + + const closeModal = () => { + modal.style.display = 'none'; + confirmBtn.onclick = null; + cancelBtn.onclick = null; + }; + + cancelBtn.onclick = closeModal; + + confirmBtn.onclick = async () => { + confirmBtn.textContent = 'Deleting...'; + confirmBtn.disabled = true; + const res = await post("/api/v2/admin/deletepost", { + postid: postid + }); + if (!res.success) { + alert(res.msg); + confirmBtn.textContent = 'Delete'; + confirmBtn.disabled = false; + } else { + closeModal(); + window.location.href = '/'; + } + }; } }; diff --git a/public/s/js/f0ck.js b/public/s/js/f0ck.js index 87dd28e..c49ae46 100644 --- a/public/s/js/f0ck.js +++ b/public/s/js/f0ck.js @@ -418,16 +418,66 @@ window.requestAnimFrame = (function () { canvas.classList.add('fader-out'); } } + } else if (e.target.closest('.removetag')) { + e.preventDefault(); + const removeBtn = e.target.closest('.removetag'); + const tagLink = removeBtn.previousElementSibling; + + if (tagLink) { + const tagName = tagLink.textContent.trim(); + const idLink = document.querySelector('.id-link'); + const id = idLink ? idLink.textContent.trim() : null; + + if (id && tagName) { + const modal = document.getElementById('delete-tag-modal'); + const nameEl = document.getElementById('delete-tag-name'); + const confirmBtn = document.getElementById('delete-tag-confirm'); + const cancelBtn = document.getElementById('delete-tag-cancel'); + + if (modal) { + nameEl.textContent = tagName; + modal.style.display = 'flex'; + + const closeModal = () => { + modal.style.display = 'none'; + confirmBtn.onclick = null; + cancelBtn.onclick = null; + }; + + cancelBtn.onclick = closeModal; + + confirmBtn.onclick = () => { + confirmBtn.textContent = 'Deleting...'; + confirmBtn.disabled = true; + fetch(`/api/v2/admin/${id}/tags/${encodeURIComponent(tagName)}`, { + method: 'DELETE' + }) + .then(r => r.json()) + .then(data => { + if (data.success) { + removeBtn.parentElement.remove(); + closeModal(); + } else { + alert('Error: ' + (data.msg || 'Unknown error')); + confirmBtn.textContent = 'Delete'; + confirmBtn.disabled = false; + } + }) + .catch(err => { + console.error(err); + alert('Failed to delete tag'); + confirmBtn.textContent = 'Delete'; + confirmBtn.disabled = false; + }); + }; + } + } + } } }); window.addEventListener('popstate', (e) => { if (window.location.href.match(/\/p\/\d+/) || window.location.href.match(/[?&]page=\d+/) || window.location.pathname === '/') { - // Ideally we should reload page or call loadPageAjax(currentUrl) if it supports it - // But if we are going BACK to index from item, we expect grid. - // loadItemAjax fails on index. - // loadPageAjax handles /p/N logic. - // If just slash, loadPageAjax might default to page 1. loadPageAjax(window.location.href); } else { loadItemAjax(window.location.href, true); diff --git a/views/snippets/footer.html b/views/snippets/footer.html index 2f6924e..b4f08b1 100644 --- a/views/snippets/footer.html +++ b/views/snippets/footer.html @@ -1,10 +1,32 @@ - - - - @if(session && session.admin) - - @elseif(session && !session.admin) - - @endif + + + + + +@if(session && session.admin) + +@elseif(session && !session.admin) + +@endif - + + \ No newline at end of file