';
var infoBtnEl = tile.querySelector(".tile-info-btn");
if (infoBtnEl) {
@@ -342,13 +344,13 @@ async function openSupportModal() {
function renderSupportInactive() {
stopSupportTimer();
var ip = _cachedExternalIp || "loading…";
- $supportBody.innerHTML = '
🛟
Need help from Sovran Systems?
This will temporarily give Sovran Systems secure SSH access to your machine so we can diagnose and fix issues for you.
Your External IP' + escHtml(ip) + '
Give this IP to your Sovran Systems technician when asked.
What happens when you click Enable:
A Sovran Systems SSH key is added to this machine
You give us your External IP shown above
We connect and help you remotely
When done, you click End Support Session to remove the key
You can end the session at any time. The access key will be completely removed.
';
+ $supportBody.innerHTML = '
🛟
Need help from Sovran Systems?
This will temporarily grant our support team SSH access to your machine so we can help diagnose and fix issues.
Your IP' + escHtml(ip) + '
This IP will be shared with Sovran Systems support
What happens:
Our public SSH key is added to your machine
We connect and help fix the issue
You click "End Session" to remove our access
You can revoke access at any time
';
document.getElementById("btn-support-enable").addEventListener("click", enableSupport);
}
function renderSupportActive() {
var ip = _cachedExternalIp || "loading…";
- $supportBody.innerHTML = '
🔓
Support Access is Active
Sovran Systems can currently connect to your machine via SSH.
Your External IP' + escHtml(ip) + '
Session Duration—
When your support session is complete, click the button below to immediately remove the access key.
';
+ $supportBody.innerHTML = '
🔓
Support Access is Active
Sovran Systems can currently connect to your machine via SSH.
Your IP' + escHtml(ip) + '
Duration…
This will remove the SSH key immediately
';
document.getElementById("btn-support-disable").addEventListener("click", disableSupport);
startSupportTimer();
}
@@ -356,7 +358,7 @@ function renderSupportActive() {
function renderSupportRemoved(verified) {
stopSupportTimer();
var icon = verified ? "✅" : "⚠️";
- var msg = verified ? "The Sovran Systems SSH key has been completely removed from your machine. We no longer have any access." : "The key removal was requested but could not be fully verified. Please reboot your machine to be sure.";
+ var msg = verified ? "The Sovran Systems SSH key has been completely removed from your machine. We no longer have any access." : "The key removal was requested but could not be fully verified. Please reboot to ensure it is gone.";
var vclass = verified ? "verified-gone" : "verify-warning";
var vlabel = verified ? "✓ Removed — No access" : "⚠ Verify by rebooting";
$supportBody.innerHTML = '
' + icon + '
Support Session Ended
' + escHtml(msg) + '
SSH Key Status:' + vlabel + '
';
@@ -513,7 +515,9 @@ function saveErrorReport() {
function doReboot() {
if ($modal) $modal.classList.remove("open");
+ if ($rebuildModal) $rebuildModal.classList.remove("open");
stopUpdatePoll();
+ stopRebuildPoll();
if ($rebootOverlay) $rebootOverlay.classList.add("visible");
fetch("/api/reboot", { method: "POST" }).catch(function() {});
setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL);
@@ -536,8 +540,10 @@ function openRebuildModal() {
_rebuildLogOffset = 0;
_rebuildServerDown = false;
_rebuildFinished = false;
- if ($rebuildLog) $rebuildLog.textContent = "";
- if ($rebuildStatus) $rebuildStatus.textContent = "Rebuilding…";
+ if ($rebuildLog) { $rebuildLog.textContent = ""; $rebuildLog.style.display = "none"; }
+ var action = _rebuildIsEnabling ? "Enabling" : "Disabling";
+ var label = _rebuildFeatureName || "feature";
+ if ($rebuildStatus) $rebuildStatus.textContent = action + " " + label + "…";
if ($rebuildSpinner) $rebuildSpinner.classList.add("spinning");
if ($rebuildReboot) $rebuildReboot.style.display = "none";
if ($rebuildSave) $rebuildSave.style.display = "none";
@@ -555,7 +561,7 @@ function closeRebuildModal() {
function appendRebuildLog(text) {
if (!text) return;
_rebuildLog += text;
- if ($rebuildLog) { $rebuildLog.textContent += text; $rebuildLog.scrollTop = $rebuildLog.scrollHeight; }
+ // Log is collected silently for error reports — not displayed to user
}
function startRebuildPoll() {
@@ -571,7 +577,7 @@ async function pollRebuildStatus() {
if (_rebuildFinished) return;
try {
var data = await apiFetch("/api/rebuild/status?offset=" + _rebuildLogOffset);
- if (_rebuildServerDown) { _rebuildServerDown = false; appendRebuildLog("[Server reconnected]\n"); if ($rebuildStatus) $rebuildStatus.textContent = "Rebuilding…"; }
+ if (_rebuildServerDown) { _rebuildServerDown = false; }
if (data.log) appendRebuildLog(data.log);
_rebuildLogOffset = data.offset;
if (data.running) return;
@@ -579,7 +585,7 @@ async function pollRebuildStatus() {
stopRebuildPoll();
onRebuildDone(data.result === "success");
} catch (err) {
- if (!_rebuildServerDown) { _rebuildServerDown = true; appendRebuildLog("\n[Server restarting — waiting for it to come back…]\n"); if ($rebuildStatus) $rebuildStatus.textContent = "Server restarting…"; }
+ if (!_rebuildServerDown) { _rebuildServerDown = true; if ($rebuildStatus) $rebuildStatus.textContent = "Applying changes…"; }
}
}
@@ -587,12 +593,11 @@ function onRebuildDone(success) {
if ($rebuildSpinner) $rebuildSpinner.classList.remove("spinning");
if ($rebuildClose) $rebuildClose.disabled = false;
if (success) {
- if ($rebuildStatus) $rebuildStatus.textContent = "✓ Rebuild complete";
- if ($rebuildReboot) $rebuildReboot.style.display = "inline-flex";
- // Refresh feature states
- loadFeatureManager();
+ if ($rebuildStatus) $rebuildStatus.textContent = "✓ Done";
+ // Auto-reload the page after a short delay so tiles and toggles reflect the new state
+ setTimeout(function() { window.location.reload(); }, 1200);
} else {
- if ($rebuildStatus) $rebuildStatus.textContent = "✗ Rebuild failed";
+ if ($rebuildStatus) $rebuildStatus.textContent = "✗ Something went wrong";
if ($rebuildSave) $rebuildSave.style.display = "inline-flex";
if ($rebuildReboot) $rebuildReboot.style.display = "inline-flex";
}
@@ -680,12 +685,12 @@ function openDomainSetupModal(feat, onSaved) {
}
}
}
- npubField = '';
+ npubField = '';
}
$domainSetupBody.innerHTML =
'
Before continuing, you need:
A subdomain purchased on njal.la
A Dynamic DNS record for it
' +
- '' +
+ '' +
'
ℹ Paste the curl URL from your Njal.la dashboard\'s Dynamic record
' +
npubField +
'';
@@ -736,6 +741,13 @@ function closeDomainSetupModal() {
// ── Feature toggle logic ──────────────────────────────────────────
async function performFeatureToggle(featId, enabled, extra) {
+ // Look up feature name for the rebuild modal
+ _rebuildIsEnabling = enabled;
+ _rebuildFeatureName = featId;
+ if (_featuresData) {
+ var found = _featuresData.features.find(function(f) { return f.id === featId; });
+ if (found) _rebuildFeatureName = found.name;
+ }
try {
var res = await fetch("/api/features/toggle", {
method: "POST",
@@ -1006,4 +1018,4 @@ async function init() {
}
}
-document.addEventListener("DOMContentLoaded", init);
+document.addEventListener("DOMContentLoaded", init);
\ No newline at end of file