series management tuning and import archive extraction troubleshooting
This commit is contained in:
@@ -105,6 +105,56 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Gallery item tag refresh (fallback if bulk-select.js not loaded)
|
||||
// ---------------------------
|
||||
function getTagDisplayNameForOverlay(name, kind) {
|
||||
if (['artist', 'character', 'series', 'fandom', 'rating'].includes(kind)) {
|
||||
return name.includes(':') ? name.split(':', 2)[1] : name;
|
||||
}
|
||||
return '#' + name;
|
||||
}
|
||||
|
||||
async function refreshItemTagsFallback(imageId) {
|
||||
const item = document.querySelector(`.img-clickable[data-id="${imageId}"]`);
|
||||
if (!item) return;
|
||||
|
||||
try {
|
||||
const r = await fetch(`/image/${imageId}/tags`);
|
||||
const data = await r.json();
|
||||
if (!data.ok) return;
|
||||
|
||||
const visibleTags = (data.tags || []).filter(t => t.kind !== 'archive');
|
||||
let overlay = item.querySelector('.tag-overlay');
|
||||
|
||||
if (visibleTags.length === 0) {
|
||||
if (overlay) overlay.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('div');
|
||||
overlay.className = 'tag-overlay';
|
||||
item.appendChild(overlay);
|
||||
}
|
||||
|
||||
overlay.innerHTML = visibleTags.map(t => {
|
||||
const displayName = getTagDisplayNameForOverlay(t.name, t.kind);
|
||||
const encodedName = encodeURIComponent(t.name);
|
||||
const escapedName = t.name.replace(/"/g, '"');
|
||||
const escapedDisplay = displayName.replace(/</g, '<').replace(/>/g, '>');
|
||||
return `<a class="tag-chip" href="/gallery?tag=${encodedName}" title="Filter by ${escapedName}" onclick="event.stopPropagation()">${escapedDisplay}</a>`;
|
||||
}).join('');
|
||||
} catch (e) {
|
||||
console.error('Failed to refresh tags for image', imageId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Register fallback if bulk-select.js hasn't registered it
|
||||
if (!window.refreshItemTags) {
|
||||
window.refreshItemTags = refreshItemTagsFallback;
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Series info helpers
|
||||
// ---------------------------
|
||||
@@ -120,7 +170,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
async function loadSeriesTags() {
|
||||
if (!seriesSelect || seriesTagsLoaded) return;
|
||||
if (!seriesSelect) return;
|
||||
if (seriesTagsLoaded) return Promise.resolve();
|
||||
try {
|
||||
// Fetch all series tags using the kind filter
|
||||
const r = await fetch('/api/tags/search?kind=series&limit=100');
|
||||
@@ -144,12 +195,26 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function showAddToSeries() {
|
||||
function showAddToSeries(seriesPage = null) {
|
||||
if (!addToSeriesEl) return;
|
||||
loadSeriesTags();
|
||||
if (seriesSelect) seriesSelect.value = '';
|
||||
if (addSeriesPageNumber) addSeriesPageNumber.value = '1';
|
||||
if (addToSeriesBtn) addToSeriesBtn.disabled = true;
|
||||
loadSeriesTags().then(() => {
|
||||
// Pre-fill if image is already in a series
|
||||
if (seriesPage && seriesSelect) {
|
||||
seriesSelect.value = seriesPage.series_tag_id;
|
||||
if (addSeriesPageNumber) addSeriesPageNumber.value = seriesPage.page_number;
|
||||
if (addToSeriesBtn) {
|
||||
addToSeriesBtn.disabled = false;
|
||||
addToSeriesBtn.textContent = 'Update';
|
||||
}
|
||||
} else {
|
||||
if (seriesSelect) seriesSelect.value = '';
|
||||
if (addSeriesPageNumber) addSeriesPageNumber.value = '1';
|
||||
if (addToSeriesBtn) {
|
||||
addToSeriesBtn.disabled = true;
|
||||
addToSeriesBtn.textContent = 'Add';
|
||||
}
|
||||
}
|
||||
});
|
||||
if (addToSeriesStatus) addToSeriesStatus.textContent = '';
|
||||
addToSeriesEl.style.display = 'block';
|
||||
}
|
||||
@@ -161,8 +226,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
if (!imageId || !seriesTagId || isNaN(pageNumber) || pageNumber < 1) return;
|
||||
|
||||
const isUpdate = addToSeriesBtn?.textContent === 'Update';
|
||||
if (addToSeriesBtn) addToSeriesBtn.disabled = true;
|
||||
if (addToSeriesStatus) addToSeriesStatus.textContent = 'Adding...';
|
||||
if (addToSeriesStatus) addToSeriesStatus.textContent = isUpdate ? 'Updating...' : 'Adding...';
|
||||
|
||||
try {
|
||||
const r = await fetch(`/api/image/${imageId}/add-to-series`, {
|
||||
@@ -174,12 +240,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
if (j.ok) {
|
||||
if (addToSeriesStatus) {
|
||||
addToSeriesStatus.textContent = '✓ Added';
|
||||
addToSeriesStatus.textContent = '✓ Saved';
|
||||
setTimeout(() => { addToSeriesStatus.textContent = ''; }, 2000);
|
||||
}
|
||||
// Switch to showing the series info instead of add-to-series
|
||||
hideAddToSeries();
|
||||
// Update the series info section with new data
|
||||
showSeriesInfo(j.series_page);
|
||||
// Re-enable the button
|
||||
if (addToSeriesBtn) addToSeriesBtn.disabled = false;
|
||||
} else {
|
||||
if (addToSeriesStatus) addToSeriesStatus.textContent = j.error || 'Error';
|
||||
if (addToSeriesBtn) addToSeriesBtn.disabled = false;
|
||||
@@ -220,7 +287,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const r = await fetch(`/api/image/${imageId}/series-info`);
|
||||
const j = await r.json();
|
||||
if (j.ok && j.in_series) {
|
||||
// Show series info (with link) and pre-fill the dropdown
|
||||
showSeriesInfo(j.series_page);
|
||||
showAddToSeries(j.series_page);
|
||||
} else {
|
||||
// Show add-to-series option when not in a series
|
||||
showAddToSeries();
|
||||
@@ -284,6 +353,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
seriesSelect.addEventListener('change', () => {
|
||||
if (addToSeriesBtn) {
|
||||
addToSeriesBtn.disabled = !seriesSelect.value;
|
||||
// Update button text: "Update" if image is in a series, "Add" if not
|
||||
if (seriesSelect.value && currentSeriesPageId) {
|
||||
addToSeriesBtn.textContent = 'Update';
|
||||
} else if (seriesSelect.value) {
|
||||
addToSeriesBtn.textContent = 'Add';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -534,6 +609,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
// Get the image ID before clearing so we can refresh its tags
|
||||
const imageId = getEditorImageId();
|
||||
|
||||
modal.classList.remove('active');
|
||||
modalImageWrapper.innerHTML = '';
|
||||
currentIndex = -1;
|
||||
@@ -544,6 +622,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
hideSeriesInfo();
|
||||
hideAddToSeries();
|
||||
history.replaceState({}, '', window.location.pathname + window.location.search);
|
||||
|
||||
// Refresh the gallery item's tags display (if function available from bulk-select.js)
|
||||
if (imageId && window.refreshItemTags) {
|
||||
window.refreshItemTags(imageId);
|
||||
}
|
||||
}
|
||||
|
||||
function showNext() {
|
||||
|
||||
Reference in New Issue
Block a user