466 lines
22 KiB
HTML
466 lines
22 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Settings — Nexus One AI</title>
|
||
<link rel="stylesheet" href="style.css?v=4">
|
||
<style>
|
||
.settings-grid { display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-bottom:24px; }
|
||
.settings-card { background:var(--navy2); border:1px solid var(--bdr); border-radius:14px; padding:28px; }
|
||
.settings-card h2 { font-size:17px; font-weight:700; color:var(--ink); margin-bottom:6px; }
|
||
.settings-card .desc { font-size:13px; color:var(--lt); margin-bottom:22px; }
|
||
|
||
/* Logo upload */
|
||
.logo-area { display:flex; gap:20px; align-items:flex-start; margin-bottom:22px; }
|
||
.logo-preview { width:100px; height:80px; border:2px dashed var(--bdr); border-radius:10px; display:flex; align-items:center; justify-content:center; background:rgba(255,255,255,.03); overflow:hidden; flex-shrink:0; }
|
||
.logo-preview img { max-width:90%; max-height:90%; object-fit:contain; display:none; }
|
||
.logo-placeholder { font-size:11px; color:var(--lt); text-align:center; line-height:1.5; }
|
||
.logo-controls { display:flex; flex-direction:column; gap:8px; justify-content:center; }
|
||
.upload-btn { display:inline-flex; align-items:center; gap:7px; background:var(--navy2); border:1.5px solid var(--bdr); color:var(--ink); padding:8px 16px; border-radius:8px; cursor:pointer; font-size:13px; font-weight:600; font-family:inherit; transition:all .15s; }
|
||
.upload-btn:hover { border-color:var(--teal); color:var(--teal); }
|
||
#logo-file-input { display:none; }
|
||
.remove-logo-btn { font-size:12px; color:#dc2626; cursor:pointer; background:none; border:none; padding:0; font-family:inherit; text-align:left; }
|
||
.logo-hint { font-size:11px; color:var(--lt); line-height:1.6; }
|
||
|
||
/* Form fields */
|
||
.form-row { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:16px; }
|
||
.form-group { display:flex; flex-direction:column; gap:5px; }
|
||
.form-group label { font-size:12px; font-weight:600; color:var(--med); text-transform:uppercase; letter-spacing:.04em; }
|
||
.form-group input { padding:9px 12px; border:1.5px solid var(--bdr); border-radius:8px; font-size:14px; color:var(--ink); font-family:inherit; outline:none; transition:.15s; background:var(--navy2); }
|
||
.form-group input:focus { border-color:var(--teal); }
|
||
.form-group input[type=color] { padding:3px 5px; height:40px; cursor:pointer; }
|
||
.accent-preview { display:flex; align-items:center; gap:8px; margin-top:6px; font-size:13px; color:var(--med); }
|
||
.accent-swatch { width:24px; height:24px; border-radius:5px; border:1px solid var(--bdr); }
|
||
|
||
/* Buttons */
|
||
.form-actions { display:flex; gap:10px; margin-top:20px; flex-wrap:wrap; }
|
||
.btn { padding:9px 20px; border-radius:8px; font-size:14px; font-weight:600; cursor:pointer; border:none; font-family:inherit; transition:all .15s; }
|
||
.btn-primary { background:var(--teal); color:var(--ink); }
|
||
.btn-primary:hover { background:#0B7A70; }
|
||
.btn-ghost { background:var(--navy2); color:var(--med); border:1.5px solid var(--bdr); }
|
||
.btn-ghost:hover { border-color:var(--teal); color:var(--teal); }
|
||
.btn-danger { background:var(--navy2); color:#dc2626; border:1.5px solid #fecaca; }
|
||
.btn-danger:hover { background:rgba(185,28,28,.08); }
|
||
|
||
/* Sessions card */
|
||
.sessions-card { background:var(--navy2); border:1px solid var(--bdr); border-radius:14px; padding:28px; margin-bottom:20px; }
|
||
.sessions-card h2 { font-size:17px; font-weight:700; color:var(--ink); margin-bottom:6px; }
|
||
.sessions-card .desc { font-size:13px; color:var(--lt); margin-bottom:18px; }
|
||
.sessions-list { display:flex; flex-wrap:wrap; gap:10px; }
|
||
.session-chip { display:flex; align-items:center; gap:8px; background:rgba(255,255,255,.03); border:1px solid var(--bdr); border-radius:20px; padding:7px 16px; font-size:13px; }
|
||
.online-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 2px #dcfce7; flex-shrink:0; }
|
||
.session-role { font-size:11px; color:var(--lt); margin-left:4px; }
|
||
|
||
/* Sysinfo */
|
||
.sysinfo-card { background:var(--navy2); border:1px solid var(--bdr); border-radius:14px; padding:28px; }
|
||
.sysinfo-card h2 { font-size:17px; font-weight:700; color:var(--ink); margin-bottom:18px; }
|
||
.sysinfo-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:12px; }
|
||
.sysinfo-item { background:rgba(255,255,255,.03); border:1px solid var(--bdr); border-radius:10px; padding:14px; }
|
||
.sysinfo-label { font-size:11px; color:var(--lt); font-weight:600; text-transform:uppercase; letter-spacing:.04em; margin-bottom:4px; }
|
||
.sysinfo-value { font-size:15px; font-weight:700; color:var(--ink); }
|
||
|
||
/* Toast */
|
||
#toast { position:fixed; bottom:24px; right:24px; padding:12px 20px; border-radius:10px; font-size:14px; font-weight:600; display:none; z-index:999; }
|
||
#toast.success { background:rgba(34,197,94,.15); color:#15803D; border:1px solid rgba(134,239,172,.3); }
|
||
#toast.error { background:rgba(185,28,28,.08); color:#B91C1C; border:1px solid rgba(239,68,68,.25); }
|
||
@media(max-width:640px){
|
||
.settings-grid,
|
||
.form-row { grid-template-columns:1fr; }
|
||
.settings-card,
|
||
.sessions-card,
|
||
.sysinfo-card { padding:22px; }
|
||
.logo-area { flex-direction:column; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body data-role="admin">
|
||
|
||
<!-- ── Top nav ──────────────────────────────────────────────────────────────── -->
|
||
<header class="topnav">
|
||
<a href="index.html" class="brand">Nexus One <span>AI</span></a>
|
||
<nav>
|
||
<a href="index.html">Home</a>
|
||
<a href="quickstart.html">Quick Start</a>
|
||
<a href="prompts.html">Prompt Library</a>
|
||
<a href="usecases.html">Use Cases</a>
|
||
<span class="nav-sep"></span>
|
||
<div class="nav-dropdown">
|
||
<button class="nav-drop-btn">Help ▾</button>
|
||
<div class="nav-drop-menu">
|
||
<span class="nav-drop-cat">LEARN /</span>
|
||
<a href="quickstart.html">Quick Start</a>
|
||
<a href="models.html">Models</a>
|
||
<span class="nav-drop-cat">SUPPORT /</span>
|
||
<a href="troubleshooting.html">Troubleshoot</a>
|
||
<a href="faq.html">FAQ</a>
|
||
<span class="nav-drop-cat">MORE /</span>
|
||
<a href="glossary.html">Glossary</a>
|
||
<a href="whats-new.html">What's New</a>
|
||
</div>
|
||
</div>
|
||
<div class="nav-dropdown">
|
||
<button class="nav-drop-btn active">Admin ▾</button>
|
||
<div class="nav-drop-menu nav-drop-menu-wide">
|
||
<span class="nav-drop-cat">DOCS /</span>
|
||
<a href="security.html">Security & Privacy</a>
|
||
<a href="admin.html">Admin Guide</a>
|
||
<span class="nav-drop-cat">MONITOR /</span>
|
||
<a href="dashboard.html">Dashboard</a>
|
||
<a href="analytics.html">Usage Analytics</a>
|
||
<a href="audit.html">Audit Log</a>
|
||
<a href="feedback.html">Feedback & Ratings</a>
|
||
<span class="nav-drop-cat">MANAGE /</span>
|
||
<a href="users.html">Users</a>
|
||
<a href="teams.html">Teams</a>
|
||
<a href="models-admin.html">Model Manager</a>
|
||
<a href="training.html">Training</a>
|
||
<a href="knowledge.html">Knowledge Base</a>
|
||
<span class="nav-drop-cat">TOOLS /</span>
|
||
<a href="apikeys.html">API Keys</a>
|
||
<a href="benchmark.html">Benchmarking</a>
|
||
<a href="model-compare.html">Model Compare</a>
|
||
<a href="api-playground.html">API Playground</a>
|
||
<a href="guardrails.html">Guardrails</a>
|
||
<a href="rag-quality.html">RAG Quality</a>
|
||
<a href="router.html">Model Router</a>
|
||
<a href="connectors.html">Connectors</a>
|
||
<span class="nav-drop-cat">SYSTEM /</span>
|
||
<a href="appliance.html">Appliance Ops</a>
|
||
<a href="console.html">Console</a>
|
||
<a href="settings.html" class="active">Settings</a>
|
||
</div>
|
||
</div>
|
||
<div class="nav-dropdown">
|
||
<button class="nav-drop-btn">AI Tools ▾</button>
|
||
<div class="nav-drop-menu">
|
||
<span class="nav-drop-cat">INTELLIGENCE /</span>
|
||
<a href="documents.html">Document Intelligence</a>
|
||
<a href="chat-multi.html">Multimodal Chat</a>
|
||
<a href="prompt-studio.html">Prompt Studio</a>
|
||
<a href="meeting.html">Meeting Assistant</a>
|
||
<span class="nav-drop-cat">AUTOMATION /</span>
|
||
<a href="agents.html">Agent Builder</a>
|
||
<a href="schedules.html">Scheduled Jobs</a>
|
||
<a href="workflows.html">Workflow Automation</a>
|
||
<span class="nav-drop-cat">QUALITY /</span>
|
||
<a href="evals.html">AI Eval Suite</a>
|
||
<a href="chatrooms.html">Chat Rooms</a>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<a href="notifications.html" style="position:relative">🔔</a>
|
||
<span class="badge" data-brand="tier">Basic Tier</span>
|
||
<div id="nav-org-logo" class="nav-org-logo"></div>
|
||
</header>
|
||
|
||
<!-- ── Hero ─────────────────────────────────────────────────────────────────── -->
|
||
<div class="page-hero">
|
||
<div class="label">Admin · Settings</div>
|
||
<h1>Settings</h1>
|
||
<p>White-label branding, active sessions, and system information.</p>
|
||
</div>
|
||
|
||
<!-- ── Content ──────────────────────────────────────────────────────────────── -->
|
||
<div class="content">
|
||
|
||
<!-- Branding card (full width) -->
|
||
<div class="settings-card" style="margin-bottom:20px">
|
||
<h2>⚙️ White-Label Branding</h2>
|
||
<p class="desc">Customise the portal identity for your PSU client. Changes take effect immediately across all active sessions.</p>
|
||
|
||
<!-- Logo -->
|
||
<div class="logo-area">
|
||
<div class="logo-preview" id="logo-preview-box">
|
||
<div class="logo-placeholder" id="logo-placeholder">No logo<br>uploaded</div>
|
||
<img id="logo-preview-img" src="" alt="Logo">
|
||
</div>
|
||
<div class="logo-controls">
|
||
<label class="upload-btn" for="logo-file-input">📁 Upload Logo</label>
|
||
<input type="file" id="logo-file-input" accept="image/png,image/jpeg,image/svg+xml,image/webp">
|
||
<div class="logo-hint">PNG, JPG, SVG, WebP · Max 2 MB<br>Recommended: 200 × 60 px</div>
|
||
<button class="remove-logo-btn" onclick="removeLogo()">✕ Remove logo</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Fields -->
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Organisation Name</label>
|
||
<input type="text" id="org_name" placeholder="e.g. BEL, DRDO, ISRO">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Stack Name (shown in nav badge)</label>
|
||
<input type="text" id="stack_name" placeholder="e.g. BEL AI Suite">
|
||
</div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Accent Color</label>
|
||
<input type="color" id="accent_color" value="#0D9488">
|
||
<div class="accent-preview">
|
||
<div class="accent-swatch" id="accent-swatch" style="background:#0D9488"></div>
|
||
<span id="accent-hex">#0D9488</span>
|
||
</div>
|
||
</div>
|
||
<div class="form-group" id="tier-field-group">
|
||
<label>Tier Label (shown in nav badge)</label>
|
||
<input type="text" id="tier_label" placeholder="e.g. Pro Tier, BEL Edition">
|
||
<!-- Shown instead when tier is locked by Cezen -->
|
||
<div id="tier-locked-display" style="display:none;margin-top:8px;">
|
||
<div style="display:flex;align-items:center;gap:8px;background:#F0FDFA;border:1.5px solid #99F6E4;border-radius:8px;padding:10px 14px;">
|
||
<span style="font-size:18px">🔒</span>
|
||
<div>
|
||
<div id="tier-locked-value" style="font-weight:700;font-size:14px;color:var(--ink)"></div>
|
||
<div style="font-size:12px;color:#0F766E;margin-top:2px">Set by Cezen — contact Cezen to change your tier</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Footer Text</label>
|
||
<input type="text" id="footer_text" placeholder="Powered by Cezen">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Support Email</label>
|
||
<input type="email" id="support_email" placeholder="support@cezentech.com">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-actions">
|
||
<button class="btn btn-primary" onclick="saveBranding()">💾 Save Branding</button>
|
||
<button class="btn btn-ghost" onclick="previewBranding()">👁️ Preview</button>
|
||
<button class="btn btn-danger" onclick="resetBranding()">↩ Reset to Defaults</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Active sessions -->
|
||
<div class="sessions-card">
|
||
<h2>👥 Active Sessions</h2>
|
||
<p class="desc">Users who have logged in within the last 8 hours. Refreshed every 30 s.</p>
|
||
<div class="sessions-list" id="sessions-list">
|
||
<span style="color:var(--lt);font-size:13px">Loading…</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- System info -->
|
||
<div class="sysinfo-card">
|
||
<h2>🖥️ System Information</h2>
|
||
<div class="sysinfo-grid" id="sysinfo-grid">
|
||
<span style="color:var(--lt);font-size:13px">Loading…</span>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /.content -->
|
||
|
||
<footer>
|
||
<p>Nexus One AI · Powered by Cezen · <span data-brand="tier">Basic Tier</span></p>
|
||
</footer>
|
||
|
||
<div id="toast"></div>
|
||
|
||
<script>
|
||
function jsonOrNull(res) {
|
||
if (!res || !res.ok) return null;
|
||
var type = res.headers.get('content-type') || '';
|
||
if (!type.includes('application/json')) return null;
|
||
return res.json().catch(function(){ return null; });
|
||
}
|
||
|
||
function toast(msg, type) {
|
||
var t = document.getElementById('toast');
|
||
t.textContent = msg;
|
||
t.className = type || 'success';
|
||
t.style.display = 'block';
|
||
clearTimeout(t._timer);
|
||
t._timer = setTimeout(function(){ t.style.display='none'; }, 3500);
|
||
}
|
||
|
||
// ── Load branding ──────────────────────────────────────────────────────────
|
||
function loadBranding() {
|
||
fetch('/api/settings/branding', {credentials:'include'})
|
||
.then(jsonOrNull)
|
||
.then(function(b) {
|
||
b = b || {};
|
||
document.getElementById('org_name').value = b.org_name || '';
|
||
document.getElementById('stack_name').value = b.stack_name || '';
|
||
document.getElementById('footer_text').value = b.footer_text || '';
|
||
document.getElementById('support_email').value = b.support_email || '';
|
||
var ac = b.accent_color || '#0D9488';
|
||
document.getElementById('accent_color').value = ac;
|
||
document.getElementById('accent-swatch').style.background = ac;
|
||
document.getElementById('accent-hex').textContent = ac;
|
||
if (b.logo_url) showLogoPreview(b.logo_url);
|
||
|
||
// Tier locking: if server says tier_locked=true, show readonly display
|
||
if (b.tier_locked === 'true') {
|
||
document.getElementById('tier_label').style.display = 'none';
|
||
var locked = document.getElementById('tier-locked-display');
|
||
locked.style.display = '';
|
||
document.getElementById('tier-locked-value').textContent = b.tier_label || '';
|
||
} else {
|
||
document.getElementById('tier_label').value = b.tier_label || '';
|
||
document.getElementById('tier_label').style.display = '';
|
||
document.getElementById('tier-locked-display').style.display = 'none';
|
||
}
|
||
})
|
||
.catch(function(){ /* keep default empty fields in static/demo mode */ });
|
||
}
|
||
|
||
document.getElementById('accent_color').addEventListener('input', function() {
|
||
document.getElementById('accent-swatch').style.background = this.value;
|
||
document.getElementById('accent-hex').textContent = this.value;
|
||
});
|
||
|
||
// ── Logo ───────────────────────────────────────────────────────────────────
|
||
document.getElementById('logo-file-input').addEventListener('change', function() {
|
||
var file = this.files[0];
|
||
if (!file) return;
|
||
if (file.size > 2*1024*1024) { toast('Logo must be under 2 MB', 'error'); return; }
|
||
var fd = new FormData();
|
||
fd.append('file', file);
|
||
fetch('/api/settings/logo', {method:'POST', credentials:'include', body:fd})
|
||
.then(r => r.json())
|
||
.then(function(d) {
|
||
if (d.logo_url) { showLogoPreview(d.logo_url); toast('Logo uploaded'); }
|
||
else toast(d.detail || 'Upload failed', 'error');
|
||
})
|
||
.catch(function(){ toast('Upload error', 'error'); });
|
||
});
|
||
|
||
function showLogoPreview(url) {
|
||
document.getElementById('logo-placeholder').style.display = 'none';
|
||
var img = document.getElementById('logo-preview-img');
|
||
img.src = url; img.style.display = 'block';
|
||
}
|
||
|
||
function removeLogo() {
|
||
if (!confirm('Remove the current logo?')) return;
|
||
fetch('/api/settings/branding', {
|
||
method:'PUT', credentials:'include',
|
||
headers:{'Content-Type':'application/json'},
|
||
body: JSON.stringify({logo_url:''})
|
||
}).then(function() {
|
||
document.getElementById('logo-placeholder').style.display = '';
|
||
var img = document.getElementById('logo-preview-img');
|
||
img.style.display='none'; img.src='';
|
||
toast('Logo removed');
|
||
});
|
||
}
|
||
|
||
// ── Save ───────────────────────────────────────────────────────────────────
|
||
function saveBranding() {
|
||
var tierInput = document.getElementById('tier_label');
|
||
var tierLocked = tierInput.style.display === 'none'; // hidden = locked
|
||
var payload = {
|
||
org_name: document.getElementById('org_name').value.trim(),
|
||
stack_name: document.getElementById('stack_name').value.trim(),
|
||
footer_text: document.getElementById('footer_text').value.trim(),
|
||
support_email: document.getElementById('support_email').value.trim(),
|
||
accent_color: document.getElementById('accent_color').value,
|
||
};
|
||
if (!tierLocked) {
|
||
payload.tier_label = tierInput.value.trim();
|
||
}
|
||
fetch('/api/settings/branding', {
|
||
method:'PUT', credentials:'include',
|
||
headers:{'Content-Type':'application/json'},
|
||
body: JSON.stringify(payload)
|
||
})
|
||
.then(r => r.json())
|
||
.then(function(d) {
|
||
if (d.ok) { toast('Branding saved — reload any page to see changes'); previewBranding(); }
|
||
else toast(d.detail || 'Save failed', 'error');
|
||
})
|
||
.catch(function(){ toast('Network error', 'error'); });
|
||
}
|
||
|
||
function previewBranding() {
|
||
// live-apply accent color to teal variable
|
||
var accent = document.getElementById('accent_color').value;
|
||
document.documentElement.style.setProperty('--teal', accent);
|
||
// Use locked tier value if tier field is hidden
|
||
var tierInput = document.getElementById('tier_label');
|
||
var tierLocked = tierInput.style.display === 'none';
|
||
var tierText = tierLocked
|
||
? document.getElementById('tier-locked-value').textContent
|
||
: (tierInput.value || 'Basic Tier');
|
||
document.querySelector('.badge').textContent = tierText;
|
||
toast('Preview applied to this page');
|
||
}
|
||
|
||
function resetBranding() {
|
||
if (!confirm('Reset all branding to Nexus One AI defaults?')) return;
|
||
fetch('/api/settings/branding', {
|
||
method:'PUT', credentials:'include',
|
||
headers:{'Content-Type':'application/json'},
|
||
body: JSON.stringify({
|
||
org_name:'Nexus One AI', stack_name:'Nexus One AI', logo_url:'',
|
||
accent_color:'#0D9488', footer_text:'Powered by Cezen',
|
||
support_email:'support@cezentech.com', tier_label:'Basic Tier'
|
||
})
|
||
}).then(function(){ loadBranding(); toast('Reset to defaults'); });
|
||
}
|
||
|
||
// ── Active sessions ────────────────────────────────────────────────────────
|
||
function loadSessions() {
|
||
fetch('/api/users/sessions', {credentials:'include'})
|
||
.then(r => r.ok ? r.json() : null)
|
||
.then(function(data) {
|
||
var el = document.getElementById('sessions-list');
|
||
if (!data || !data.sessions || !data.sessions.length) {
|
||
el.innerHTML = '<span style="color:var(--lt);font-size:13px">No active sessions found.</span>';
|
||
return;
|
||
}
|
||
el.innerHTML = data.sessions.map(function(s) {
|
||
return '<div class="session-chip"><div class="online-dot"></div>'
|
||
+ '<strong>' + esc(s.username) + '</strong>'
|
||
+ '<span class="session-role">' + esc(s.role) + '</span></div>';
|
||
}).join('');
|
||
})
|
||
.catch(function(){
|
||
document.getElementById('sessions-list').innerHTML =
|
||
'<span style="color:var(--lt);font-size:13px">Session data unavailable.</span>';
|
||
});
|
||
}
|
||
|
||
// ── System info ────────────────────────────────────────────────────────────
|
||
function loadSysInfo() {
|
||
fetch('/api/system/info', {credentials:'include'})
|
||
.then(jsonOrNull)
|
||
.then(function(d) {
|
||
if (!d) throw new Error('system info unavailable');
|
||
var pairs = [
|
||
['Hostname', d.hostname||'—'], ['OS', d.os||'—'],
|
||
['CPU Cores', d.cpu_cores||'—'],
|
||
['RAM Total', d.ram_total_gb ? d.ram_total_gb+' GB' : '—'],
|
||
['Disk Total', d.disk_total_gb ? d.disk_total_gb+' GB' : '—'],
|
||
['GPU', d.gpu_name||'—'], ['Uptime', d.uptime||'—'],
|
||
['Backend', 'v'+(d.version||'1.0')],
|
||
];
|
||
document.getElementById('sysinfo-grid').innerHTML = pairs.map(function(p){
|
||
return '<div class="sysinfo-item"><div class="sysinfo-label">'+p[0]+'</div>'
|
||
+'<div class="sysinfo-value">'+esc(p[1])+'</div></div>';
|
||
}).join('');
|
||
})
|
||
.catch(function(){
|
||
document.getElementById('sysinfo-grid').innerHTML =
|
||
'<span style="color:var(--lt)">Could not load system info.</span>';
|
||
});
|
||
}
|
||
|
||
function esc(s){ return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }
|
||
|
||
loadBranding();
|
||
loadSessions();
|
||
loadSysInfo();
|
||
setInterval(loadSessions, 30000);
|
||
</script>
|
||
|
||
<script src="auth.js"></script>
|
||
<script src="branding.js"></script>
|
||
</body>
|
||
</html>
|