import { services as api } from '../api.js'; import { icons } from '../icons.js'; import { navigate } from '../router.js'; function formatTime(dateStr) { if (!dateStr) return '–'; const d = new Date(dateStr), diff = Math.floor((Date.now() - d) / 60000); if (diff < 1) return 'ora'; if (diff < 60) return `${diff}m fa`; const h = Math.floor(diff / 60); if (h < 24) return `${h}h fa`; return `${Math.floor(h / 24)}g fa`; } function serviceCardHTML(s) { const status = s.container?.status || s.status || 'stopped'; const repo = s.gitea_repo_url?.replace(/https?:\/\/[^/]+\//, '').replace('.git', '') || ''; const ld = s.last_deploy; return `
${s.name} ${status}
${s.description ? `

${s.description}

` : ''}
${icons.gitBranch(12)} ${repo} :${s.gitea_branch}
${s.traefik_domain ? `
${icons.globe(12)} ${s.traefik_domain}
` : ''}
${icons.clock(12)} ${ld ? `${ld.status === 'success' ? '✅' : ld.status === 'failed' ? '❌' : '⏳'} ${formatTime(ld.created_at)}` : 'Mai deployato'}
${ld?.commit_sha ? `
${ld.commit_sha}
` : ''}
${status === 'running' || status === 'error' ? `` : ''}
`; } export function renderDashboard(container) { let interval; container.innerHTML = `
`; async function load() { const grid = document.getElementById('services-grid'); try { const list = await api.list(); if (list.length === 0) { grid.innerHTML = `

Nessun servizio configurato

Crea il tuo primo servizio per iniziare

`; return; } grid.innerHTML = list.map(serviceCardHTML).join(''); // Events grid.querySelectorAll('.service-card').forEach(el => { el.onclick = (e) => { if (!e.target.closest('button')) navigate(`/services/${el.dataset.id}`); }; }); grid.querySelectorAll('.btn-deploy').forEach(b => { b.onclick = async (e) => { e.stopPropagation(); await api.deploy(b.dataset.id); load(); }; }); grid.querySelectorAll('.btn-stop').forEach(b => { b.onclick = async (e) => { e.stopPropagation(); await api.stop(b.dataset.id); load(); }; }); } catch (err) { grid.innerHTML = `

Errore: ${err.message}

`; } } document.getElementById('refresh-btn').onclick = load; document.getElementById('create-btn').onclick = () => showCreateModal(load); load(); interval = setInterval(load, 10000); return () => clearInterval(interval); } function showCreateModal(onCreated) { const modal = document.getElementById('create-modal'); modal.innerHTML = ` `; const close = () => { modal.innerHTML = ''; }; document.getElementById('modal-overlay').onclick = close; document.getElementById('modal-close').onclick = close; document.getElementById('modal-cancel').onclick = close; document.getElementById('cf-name').oninput = (e) => { document.getElementById('cf-container').value = e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '-'); }; document.getElementById('create-form').onsubmit = async (e) => { e.preventDefault(); const errEl = document.getElementById('modal-error'); errEl.classList.add('hidden'); try { const s = await api.create({ name: document.getElementById('cf-name').value, container_name: document.getElementById('cf-container').value, description: document.getElementById('cf-desc').value, gitea_repo_url: document.getElementById('cf-repo').value, gitea_branch: document.getElementById('cf-branch').value, container_port: parseInt(document.getElementById('cf-port').value), traefik_domain: document.getElementById('cf-domain').value, traefik_enabled: true, traefik_tls_resolver: 'cloudflare', traefik_network: 'meb-public', networks: ['meb-public'], }); close(); onCreated(); navigate(`/services/${s.id}`); } catch (err) { errEl.textContent = err.message; errEl.classList.remove('hidden'); } }; }