Fix player page now playing updates and spectrum analyzer MUTED indicator
- Execute scripts after AJAX navigation to enable dynamic content updates - Fix spectrum analyzer audio element reference across navigation - Stop and restart spectrum analyzer when re-initializing after AJAX load - Find audio element in parent frame for frameset mode - Clear all intervals/timeouts before navigation to prevent errors - Add status-content.ctml placeholder page - Remove debug logging from spectrum analyzer Fixes: - Now playing panel updates on player page after navigation - MUTED indicator appears correctly across all pages - No console errors from abandoned intervals - Clean resource cleanup on page transitions
This commit is contained in:
parent
3a8827f442
commit
ca07b6e670
|
|
@ -607,6 +607,13 @@
|
|||
:top-artist-3 ""
|
||||
:top-artist-3-plays ""))
|
||||
|
||||
;; Status content frame (for frameset mode)
|
||||
(define-page status-content #@"/status-content" ()
|
||||
"Status page content (displayed in content frame)"
|
||||
(clip:process-to-string
|
||||
(load-template "status-content")
|
||||
:title "📡 Asteroid Radio - Status"))
|
||||
|
||||
;; Configure static file serving for other files
|
||||
;; BUT exclude ParenScript-compiled JS files
|
||||
(define-page static #@"/static/(.*)" (:uri-groups (path))
|
||||
|
|
|
|||
|
|
@ -43,24 +43,22 @@
|
|||
(let ((audio-element nil)
|
||||
(canvas-element (ps:chain document (get-element-by-id "spectrum-canvas"))))
|
||||
|
||||
;; Try to find audio element in current frame first
|
||||
;; Try current document first
|
||||
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
||||
(ps:chain document (get-element-by-id "persistent-audio"))))
|
||||
|
||||
;; If not found and we're in a frame, try to access from parent frameset
|
||||
;; If not found and we're in a frame, try parent frame (frameset mode)
|
||||
(when (and (not audio-element)
|
||||
(ps:@ window parent)
|
||||
(not (eq (ps:@ window parent) window)))
|
||||
(ps:chain console (log "Trying to access audio from parent frame..."))
|
||||
(ps:try
|
||||
(progn
|
||||
;; Try accessing via parent.frames
|
||||
(let ((player-frame (ps:getprop (ps:@ window parent) "player-frame")))
|
||||
(when player-frame
|
||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
||||
(ps:chain console (log "Found audio in player-frame:" audio-element)))))
|
||||
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
|
||||
(when player-frame
|
||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
||||
(when audio-element
|
||||
(ps:chain console (log "Found persistent-audio in player-frame")))))
|
||||
(:catch (e)
|
||||
(ps:chain console (log "Cross-frame access error:" e)))))
|
||||
(ps:chain console (log "Could not access parent frame:" e)))))
|
||||
|
||||
(when (and audio-element canvas-element)
|
||||
;; Store current audio element
|
||||
|
|
@ -218,49 +216,72 @@
|
|||
"Return array of available visualization styles"
|
||||
(array "bars" "wave" "dots"))
|
||||
|
||||
;; Initialize when audio starts playing
|
||||
(ps:chain document (add-event-listener "DOMContentLoaded"
|
||||
(lambda ()
|
||||
;; Load saved theme and style preferences
|
||||
(let ((saved-theme (ps:chain local-storage (get-item "spectrum-theme")))
|
||||
(saved-style (ps:chain local-storage (get-item "spectrum-style"))))
|
||||
(when (and saved-theme (ps:getprop *themes* saved-theme))
|
||||
(setf *current-theme* saved-theme))
|
||||
(when (and saved-style (or (= saved-style "bars") (= saved-style "wave") (= saved-style "dots")))
|
||||
(setf *current-style* saved-style))
|
||||
|
||||
;; Update UI selectors, canvas border, and dropdown colors
|
||||
(let ((theme-selector (ps:chain document (get-element-by-id "spectrum-theme-selector")))
|
||||
(style-selector (ps:chain document (get-element-by-id "spectrum-style-selector")))
|
||||
(canvas (ps:chain document (get-element-by-id "spectrum-canvas")))
|
||||
(theme (ps:getprop *themes* *current-theme*)))
|
||||
(when theme-selector
|
||||
(setf (ps:@ theme-selector value) *current-theme*)
|
||||
(setf (ps:@ theme-selector style color) (ps:@ theme top))
|
||||
(setf (ps:@ theme-selector style border-color) (ps:@ theme top)))
|
||||
(when style-selector
|
||||
(setf (ps:@ style-selector value) *current-style*)
|
||||
(setf (ps:@ style-selector style color) (ps:@ theme top))
|
||||
(setf (ps:@ style-selector style border-color) (ps:@ theme top)))
|
||||
|
||||
;; Set initial canvas border color
|
||||
(when canvas
|
||||
(setf (ps:@ canvas style border-color) (ps:@ theme top)))))
|
||||
(defun initialize-spectrum-analyzer ()
|
||||
"Initialize or re-initialize the spectrum analyzer (can be called after AJAX navigation)"
|
||||
;; Stop existing analyzer if running
|
||||
(when *animation-id*
|
||||
(ps:chain window (cancel-animation-frame *animation-id*))
|
||||
(setf *animation-id* nil))
|
||||
|
||||
;; Load saved theme and style preferences
|
||||
(let ((saved-theme (ps:chain local-storage (get-item "spectrum-theme")))
|
||||
(saved-style (ps:chain local-storage (get-item "spectrum-style"))))
|
||||
(when (and saved-theme (ps:getprop *themes* saved-theme))
|
||||
(setf *current-theme* saved-theme))
|
||||
(when (and saved-style (or (= saved-style "bars") (= saved-style "wave") (= saved-style "dots")))
|
||||
(setf *current-style* saved-style))
|
||||
|
||||
(let ((audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
||||
(ps:chain document (get-element-by-id "persistent-audio")))))
|
||||
;; Update UI selectors, canvas border, and dropdown colors
|
||||
(let ((theme-selector (ps:chain document (get-element-by-id "spectrum-theme-selector")))
|
||||
(style-selector (ps:chain document (get-element-by-id "spectrum-style-selector")))
|
||||
(canvas (ps:chain document (get-element-by-id "spectrum-canvas")))
|
||||
(theme (ps:getprop *themes* *current-theme*)))
|
||||
(when theme-selector
|
||||
(setf (ps:@ theme-selector value) *current-theme*)
|
||||
(setf (ps:@ theme-selector style color) (ps:@ theme top))
|
||||
(setf (ps:@ theme-selector style border-color) (ps:@ theme top)))
|
||||
(when style-selector
|
||||
(setf (ps:@ style-selector value) *current-style*)
|
||||
(setf (ps:@ style-selector style color) (ps:@ theme top))
|
||||
(setf (ps:@ style-selector style border-color) (ps:@ theme top)))
|
||||
|
||||
;; If not found and we're in a frame, try parent
|
||||
(when (and (not audio-element)
|
||||
(ps:@ window parent)
|
||||
(not (eq (ps:@ window parent) window)))
|
||||
(ps:try
|
||||
(let ((player-frame (ps:getprop (ps:@ window parent) "player-frame")))
|
||||
(when player-frame
|
||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))))
|
||||
(:catch (e)
|
||||
(ps:chain console (log "Event listener cross-frame error:" e)))))
|
||||
;; Set initial canvas border color
|
||||
(when canvas
|
||||
(setf (ps:@ canvas style border-color) (ps:@ theme top)))))
|
||||
|
||||
(let ((audio-element nil))
|
||||
|
||||
;; Try current document first
|
||||
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
||||
(ps:chain document (get-element-by-id "persistent-audio"))))
|
||||
|
||||
;; If not found and we're in a frame, try parent frame (frameset mode)
|
||||
(when (and (not audio-element)
|
||||
(ps:@ window parent)
|
||||
(not (eq (ps:@ window parent) window)))
|
||||
(ps:try
|
||||
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
|
||||
(when player-frame
|
||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
||||
(when audio-element
|
||||
(ps:chain console (log "Found persistent-audio in player-frame")))))
|
||||
(:catch (e)
|
||||
(ps:chain console (log "Could not access parent frame:" e)))))
|
||||
|
||||
(when audio-element
|
||||
;; Store reference for muted detection
|
||||
(setf *current-audio-element* audio-element)
|
||||
(ps:chain audio-element (add-event-listener "play" init-spectrum-analyzer))
|
||||
(ps:chain audio-element (add-event-listener "pause" stop-spectrum-analyzer))
|
||||
|
||||
(when audio-element
|
||||
(ps:chain audio-element (add-event-listener "play" init-spectrum-analyzer))
|
||||
(ps:chain audio-element (add-event-listener "pause" stop-spectrum-analyzer)))))))))
|
||||
;; If audio is already playing, restart the analyzer with new reference
|
||||
(when (and (not (ps:@ audio-element paused))
|
||||
(ps:chain document (get-element-by-id "spectrum-canvas")))
|
||||
(ps:chain console (log "Audio already playing, restarting spectrum analyzer"))
|
||||
(init-spectrum-analyzer)))))
|
||||
|
||||
;; Make initialization function globally accessible
|
||||
(setf (ps:@ window |initializeSpectrumAnalyzer|) initialize-spectrum-analyzer)
|
||||
|
||||
;; Initialize when audio starts playing
|
||||
(ps:chain document (add-event-listener "DOMContentLoaded" initialize-spectrum-analyzer))))
|
||||
|
|
|
|||
|
|
@ -34,6 +34,13 @@
|
|||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
|
|
@ -41,6 +48,23 @@
|
|||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@
|
|||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
|
|
@ -47,6 +54,23 @@
|
|||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
// Update browser history
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
|
|
@ -101,13 +125,13 @@
|
|||
</div>
|
||||
|
||||
<nav class="nav">
|
||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
||||
<a href="/asteroid/player-content" target="content-frame">Player</a>
|
||||
<a href="/asteroid/status" target="content-frame">Status</a>
|
||||
<a href="/asteroid/profile" target="content-frame" data-show-if-logged-in>Profile</a>
|
||||
<a href="/asteroid/admin" target="content-frame" data-show-if-admin>Admin</a>
|
||||
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||
<a href="/asteroid/player-content" target="content-frame" onclick="return loadInFrame(this)">Player</a>
|
||||
<a href="/asteroid/status-content" target="content-frame" onclick="return loadInFrame(this)">Status</a>
|
||||
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||
<a href="/asteroid/register" target="content-frame" data-show-if-logged-out>Register</a>
|
||||
<a href="/asteroid/register-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Register</a>
|
||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@
|
|||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
|
|
@ -21,6 +28,23 @@
|
|||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
|
|
@ -74,9 +98,9 @@
|
|||
<span>ASTEROID RADIO - LOGIN</span>
|
||||
</h1>
|
||||
<nav class="nav">
|
||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
||||
<a href="/asteroid/status" target="content-frame">Status</a>
|
||||
<a href="/asteroid/register-content" target="content-frame">Register</a>
|
||||
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||
<a href="/asteroid/status-content" target="content-frame" onclick="return loadInFrame(this)">Status</a>
|
||||
<a href="/asteroid/register-content" target="content-frame" onclick="return loadInFrame(this)">Register</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,13 @@
|
|||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
|
|
@ -43,6 +50,23 @@
|
|||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
// Update browser history
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
|
|
@ -95,11 +119,11 @@
|
|||
</div>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
||||
<a href="/asteroid/profile" target="content-frame" data-show-if-logged-in>Profile</a>
|
||||
<a href="/asteroid/admin" target="content-frame" data-show-if-admin>Admin</a>
|
||||
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||
<a href="/asteroid/register" target="content-frame" data-show-if-logged-out>Register</a>
|
||||
<a href="/asteroid/register-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Register</a>
|
||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,13 @@
|
|||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
|
|
@ -41,6 +48,23 @@
|
|||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Asteroid Radio - Status</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||
<script>
|
||||
// Handle logout without navigation
|
||||
function handleLogout() {
|
||||
fetch('/asteroid/logout', {
|
||||
method: 'GET',
|
||||
redirect: 'manual'
|
||||
})
|
||||
.then(() => {
|
||||
// Reload the current page content to show logged-out state
|
||||
fetch(window.location.href)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
document.open();
|
||||
document.write(html);
|
||||
document.close();
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Logout failed:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Load content via AJAX to prevent audio interruption
|
||||
function loadInFrame(link) {
|
||||
const url = link.href;
|
||||
console.log('Loading via AJAX:', url);
|
||||
|
||||
// Clear all intervals to prevent old page scripts from running
|
||||
const highestId = window.setTimeout(() => {}, 0);
|
||||
for (let i = 0; i < highestId; i++) {
|
||||
window.clearInterval(i);
|
||||
window.clearTimeout(i);
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
document.open();
|
||||
document.write(html);
|
||||
document.close();
|
||||
|
||||
// Execute scripts in the new content
|
||||
const scripts = document.querySelectorAll('script');
|
||||
scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
}
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
// Re-initialize spectrum analyzer after navigation
|
||||
if (window.initializeSpectrumAnalyzer) {
|
||||
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||
}
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Failed to load content:', error);
|
||||
return true;
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>📡 SYSTEM STATUS</h1>
|
||||
<div class="nav">
|
||||
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||
<a href="/asteroid/player-content" target="content-frame" onclick="return loadInFrame(this)">Player</a>
|
||||
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||
</div>
|
||||
|
||||
<div class="admin-section">
|
||||
<h2>Server Status</h2>
|
||||
<p>Status page coming soon...</p>
|
||||
<p>For now, administrators can view detailed status information in the <a href="/asteroid/admin-content" target="content-frame" onclick="return loadInFrame(this)">Admin Dashboard</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue