From 72886bd204e597616d14c60da0fe7fbc5880d20a Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Tue, 12 Dec 2023 09:18:50 +0100 Subject: [PATCH] Save collapse status of secondary navigation Pushed-by: Florian Scholdei Co-authored-by: Florian Scholdei Co-authored-by: Konstantin Schaper Committed-by: Florian Scholdei --- .../secondary_navigation_status.yaml | 2 + scm-ui/ui-api/src/localStorage.tsx | 20 +- .../src/__snapshots__/storyshots.test.ts.snap | 12 +- scm-ui/ui-components/src/index.ts | 1 + .../src/layout/Footer.stories.tsx | 2 + .../src/layout/PrimaryContentColumn.tsx | 19 +- .../src/layout/SecondaryNavigationColumn.tsx | 21 +- .../src/navigation/ExternalNavLink.tsx | 11 +- .../src/navigation/MenuContext.tsx | 3 + .../ui-components/src/navigation/NavLink.tsx | 22 +- .../SecondaryNavigation.stories.tsx | 8 +- .../src/navigation/SecondaryNavigation.tsx | 46 ++- .../navigation/SecondaryNavigationContext.ts | 26 ++ .../src/navigation/SubNavigation.tsx | 37 ++- .../src/navigation/SubNavigationContext.ts | 26 ++ .../src/useSecondaryNavigation.tsx | 52 ++++ .../ui-webapp/src/admin/containers/Admin.tsx | 203 +++++++------ scm-ui/ui-webapp/src/containers/Profile.tsx | 109 ++++--- .../src/groups/containers/SingleGroup.tsx | 99 +++--- .../repos/components/EditRepoNavLink.test.tsx | 15 +- .../components/PermissionsNavLink.test.tsx | 15 +- .../components/RepositoryNavLink.test.tsx | 25 +- .../repos/components/RepositoryNavLink.tsx | 18 +- .../src/repos/containers/RepositoryRoot.tsx | 283 +++++++++--------- .../namespaces/containers/NamespaceRoot.tsx | 73 +++-- .../src/users/containers/SingleUser.tsx | 121 ++++---- 26 files changed, 675 insertions(+), 594 deletions(-) create mode 100644 gradle/changelog/secondary_navigation_status.yaml create mode 100644 scm-ui/ui-components/src/navigation/SecondaryNavigationContext.ts create mode 100644 scm-ui/ui-components/src/navigation/SubNavigationContext.ts create mode 100644 scm-ui/ui-components/src/useSecondaryNavigation.tsx diff --git a/gradle/changelog/secondary_navigation_status.yaml b/gradle/changelog/secondary_navigation_status.yaml new file mode 100644 index 0000000000..d6a68411fd --- /dev/null +++ b/gradle/changelog/secondary_navigation_status.yaml @@ -0,0 +1,2 @@ +- type: changed + description: Save collapse status of secondary navigation diff --git a/scm-ui/ui-api/src/localStorage.tsx b/scm-ui/ui-api/src/localStorage.tsx index d4dc8d1361..e2e7c6fa4e 100644 --- a/scm-ui/ui-api/src/localStorage.tsx +++ b/scm-ui/ui-api/src/localStorage.tsx @@ -22,11 +22,12 @@ * SOFTWARE. */ -import React, { createContext, FC, useCallback, useContext, useMemo, useState } from "react"; +import React, { createContext, FC, useCallback, useContext, useEffect, useMemo, useState } from "react"; type LocalStorage = { - getItem: (key: string, initialValue: T) => T; + getItem: (key: string, fallback: T) => T; setItem: (key: string, value: T) => void; + preload: (key: string, initialValue: T) => void; }; const LocalStorageContext = createContext(null as unknown as LocalStorage); @@ -50,9 +51,14 @@ export const LocalStorageProvider: FC = ({ children }) => { }, []); const getItem = useCallback( - (key: string, initialValue: T): T => { - let initialLoadResult: T | undefined; + (key: string, fallback: T): T => (key in localStorageCache ? (localStorageCache[key] as T) : fallback), + [localStorageCache] + ); + + const preload = useCallback( + (key: string, initialValue: T) => { if (!(key in localStorageCache)) { + let initialLoadResult: T | undefined; try { const item = localStorage.getItem(key); initialLoadResult = item ? JSON.parse(item) : initialValue; @@ -63,13 +69,12 @@ export const LocalStorageProvider: FC = ({ children }) => { } setItem(key, initialLoadResult); } - return initialLoadResult ?? (localStorageCache[key] as T); }, [localStorageCache, setItem] ); return ( - ({ getItem, setItem }), [getItem, setItem])}> + ({ getItem, setItem, preload }), [getItem, preload, setItem])}> {children} ); @@ -85,7 +90,7 @@ export function useLocalStorage( key: string, initialValue: T ): [value: T, setValue: (value: T | ((previousConfig: T) => T)) => void] { - const { getItem, setItem } = useContext(LocalStorageContext); + const { getItem, setItem, preload } = useContext(LocalStorageContext); const value = useMemo(() => getItem(key, initialValue), [getItem, initialValue, key]); const setValue = useCallback( (newValue: T | ((previousConfig: T) => T)) => @@ -95,5 +100,6 @@ export function useLocalStorage( // eslint-disable-next-line react-hooks/exhaustive-deps [key, setItem, value] ); + useEffect(() => preload(key, initialValue), [initialValue, key, preload]); return useMemo(() => [value, setValue], [setValue, value]); } diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index 64255ef8bd..661171f18a 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -72218,7 +72218,7 @@ exports[`Storyshots Secondary Navigation Active when match 1`] = ` className="column is-3" >