series management tuning and import archive extraction troubleshooting

This commit is contained in:
Bryan Van Deusen
2026-01-23 23:05:25 -05:00
parent d3e73b9533
commit 9ebeeed133
7 changed files with 373 additions and 77 deletions
+7 -7
View File
@@ -153,7 +153,7 @@
<label for="startPageInput">Starting page:</label>
<input type="number" id="startPageInput" value="{{ series_info.page_count + 1 }}" min="1" class="form-input">
</div>
<button id="addToSeriesBtn" class="btn primary-btn" disabled>
<button id="bulkAddToSeriesBtn" class="btn primary-btn" disabled>
Add to Series
</button>
</div>
@@ -184,15 +184,15 @@
// Series Editor functionality (integrated into bulk editor panel)
document.addEventListener('DOMContentLoaded', () => {
const startPageInput = document.getElementById('startPageInput');
const addToSeriesBtn = document.getElementById('addToSeriesBtn');
const bulkAddToSeriesBtn = document.getElementById('bulkAddToSeriesBtn');
const feedbackEl = document.getElementById('seriesEditorFeedback');
const seriesTagId = {{ series_info.tag_id }};
// Update button state based on selection
function updateAddButtonState() {
const selectedCount = window.selectedImages ? window.selectedImages.size : 0;
addToSeriesBtn.disabled = selectedCount === 0;
addToSeriesBtn.textContent = selectedCount > 0
bulkAddToSeriesBtn.disabled = selectedCount === 0;
bulkAddToSeriesBtn.textContent = selectedCount > 0
? `Add ${selectedCount} to Series`
: 'Add to Series';
}
@@ -201,15 +201,15 @@ document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('selectionChanged', updateAddButtonState);
// Add selected images to series
addToSeriesBtn.addEventListener('click', async () => {
bulkAddToSeriesBtn.addEventListener('click', async () => {
if (!window.selectedImages || window.selectedImages.size === 0) return;
// Use selectionOrder (click order) for page ordering
const imageIds = window.selectionOrder ? [...window.selectionOrder] : Array.from(window.selectedImages);
const startPage = parseInt(startPageInput.value) || 1;
addToSeriesBtn.disabled = true;
addToSeriesBtn.textContent = 'Adding...';
bulkAddToSeriesBtn.disabled = true;
bulkAddToSeriesBtn.textContent = 'Adding...';
feedbackEl.innerHTML = '';
try {
+36
View File
@@ -56,6 +56,7 @@
<button id="clearCompletedBtn" class="btn secondary-btn">Clear Completed</button>
<button id="regenMissingThumbsBtn" class="btn secondary-btn">Regenerate Missing Thumbnails</button>
<button id="reapplyArtistTagsBtn" class="btn secondary-btn">Reapply Artist Tags from Paths</button>
<button id="cleanupOrphanedTagsBtn" class="btn secondary-btn">Cleanup Orphaned Tags</button>
</div>
<div id="celeryWorkerInfo" style="margin-top: 1rem;">
@@ -762,6 +763,41 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
// Cleanup Orphaned Tags
document.getElementById('cleanupOrphanedTagsBtn').addEventListener('click', async () => {
const btn = document.getElementById('cleanupOrphanedTagsBtn');
if (!confirm('This will delete all tags that are not attached to any images. Continue?')) {
return;
}
btn.disabled = true;
btn.textContent = 'Cleaning up...';
try {
const r = await fetch('/api/cleanup-orphaned-tags', { method: 'POST' });
const data = await r.json();
if (data.ok) {
if (data.deleted_count === 0) {
alert('No orphaned tags found.');
} else {
const tagList = data.deleted_tags.map(t => `${t.name} (${t.kind || 'user'})`).join('\n');
alert(`Deleted ${data.deleted_count} orphaned tag(s):\n\n${tagList}`);
}
// Refresh the tag dropdown if visible
loadTagsForDeletion();
} else {
alert('Failed: ' + (data.error || 'Unknown error'));
}
} catch (e) {
alert('Failed: ' + e.message);
} finally {
btn.disabled = false;
btn.textContent = 'Cleanup Orphaned Tags';
}
});
// Load import settings
fetch('/api/import-settings')
.then(r => r.json())