🚧 Refactor the UI menu

This commit is contained in:
Jonas Bengtsson
2026-09-19 10:08:13 +02:00
parent 19bccce083
commit 1c919d89e7
3 changed files with 114 additions and 6 deletions
+78 -4
View File
@@ -6,6 +6,63 @@ import { RolesPage } from "./pages/Roles";
import { GroupsPage } from "./pages/Groups"; import { GroupsPage } from "./pages/Groups";
import { BrokerConfigPage } from "./pages/BrokerConfig"; import { BrokerConfigPage } from "./pages/BrokerConfig";
// Navigation structure per spec section 57. Entries with a `to` route are
// implemented; entries without one are planned pages, rendered greyed out
// so the full target information architecture stays visible.
const NAV_SECTIONS: {
title: string;
items: { label: string; to?: string; hint?: string }[];
}[] = [
{
title: "Broker",
items: [
{ label: "Status", hint: "Dashboard / $SYS monitoring (Release 3)" },
{ label: "Configuration", to: "/broker" },
{ label: "Listeners", to: "/broker#listeners" },
{ label: "Bridges", hint: "Bridge management (post-MVP)" },
{ label: "Revisions", to: "/broker#revisions" },
],
},
{
title: "MQTT Security",
items: [
{ label: "Clients", to: "/clients" },
{ label: "Groups", to: "/groups" },
{ label: "Roles", to: "/roles" },
{ label: "ACL Simulator", hint: "ACL simulator (post-MVP)" },
{ label: "Authentication", hint: "Auth mechanism configuration (Release 2)" },
],
},
{
title: "Certificates",
items: [
{ label: "Authorities", hint: "PKI (Release 2)" },
{ label: "Server Certificates", hint: "PKI (Release 2)" },
{ label: "Client Certificates", hint: "PKI (Release 2)" },
{ label: "CSRs", hint: "CSR signing (Release 2)" },
{ label: "Revocations", hint: "CRL management (Release 2)" },
],
},
{
title: "Tools",
items: [
{ label: "Topic Explorer", hint: "Test console (post-MVP)" },
{ label: "Connection Test", hint: "Connectivity tester (post-MVP)" },
{ label: "Client Provisioning", hint: "Provisioning wizard (post-MVP)" },
],
},
{
title: "Administration",
items: [
{ label: "Users", hint: "User management page (Release 3)" },
{ label: "Roles", hint: "Management roles admin (Release 3)" },
{ label: "Audit Log", hint: "Audit viewer (Release 3)" },
{ label: "Backup", hint: "Backup/restore (Release 3)" },
{ label: "System", hint: "System settings (Release 3)" },
],
},
];
function Layout({ children }: { children: React.ReactNode }) { function Layout({ children }: { children: React.ReactNode }) {
const { session, logout } = useAuth(); const { session, logout } = useAuth();
return ( return (
@@ -13,10 +70,27 @@ function Layout({ children }: { children: React.ReactNode }) {
<aside className="sidebar"> <aside className="sidebar">
<h1>MQTT Management</h1> <h1>MQTT Management</h1>
<nav> <nav>
<NavLink to="/clients">Clients</NavLink> {NAV_SECTIONS.map((section) => (
<NavLink to="/groups">Groups</NavLink> <div key={section.title} className="nav-section">
<NavLink to="/roles">Roles &amp; ACLs</NavLink> <h2>{section.title}</h2>
<NavLink to="/broker">Broker configuration</NavLink> {section.items.map((item) =>
item.to ? (
<NavLink key={item.label} to={item.to}>
{item.label}
</NavLink>
) : (
<button
key={item.label}
className="nav-disabled"
disabled
title={item.hint}
>
{item.label}
</button>
),
)}
</div>
))}
</nav> </nav>
<p style={{ marginTop: "2rem", fontSize: "0.8rem", opacity: 0.7 }}> <p style={{ marginTop: "2rem", fontSize: "0.8rem", opacity: 0.7 }}>
{session?.username} ({session?.role}) {session?.username} ({session?.role})
+2 -2
View File
@@ -113,7 +113,7 @@ export function BrokerConfigPage() {
<div className="banner error">{(addListener.error as Error).message}</div> <div className="banner error">{(addListener.error as Error).message}</div>
)} )}
<h3 style={{ marginTop: "2rem" }}>Listeners</h3> <h3 id="listeners" style={{ marginTop: "2rem" }}>Listeners</h3>
<table> <table>
<thead> <thead>
<tr> <tr>
@@ -231,7 +231,7 @@ export function BrokerConfigPage() {
<div className="banner error">{(deploy.error as Error).message}</div> <div className="banner error">{(deploy.error as Error).message}</div>
)} )}
<h3 style={{ marginTop: "2rem" }}>Revisions</h3> <h3 id="revisions" style={{ marginTop: "2rem" }}>Revisions</h3>
<table> <table>
<thead> <thead>
<tr> <tr>
+34
View File
@@ -39,6 +39,40 @@ body {
text-decoration: none; text-decoration: none;
} }
/* --- Grouped navigation (spec section 57) --- */
.nav-section {
margin-bottom: 0.9rem;
}
.nav-section h2 {
font-size: 0.68rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.07em;
color: #7b8794;
margin: 0.5rem 0 0.25rem;
padding-left: 0.6rem;
}
/* Unimplemented pages: greyed out, not clickable, tooltip explains why. */
.nav-section button.nav-disabled {
display: block;
width: 100%;
text-align: left;
background: transparent;
border: none;
color: #616e7c;
padding: 0.45rem 0.6rem;
margin: 0.1rem 0;
border-radius: 6px;
opacity: 0.55;
}
/* Anchor targets inside pages: keep headings clear of the viewport top. */
h3[id] {
scroll-margin-top: 1rem;
}
.sidebar nav a.active, .sidebar nav a.active,
.sidebar nav a:hover { .sidebar nav a:hover {
background: #323f4b; background: #323f4b;