switched to tagging and added views to support it, in progress for other tagging functions.
This commit is contained in:
@@ -7,6 +7,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const modalClose = document.getElementById('modalClose');
|
||||
const modalImageWrapper = document.querySelector('.modal-image-wrapper');
|
||||
|
||||
// NEW: tag editor elements
|
||||
const tagEditor = document.getElementById('modalTagEditor');
|
||||
const tagList = document.getElementById('modalTagList');
|
||||
const tagForm = document.getElementById('modalTagForm');
|
||||
const tagInput = tagForm ? tagForm.querySelector('input[name="name"]') : null;
|
||||
|
||||
let images = Array.from(document.querySelectorAll('.img-clickable'));
|
||||
let currentIndex = -1;
|
||||
let isZoomed = false;
|
||||
@@ -21,9 +27,93 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const hasPrevPageInput = document.getElementById('hasPrevPage');
|
||||
const prevPageUrlInput = document.getElementById('prevPageUrl');
|
||||
|
||||
// ---------------------------
|
||||
// Tag editor helpers
|
||||
// ---------------------------
|
||||
function setEditorImageId(id) {
|
||||
if (tagEditor) tagEditor.dataset.imageId = id || '';
|
||||
}
|
||||
function getEditorImageId() {
|
||||
return tagEditor ? tagEditor.dataset.imageId : '';
|
||||
}
|
||||
function renderTags(tags) {
|
||||
if (!tagList) return;
|
||||
tagList.innerHTML = '';
|
||||
(tags || []).forEach(t => {
|
||||
const chip = document.createElement('span');
|
||||
chip.className = 'tag-chip';
|
||||
const label = (t.kind === 'artist')
|
||||
? `🎨 ${t.name.split(':', 1)[0] === 'artist' ? t.name.split(':', 2)[1] : t.name}`
|
||||
: (t.kind === 'archive')
|
||||
? `🗜️ ${t.name.split(':', 1)[0] === 'archive' ? t.name.split(':', 2)[1] : t.name}`
|
||||
: `#${t.name}`;
|
||||
chip.innerHTML = `${label} <button class="x" data-name="${t.name}" title="Remove">×</button>`;
|
||||
tagList.appendChild(chip);
|
||||
});
|
||||
}
|
||||
async function loadTags(imageId) {
|
||||
if (!imageId) { renderTags([]); return; }
|
||||
try {
|
||||
const r = await fetch(`/image/${imageId}/tags`);
|
||||
const j = await r.json();
|
||||
if (j.ok) renderTags(j.tags);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
async function addTag(imageId, name) {
|
||||
const fd = new FormData();
|
||||
fd.append('name', name);
|
||||
const r = await fetch(`/image/${imageId}/tags/add`, { method: 'POST', body: fd });
|
||||
const j = await r.json();
|
||||
if (j.ok) {
|
||||
await loadTags(imageId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
async function removeTag(imageId, name) {
|
||||
const fd = new FormData();
|
||||
fd.append('name', name);
|
||||
const r = await fetch(`/image/${imageId}/tags/remove`, { method: 'POST', body: fd });
|
||||
const j = await r.json();
|
||||
if (j.ok) {
|
||||
await loadTags(imageId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tagForm) {
|
||||
tagForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const id = getEditorImageId();
|
||||
const name = (tagInput.value || '').trim();
|
||||
if (!id || !name) return;
|
||||
await addTag(id, name);
|
||||
tagInput.value = '';
|
||||
});
|
||||
}
|
||||
if (tagList) {
|
||||
tagList.addEventListener('click', async (e) => {
|
||||
const btn = e.target.closest('button.x');
|
||||
if (!btn) return;
|
||||
const id = getEditorImageId();
|
||||
const name = btn.dataset.name;
|
||||
if (!id || !name) return;
|
||||
await removeTag(id, name);
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Existing viewer logic
|
||||
// ---------------------------
|
||||
function updateImage(index) {
|
||||
const img = images[index];
|
||||
const fileType = img.dataset.type || "image";
|
||||
const imageId = img.dataset.id || "";
|
||||
|
||||
// clear wrapper
|
||||
modalImageWrapper.innerHTML = "";
|
||||
|
||||
if (fileType === "video") {
|
||||
@@ -45,6 +135,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
currentIndex = index;
|
||||
resetZoom();
|
||||
|
||||
// NEW: load tags for this image into the modal editor
|
||||
setEditorImageId(imageId);
|
||||
loadTags(imageId);
|
||||
}
|
||||
|
||||
function openModal(index) {
|
||||
@@ -58,6 +152,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
modalImageWrapper.innerHTML = '';
|
||||
currentIndex = -1;
|
||||
resetZoom();
|
||||
// clear tag UI
|
||||
setEditorImageId('');
|
||||
renderTags([]);
|
||||
history.replaceState({}, '', window.location.pathname + window.location.search);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user