mirror of
https://github.com/sol1/rustguac.git
synced 2026-09-10 17:47:13 +00:00
fb0f965bb2
Logout link moved inside the float-right user-menu-wrapper so both Logout and Settings appear on the far right of the nav bar. Fixed addressbook.html Settings font size to match other pages (1.3em).
244 lines
14 KiB
HTML
244 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>rustguac - Docs</title>
|
|
<style>
|
|
:root { --primary: #e94560; --primary-hover: #c73652; --accent: #5bc0be; --accent-hover: #4aa3a1; --bg: #1a1a2e; --surface: #16213e; --input: #0f3460; --text: #e0e0e0; --text-muted: #aaa; --border: #333; --text-dim: #666; --text-on-primary: #fff; --btn-disabled: #555; --status-pending: #f0c040; --status-active: #5bc0be; --status-completed: #888; --status-error: #e94560; --status-expired: #666; --type-ssh-bg: #1b4332; --type-ssh-fg: #52b788; --type-rdp-bg: #3d1f00; --type-rdp-fg: #f0a050; --type-vnc-bg: #2d1b4e; --type-vnc-fg: #b07ff0; --type-web-bg: #1a1a4e; --type-web-fg: #7b8ff0; --hop-bg: #1b4332; --hop-fg: #52b788; --bg-pattern: none; }
|
|
body { font-family: monospace; background-color: var(--bg); background-image: var(--bg-pattern); background-attachment: fixed; min-height: 100vh; color: var(--text); padding: 2em; font-size: 18px; }
|
|
h1 { color: var(--primary); }
|
|
nav { margin-top: 0.8em; margin-bottom: 1.5em; padding-bottom: 0.8em; border-bottom: 1px solid var(--border); font-size: 0.95em; }
|
|
nav a { margin-right: 1.5em; text-decoration: none; color: var(--accent); }
|
|
nav a:hover { text-decoration: underline; }
|
|
nav .active { color: var(--primary); font-weight: bold; }
|
|
#user-menu-wrapper { position: relative; float: right; }
|
|
#user-menu-btn { cursor: pointer; font-size: 1.3em; color: var(--text-muted); }
|
|
#user-menu-btn:hover { color: var(--text); }
|
|
#user-menu { display:none; position:absolute; right:0; top:1.8em; background:var(--surface); border:1px solid var(--border); border-radius:6px; min-width:220px; z-index:50; padding:0.4em 0; }
|
|
.um-section-label { padding:0.4em 0.9em; font-size:0.8em; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.05em; }
|
|
.um-item { padding:0.5em 0.9em; cursor:pointer; display:flex; align-items:center; gap:0.6em; font-size:0.9em; }
|
|
.um-item:hover { background:var(--input); }
|
|
.um-item.active { color:var(--accent); }
|
|
.um-theme-info { display:flex; flex-direction:column; }
|
|
.um-theme-name { font-weight:bold; }
|
|
.um-theme-desc { font-size:0.8em; color:var(--text-dim); }
|
|
.um-swatch { display:inline-block; width:16px; height:16px; border-radius:50%; border:1px solid var(--border); flex-shrink:0; }
|
|
.um-divider { height:1px; background:var(--border); margin:0.3em 0; }
|
|
.um-logout { color:var(--text-muted); }
|
|
.um-logout:hover { color:var(--primary); background:var(--input); }
|
|
|
|
/* Layout */
|
|
.docs-layout { display: flex; min-height: calc(100vh - 160px); border-top: 1px solid var(--border); margin-top: 1em; }
|
|
|
|
/* Sidebar */
|
|
.sidebar {
|
|
width: 220px;
|
|
min-width: 220px;
|
|
border-right: 1px solid var(--border);
|
|
padding: 1em 0;
|
|
overflow-y: auto;
|
|
}
|
|
.sidebar a {
|
|
display: block;
|
|
padding: 0.5em 1.2em;
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
font-size: 0.9em;
|
|
border-left: 3px solid transparent;
|
|
}
|
|
.sidebar a:hover { color: var(--text); background: var(--surface); }
|
|
.sidebar a.active {
|
|
color: var(--primary);
|
|
border-left-color: var(--primary);
|
|
background: var(--surface);
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* Content area */
|
|
.content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 2em 2.5em;
|
|
max-width: 900px;
|
|
}
|
|
.content h1 { color: var(--primary); font-size: 1.5em; margin-bottom: 0.8em; }
|
|
.content h2 { color: var(--primary); font-size: 1.15em; margin-top: 2em; margin-bottom: 0.5em; border-bottom: 1px solid var(--border); padding-bottom: 0.3em; }
|
|
.content h3 { color: var(--accent); font-size: 1em; margin-top: 1.5em; margin-bottom: 0.4em; }
|
|
.content h4 { color: var(--accent); font-size: 0.95em; margin-top: 1.2em; margin-bottom: 0.3em; }
|
|
.content p { margin: 0.6em 0; line-height: 1.6; }
|
|
.content ul, .content ol { margin: 0.5em 0 0.5em 1.5em; line-height: 1.6; }
|
|
.content li { margin: 0.2em 0; }
|
|
.content a { color: var(--accent); }
|
|
.content a:hover { text-decoration: underline; }
|
|
.content code {
|
|
background: var(--surface);
|
|
padding: 0.15em 0.4em;
|
|
border-radius: 3px;
|
|
font-size: 0.9em;
|
|
}
|
|
.content pre {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
padding: 1em;
|
|
border-radius: 6px;
|
|
overflow-x: auto;
|
|
line-height: 1.5;
|
|
margin: 0.8em 0;
|
|
}
|
|
.content pre code {
|
|
background: none;
|
|
padding: 0;
|
|
border-radius: 0;
|
|
font-size: 0.85em;
|
|
}
|
|
.content table { border-collapse: collapse; width: 100%; margin: 0.8em 0; }
|
|
.content th, .content td { text-align: left; padding: 0.4em 0.8em; border-bottom: 1px solid var(--border); }
|
|
.content th { color: var(--text-muted); font-size: 0.85em; }
|
|
.content blockquote {
|
|
border-left: 3px solid var(--accent);
|
|
margin: 0.8em 0;
|
|
padding: 0.4em 1em;
|
|
color: var(--text-muted);
|
|
}
|
|
.content hr { border: none; border-top: 1px solid var(--border); margin: 2em 0; }
|
|
|
|
.loading { padding: 2em; color: var(--text-muted); }
|
|
|
|
@media (max-width: 700px) {
|
|
.sidebar { width: 160px; min-width: 160px; }
|
|
.content { padding: 1em; }
|
|
}
|
|
</style>
|
|
<script>(function(){var c=localStorage.getItem('rustguac_theme_colors');if(c){try{var o=JSON.parse(c),r=document.documentElement.style;for(var k in o)r.setProperty('--'+k.replace(/_/g,'-'),o[k]);if(o.bg_pattern&&o.bg_pattern!=='none'){var s=document.createElement('style');s.id='bg-pattern-style';s.textContent='body{background-image:'+o.bg_pattern+';background-attachment:fixed}';document.head.appendChild(s)}}catch(e){}}})();</script>
|
|
</head>
|
|
<body>
|
|
<img id="site-logo" src="/logo.svg" style="max-height:40px;vertical-align:middle;margin-right:0.5em" alt=""><h1 style="display:inline;vertical-align:middle">rustguac</h1>
|
|
<nav>
|
|
<a href="/addressbook.html">Address Book</a>
|
|
<a href="/sessions.html" id="sessions-link">Sessions</a>
|
|
<a href="/recordings.html">Recordings</a>
|
|
<a href="/reports.html" id="reports-link" style="display:none">Reports</a>
|
|
<a href="/docs.html" class="active">Docs</a>
|
|
<a href="/tokens.html" id="tokens-link" style="display:none">Tokens</a>
|
|
<a href="/admin.html" id="admin-link" style="display:none">Admin</a>
|
|
<span id="user-menu-wrapper"><a href="#" id="logout-item" style="color:var(--text-muted);text-decoration:none;margin-right:1em">Logout</a><span id="user-menu-btn" title="Preferences">⚙ Settings</span><div id="user-menu"><div class="um-section-label">Theme</div><div id="um-theme-list"></div></div></span>
|
|
</nav>
|
|
|
|
<div class="docs-layout">
|
|
<div class="sidebar" id="sidebar"></div>
|
|
<div class="content" id="content">
|
|
<div class="loading">Loading documentation...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
var docs = [];
|
|
var sidebar = document.getElementById('sidebar');
|
|
var content = document.getElementById('content');
|
|
|
|
function showSection(slug) {
|
|
var doc = docs.find(function(d) { return d.slug === slug; });
|
|
if (!doc && docs.length) doc = docs[0];
|
|
if (!doc) return;
|
|
|
|
content.innerHTML = doc.html;
|
|
|
|
// Update sidebar active state
|
|
var links = sidebar.querySelectorAll('a');
|
|
for (var i = 0; i < links.length; i++) {
|
|
links[i].classList.toggle('active', links[i].dataset.slug === doc.slug);
|
|
}
|
|
|
|
// Update hash without triggering hashchange
|
|
if (location.hash !== '#' + doc.slug) {
|
|
history.replaceState(null, '', '#' + doc.slug);
|
|
}
|
|
|
|
content.scrollTop = 0;
|
|
}
|
|
|
|
function getSlugFromHash() {
|
|
return location.hash ? location.hash.substring(1) : '';
|
|
}
|
|
|
|
// Load docs from API
|
|
fetch('/api/docs')
|
|
.then(function(r) { return r.json(); })
|
|
.then(function(data) {
|
|
docs = data;
|
|
|
|
// Build sidebar
|
|
var html = '';
|
|
for (var i = 0; i < docs.length; i++) {
|
|
html += '<a href="#' + docs[i].slug + '" data-slug="' + docs[i].slug + '">' + docs[i].title + '</a>';
|
|
}
|
|
sidebar.innerHTML = html;
|
|
|
|
// Click handler for sidebar links
|
|
sidebar.addEventListener('click', function(e) {
|
|
var a = e.target.closest('a');
|
|
if (!a) return;
|
|
e.preventDefault();
|
|
var slug = a.dataset.slug;
|
|
history.pushState(null, '', '#' + slug);
|
|
showSection(slug);
|
|
});
|
|
|
|
// Show initial section from hash or first
|
|
showSection(getSlugFromHash() || docs[0].slug);
|
|
})
|
|
.catch(function() {
|
|
content.innerHTML = '<div class="loading">Failed to load documentation.</div>';
|
|
});
|
|
|
|
// Handle browser back/forward
|
|
window.addEventListener('popstate', function() {
|
|
showSection(getSlugFromHash());
|
|
});
|
|
|
|
// Theme and auth
|
|
function applyThemeColors(colors){var r=document.documentElement.style;for(var k in colors)r.setProperty('--'+k.replace(/_/g,'-'),colors[k]);var s=document.getElementById('bg-pattern-style');if(!s){s=document.createElement('style');s.id='bg-pattern-style';document.head.appendChild(s)}s.textContent=colors.bg_pattern&&colors.bg_pattern!=='none'?'body{background-image:'+colors.bg_pattern+';background-attachment:fixed}':'';localStorage.setItem('rustguac_theme_colors',JSON.stringify(colors))}
|
|
var _themePresets={},_adminPreset='dark';
|
|
var _themeDescriptions={dark:'Navy & cyan \u2014 the default',light:'Clean white & blue','high-contrast':'Maximum readability',terminal:'Retro green-on-black',nord:'Arctic, muted blues',corporate:'Slate & steel blue',aurora:'Midnight blue with ambient glow',jaguar:'Racing green & gold'};
|
|
function initTheme(t){if(!t)return;_themePresets=t.presets||{};_adminPreset=t.admin_preset||'dark';var u=localStorage.getItem('rustguac_theme'),active=u&&_themePresets[u]?u:_adminPreset,colors=(active===_adminPreset)?t.admin_colors:_themePresets[active];if(colors)applyThemeColors(colors);if(t.logo_url){var l=document.getElementById('site-logo');if(l){if(l.src!==t.logo_url&&!l.src.endsWith(t.logo_url))l.src=t.logo_url;l.style.display=''}}var menu=document.getElementById('um-theme-list');if(menu){menu.innerHTML='';Object.keys(_themePresets).forEach(function(name){var item=document.createElement('div');item.className='um-item'+(name===active?' active':'');var sw=document.createElement('span');sw.className='um-swatch';var p=_themePresets[name];sw.style.background='linear-gradient(135deg,'+p.primary+' 50%,'+p.accent+' 50%)';item.appendChild(sw);var info=document.createElement('div');info.className='um-theme-info';var nm=document.createElement('span');nm.className='um-theme-name';nm.textContent=name;info.appendChild(nm);var desc=document.createElement('span');desc.className='um-theme-desc';desc.textContent=_themeDescriptions[name]||'';info.appendChild(desc);item.appendChild(info);item.addEventListener('click',function(){localStorage.setItem('rustguac_theme',name);applyThemeColors(_themePresets[name]);menu.querySelectorAll('.um-item').forEach(function(el){el.classList.remove('active')});item.classList.add('active');document.getElementById('user-menu').style.display='none'});menu.appendChild(item)})}}
|
|
var _ub=document.getElementById('user-menu-btn');if(_ub)_ub.addEventListener('click',function(e){e.stopPropagation();var m=document.getElementById('user-menu');m.style.display=m.style.display==='block'?'none':'block'});document.addEventListener('click',function(){var m=document.getElementById('user-menu');if(m)m.style.display='none'});
|
|
fetch('/api/auth/status').then(function(r){return r.json()}).then(function(d){
|
|
if(d.site_title){document.title=d.site_title+' - Docs';document.querySelector('h1').textContent=d.site_title;}
|
|
initTheme(d.theme);
|
|
});
|
|
var apiKey = sessionStorage.getItem('rustguac_api_key');
|
|
var roleLevel = { admin: 4, poweruser: 3, operator: 2, viewer: 1 };
|
|
if (apiKey) {
|
|
document.getElementById('admin-link').style.display = '';
|
|
document.getElementById('tokens-link').style.display = '';
|
|
document.getElementById('reports-link').style.display = '';
|
|
} else {
|
|
fetch('/api/me', { credentials: 'same-origin' })
|
|
.then(function(res) {
|
|
if (res.status === 401 || res.status === 403) { window.location.href = '/'; return; }
|
|
if (!res.ok) return;
|
|
return res.json();
|
|
})
|
|
.then(function(data) {
|
|
if (!data) return;
|
|
if (data.role === 'admin') document.getElementById('admin-link').style.display = '';
|
|
var level = roleLevel[data.role] || 0;
|
|
if (level >= 2) document.getElementById('tokens-link').style.display = '';
|
|
if (level >= 3) {
|
|
document.getElementById('reports-link').style.display = '';
|
|
}
|
|
if (level < 3) {
|
|
document.getElementById('sessions-link').style.display = 'none';
|
|
}
|
|
})
|
|
.catch(function() {});
|
|
}
|
|
document.getElementById('logout-item').addEventListener('click', function() {
|
|
sessionStorage.removeItem('rustguac_api_key');
|
|
fetch('/auth/logout', { credentials: 'same-origin' })
|
|
.finally(function() { window.location.href = '/'; });
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|