mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2026-10-27 09:40:40 +00:00
153 lines
5.6 KiB
HTML
153 lines
5.6 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>VoxVera GUI</title>
|
|
<style>
|
|
body {
|
|
font-family: sans-serif;
|
|
margin: 1rem;
|
|
}
|
|
#status {
|
|
border: 1px solid #ccc;
|
|
padding: 0.75rem;
|
|
margin-bottom: 1rem;
|
|
background: #fafafa;
|
|
}
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 0.15rem 0.4rem;
|
|
border-radius: 999px;
|
|
font-size: 0.85rem;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
}
|
|
.status-supported {
|
|
background: #dff3e4;
|
|
color: #14532d;
|
|
}
|
|
.status-experimental {
|
|
background: #fff4d6;
|
|
color: #854d0e;
|
|
}
|
|
.status-error {
|
|
background: #fee2e2;
|
|
color: #991b1b;
|
|
}
|
|
#log {
|
|
border: 1px solid #ccc;
|
|
padding: 5px;
|
|
height: 150px;
|
|
overflow-y: auto;
|
|
background: #f8f8f8;
|
|
white-space: pre-wrap;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>VoxVera</h1>
|
|
<div id="status">
|
|
<strong>Runtime status</strong>
|
|
<div id="platform-tier"></div>
|
|
<div id="platform-model"></div>
|
|
<div id="autostart-state"></div>
|
|
<div id="doctor-summary"></div>
|
|
</div>
|
|
<form id="config-form">
|
|
<div><label>Name <input type="text" id="name"></label></div>
|
|
<div><label>Subdomain <input type="text" id="folder_name"></label></div>
|
|
<div><label>Title <input type="text" id="title"></label></div>
|
|
<div><label>Subtitle <input type="text" id="subtitle"></label></div>
|
|
<div><label>Headline <input type="text" id="headline"></label></div>
|
|
<div><label>Content<br><textarea id="content" rows="5" cols="60"></textarea></label></div>
|
|
<div><label>URL Message <input type="text" id="url_message"></label></div>
|
|
<div><label>URL <input type="text" id="url"></label></div>
|
|
<div><label>Tear-off link <input type="text" id="tear_off_link"></label></div>
|
|
<div><label>Footer message <input type="text" id="footer_message"></label></div>
|
|
<button type="button" id="quickstart">Generate & Serve</button>
|
|
</form>
|
|
<p id="onion-address"></p>
|
|
<pre id="log"></pre>
|
|
<script>
|
|
function setStatusBadge(targetId, label, tier) {
|
|
const el = document.getElementById(targetId);
|
|
const className = tier === 'supported' ? 'status-supported'
|
|
: tier === 'experimental' ? 'status-experimental'
|
|
: 'status-error';
|
|
el.innerHTML = `<span class="status-badge ${className}">${label}</span>`;
|
|
}
|
|
|
|
function summarizeDoctorChecks(doctor) {
|
|
const sections = doctor && doctor.sections ? Object.values(doctor.sections) : [];
|
|
if (sections.length > 0) {
|
|
const failedSections = sections.filter(section => section.checks && section.checks.length > 0 && !section.ok);
|
|
if (failedSections.length === 0) return 'All doctor sections passed.';
|
|
return `Doctor warnings in: ${failedSections.map(section => section.title).join(', ')}`;
|
|
}
|
|
const checks = doctor && Array.isArray(doctor.checks) ? doctor.checks : [];
|
|
if (checks.length === 0) return 'No diagnostics available.';
|
|
const failed = checks.filter(check => !check.ok);
|
|
if (failed.length === 0) return 'All doctor checks passed.';
|
|
return `Doctor reports ${failed.length} failing check(s): ${failed.map(check => check.name).join(', ')}`;
|
|
}
|
|
|
|
async function loadRuntimeStatus() {
|
|
const runtime = await window.voxvera.loadRuntimeStatus();
|
|
if (!runtime.ok) {
|
|
setStatusBadge('platform-tier', 'error', 'error');
|
|
document.getElementById('platform-model').textContent = runtime.error;
|
|
document.getElementById('autostart-state').textContent = '';
|
|
document.getElementById('doctor-summary').textContent = '';
|
|
return;
|
|
}
|
|
|
|
const { platformStatus, autostart, doctor } = runtime;
|
|
setStatusBadge('platform-tier', platformStatus.tier, platformStatus.tier);
|
|
document.getElementById('platform-model').textContent = platformStatus.hosting_model || '';
|
|
if (autostart && !autostart.error) {
|
|
document.getElementById('autostart-state').textContent = `Autostart: ${autostart.message}`;
|
|
} else if (autostart && autostart.error) {
|
|
document.getElementById('autostart-state').textContent = `Autostart status unavailable: ${autostart.error}`;
|
|
}
|
|
document.getElementById('doctor-summary').textContent = summarizeDoctorChecks(doctor);
|
|
}
|
|
|
|
async function load() {
|
|
const cfg = await window.voxvera.loadConfig();
|
|
for (const [k, v] of Object.entries(cfg)) {
|
|
const el = document.getElementById(k);
|
|
if (el) el.value = v;
|
|
}
|
|
await loadRuntimeStatus();
|
|
}
|
|
document.addEventListener('DOMContentLoaded', load);
|
|
|
|
document.getElementById('quickstart').addEventListener('click', async () => {
|
|
const ids = ['name','folder_name','title','subtitle','headline','content','url_message','url','tear_off_link','footer_message'];
|
|
const cfg = {};
|
|
ids.forEach(id => {
|
|
const el = document.getElementById(id);
|
|
if (el) cfg[id] = el.value;
|
|
});
|
|
await window.voxvera.quickstart(cfg);
|
|
await loadRuntimeStatus();
|
|
});
|
|
|
|
window.voxvera.onOnionUrl(url => {
|
|
document.getElementById('onion-address').textContent = `Onion address: ${url}`;
|
|
const tear = document.getElementById('tear_off_link');
|
|
if (tear) tear.value = url;
|
|
});
|
|
|
|
window.voxvera.onLog((msg, isErr) => {
|
|
const container = document.getElementById('log');
|
|
const span = document.createElement('span');
|
|
if (isErr) span.style.color = 'red';
|
|
span.textContent = msg;
|
|
container.appendChild(span);
|
|
container.scrollTop = container.scrollHeight;
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|