Basic activity counters from chat history and moderation audit logs.
+
+
+
+
+
+
+
Total Messages
+
0
+
+
+
Last 24 Hours
+
0
+
+
+
Distinct Rooms
+
0
+
+
+
Moderation Actions
+
0
+
+
+
+
+
+
Top Rooms
+
loading...
+
+
+
+
+
+
Room
+
Messages
+
+
+
+
+
+
Loading analytics...
+
diff --git a/frontend/admin/chat-log.html b/frontend/admin/chat-log.html
new file mode 100644
index 0000000..3927291
--- /dev/null
+++ b/frontend/admin/chat-log.html
@@ -0,0 +1,46 @@
+
+
+
Chat Log
+
Browse and manage stored chat messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ID
+
Room
+
Username
+
Message
+
Type
+
Timestamp
+
Actions
+
+
+
+
+
+
+
+ Page 1
+
+
+
Loading chat log...
+
diff --git a/frontend/admin/dashboard.html b/frontend/admin/dashboard.html
new file mode 100644
index 0000000..b006f74
--- /dev/null
+++ b/frontend/admin/dashboard.html
@@ -0,0 +1,21 @@
+
Dashboard
+
+
+
Concurrent Viewers
+
0
+
+
+
Stored Messages
+
0
+
+
+
Moderation Actions
+
0
+
+
+
Media Runtime
+
00:00:00
+
0 files
+
+
+
Loading live admin overview...
\ No newline at end of file
diff --git a/frontend/admin/index.html b/frontend/admin/index.html
index b73f506..df41d9f 100644
--- a/frontend/admin/index.html
+++ b/frontend/admin/index.html
@@ -24,6 +24,7 @@
+
@@ -31,313 +32,7 @@
-
-
Dashboard
-
-
-
Concurrent Viewers
-
0
-
-
-
Stored Messages
-
0
-
-
-
Moderation Actions
-
0
-
-
-
Media Runtime
-
00:00:00
-
0 files
-
-
-
Loading live admin overview...
-
-
-
-
-
-
Upload Video
-
Upload media files into the local media library mounted for playout.
-
-
-
-
-
-
-
-
Resumable chunk upload enabled • up to 2GB per file.
-
-
-
Uploading (0%)
-
-
Loading media library...
-
-
-
-
-
Media Library
-
loading...
-
-
-
-
-
-
File
-
Title
-
Runtime
-
Status
-
Size
-
Modified
-
Actions
-
-
-
-
-
-
-
-
-
-
-
-
Schedule
-
Read-only view of the currently configured playout order.
-
-
-
-
-
-
0/0 matched • total runtime 00:00:00
-
-
-
-
-
#
-
Label
-
Runtime
-
Status
-
Path
-
-
-
-
-
-
Loading schedule...
-
-
-
-
-
-
-
Playlist
-
Edit the active concat playlist used by the playout service.
-
-
-
-
-
-
-
-
-
-
-
Loading playlist...
-
-
-
-
-
-
-
Moderation
-
Create moderation actions and review the recent immutable audit log.
-
-
-
-
-
-
-
New Action
-
-
-
-
-
-
Recent Audit Log
-
Latest entries
-
-
-
-
-
-
When
-
Action
-
Target
-
Moderator
-
Reason
-
-
-
-
-
-
-
-
-
-
-
-
-
Analytics
-
Basic activity counters from chat history and moderation audit logs.
-
-
-
-
-
-
-
Total Messages
-
0
-
-
-
Last 24 Hours
-
0
-
-
-
Distinct Rooms
-
0
-
-
-
Moderation Actions
-
0
-
-
-
-
-
-
Top Rooms
-
loading...
-
-
-
-
-
-
Room
-
Messages
-
-
-
-
-
-
Loading analytics...
-
-
-
-
-
System Configuration
-
-
-
Redis Stats
-
-
-
Memory Used
-
loading...
-
-
-
Connected Clients
-
0
-
-
-
Redis Enabled
-
no
-
-
-
-
-
Storage
-
-
-
Database Driver
-
loading...
-
-
-
Stored Messages
-
0
-
-
-
Last Refresh
-
loading...
-
-
-
Playlist Path
-
loading...
-
-
-
Playlist Present
-
no
-
-
-
-
-
-
-
-
Service Health
-
-
-
-
Loading system summary...
-
-
-
-
-
-
-
Users
-
Current room presence derived from Redis presence keys.
-
-
-
-
-
-
-
-
-
-
Username
-
Room
-
Online
-
-
-
-
-
-
Loading active users...
-
-
+
Loading...
diff --git a/frontend/admin/moderation.html b/frontend/admin/moderation.html
new file mode 100644
index 0000000..0f26bdf
--- /dev/null
+++ b/frontend/admin/moderation.html
@@ -0,0 +1,58 @@
+
+
+
Moderation
+
Create moderation actions and review the recent immutable audit log.
+
+
+
+
+
+
+
New Action
+
+
+
+
+
+
Recent Audit Log
+
Latest entries
+
+
+
+
+
+
When
+
Action
+
Target
+
Moderator
+
Reason
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/admin/playlist.html b/frontend/admin/playlist.html
new file mode 100644
index 0000000..ed84697
--- /dev/null
+++ b/frontend/admin/playlist.html
@@ -0,0 +1,16 @@
+
+
+
Playlist
+
Edit the active concat playlist used by the playout service.
+
+
+
+
+
+
+
+
+
+
+
Loading playlist...
+
\ No newline at end of file
diff --git a/frontend/admin/schedule.html b/frontend/admin/schedule.html
new file mode 100644
index 0000000..065669e
--- /dev/null
+++ b/frontend/admin/schedule.html
@@ -0,0 +1,26 @@
+
+
+
Schedule
+
Read-only view of the currently configured playout order.
+
+
+
+
+
+
0/0 matched • total runtime 00:00:00
+
+
+
+
+
#
+
Label
+
Runtime
+
Status
+
Path
+
+
+
+
+
+
Loading schedule...
+
\ No newline at end of file
diff --git a/frontend/admin/system.html b/frontend/admin/system.html
new file mode 100644
index 0000000..5f5a624
--- /dev/null
+++ b/frontend/admin/system.html
@@ -0,0 +1,54 @@
+
System Configuration
+
+
+
Redis Stats
+
+
+
Memory Used
+
loading...
+
+
+
Connected Clients
+
0
+
+
+
Redis Enabled
+
no
+
+
+
+
+
Storage
+
+
+
Database Driver
+
loading...
+
+
+
Stored Messages
+
0
+
+
+
Last Refresh
+
loading...
+
+
+
Playlist Path
+
loading...
+
+
+
Playlist Present
+
no
+
+
+
+
+
+
+
+
Service Health
+
+
+
+
Loading system summary...
+
diff --git a/frontend/admin/upload.html b/frontend/admin/upload.html
new file mode 100644
index 0000000..356c606
--- /dev/null
+++ b/frontend/admin/upload.html
@@ -0,0 +1,41 @@
+
+
+
Upload Video
+
Upload media files into the local media library mounted for playout.
+
+
+
+
+
+
+
+
Resumable chunk upload enabled • up to 2GB per file.
+
+
+
Uploading (0%)
+
+
Loading media library...
+
+
+
+
+
Media Library
+
loading...
+
+
+
+
+
+
File
+
Title
+
Runtime
+
Status
+
Size
+
Modified
+
Actions
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/admin/users.html b/frontend/admin/users.html
new file mode 100644
index 0000000..dd9896d
--- /dev/null
+++ b/frontend/admin/users.html
@@ -0,0 +1,23 @@
+
+
+
Users
+
Current room presence derived from Redis presence keys.
+
+
+
+
+
+
+
+
+
+
Username
+
Room
+
Online
+
+
+
+
+
+
Loading active users...
+
\ No newline at end of file
diff --git a/frontend/src/admin.ts b/frontend/src/admin.ts
index ca33e20..a9a4a95 100644
--- a/frontend/src/admin.ts
+++ b/frontend/src/admin.ts
@@ -47,7 +47,9 @@ const uploadProgressWrap = () =>
document.getElementById("media-upload-progress-wrap") as HTMLElement | null;
const uploadProgressBar = () =>
- document.getElementById("media-upload-progress") as HTMLProgressElement | null;
+ document.getElementById(
+ "media-upload-progress",
+ ) as HTMLProgressElement | null;
const uploadProgressText = () =>
document.getElementById("media-upload-progress-text") as HTMLElement | null;
@@ -135,9 +137,21 @@ const fmtSize = (value?: number) => {
return `${size.toFixed(size >= 10 || unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;
};
-function switchTab(tabName: string) {
+// Page content cache: maps tab name to loaded HTML string
+const pageCache: Record = {};
+
+async function loadPageContent(tabName: string): Promise {
+ if (pageCache[tabName]) return pageCache[tabName];
+
+ const response = await fetch(`/admin/${tabName}.html`);
+ if (!response.ok) throw new Error(`Failed to load page: ${tabName}`);
+ const html = await response.text();
+ pageCache[tabName] = html;
+ return html;
+}
+
+async function switchTab(tabName: string) {
const triggers = document.querySelectorAll(".tab-trigger");
- const panels = document.querySelectorAll(".tab-panel");
triggers.forEach((trigger) => {
const active = trigger.dataset.tab === tabName;
@@ -145,16 +159,27 @@ function switchTab(tabName: string) {
trigger.setAttribute("aria-selected", String(active));
});
- panels.forEach((panel) => {
- const active = panel.id === `tab-${tabName}`;
- panel.hidden = !active;
- panel.classList.toggle("is-active", active);
- });
+ const container = document.getElementById("tab-content-container");
+ if (!container) return;
+ try {
+ const html = await loadPageContent(tabName);
+ container.innerHTML = html;
+ } catch (error) {
+ console.error("Failed to load tab content", error);
+ container.innerHTML = `