changes to series order system. add artist retagging tool

This commit is contained in:
Bryan Van Deusen
2026-01-23 08:38:07 -05:00
parent 82cf3b782b
commit d3e73b9533
5 changed files with 316 additions and 1 deletions
+115 -1
View File
@@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
const tagInput = tagForm ? tagForm.querySelector('input[name="name"]') : null;
const tagAutocomplete = document.getElementById('tagAutocomplete');
// Series info elements
// Series info elements (when image IS in a series)
const seriesInfoEl = document.getElementById('modalSeriesInfo');
const seriesNameEl = document.getElementById('modalSeriesName');
const pageNumberInput = document.getElementById('modalPageNumber');
@@ -22,6 +22,14 @@ document.addEventListener('DOMContentLoaded', () => {
const pageUpdateStatus = document.getElementById('pageUpdateStatus');
let currentSeriesPageId = null;
// Add to series elements (when image is NOT in a series)
const addToSeriesEl = document.getElementById('modalAddToSeries');
const seriesSelect = document.getElementById('seriesSelect');
const addSeriesPageNumber = document.getElementById('addSeriesPageNumber');
const addToSeriesBtn = document.getElementById('addToSeriesBtn');
const addToSeriesStatus = document.getElementById('addToSeriesStatus');
let seriesTagsLoaded = false;
// Autocomplete state
let autocompleteItems = [];
let autocompleteSelectedIndex = -1;
@@ -106,6 +114,82 @@ document.addEventListener('DOMContentLoaded', () => {
if (pageUpdateStatus) pageUpdateStatus.textContent = '';
}
function hideAddToSeries() {
if (addToSeriesEl) addToSeriesEl.style.display = 'none';
if (addToSeriesStatus) addToSeriesStatus.textContent = '';
}
async function loadSeriesTags() {
if (!seriesSelect || seriesTagsLoaded) return;
try {
// Fetch all series tags using the kind filter
const r = await fetch('/api/tags/search?kind=series&limit=100');
const j = await r.json();
const seriesTags = j.tags || [];
// Clear existing options except the first placeholder
seriesSelect.innerHTML = '<option value="">Select series...</option>';
seriesTags.forEach(tag => {
const opt = document.createElement('option');
opt.value = tag.id;
// Display name without prefix
opt.textContent = tag.name.includes(':') ? tag.name.split(':', 2)[1] : tag.name;
seriesSelect.appendChild(opt);
});
seriesTagsLoaded = true;
} catch {
// ignore
}
}
function showAddToSeries() {
if (!addToSeriesEl) return;
loadSeriesTags();
if (seriesSelect) seriesSelect.value = '';
if (addSeriesPageNumber) addSeriesPageNumber.value = '1';
if (addToSeriesBtn) addToSeriesBtn.disabled = true;
if (addToSeriesStatus) addToSeriesStatus.textContent = '';
addToSeriesEl.style.display = 'block';
}
async function handleAddToSeries() {
const imageId = getEditorImageId();
const seriesTagId = seriesSelect?.value;
const pageNumber = parseInt(addSeriesPageNumber?.value);
if (!imageId || !seriesTagId || isNaN(pageNumber) || pageNumber < 1) return;
if (addToSeriesBtn) addToSeriesBtn.disabled = true;
if (addToSeriesStatus) addToSeriesStatus.textContent = 'Adding...';
try {
const r = await fetch(`/api/image/${imageId}/add-to-series`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ series_tag_id: parseInt(seriesTagId), page_number: pageNumber })
});
const j = await r.json();
if (j.ok) {
if (addToSeriesStatus) {
addToSeriesStatus.textContent = '✓ Added';
setTimeout(() => { addToSeriesStatus.textContent = ''; }, 2000);
}
// Switch to showing the series info instead of add-to-series
hideAddToSeries();
showSeriesInfo(j.series_page);
} else {
if (addToSeriesStatus) addToSeriesStatus.textContent = j.error || 'Error';
if (addToSeriesBtn) addToSeriesBtn.disabled = false;
}
} catch (e) {
if (addToSeriesStatus) addToSeriesStatus.textContent = 'Error';
if (addToSeriesBtn) addToSeriesBtn.disabled = false;
}
}
function showSeriesInfo(seriesPage) {
if (!seriesInfoEl || !seriesPage) return;
currentSeriesPageId = seriesPage.id;
@@ -130,12 +214,16 @@ document.addEventListener('DOMContentLoaded', () => {
async function loadSeriesInfo(imageId) {
hideSeriesInfo();
hideAddToSeries();
if (!imageId) return;
try {
const r = await fetch(`/api/image/${imageId}/series-info`);
const j = await r.json();
if (j.ok && j.in_series) {
showSeriesInfo(j.series_page);
} else {
// Show add-to-series option when not in a series
showAddToSeries();
}
} catch {
// ignore
@@ -190,6 +278,31 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
}
// Enable/disable add button based on series selection
if (seriesSelect) {
seriesSelect.addEventListener('change', () => {
if (addToSeriesBtn) {
addToSeriesBtn.disabled = !seriesSelect.value;
}
});
}
// Add to series button click
if (addToSeriesBtn) {
addToSeriesBtn.addEventListener('click', handleAddToSeries);
}
// Allow Enter key in add-to-series page number input
if (addSeriesPageNumber) {
addSeriesPageNumber.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && seriesSelect?.value) {
e.preventDefault();
handleAddToSeries();
}
});
}
async function addTag(imageId, name) {
const fd = new FormData();
fd.append('name', name);
@@ -429,6 +542,7 @@ document.addEventListener('DOMContentLoaded', () => {
setEditorImageId('');
renderTags([]);
hideSeriesInfo();
hideAddToSeries();
history.replaceState({}, '', window.location.pathname + window.location.search);
}