const API_BASE = '/api';
let currentPage = null;
let chatHistory = [];
document.addEventListener('DOMContentLoaded', () => {
initTabs();
loadWikiList();
loadRawList();
});
function initTabs() {
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('tab-active'));
btn.classList.add('tab-active');
document.querySelectorAll('.tab-panel').forEach(p => p.classList.add('hidden'));
document.getElementById(`tab-${btn.dataset.tab}`).classList.remove('hidden');
});
});
}
async function loadWikiList() {
try {
const res = await fetch(`${API_BASE}/wiki/list`);
const data = await res.json();
const list = document.getElementById('page-list');
list.innerHTML = '';
const categories = ['entities', 'concepts', 'sources', 'topics', 'comparisons'];
categories.forEach(cat => {
if (data[cat] && data[cat].length > 0) {
const catDiv = document.createElement('div');
catDiv.innerHTML = `
${cat}
`;
data[cat].forEach(page => {
const a = document.createElement('a');
a.href = '#';
a.textContent = page.name;
a.className = 'block px-2 py-1 rounded hover:bg-gray-700 text-blue-400';
a.onclick = () => loadPage(page.file);
catDiv.appendChild(a);
});
list.appendChild(catDiv);
}
});
} catch (e) {
console.error('Error loading wiki list:', e);
}
}
async function loadPage(file) {
try {
const res = await fetch(`${API_BASE}/wiki/page/${file}`);
const data = await res.json();
currentPage = data;
const container = document.getElementById('page-content');
let html = `${data.file.split('/').pop().replace('.md', '')}
`;
if (data.metadata && Object.keys(data.metadata).length > 0) {
html += `Tags: ${Object.values(data.metadata).join(', ')}
`;
}
let content = data.content || '';
content = content.replace(/\[\[([^\]]+)\]\]/g, '[[$1]]');
html += `${marked.parse(content)}
`;
container.innerHTML = html;
} catch (e) {
document.getElementById('page-content').innerHTML = `Errore: ${e.message}
`;
}
}
function navigateTo(name) {
const normalized = name.toLowerCase().replace(/\s+/g, '-');
loadPage(normalized);
}
async function loadRawList() {
try {
const res = await fetch(`${API_BASE}/raw/list`);
const data = await res.json();
const list = document.getElementById('raw-list');
list.innerHTML = '';
Object.entries(data).forEach(([cat, files]) => {
if (files.length > 0) {
const div = document.createElement('div');
div.innerHTML = `${cat}
`;
files.forEach(f => {
const label = document.createElement('label');
label.className = 'flex items-center gap-2 px-2 py-1 hover:bg-gray-700 rounded cursor-pointer';
label.innerHTML = ` ${f}`;
div.appendChild(label);
});
list.appendChild(div);
}
});
} catch (e) {
console.error('Error loading raw list:', e);
}
}
async function runIngest() {
const selected = document.querySelector('input[name="source"]:checked');
if (!selected) {
alert('Seleziona un file da ingestire');
return;
}
const log = document.getElementById('ingest-log');
log.innerHTML = 'Avvio ingest...\n';
try {
const eventSource = new EventSource(`${API_BASE}/ingest/stream/${selected.value}`);
eventSource.onmessage = (e) => {
log.innerHTML += e.data + '\n';
log.scrollTop = log.scrollHeight;
};
eventSource.onerror = () => {
eventSource.close();
log.innerHTML += 'Completato!\n';
loadWikiList();
};
} catch (e) {
log.innerHTML += `Errore: ${e.message}\n`;
}
}
async function doSearch() {
const query = document.getElementById('search-input').value.trim();
if (!query) return;
const results = document.getElementById('search-results');
results.innerHTML = 'Ricerca in corso...';
try {
const res = await fetch(`${API_BASE}/search?q=${encodeURIComponent(query)}`);
const data = await res.json();
results.innerHTML = '';
if (data.by_name && data.by_name.length > 0) {
const section = document.createElement('div');
section.innerHTML = `Per nome
`;
data.by_name.forEach(r => {
section.innerHTML += ``;
});
results.appendChild(section);
}
if (data.by_content && data.by_content.length > 0) {
const section = document.createElement('div');
section.innerHTML = `Nel contenuto
`;
data.by_content.forEach(r => {
const matchesHtml = r.matches.map(m => `Linea ${m.line}: ${m.text}
`).join('');
section.innerHTML += ``;
});
results.appendChild(section);
}
if ((!data.by_name || data.by_name.length === 0) && (!data.by_content || data.by_content.length === 0)) {
results.innerHTML = 'Nessun risultato';
}
} catch (e) {
results.innerHTML = `Errore: ${e.message}`;
}
}
async function sendChat() {
const input = document.getElementById('chat-input');
const message = input.value.trim();
if (!message) return;
const messages = document.getElementById('chat-messages');
messages.innerHTML += `Tu: ${escapeHtml(message)}
`;
input.value = '';
const responseDiv = document.createElement('div');
responseDiv.className = 'mb-2 p-2 bg-gray-800 rounded';
responseDiv.innerHTML = 'Wiki: ';
messages.appendChild(responseDiv);
messages.scrollTop = messages.scrollHeight;
try {
const res = await fetch(`${API_BASE}/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, history: chatHistory })
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
let response = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
response += chunk;
responseDiv.innerHTML = `Wiki: ${formatResponse(response)}`;
}
chatHistory.push({ role: 'user', content: message });
chatHistory.push({ role: 'assistant', content: response });
} catch (e) {
responseDiv.innerHTML = `Errore: ${e.message}`;
}
}
function formatResponse(text) {
text = escapeHtml(text);
text = text.replace(/\[\[([^\]]+)\]\]/g, '[[$1]]');
return text + '';
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
const marked = {
parse: function(text) {
text = text.replace(/^### (.+)$/gm, '$1
');
text = text.replace(/^## (.+)$/gm, '$1
');
text = text.replace(/^# (.+)$/gm, '$1
');
text = text.replace(/\*\*(.+?)\*\*/g, '$1');
text = text.replace(/\*(.+?)\*/g, '$1');
text = text.replace(/`(.+?)`/g, '$1');
text = text.replace(/\n/g, '
');
return text;
}
};