This repository has been archived on 2026-05-11. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
autodeployer-old-version/dashboard/js/pages/settings.js
Giuseppe Raffa 87d698bc5c feat: add Docker and Gitea services, monitoring, queue, and Telegram notification functionalities
- Implemented Docker operations including image building, container management, and resource stats.
- Added Gitea API client for repository management and webhook handling.
- Introduced monitoring service to collect and store container metrics in InfluxDB.
- Created a queue system using BullMQ for managing deployment jobs with real-time log streaming.
- Developed Telegram notification service for deployment status updates.
- Added Traefik label generation for dynamic reverse proxy configuration.
- Implemented WebSocket endpoints for log streaming and terminal access to containers.
- Created an updater sidecar for self-updating the AutoDeployer container.
2026-04-13 23:23:18 +02:00

169 lines
8.6 KiB
JavaScript

import { settingsApi, auth, system as systemApi, services as servicesApi } from '../api.js';
import { icons } from '../icons.js';
export function renderSettings(container) {
let queueStatus = null;
let version = null;
let interval;
container.innerHTML = `
<div class="page-header"><div><h2>Settings</h2><p>Configurazione globale e test connessioni</p></div></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px" id="settings-grid">
<!-- Gitea -->
<div class="card" id="s-gitea">
<h3 class="card-title mb-4">${icons.gitBranch(16)} Connessione Gitea</h3>
<p class="text-sm text-muted mb-4">Testa la connessione al server Gitea configurato</p>
<button class="btn btn-secondary" id="test-gitea">Test Connessione</button>
<div id="gitea-result" class="mt-4 text-sm hidden"></div>
</div>
<!-- Telegram -->
<div class="card" id="s-telegram">
<h3 class="card-title mb-4">${icons.bell(16)} Notifiche Telegram</h3>
<p class="text-sm text-muted mb-4">Invia un messaggio di test al bot Telegram configurato</p>
<button class="btn btn-secondary" id="test-telegram">Test Telegram</button>
<div id="telegram-result" class="mt-4 text-sm hidden"></div>
</div>
<!-- Queue -->
<div class="card" id="s-queue">
<h3 class="card-title mb-4">${icons.database(16)} Build Queue</h3>
<div id="queue-content"><p class="text-muted text-sm">Caricamento...</p></div>
</div>
<!-- Password -->
<div class="card">
<h3 class="card-title mb-4">${icons.key(16)} Cambia Password</h3>
<form id="pw-form">
<div class="form-group"><label class="form-label">Password Attuale</label><input type="password" class="form-input" id="pw-current" required></div>
<div class="form-group"><label class="form-label">Nuova Password</label><input type="password" class="form-input" id="pw-new" required minlength="12"><div class="form-hint">Minimo 12 caratteri</div></div>
<div class="form-group"><label class="form-label">Conferma</label><input type="password" class="form-input" id="pw-confirm" required></div>
<div id="pw-msg" class="text-sm mb-2 hidden"></div>
<button type="submit" class="btn btn-primary">Aggiorna Password</button>
</form>
</div>
<!-- Self-Update -->
<div class="card">
<h3 class="card-title mb-4">${icons.refreshCw(16)} Self-Update</h3>
<div id="version-info" class="text-sm text-muted mb-4"></div>
<p class="text-sm text-muted mb-4">Aggiorna AutoDeployer all'ultima versione. Il servizio si riavvierà automaticamente.</p>
<button class="btn btn-primary" id="self-update">Aggiorna AutoDeployer</button>
<div id="update-result" class="mt-4 text-sm hidden"></div>
</div>
<!-- Cleanup -->
<div class="card">
<h3 class="card-title mb-4">${icons.trash2(16)} Pulizia Container Orfani</h3>
<p class="text-sm text-muted mb-4">Rimuovi container temporanei rimasti da deploy falliti.</p>
<button class="btn btn-secondary" id="cleanup-btn">Scansiona e Pulisci</button>
<div id="cleanup-result" class="mt-4 text-sm hidden"></div>
</div>
<!-- Prune -->
<div class="card">
<h3 class="card-title mb-4">${icons.hardDrive(16)} Pulizia Immagini Vecchie</h3>
<p class="text-sm text-muted mb-4">Rimuovi immagini Docker obsolete, mantenendo le 2 più recenti per servizio.</p>
<button class="btn btn-secondary" id="prune-btn">Pulisci Immagini</button>
<div id="prune-result" class="mt-4 text-sm hidden"></div>
</div>
</div>`;
// Gitea test
document.getElementById('test-gitea').onclick = async () => {
const btn = document.getElementById('test-gitea');
btn.textContent = '⏳ Testing...'; btn.disabled = true;
const res = document.getElementById('gitea-result');
try {
const r = await settingsApi.testGitea();
res.innerHTML = r.ok ? `${icons.checkCircle(16)} Connesso come <strong>${r.user}</strong>` : `${icons.xCircle(16)} ${r.error}`;
} catch (err) { res.innerHTML = `${icons.xCircle(16)} ${err.message}`; }
res.classList.remove('hidden'); btn.textContent = 'Test Connessione'; btn.disabled = false;
};
// Telegram test
document.getElementById('test-telegram').onclick = async () => {
const btn = document.getElementById('test-telegram');
btn.textContent = '⏳ Testing...'; btn.disabled = true;
const res = document.getElementById('telegram-result');
try {
const r = await settingsApi.testTelegram();
res.innerHTML = r.ok ? `${icons.checkCircle(16)} Messaggio inviato` : `${icons.xCircle(16)} ${r.error}`;
} catch (err) { res.innerHTML = `${icons.xCircle(16)} ${err.message}`; }
res.classList.remove('hidden'); btn.textContent = 'Test Telegram'; btn.disabled = false;
};
// Queue status
async function loadQueue() {
try {
queueStatus = await settingsApi.queueStatus();
document.getElementById('queue-content').innerHTML = `
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
<div><div class="metric-label">In Attesa</div><div class="metric-value" style="font-size:1.5rem">${queueStatus.waiting}</div></div>
<div><div class="metric-label">Attive</div><div class="metric-value" style="font-size:1.5rem">${queueStatus.active}</div></div>
<div><div class="metric-label">Completate</div><div class="text-sm font-bold" style="color:var(--status-running)">${queueStatus.completed}</div></div>
<div><div class="metric-label">Fallite</div><div class="text-sm font-bold" style="color:var(--status-error)">${queueStatus.failed}</div></div>
</div>`;
} catch {}
}
// Version
async function loadVersion() {
try {
version = await systemApi.version();
document.getElementById('version-info').innerHTML = `Versione: <strong class="mono">${version.commit}</strong> (${version.branch})<br><span class="text-xs">${version.date}</span>`;
} catch {}
}
// Password
document.getElementById('pw-form').onsubmit = async (e) => {
e.preventDefault();
const msg = document.getElementById('pw-msg');
msg.classList.add('hidden');
const newPw = document.getElementById('pw-new').value;
const confirm = document.getElementById('pw-confirm').value;
if (newPw !== confirm) { msg.textContent = 'Le password non coincidono'; msg.classList.remove('hidden'); return; }
try {
await auth.changePassword(document.getElementById('pw-current').value, newPw);
msg.textContent = '✅ Password aggiornata'; msg.classList.remove('hidden');
document.getElementById('pw-form').reset();
} catch (err) { msg.textContent = '❌ ' + err.message; msg.classList.remove('hidden'); }
};
// Self-update
document.getElementById('self-update').onclick = async () => {
const btn = document.getElementById('self-update');
btn.textContent = 'Aggiornamento...'; btn.disabled = true;
const res = document.getElementById('update-result');
try {
await systemApi.selfUpdate();
res.innerHTML = `${icons.checkCircle(14)} Update avviato. AutoDeployer si riavvierà a breve.`;
} catch (err) { res.innerHTML = `${icons.xCircle(14)} ${err.message}`; }
res.classList.remove('hidden'); btn.textContent = 'Aggiorna AutoDeployer'; btn.disabled = false;
};
// Cleanup
document.getElementById('cleanup-btn').onclick = async () => {
const btn = document.getElementById('cleanup-btn');
btn.textContent = 'Scansione...'; btn.disabled = true;
const res = document.getElementById('cleanup-result');
try {
const r = await servicesApi.cleanup();
res.textContent = `${r.orphans_found} orfani trovati, ${r.results?.filter(x => x.status === 'removed').length || 0} rimossi`;
} catch (err) { res.innerHTML = `<span style="color:var(--status-error)">${err.message}</span>`; }
res.classList.remove('hidden'); btn.textContent = 'Scansiona e Pulisci'; btn.disabled = false;
};
// Prune
document.getElementById('prune-btn').onclick = async () => {
const btn = document.getElementById('prune-btn');
btn.textContent = 'Pulizia...'; btn.disabled = true;
const res = document.getElementById('prune-result');
try {
const r = await servicesApi.pruneImages();
res.textContent = `${r.results?.filter(x => x.status === 'removed').length || 0} immagini rimosse`;
} catch (err) { res.innerHTML = `<span style="color:var(--status-error)">${err.message}</span>`; }
res.classList.remove('hidden'); btn.textContent = 'Pulisci Immagini'; btn.disabled = false;
};
loadQueue();
loadVersion();
interval = setInterval(loadQueue, 10000);
return () => clearInterval(interval);
}