feat(admin): Konfigurowalne limity dla operacji ZOPK

- Scraping: domyślnie 1, max 100
- Ekstrakcja: domyślnie 1, max 100
- Embeddingi: domyślnie 1, max 500
- Usunięto stałe liczby z etykiet przycisków

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-01-16 20:30:54 +01:00
parent 0797afe162
commit a20d94883e

View File

@ -379,13 +379,13 @@
<span class="text-muted">Baza wiedzy:</span>
<button class="action-btn" onclick="batchScrapeContent()" style="padding: 6px 12px; background: #e0f2fe; border-color: #0284c7; color: #0369a1;">
📥 Scrapuj treść (50)
📥 Scrapuj treść
</button>
<button class="action-btn" onclick="batchExtractKnowledge()" style="padding: 6px 12px; background: #dcfce7; border-color: #16a34a; color: #15803d;">
🧠 Ekstraktuj wiedzę (50)
🧠 Ekstraktuj wiedzę
</button>
<button class="action-btn" onclick="batchGenerateEmbeddings()" style="padding: 6px 12px; background: #fef3c7; border-color: #d97706; color: #b45309;">
🔢 Generuj embeddingi (100)
🔢 Generuj embeddingi
</button>
<button class="action-btn" onclick="showKnowledgeStats()" style="padding: 6px 12px; background: #f3f4f6; border-color: #6b7280; color: #374151;">
📊 Statystyki
@ -903,19 +903,28 @@ document.getElementById('massRejectModal').addEventListener('click', (e) => {
// ============================================
async function batchScrapeContent() {
const confirmed = await showConfirm(
'Rozpocząć scraping treści artykułów?\n\nTo pobierze pełną treść z 50 artykułów ze statusem "pending" lub "auto_approved".',
const limitInput = await showConfirm(
'Ile artykułów chcesz zescrapować?\n\nPobierze pełną treść z artykułów ze statusem "auto_approved".',
{
icon: '📥',
title: 'Scraping treści',
showInput: true,
inputLabel: 'Liczba artykułów (1-100):',
inputPlaceholder: '1',
okText: 'Rozpocznij scraping',
okClass: 'btn-primary'
}
);
if (!confirmed) return;
if (limitInput === false) return;
showToast('Rozpoczynam scraping treści...', 'info', 10000);
const limit = parseInt(limitInput) || 1;
if (limit < 1 || limit > 100) {
showToast('Limit musi być między 1 a 100', 'warning');
return;
}
showToast(`Rozpoczynam scraping ${limit} artykułów...`, 'info', 10000);
try {
const response = await fetch('/admin/zopk/news/scrape-content', {
@ -924,12 +933,12 @@ async function batchScrapeContent() {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify({ limit: 50 })
body: JSON.stringify({ limit: limit })
});
const data = await response.json();
if (data.success) {
showToast(`✅ Scraping zakończony: ${data.scraped} artykułów, ${data.failed} błędów`, 'success', 8000);
showToast(`✅ Scraping zakończony: ${data.scraped} pobrano, ${data.failed} błędów`, 'success', 8000);
} else {
showToast(data.error || 'Wystąpił błąd', 'error');
}
@ -939,19 +948,28 @@ async function batchScrapeContent() {
}
async function batchExtractKnowledge() {
const confirmed = await showConfirm(
'Rozpocząć ekstrakcję wiedzy?\n\nTo przetworzy 50 artykułów ze scraped treścią i wyekstraktuje chunks, fakty i encje.',
const limitInput = await showConfirm(
'Ile artykułów chcesz przetworzyć?\n\nWyekstraktuje chunks, fakty i encje z artykułów ze scraped treścią.',
{
icon: '🧠',
title: 'Ekstrakcja wiedzy',
showInput: true,
inputLabel: 'Liczba artykułów (1-100):',
inputPlaceholder: '1',
okText: 'Rozpocznij ekstrakcję',
okClass: 'btn-primary'
}
);
if (!confirmed) return;
if (limitInput === false) return;
showToast('Rozpoczynam ekstrakcję wiedzy (może potrwać kilka minut)...', 'info', 30000);
const limit = parseInt(limitInput) || 1;
if (limit < 1 || limit > 100) {
showToast('Limit musi być między 1 a 100', 'warning');
return;
}
showToast(`Rozpoczynam ekstrakcję wiedzy z ${limit} artykułów...`, 'info', 30000);
try {
const response = await fetch('/admin/zopk/knowledge/extract', {
@ -960,13 +978,12 @@ async function batchExtractKnowledge() {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify({ limit: 50 })
body: JSON.stringify({ limit: limit })
});
const data = await response.json();
if (data.success) {
// Fields: processed (count), total, chunks_created, facts_created, entities_created, relations_created
showToast(`✅ Ekstrakcja zakończona: ${data.processed || 0}/${data.total || 0} artykułów, ${data.chunks_created || 0} chunks, ${data.facts_created || 0} faktów`, 'success', 10000);
showToast(`✅ Ekstrakcja: ${data.processed || 0}/${data.total || 0} art., ${data.chunks_created || 0} chunks, ${data.facts_created || 0} faktów`, 'success', 10000);
} else {
showToast(data.error || 'Wystąpił błąd', 'error');
}
@ -976,19 +993,28 @@ async function batchExtractKnowledge() {
}
async function batchGenerateEmbeddings() {
const confirmed = await showConfirm(
'Rozpocząć generowanie embeddingów?\n\nTo wygeneruje wektory dla 100 chunks bez embeddingów (potrzebne do semantic search).',
const limitInput = await showConfirm(
'Ile chunks chcesz przetworzyć?\n\nWygeneruje wektory dla chunks bez embeddingów (potrzebne do semantic search).',
{
icon: '🔢',
title: 'Generowanie embeddingów',
showInput: true,
inputLabel: 'Liczba chunks (1-500):',
inputPlaceholder: '1',
okText: 'Generuj embeddingi',
okClass: 'btn-primary'
}
);
if (!confirmed) return;
if (limitInput === false) return;
showToast('Generuję embeddingi...', 'info', 15000);
const limit = parseInt(limitInput) || 1;
if (limit < 1 || limit > 500) {
showToast('Limit musi być między 1 a 500', 'warning');
return;
}
showToast(`Generuję embeddingi dla ${limit} chunks...`, 'info', 15000);
try {
const response = await fetch('/admin/zopk/knowledge/embeddings', {
@ -997,13 +1023,12 @@ async function batchGenerateEmbeddings() {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify({ limit: 100 })
body: JSON.stringify({ limit: limit })
});
const data = await response.json();
if (data.success) {
// Fields: generated (count), total, failed
showToast(`✅ Embeddingi wygenerowane: ${data.generated || 0}/${data.total || 0} chunks`, 'success', 8000);
showToast(`✅ Embeddingi: ${data.generated || 0}/${data.total || 0} chunks`, 'success', 8000);
} else {
showToast(data.error || 'Wystąpił błąd', 'error');
}