const API_BASE = '/api/v1'; async function api(method, path, body) { const options = { method, headers: { 'Content-Type': 'application/json' } }; if (body) options.body = JSON.stringify(body); const res = await fetch(API_BASE + path, options); if (!res.ok) { const err = await res.json(); throw new Error(err.error || 'Request failed'); } return res.json(); } function showMessage(text, type = 'success') { const msg = document.getElementById('message'); if (!msg) return; msg.textContent = text; msg.className = `message ${type}`; setTimeout(() => msg.className = 'hidden', 5000); } function formatDate(dateStr) { if (!dateStr) return '-'; return new Date(dateStr).toLocaleString(); } function statusBadge(status) { const colors = { pending: '#f39c12', running: '#3498db', success: '#27ae60', failed: '#e74c3c' }; return `${status}`; } async function initGeneratePage() { try { const plugins = await api('GET', '/plugins'); const select = document.getElementById('language'); plugins.forEach(p => { const opt = document.createElement('option'); opt.value = p.language; opt.textContent = p.language; select.appendChild(opt); }); } catch (e) { console.error('Failed to load plugins:', e); } document.getElementById('generateForm').addEventListener('submit', async (e) => { e.preventDefault(); const btn = e.target.querySelector('button[type="submit"]'); btn.disabled = true; btn.textContent = 'Generating...'; try { const task = await api('POST', '/tasks', { language: document.getElementById('language').value, proto_repo: document.getElementById('protoRepo').value, proto_branch: document.getElementById('protoBranch').value, target_repo: document.getElementById('targetRepo').value || undefined }); showMessage(`Task created: ${task.id}`, 'success'); e.target.reset(); document.getElementById('protoBranch').value = 'main'; } catch (err) { showMessage(err.message, 'error'); } finally { btn.disabled = false; btn.textContent = 'Generate'; } }); } async function initTasksPage() { await refreshTasks(); document.getElementById('statusFilter').addEventListener('change', refreshTasks); setInterval(refreshTasks, 10000); } async function refreshTasks() { const status = document.getElementById('statusFilter').value; const params = status ? `?status=${status}` : ''; try { const tasks = await api('GET', `/tasks${params}`); const tbody = document.getElementById('tasksBody'); const noTasks = document.getElementById('noTasks'); if (!tasks || tasks.length === 0) { tbody.innerHTML = ''; noTasks.classList.remove('hidden'); return; } noTasks.classList.add('hidden'); tbody.innerHTML = tasks.map(t => ` ${t.id.substring(0, 8)} ${t.language} ${t.proto_repo} ${t.target_repo} ${statusBadge(t.status)} ${formatDate(t.created_at)} ${t.status === 'failed' ? `` : ''} `).join(''); } catch (err) { console.error('Failed to load tasks:', err); } } async function retryTask(id) { try { await api('POST', `/tasks/${id}/retry`); showMessage('Task queued for retry'); refreshTasks(); } catch (err) { showMessage(err.message, 'error'); } } async function initSettingsPage() { try { const plugins = await api('GET', '/plugins'); const container = document.getElementById('pluginsList'); container.innerHTML = plugins.map(p => `

${p.language}

Image: ${p.image}

`).join(''); } catch (err) { console.error('Failed to load plugins:', err); } }