mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: make favorites a global preference (#2685)
https://linear.app/unleash/issue/2-508/make-pinned-favorites-a-global-preference Also introduces a `useGlobalLocalStorage` hook where system-wide preferences that are stored in LocalStorage can be maintained.
This commit is contained in:
		
							parent
							
								
									e05d924663
								
							
						
					
					
						commit
						4afd505164
					
				@ -25,7 +25,7 @@ import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi
 | 
				
			|||||||
import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell';
 | 
					import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell';
 | 
				
			||||||
import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader';
 | 
					import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader';
 | 
				
			||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
					import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
				
			||||||
import { usePlausibleTracker } from '../../../hooks/usePlausibleTracker';
 | 
					import { useGlobalLocalStorage } from 'hooks/useGlobalLocalStorage';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const featuresPlaceholder: FeatureSchema[] = Array(15).fill({
 | 
					export const featuresPlaceholder: FeatureSchema[] = Array(15).fill({
 | 
				
			||||||
    name: 'Name of the feature',
 | 
					    name: 'Name of the feature',
 | 
				
			||||||
@ -43,7 +43,7 @@ const defaultSort: SortingRule<string> = { id: 'createdAt' };
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const { value: storedParams, setValue: setStoredParams } = createLocalStorage(
 | 
					const { value: storedParams, setValue: setStoredParams } = createLocalStorage(
 | 
				
			||||||
    'FeatureToggleListTable:v1',
 | 
					    'FeatureToggleListTable:v1',
 | 
				
			||||||
    { ...defaultSort, favorites: false }
 | 
					    defaultSort
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const FeatureToggleListTable: VFC = () => {
 | 
					export const FeatureToggleListTable: VFC = () => {
 | 
				
			||||||
@ -64,11 +64,13 @@ export const FeatureToggleListTable: VFC = () => {
 | 
				
			|||||||
        hiddenColumns: ['description'],
 | 
					        hiddenColumns: ['description'],
 | 
				
			||||||
        globalFilter: searchParams.get('search') || '',
 | 
					        globalFilter: searchParams.get('search') || '',
 | 
				
			||||||
    }));
 | 
					    }));
 | 
				
			||||||
 | 
					    const { value: globalStore, setValue: setGlobalStore } =
 | 
				
			||||||
 | 
					        useGlobalLocalStorage();
 | 
				
			||||||
    const { isFavoritesPinned, sortTypes, onChangeIsFavoritePinned } =
 | 
					    const { isFavoritesPinned, sortTypes, onChangeIsFavoritePinned } =
 | 
				
			||||||
        usePinnedFavorites(
 | 
					        usePinnedFavorites(
 | 
				
			||||||
            searchParams.has('favorites')
 | 
					            searchParams.has('favorites')
 | 
				
			||||||
                ? searchParams.get('favorites') === 'true'
 | 
					                ? searchParams.get('favorites') === 'true'
 | 
				
			||||||
                : storedParams.favorites
 | 
					                : globalStore.favorites
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    const [searchValue, setSearchValue] = useState(initialState.globalFilter);
 | 
					    const [searchValue, setSearchValue] = useState(initialState.globalFilter);
 | 
				
			||||||
    const { favorite, unfavorite } = useFavoriteFeaturesApi();
 | 
					    const { favorite, unfavorite } = useFavoriteFeaturesApi();
 | 
				
			||||||
@ -244,8 +246,11 @@ export const FeatureToggleListTable: VFC = () => {
 | 
				
			|||||||
        setStoredParams({
 | 
					        setStoredParams({
 | 
				
			||||||
            id: sortBy[0].id,
 | 
					            id: sortBy[0].id,
 | 
				
			||||||
            desc: sortBy[0].desc || false,
 | 
					            desc: sortBy[0].desc || false,
 | 
				
			||||||
            favorites: isFavoritesPinned || false,
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        setGlobalStore(params => ({
 | 
				
			||||||
 | 
					            ...params,
 | 
				
			||||||
 | 
					            favorites: Boolean(isFavoritesPinned),
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
    }, [sortBy, searchValue, setSearchParams, isFavoritesPinned]);
 | 
					    }, [sortBy, searchValue, setSearchParams, isFavoritesPinned]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ import { useStyles } from './ProjectFeatureToggles.styles';
 | 
				
			|||||||
import { usePinnedFavorites } from 'hooks/usePinnedFavorites';
 | 
					import { usePinnedFavorites } from 'hooks/usePinnedFavorites';
 | 
				
			||||||
import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi';
 | 
					import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi';
 | 
				
			||||||
import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/FeatureTagCell';
 | 
					import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/FeatureTagCell';
 | 
				
			||||||
 | 
					import { useGlobalLocalStorage } from 'hooks/useGlobalLocalStorage';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IProjectFeatureTogglesProps {
 | 
					interface IProjectFeatureTogglesProps {
 | 
				
			||||||
    features: IProject['features'];
 | 
					    features: IProject['features'];
 | 
				
			||||||
@ -67,7 +68,6 @@ const staticColumns = ['Actions', 'name', 'favorite'];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const defaultSort: SortingRule<string> & {
 | 
					const defaultSort: SortingRule<string> & {
 | 
				
			||||||
    columns?: string[];
 | 
					    columns?: string[];
 | 
				
			||||||
    favorites?: boolean;
 | 
					 | 
				
			||||||
} = { id: 'createdAt' };
 | 
					} = { id: 'createdAt' };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ProjectFeatureToggles = ({
 | 
					export const ProjectFeatureToggles = ({
 | 
				
			||||||
@ -97,6 +97,8 @@ export const ProjectFeatureToggles = ({
 | 
				
			|||||||
            `${projectId}:FeatureToggleListTable:v1`,
 | 
					            `${projectId}:FeatureToggleListTable:v1`,
 | 
				
			||||||
            defaultSort
 | 
					            defaultSort
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					    const { value: globalStore, setValue: setGlobalStore } =
 | 
				
			||||||
 | 
					        useGlobalLocalStorage();
 | 
				
			||||||
    const navigate = useNavigate();
 | 
					    const navigate = useNavigate();
 | 
				
			||||||
    const [searchParams, setSearchParams] = useSearchParams();
 | 
					    const [searchParams, setSearchParams] = useSearchParams();
 | 
				
			||||||
    const { uiConfig } = useUiConfig();
 | 
					    const { uiConfig } = useUiConfig();
 | 
				
			||||||
@ -110,7 +112,7 @@ export const ProjectFeatureToggles = ({
 | 
				
			|||||||
        usePinnedFavorites(
 | 
					        usePinnedFavorites(
 | 
				
			||||||
            searchParams.has('favorites')
 | 
					            searchParams.has('favorites')
 | 
				
			||||||
                ? searchParams.get('favorites') === 'true'
 | 
					                ? searchParams.get('favorites') === 'true'
 | 
				
			||||||
                : storedParams.favorites
 | 
					                : globalStore.favorites
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    const { toggleFeatureEnvironmentOn, toggleFeatureEnvironmentOff } =
 | 
					    const { toggleFeatureEnvironmentOn, toggleFeatureEnvironmentOff } =
 | 
				
			||||||
        useFeatureApi();
 | 
					        useFeatureApi();
 | 
				
			||||||
@ -469,7 +471,10 @@ export const ProjectFeatureToggles = ({
 | 
				
			|||||||
            id: sortBy[0].id,
 | 
					            id: sortBy[0].id,
 | 
				
			||||||
            desc: sortBy[0].desc || false,
 | 
					            desc: sortBy[0].desc || false,
 | 
				
			||||||
            columns: tableState.columns.split(','),
 | 
					            columns: tableState.columns.split(','),
 | 
				
			||||||
            favorites: isFavoritesPinned || false,
 | 
					        }));
 | 
				
			||||||
 | 
					        setGlobalStore(params => ({
 | 
				
			||||||
 | 
					            ...params,
 | 
				
			||||||
 | 
					            favorites: Boolean(isFavoritesPinned),
 | 
				
			||||||
        }));
 | 
					        }));
 | 
				
			||||||
        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
    }, [
 | 
					    }, [
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								frontend/src/hooks/useGlobalLocalStorage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								frontend/src/hooks/useGlobalLocalStorage.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import { createLocalStorage } from 'utils/createLocalStorage';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IGlobalStore {
 | 
				
			||||||
 | 
					    favorites?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useGlobalLocalStorage = () => {
 | 
				
			||||||
 | 
					    const { value, setValue } = createLocalStorage<IGlobalStore>(
 | 
				
			||||||
 | 
					        'global:v1',
 | 
				
			||||||
 | 
					        {}
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        value,
 | 
				
			||||||
 | 
					        setValue,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user