From 9d37b0a60fba6efa28fdf1bf402970b111b57a56 Mon Sep 17 00:00:00 2001 From: Djeex Date: Sat, 16 Aug 2025 22:57:56 +0200 Subject: [PATCH] Better tag UI --- config/gallery.yaml | 1 + src/webui/js/main.js | 46 +++++++++++++++++++++------------------ src/webui/style/style.css | 16 +++++++++++--- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/config/gallery.yaml b/config/gallery.yaml index fc1920d..7463218 100644 --- a/config/gallery.yaml +++ b/config/gallery.yaml @@ -2,3 +2,4 @@ hero: images: [] gallery: images: [] + diff --git a/src/webui/js/main.js b/src/webui/js/main.js index d1bef7f..bf2968c 100644 --- a/src/webui/js/main.js +++ b/src/webui/js/main.js @@ -41,23 +41,30 @@ function renderGallery() {
-
+
-
- +
+ +
+
`; container.appendChild(div); - renderTags(div.querySelector('.tag-input'), img.tags || [], i); + renderTags(i, img.tags || []); }); } // --- Render tags for a single image --- -function renderTags(container, tags, imgIndex) { - container.innerHTML = ''; +function renderTags(imgIndex, tags) { + const tagsDisplay = document.querySelector(`.tags-display[data-index="${imgIndex}"]`); + const inputContainer = document.querySelector(`.tag-input[data-index="${imgIndex}"]`); - // Render existing tags + // vider + tagsDisplay.innerHTML = ''; + inputContainer.innerHTML = ''; + + // --- rendre les tags (en haut) --- tags.forEach(tag => { const span = document.createElement('span'); span.className = 'tag'; @@ -69,23 +76,23 @@ function renderTags(container, tags, imgIndex) { remove.onclick = () => { tags.splice(tags.indexOf(tag), 1); updateTags(imgIndex, tags); - renderTags(container, tags, imgIndex); + renderTags(imgIndex, tags); }; span.appendChild(remove); - container.appendChild(span); + tagsDisplay.appendChild(span); }); - // Input for new tags + // --- input (en bas) --- const input = document.createElement('input'); input.type = 'text'; input.placeholder = 'Add tag...'; - container.appendChild(input); + inputContainer.appendChild(input); - // Suggestion dropdown + // suggestion box const suggestionBox = document.createElement('ul'); suggestionBox.className = 'suggestions'; - container.appendChild(suggestionBox); + inputContainer.appendChild(suggestionBox); let selectedIndex = -1; @@ -93,8 +100,8 @@ function renderTags(container, tags, imgIndex) { tag = tag.trim(); if (!tag) return; if (!tags.includes(tag)) tags.push(tag); - updateTags(imgIndex, tags); // save to galleryImages and server - renderTags(container, tags, imgIndex); + updateTags(imgIndex, tags); + renderTags(imgIndex, tags); }; const updateSuggestions = () => { @@ -107,7 +114,6 @@ function renderTags(container, tags, imgIndex) { const allTagsSorted = Object.keys(tagCount) .sort((a, b) => tagCount[b] - tagCount[a]); - // Show suggestions that start with input (or all if empty) const suggestions = allTagsSorted.filter(t => t.toLowerCase().startsWith(value) && !tags.includes(t)); suggestionBox.innerHTML = ''; @@ -141,8 +147,7 @@ function renderTags(container, tags, imgIndex) { }; input.addEventListener('input', updateSuggestions); - - input.addEventListener('focus', updateSuggestions); // Show suggestions on focus + input.addEventListener('focus', updateSuggestions); input.addEventListener('keydown', (e) => { const items = suggestionBox.querySelectorAll('li'); @@ -176,15 +181,14 @@ function renderTags(container, tags, imgIndex) { input.addEventListener('blur', () => { setTimeout(() => { suggestionBox.style.display = 'none'; - input.value = ''; // Clear input without saving + input.value = ''; }, 150); }); input.focus(); - updateSuggestions(); // show suggestions on render + updateSuggestions(); } - // --- Update tags in galleryImages array --- function updateTags(index, tags) { galleryImages[index].tags = tags; diff --git a/src/webui/style/style.css b/src/webui/style/style.css index 60092a4..c715583 100644 --- a/src/webui/style/style.css +++ b/src/webui/style/style.css @@ -80,7 +80,7 @@ h1, h2 { border-radius: 30px; cursor: pointer; transition: background-color 0.2s; - margin-top: 10px; + margin: 5px 4px 0 4px; width:100%; } @@ -139,20 +139,22 @@ h1, h2 { /* Tags */ .tag-input { display: flex; - flex-wrap: wrap; + flex-wrap: wrap-reverse; + align-content: flex-start; gap: 4px; padding: 4px; position: relative; z-index: 1; + margin-top: 10px; } .tag-input input { border: none; outline: none; - flex: 1; min-width: 60px; background-color: #1f2223; border: 1px solid #585858; + margin-top: 5px; } .tag { @@ -195,6 +197,13 @@ h1, h2 { background-color: #007782; } +.tags-display { + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-top: 8px; +} + .suggestions li.selected { background-color: #007782; color: white; @@ -214,6 +223,7 @@ h1, h2 { .flex-full { flex: 1; + flex-direction: column-reverse; } .flex-end {