Keep the sidebar section synced with the URL on full page loads

This commit is contained in:
Steven RYDELL
2026-07-29 07:21:27 +02:00
parent c15cb22be4
commit 6d3ea6c6b1
2 changed files with 20 additions and 24 deletions
+10 -15
View File
@@ -288,24 +288,19 @@ export function Sidebar() {
const setSidebarOpen = useUIStore((s) => s.setSidebarOpen); const setSidebarOpen = useUIStore((s) => s.setSidebarOpen);
const schema = useSchemaStore((s) => s.schema); const schema = useSchemaStore((s) => s.schema);
const edition = useAccountStore((s) => s.edition); 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 hasPermission = useAccountStore((s) => s.hasPermission);
const [upsellOpen, setUpsellOpen] = useState(false); const [upsellOpen, setUpsellOpen] = useState(false);
const navRef = useRef<HTMLElement>(null); const navRef = useRef<HTMLElement>(null);
const layouts = useMemo( // Build the permission checks from the permissions array itself: the store
() => // accessors are stable refs, so depending on them alone would keep a stale
schema ? visibleLayouts(schema, edition, (prefix) => hasObjectPermission(prefix, 'Get'), hasPermission) : [], // layout list after access data finishes loading.
[schema, edition, hasObjectPermission, hasPermission], const layouts = useMemo(() => {
); if (!schema) return [];
const canGet = (prefix: string) => permissions.includes(`${prefix}Get`);
useEffect(() => { return visibleLayouts(schema, edition, canGet, hasPermission);
if (!schema) return; }, [schema, edition, permissions, hasPermission]);
if (layouts.length === 0) return;
if (!layouts.find((l) => l.name === activeSection)) {
setActiveSection(layouts[0].name);
}
}, [schema, layouts, activeSection, setActiveSection]);
useEffect(() => { useEffect(() => {
if (typeof window === 'undefined') return; if (typeof window === 'undefined') return;
@@ -328,7 +323,7 @@ export function Sidebar() {
const handleSectionClick = (target: Layout) => { const handleSectionClick = (target: Layout) => {
setActiveSection(target.name); setActiveSection(target.name);
const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); const canGet = (prefix: string) => permissions.includes(`${prefix}Get`);
const first = const first =
findFirstAccessibleLinkInLayout(schema, target, edition, canGet, hasPermission) ?? findFirstAccessibleLinkInLayout(schema, target, edition, canGet, hasPermission) ??
findFirstVisibleLinkInLayout(schema, target, edition, canGet, hasPermission); findFirstVisibleLinkInLayout(schema, target, edition, canGet, hasPermission);
+10 -9
View File
@@ -75,7 +75,7 @@ export default function AdminPanel() {
const setSchema = useSchemaStore((s) => s.setSchema); const setSchema = useSchemaStore((s) => s.setSchema);
const setAccountInfo = useAccountStore((s) => s.setAccountInfo); const setAccountInfo = useAccountStore((s) => s.setAccountInfo);
const edition = useAccountStore((s) => s.edition); 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 setSession = useAuthStore((s) => s.setSession);
const accessToken = useAuthStore((s) => s.accessToken); const accessToken = useAuthStore((s) => s.accessToken);
const setActiveSection = useUIStore((s) => s.setActiveSection); const setActiveSection = useUIStore((s) => s.setActiveSection);
@@ -146,20 +146,22 @@ export default function AdminPanel() {
}; };
}, [isSchemaLoaded, setSession, setSchema, setAccountInfo, t]); }, [isSchemaLoaded, setSession, setSchema, setAccountInfo, t]);
const hasPermission = useAccountStore((s) => s.hasPermission);
const isBootstrapMode = useMemo(() => { const isBootstrapMode = useMemo(() => {
if (!schema) return false; if (!schema) return false;
if (!canViewObject('x:Bootstrap')) return false; if (!canViewObject('x:Bootstrap')) return false;
const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); // Read the permissions array directly: the store accessors are stable
const hasPerm = (perm: string) => hasPermission(perm); // 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; return visibleLayouts(schema, edition, canGet, hasPerm).length === 0;
}, [schema, canViewObject, edition, hasObjectPermission, hasPermission]); }, [schema, canViewObject, edition, permissions]);
useEffect(() => { useEffect(() => {
if (!schema) return; if (!schema) return;
if (isBootstrapMode) return; if (isBootstrapMode) return;
const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); const canGet = (prefix: string) => permissions.includes(`${prefix}Get`);
const hasPerm = (perm: string) => hasPermission(perm); const hasPerm = (perm: string) => permissions.includes(perm);
const layouts = visibleLayouts(schema, edition, canGet, hasPerm); const layouts = visibleLayouts(schema, edition, canGet, hasPerm);
const pickDefault = (): { layoutName: string; link: string | null } | null => { const pickDefault = (): { layoutName: string; link: string | null } | null => {
for (const layout of layouts) { for (const layout of layouts) {
@@ -205,8 +207,7 @@ export default function AdminPanel() {
setActiveSection, setActiveSection,
navigate, navigate,
edition, edition,
hasObjectPermission, permissions,
hasPermission,
isBootstrapMode, isBootstrapMode,
]); ]);