From 6d3ea6c6b1c5c4578a44b35421c54a388b851cee Mon Sep 17 00:00:00 2001 From: Steven RYDELL Date: Wed, 29 Jul 2026 07:21:27 +0200 Subject: [PATCH] Keep the sidebar section synced with the URL on full page loads --- src/components/layout/Sidebar.tsx | 25 ++++++++++--------------- src/pages/AdminPanel.tsx | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 2e33fb5..c512c16 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -288,24 +288,19 @@ export function Sidebar() { const setSidebarOpen = useUIStore((s) => s.setSidebarOpen); const schema = useSchemaStore((s) => s.schema); const edition = useAccountStore((s) => s.edition); - const hasObjectPermission = useAccountStore((s) => s.hasObjectPermission); + const permissions = useAccountStore((s) => s.permissions); const hasPermission = useAccountStore((s) => s.hasPermission); const [upsellOpen, setUpsellOpen] = useState(false); const navRef = useRef(null); - const layouts = useMemo( - () => - schema ? visibleLayouts(schema, edition, (prefix) => hasObjectPermission(prefix, 'Get'), hasPermission) : [], - [schema, edition, hasObjectPermission, hasPermission], - ); - - useEffect(() => { - if (!schema) return; - if (layouts.length === 0) return; - if (!layouts.find((l) => l.name === activeSection)) { - setActiveSection(layouts[0].name); - } - }, [schema, layouts, activeSection, setActiveSection]); + // Build the permission checks from the permissions array itself: the store + // accessors are stable refs, so depending on them alone would keep a stale + // layout list after access data finishes loading. + const layouts = useMemo(() => { + if (!schema) return []; + const canGet = (prefix: string) => permissions.includes(`${prefix}Get`); + return visibleLayouts(schema, edition, canGet, hasPermission); + }, [schema, edition, permissions, hasPermission]); useEffect(() => { if (typeof window === 'undefined') return; @@ -328,7 +323,7 @@ export function Sidebar() { const handleSectionClick = (target: Layout) => { setActiveSection(target.name); - const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); + const canGet = (prefix: string) => permissions.includes(`${prefix}Get`); const first = findFirstAccessibleLinkInLayout(schema, target, edition, canGet, hasPermission) ?? findFirstVisibleLinkInLayout(schema, target, edition, canGet, hasPermission); diff --git a/src/pages/AdminPanel.tsx b/src/pages/AdminPanel.tsx index 0b3bb55..bb16eb6 100644 --- a/src/pages/AdminPanel.tsx +++ b/src/pages/AdminPanel.tsx @@ -75,7 +75,7 @@ export default function AdminPanel() { const setSchema = useSchemaStore((s) => s.setSchema); const setAccountInfo = useAccountStore((s) => s.setAccountInfo); const edition = useAccountStore((s) => s.edition); - const hasObjectPermission = useAccountStore((s) => s.hasObjectPermission); + const permissions = useAccountStore((s) => s.permissions); const setSession = useAuthStore((s) => s.setSession); const accessToken = useAuthStore((s) => s.accessToken); const setActiveSection = useUIStore((s) => s.setActiveSection); @@ -146,20 +146,22 @@ export default function AdminPanel() { }; }, [isSchemaLoaded, setSession, setSchema, setAccountInfo, t]); - const hasPermission = useAccountStore((s) => s.hasPermission); const isBootstrapMode = useMemo(() => { if (!schema) return false; if (!canViewObject('x:Bootstrap')) return false; - const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); - const hasPerm = (perm: string) => hasPermission(perm); + // Read the permissions array directly: the store accessors are stable + // refs, so depending on them alone would keep stale results after access + // data finishes loading. + const canGet = (prefix: string) => permissions.includes(`${prefix}Get`); + const hasPerm = (perm: string) => permissions.includes(perm); return visibleLayouts(schema, edition, canGet, hasPerm).length === 0; - }, [schema, canViewObject, edition, hasObjectPermission, hasPermission]); + }, [schema, canViewObject, edition, permissions]); useEffect(() => { if (!schema) return; if (isBootstrapMode) return; - const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); - const hasPerm = (perm: string) => hasPermission(perm); + const canGet = (prefix: string) => permissions.includes(`${prefix}Get`); + const hasPerm = (perm: string) => permissions.includes(perm); const layouts = visibleLayouts(schema, edition, canGet, hasPerm); const pickDefault = (): { layoutName: string; link: string | null } | null => { for (const layout of layouts) { @@ -205,8 +207,7 @@ export default function AdminPanel() { setActiveSection, navigate, edition, - hasObjectPermission, - hasPermission, + permissions, isBootstrapMode, ]);