mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: Persist navigation settings (#7144)
This commit is contained in:
parent
81c6caf211
commit
68427f841b
@ -45,13 +45,7 @@ import CorsIcon from '@mui/icons-material/StorageOutlined';
|
||||
import BillingIcon from '@mui/icons-material/CreditCardOutlined';
|
||||
import SignOutIcon from '@mui/icons-material/ExitToApp';
|
||||
import { ReactComponent as ProjectIcon } from 'assets/icons/projectIconSmall.svg';
|
||||
import {
|
||||
type FC,
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { type FC, type ReactNode, useCallback, useEffect } from 'react';
|
||||
import { getCondensedRoutes, getRoutes } from '../../../menu/routes';
|
||||
import { useAdminRoutes } from '../../../admin/useAdminRoutes';
|
||||
import { filterByConfig, mapRouteLink } from 'component/common/util';
|
||||
@ -64,6 +58,7 @@ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import LibraryBooksIcon from '@mui/icons-material/LibraryBooks';
|
||||
import { basePath } from 'utils/formatPath';
|
||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||
|
||||
export const StyledProjectIcon = styled(ProjectIcon)(({ theme }) => ({
|
||||
fill: theme.palette.neutral.main,
|
||||
@ -276,7 +271,10 @@ const useShowBadge = () => {
|
||||
};
|
||||
|
||||
const useNavigationMode = () => {
|
||||
const [mode, setMode] = useState<'mini' | 'full'>('full');
|
||||
const [mode, setMode] = useLocalStorageState<'mini' | 'full'>(
|
||||
'navigation-mode:v1',
|
||||
'full',
|
||||
);
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === 'b' && (event.metaKey || event.ctrlKey)) {
|
||||
|
61
frontend/src/hooks/useLocalStorageState.test.tsx
Normal file
61
frontend/src/hooks/useLocalStorageState.test.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import { useLocalStorageState } from './useLocalStorageState';
|
||||
import { createLocalStorage } from '../utils/createLocalStorage';
|
||||
import { render } from 'utils/testRenderer';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
const TestComponent: FC<{
|
||||
keyName: string;
|
||||
initialValue: any;
|
||||
}> = ({ keyName, initialValue }) => {
|
||||
const [value, setValue] = useLocalStorageState(keyName, initialValue);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span data-testid='storedValue'>{value}</span>
|
||||
<button
|
||||
type='submit'
|
||||
onClick={() => setValue('updatedValue')}
|
||||
data-testid='updateButton'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useLocalStorageState', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear();
|
||||
});
|
||||
|
||||
it('should initialize with the initial value if local storage is empty', () => {
|
||||
render(<TestComponent keyName='testKey' initialValue='initialValue' />);
|
||||
|
||||
expect(screen.getByTestId('storedValue').textContent).toBe(
|
||||
'initialValue',
|
||||
);
|
||||
});
|
||||
|
||||
it('updates the local storage and state when value changes', async () => {
|
||||
render(<TestComponent keyName='testKey' initialValue='initialValue' />);
|
||||
|
||||
screen.getByTestId('updateButton').click();
|
||||
|
||||
expect(screen.getByTestId('storedValue').textContent).toBe(
|
||||
'updatedValue',
|
||||
);
|
||||
await waitFor(() => {
|
||||
const { value } = createLocalStorage('testKey', {});
|
||||
expect(value).toStrictEqual('updatedValue');
|
||||
});
|
||||
});
|
||||
|
||||
it('initializes with the value from local storage if available', async () => {
|
||||
createLocalStorage('testKey', {}).setValue('storedValue');
|
||||
|
||||
render(<TestComponent keyName='testKey' initialValue='initialValue' />);
|
||||
|
||||
expect(screen.getByTestId('storedValue').textContent).toBe(
|
||||
'storedValue',
|
||||
);
|
||||
});
|
||||
});
|
18
frontend/src/hooks/useLocalStorageState.ts
Normal file
18
frontend/src/hooks/useLocalStorageState.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createLocalStorage } from '../utils/createLocalStorage';
|
||||
|
||||
export const useLocalStorageState = <T extends object | string>(
|
||||
key: string,
|
||||
initialValue: T,
|
||||
) => {
|
||||
const { value: initialStoredValue, setValue: setStoredValue } =
|
||||
createLocalStorage<T>(key, initialValue);
|
||||
|
||||
const [localValue, setLocalValue] = useState<T>(initialStoredValue);
|
||||
|
||||
useEffect(() => {
|
||||
setStoredValue(localValue);
|
||||
}, [localValue]);
|
||||
|
||||
return [localValue, setLocalValue] as const;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { basePath } from './formatPath';
|
||||
import { getLocalStorageItem, setLocalStorageItem } from './storage';
|
||||
|
||||
export const createLocalStorage = <T extends object>(
|
||||
export const createLocalStorage = <T extends object | string>(
|
||||
key: string,
|
||||
initialValue: T,
|
||||
) => {
|
||||
|
Loading…
Reference in New Issue
Block a user