validation
This commit is contained in:
@@ -393,6 +393,7 @@ const state = {
|
||||
currentUser: null, // {id, username, role}
|
||||
authWarnings: {}, // source_slug → {source_slug, source_name}
|
||||
metaUpdating: new Set(), // urls where meta refresh is in progress
|
||||
validating: {}, // url → {checked, total} for in-progress validations
|
||||
};
|
||||
|
||||
// ── Auth ─────────────────────────────────────
|
||||
@@ -703,6 +704,31 @@ function handleEvent(msg) {
|
||||
_updateMetaBtn(msg.url, msg.failed === -1 ? 'error' : 'done');
|
||||
break;
|
||||
|
||||
case 'validate_started':
|
||||
state.validating[msg.url] = {checked: 0, total: 0};
|
||||
_updateValidateBtn(msg.url);
|
||||
break;
|
||||
|
||||
case 'validate_progress':
|
||||
if(state.validating[msg.url]) {
|
||||
state.validating[msg.url].checked = msg.checked;
|
||||
state.validating[msg.url].total = msg.total;
|
||||
}
|
||||
_updateValidateBtn(msg.url);
|
||||
break;
|
||||
|
||||
case 'validate_done': {
|
||||
delete state.validating[msg.url];
|
||||
const result = msg.total_to_redownload > 0 || msg.new_chapters > 0 ? 'issues' : 'ok';
|
||||
_updateValidateBtn(msg.url, result, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'validate_error':
|
||||
delete state.validating[msg.url];
|
||||
_updateValidateBtn(msg.url, 'error');
|
||||
break;
|
||||
|
||||
case 'manga_meta_updated':
|
||||
if(state.mangas[msg.url]) {
|
||||
state.mangas[msg.url].title = msg.title;
|
||||
@@ -1691,6 +1717,63 @@ async function refreshMetaModal(url) {
|
||||
// Спиннер появится через WS meta_refresh_started, исчезнет через meta_refreshed
|
||||
}
|
||||
|
||||
function _updateValidateBtn(url, result, data) {
|
||||
const modal = document.getElementById('modal');
|
||||
if(!modal || modal.classList.contains('hidden') || modal.dataset.currentUrl !== url) return;
|
||||
const btn = document.getElementById('modal-validate-btn');
|
||||
if(!btn) return;
|
||||
const v = state.validating[url];
|
||||
if(v !== undefined) {
|
||||
const prog = v.total > 0 ? ` ${v.checked}/${v.total}` : '...';
|
||||
btn.innerHTML = `<span class="meta-spinner"></span> Проверка${prog}`;
|
||||
btn.disabled = true;
|
||||
btn.style.color = '#94a3b8';
|
||||
btn.style.borderColor = '#334155';
|
||||
} else if(result === 'ok') {
|
||||
btn.innerHTML = '✅ Всё в порядке';
|
||||
btn.disabled = false;
|
||||
btn.style.color = '#4ade80';
|
||||
btn.style.borderColor = '#166534';
|
||||
setTimeout(() => { btn.innerHTML = '🔍 Проверить целостность'; btn.style.color='#67e8f9'; btn.style.borderColor='#164e63'; btn.disabled=false; }, 3000);
|
||||
} else if(result === 'issues') {
|
||||
const n = data ? (data.total_to_redownload + data.new_chapters) : '?';
|
||||
btn.innerHTML = `⚡ Найдено проблем: ${n} — поставлено в очередь`;
|
||||
btn.disabled = true;
|
||||
btn.style.color = '#fbbf24';
|
||||
btn.style.borderColor = '#78350f';
|
||||
setTimeout(() => { btn.innerHTML = '🔍 Проверить целостность'; btn.style.color='#67e8f9'; btn.style.borderColor='#164e63'; btn.disabled=false; }, 5000);
|
||||
} else if(result === 'error') {
|
||||
btn.innerHTML = '❌ Ошибка валидации';
|
||||
btn.disabled = false;
|
||||
btn.style.color = '#f87171';
|
||||
btn.style.borderColor = '#7f1d1d';
|
||||
setTimeout(() => { btn.innerHTML = '🔍 Проверить целостность'; btn.style.color='#67e8f9'; btn.style.borderColor='#164e63'; btn.disabled=false; }, 3000);
|
||||
} else {
|
||||
btn.innerHTML = '🔍 Проверить целостность';
|
||||
btn.disabled = false;
|
||||
btn.style.color = '#67e8f9';
|
||||
btn.style.borderColor = '#164e63';
|
||||
}
|
||||
}
|
||||
|
||||
async function validateManga(url) {
|
||||
const btn = document.getElementById('modal-validate-btn');
|
||||
if(btn) {
|
||||
btn.innerHTML = '<span class="meta-spinner"></span> Запуск...';
|
||||
btn.disabled = true;
|
||||
}
|
||||
const r = await fetch('/api/mangas/validate?url='+encodeURIComponent(url), {method:'POST'});
|
||||
if(!r.ok) {
|
||||
const err = await r.json().catch(() => ({}));
|
||||
if(btn) {
|
||||
btn.innerHTML = '❌ ' + (err.detail || 'Ошибка');
|
||||
btn.style.color = '#f87171';
|
||||
btn.style.borderColor = '#7f1d1d';
|
||||
setTimeout(() => { btn.innerHTML = '🔍 Проверить целостность'; btn.style.color='#67e8f9'; btn.style.borderColor='#164e63'; btn.disabled=false; }, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function forceRedownload(url, closeModalAfter = false) {
|
||||
if(!confirm('Скачать заново ВСЕ главы? Уже скачанные файлы будут перезаписаны.')) return;
|
||||
const r = await fetch('/api/mangas/force_redownload?url='+encodeURIComponent(url), {method:'POST'});
|
||||
@@ -2233,6 +2316,15 @@ function renderModalBody(data) {
|
||||
📁 Переименовать папку
|
||||
</button>` : ''}
|
||||
${data.status === 'done' && canManage(data) ? `
|
||||
<button id="modal-validate-btn" onclick="validateManga('${escHtml(data.url)}')"
|
||||
class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
|
||||
style="background:#0c1a2e;color:#67e8f9;border:1px solid #164e63"
|
||||
${state.validating[data.url] !== undefined ? 'disabled' : ''}>
|
||||
${state.validating[data.url] !== undefined
|
||||
? `<span class="meta-spinner"></span> Проверка${state.validating[data.url].total > 0 ? ' '+state.validating[data.url].checked+'/'+state.validating[data.url].total : '...'}`
|
||||
: '🔍 Проверить целостность'}
|
||||
</button>` : ''}
|
||||
${data.status === 'done' && canManage(data) ? `
|
||||
<button id="modal-refresh-meta-btn" onclick="refreshMetaModal('${escHtml(data.url)}')"
|
||||
class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
|
||||
style="background:#1e1b4b;color:#a78bfa;border:1px solid #312e81">
|
||||
|
||||
Reference in New Issue
Block a user