Sync cezen-portal/ from live working copy (V1.0 GA polish + search-icon ordering fix)
Brings the ISO-packaged portal copy current with the live cezen-portal/ working directory, which had drifted across the entire V1.0 GA polish initiative (Phases 1-10) plus this session's topnav icon-order bugfix. - 52 existing files updated, 2 new pages added (about.html, health.html) - cgit/cezen-portal/ is now byte-identical to cezen-portal/ - Backend files (rag_ingest.py, cezen_license.py) already in sync; main.py intentionally left as-is (cgit is ahead there with workstation-category commercial-fit logic not yet backported to the live working copy) Next: rebuild the ISO (bash autoinstall/build-iso.sh) to bake this in.
This commit is contained in:
1 parent
7540da04a8
commit
b3eec34158
57 files changed
+2832
-1354
No files matched your search
+21
-8
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>User Management — Nexus One AI</title>
|
||||
<link rel="stylesheet" href="style.css?v=4">
|
||||
<link rel="stylesheet" href="style.css?v=12">
|
||||
<style>
|
||||
.um-toolbar { display:flex; align-items:center; gap:12px; margin-bottom:24px; flex-wrap:wrap; }
|
||||
.um-btn { padding:9px 18px; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer; border:none; transition:all .15s; font-family:inherit; }
|
||||
@@ -91,6 +91,7 @@
|
||||
<a href="dashboard.html">Dashboard</a>
|
||||
<a href="analytics.html">Usage Analytics</a>
|
||||
<a href="audit.html">Governance & Audit</a>
|
||||
<a href="health.html">Health Center</a>
|
||||
<a href="feedback.html">Feedback & Ratings</a>
|
||||
<span class="nav-drop-cat">MANAGE /</span>
|
||||
<a href="users.html" class="active">Users</a>
|
||||
@@ -129,7 +130,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<a href="notifications.html" style="position:relative">🔔</a>
|
||||
<a href="notifications.html" class="nav-icon-btn" style="position:relative" aria-label="Notifications"><span class="icon-svg icon-sm" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M15 17h5l-1.4-1.4A2 2 0 0 1 18 14.2V11a6 6 0 1 0-12 0v3.2a2 2 0 0 1-.6 1.4L4 17h5"/><path d="M10 17a2 2 0 0 0 4 0"/></svg></span></a>
|
||||
<span class="badge" data-brand="tier">Basic Tier</span>
|
||||
<div id="nav-org-logo" class="nav-org-logo"></div>
|
||||
</header>
|
||||
@@ -145,7 +146,8 @@
|
||||
<div class="section-title">User Accounts</div>
|
||||
<div class="um-toolbar">
|
||||
<button class="um-btn primary" onclick="openCreate()">+ New User</button>
|
||||
<button class="um-btn ghost" onclick="loadAll()">↺ Refresh</button>
|
||||
<button class="um-btn ghost" onclick="loadAll()">Refresh</button>
|
||||
<input type="text" id="user-filter" placeholder="Filter by username or email…" oninput="renderUsers()" style="margin-left:auto;padding:8px 10px;border:1px solid var(--bdr);border-radius:7px;font-size:12.5px;font-family:inherit;min-width:220px">
|
||||
</div>
|
||||
|
||||
<div class="um-table-wrap">
|
||||
@@ -237,13 +239,14 @@
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>Nexus One AI · Powered by Cezen · Basic Tier</p>
|
||||
<p>Nexus One AI · Powered by Cezen · <span data-brand="tier">Basic Tier</span></p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const _API = '/api';
|
||||
let resetTargetId = null;
|
||||
let meId = null;
|
||||
let allUsers = [];
|
||||
|
||||
function fmt(iso) {
|
||||
if (!iso) return '—';
|
||||
@@ -254,10 +257,20 @@ function fmt(iso) {
|
||||
|
||||
async function loadUsers() {
|
||||
const data = await fetch(`${_API}/users`, { credentials:'include' }).then(r => r.json()).catch(() => []);
|
||||
const rows = Array.isArray(data) ? data : (Array.isArray(data.users) ? data.users : []);
|
||||
allUsers = Array.isArray(data) ? data : (Array.isArray(data.users) ? data.users : []);
|
||||
renderUsers();
|
||||
}
|
||||
|
||||
function renderUsers() {
|
||||
const tb = document.getElementById('users-tbody');
|
||||
if (!allUsers.length) {
|
||||
tb.innerHTML = '<tr><td colspan="6"><div class="cezen-list-empty">No users yet — <a onclick="openCreate()">create the first one</a>.</div></td></tr>';
|
||||
return;
|
||||
}
|
||||
const q = (document.getElementById('user-filter')?.value || '').trim().toLowerCase();
|
||||
const rows = q ? allUsers.filter(u => (u.username || '').toLowerCase().includes(q) || (u.email || '').toLowerCase().includes(q)) : allUsers;
|
||||
if (!rows.length) {
|
||||
tb.innerHTML = '<tr><td colspan="6" style="color:var(--lt);text-align:center;padding:24px">No users available.</td></tr>';
|
||||
tb.innerHTML = '<tr><td colspan="6"><div class="cezen-list-empty">No users match your filter.</div></td></tr>';
|
||||
return;
|
||||
}
|
||||
tb.innerHTML = rows.map(u => `
|
||||
@@ -286,7 +299,7 @@ async function loadSessions() {
|
||||
const rows = data.sessions || [];
|
||||
const tb = document.getElementById('sessions-tbody');
|
||||
if (!rows.length) {
|
||||
tb.innerHTML = '<tr><td colspan="6" style="color:var(--lt);text-align:center;padding:20px">No active sessions</td></tr>';
|
||||
tb.innerHTML = '<tr><td colspan="6"><div class="cezen-list-empty">No active sessions right now.</div></td></tr>';
|
||||
return;
|
||||
}
|
||||
tb.innerHTML = rows.map(s => {
|
||||
@@ -374,6 +387,6 @@ document.querySelectorAll('.modal-overlay').forEach(o => o.addEventListener('cli
|
||||
})();
|
||||
</script>
|
||||
<script src="auth.js"></script>
|
||||
<script src="branding.js"></script>
|
||||
<script src="branding.js?v=3"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user