diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index 41632b4..1397672 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -166,12 +166,10 @@ function AccountMenu({ user, onLogout }) { setOpen(false)}>Dashboard {/* Settings opens on the account, so a separate Account entry was two doors to the same room. */} + {/* One door. Settings already shows the site sections to an + administrator, so a second entry pointing into the same page was + two names for one place. */} setOpen(false)}>Settings - {user?.role === 'admin' && ( - setOpen(false)}> - Administration - - )} diff --git a/frontend/src/pages/AccessPage.css b/frontend/src/pages/AccessPage.css index 65f9a34..3f90a60 100644 --- a/frontend/src/pages/AccessPage.css +++ b/frontend/src/pages/AccessPage.css @@ -83,3 +83,27 @@ .ac-people ul { max-height: 240px; } .ac-counts { display: none; } } + +/* ── Bounded branch list ─────────────────────────────────────────────── + The category tree runs to hundreds of rows. Left to its own height it + pushed the image libraries and everything else off the bottom of the + page, so it scrolls inside itself and starts fully collapsed. */ +.ac-tree-box { + max-height: 380px; + overflow-y: auto; + border: 1px solid var(--border); + border-radius: 10px; + padding: 6px 4px; +} +.ac-tree-box .ac-tree { margin: 0; } + +.ac-person-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; } +.ac-reset { + flex: 0 0 auto; + font: inherit; font-size: 0.8rem; font-weight: 600; + color: var(--danger, #dc2626); + background: none; border: 1px solid var(--border); border-radius: 8px; + padding: 6px 12px; cursor: pointer; +} +.ac-reset:hover:not(:disabled) { border-color: var(--danger, #dc2626); } +.ac-reset:disabled { opacity: .55; cursor: default; } diff --git a/frontend/src/pages/AccessPage.jsx b/frontend/src/pages/AccessPage.jsx index ae0fa32..6e1f333 100644 --- a/frontend/src/pages/AccessPage.jsx +++ b/frontend/src/pages/AccessPage.jsx @@ -27,8 +27,13 @@ function buildTree(categories) { * separately grantable: the grant already reaches them, and offering a * checkbox that changes nothing is how a permissions screen starts lying. */ -function Branch({ node, byParent, granted, covered, onToggle, busy, depth = 0 }) { - const [open, setOpen] = useState(depth === 0) +function Branch({ node, byParent, granted, covered, onToggle, busy, depth = 0, openPath, onOpen }) { + // Which branch is open is held above rather than per-node: opening one has to + // close the one before it, and a node cannot know about its siblings. Every + // branch starts closed — the full tree is hundreds of rows, and scrolling + // past all of it to reach the next top-level subject is the thing that made + // this unusable. + const open = openPath.includes(node.id) const children = byParent.get(node.id) || [] const isGranted = granted.has(node.id) const isCovered = !isGranted && covered.has(node.id) @@ -39,7 +44,7 @@ function Branch({ node, byParent, granted, covered, onToggle, busy, depth = 0 }) {children.length > 0 ? ( + onClick={() => onOpen(node.id, depth, !open)}>{open ? '▾' : '▸'} ) :