From 0ef451e15dbbdfecdda3188a0b3e619639c1fc1c Mon Sep 17 00:00:00 2001 From: William Mantly Date: Wed, 29 Jul 2026 22:20:56 -0400 Subject: [PATCH] Match page width to sso-manager-node; gate Audit nav to admins - Dashboard, Sessions, and Audit pages now wrap their content in
, matching sso-manager-node/proxy's width instead of rendering full-bleed inside the fluid shell. - Audit's nav entry now carries groups: ['admin'] (utils/ui.js), reusing the existing synthetic-admin-group nav-gating convention -- the API route was already server-side admin-gated, this closes the last gap by hiding the nav link/page for non-admins too. - app-base.js (byte-identical across the 3 apps): added app.util.revealItem() and the --sw-content-offset sticky-positioning variable, carried over from the same round of changes in sso-manager-node/proxy. Not yet called anywhere in this app -- no sticky/reveal use case here yet -- but keeps the shared file in sync. --- nodejs/public/css/styles.css | 6 ++++++ nodejs/public/lib/js/app-base.js | 21 +++++++++++++++++++++ nodejs/utils/ui.js | 2 +- nodejs/views/audit.ejs | 2 ++ nodejs/views/dashboard.ejs | 2 ++ nodejs/views/sessions.ejs | 2 ++ nodejs/views/top.ejs | 10 +++++++++- 7 files changed, 43 insertions(+), 2 deletions(-) diff --git a/nodejs/public/css/styles.css b/nodejs/public/css/styles.css index a34ad78..7065eae 100755 --- a/nodejs/public/css/styles.css +++ b/nodejs/public/css/styles.css @@ -7,6 +7,12 @@ body { display: flex; flex-direction: column; min-height: 100vh; + /* Height of the fixed navbar (plus the update banner, while shown -- + see top.ejs's showUpdateBanner/dismissUpdateBanner). Lets an in-page + sticky element offset itself below both fixed elements via + `top: var(--sw-content-offset)` instead of colliding with them at the + viewport's true top:0. */ + --sw-content-offset: 4.5rem; } #spa-shell { diff --git a/nodejs/public/lib/js/app-base.js b/nodejs/public/lib/js/app-base.js index 3d4398d..88f4290 100644 --- a/nodejs/public/lib/js/app-base.js +++ b/nodejs/public/lib/js/app-base.js @@ -584,10 +584,31 @@ app.util = (function(app){ document.body.removeChild(element); } + // Scroll a just-added/-edited element into view and flash its + // background, so the user's eye lands on the row that changed instead of + // it silently appearing/updating somewhere off-screen. Takes a jQuery + // object or a raw DOM node (e.g. jq-repeat's `item.__jq_$el`). + function revealItem(el){ + var node = el && el.jquery ? el[0] : el; + if (!node) return; + if (typeof node.scrollIntoView === 'function') { + node.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + var prevTransition = node.style.transition; + var prevBg = node.style.backgroundColor; + node.style.transition = 'background-color 1.5s ease'; + node.style.backgroundColor = 'var(--bs-success-bg-subtle, #d1e7dd)'; + setTimeout(function(){ + node.style.backgroundColor = prevBg; + setTimeout(function(){ node.style.transition = prevTransition; }, 1500); + }, 300); + } + return { downloadFile: downloadFile, getUrlParameter: getUrlParameter, escapeHtml: escapeHtml, + revealItem: revealItem, } })(app); diff --git a/nodejs/utils/ui.js b/nodejs/utils/ui.js index 1596c95..410da16 100644 --- a/nodejs/utils/ui.js +++ b/nodejs/utils/ui.js @@ -37,6 +37,6 @@ module.exports = { nav: [ {href: '/dashboard', icon: 'fa-solid fa-gauge-high', label: 'Dashboard', groups: []}, {href: '/sessions', icon: 'fa-solid fa-plug-circle-bolt', label: 'Sessions', groups: []}, - {href: '/audit', icon: 'fa-solid fa-clipboard-list', label: 'Audit', groups: []}, + {href: '/audit', icon: 'fa-solid fa-clipboard-list', label: 'Audit', groups: ['admin']}, ], }; diff --git a/nodejs/views/audit.ejs b/nodejs/views/audit.ejs index ee1b45a..b2297a4 100644 --- a/nodejs/views/audit.ejs +++ b/nodejs/views/audit.ejs @@ -1,6 +1,7 @@ <%- include('top') %> +
Audit log
@@ -29,6 +30,7 @@
+
+
@@ -117,6 +118,7 @@
+
+
Active sessions @@ -13,6 +14,7 @@
+