🚧 Refactor the UI menu
This commit is contained in:
+78
-4
@@ -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 & 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})
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user