1
0
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:
Mateusz Kwasniewski 2024-05-24 13:21:12 +02:00 committed by GitHub
parent 81c6caf211
commit 68427f841b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 86 additions and 9 deletions

View File

@ -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)) {

View 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',
);
});
});

View 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;
};

View File

@ -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,
) => {