mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: command bar search projects (#7388)
Now can search for projects. Also adding debounce to not spam backend with requests. Also the UI is less flickery.
This commit is contained in:
		
							parent
							
								
									3c56bfa992
								
							
						
					
					
						commit
						09d9676d66
					
				@ -21,6 +21,8 @@ import {
 | 
				
			|||||||
    CommandResultGroup,
 | 
					    CommandResultGroup,
 | 
				
			||||||
    type CommandResultGroupItem,
 | 
					    type CommandResultGroupItem,
 | 
				
			||||||
} from './RecentlyVisited/CommandResultGroup';
 | 
					} from './RecentlyVisited/CommandResultGroup';
 | 
				
			||||||
 | 
					import { useAsyncDebounce } from 'react-table';
 | 
				
			||||||
 | 
					import useProjects from 'hooks/api/getters/useProjects/useProjects';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
 | 
					export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
 | 
				
			||||||
    position: 'absolute',
 | 
					    position: 'absolute',
 | 
				
			||||||
@ -83,6 +85,9 @@ export const CommandBar = () => {
 | 
				
			|||||||
    const searchInputRef = useRef<HTMLInputElement>(null);
 | 
					    const searchInputRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
    const searchContainerRef = useRef<HTMLInputElement>(null);
 | 
					    const searchContainerRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
    const [showSuggestions, setShowSuggestions] = useState(false);
 | 
					    const [showSuggestions, setShowSuggestions] = useState(false);
 | 
				
			||||||
 | 
					    const [searchedProjects, setSearchedProjects] = useState<
 | 
				
			||||||
 | 
					        CommandResultGroupItem[]
 | 
				
			||||||
 | 
					    >([]);
 | 
				
			||||||
    const { lastVisited } = useRecentlyVisited();
 | 
					    const { lastVisited } = useRecentlyVisited();
 | 
				
			||||||
    const hideSuggestions = () => {
 | 
					    const hideSuggestions = () => {
 | 
				
			||||||
        setShowSuggestions(false);
 | 
					        setShowSuggestions(false);
 | 
				
			||||||
@ -90,8 +95,26 @@ export const CommandBar = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const [value, setValue] = useState<string>('');
 | 
					    const [value, setValue] = useState<string>('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const { features, setTableState } = useGlobalFeatureSearch(3);
 | 
				
			||||||
 | 
					    const { projects } = useProjects();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const debouncedSetSearchState = useAsyncDebounce((query) => {
 | 
				
			||||||
 | 
					        setTableState({ query });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const filteredProjects = projects.filter((project) =>
 | 
				
			||||||
 | 
					            project.name.toLowerCase().includes(query.toLowerCase()),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const mappedProjects = filteredProjects.map((project) => ({
 | 
				
			||||||
 | 
					            name: project.name,
 | 
				
			||||||
 | 
					            link: `/projects/${project.id}`,
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setSearchedProjects(mappedProjects);
 | 
				
			||||||
 | 
					    }, 200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onSearchChange = (value: string) => {
 | 
					    const onSearchChange = (value: string) => {
 | 
				
			||||||
        setTableState({ query: value });
 | 
					        debouncedSetSearchState(value);
 | 
				
			||||||
        setValue(value);
 | 
					        setValue(value);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,8 +142,6 @@ export const CommandBar = () => {
 | 
				
			|||||||
    useOnClickOutside([searchContainerRef], hideSuggestions);
 | 
					    useOnClickOutside([searchContainerRef], hideSuggestions);
 | 
				
			||||||
    useOnBlur(searchContainerRef, hideSuggestions);
 | 
					    useOnBlur(searchContainerRef, hideSuggestions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { features, setTableState } = useGlobalFeatureSearch(3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const flags: CommandResultGroupItem[] = features.map((feature) => ({
 | 
					    const flags: CommandResultGroupItem[] = features.map((feature) => ({
 | 
				
			||||||
        name: feature.name,
 | 
					        name: feature.name,
 | 
				
			||||||
        link: `/projects/${feature.project}/features/${feature.name}`,
 | 
					        link: `/projects/${feature.project}/features/${feature.name}`,
 | 
				
			||||||
@ -181,6 +202,11 @@ export const CommandBar = () => {
 | 
				
			|||||||
                            icon={'flag'}
 | 
					                            icon={'flag'}
 | 
				
			||||||
                            items={flags}
 | 
					                            items={flags}
 | 
				
			||||||
                        />
 | 
					                        />
 | 
				
			||||||
 | 
					                        <CommandResultGroup
 | 
				
			||||||
 | 
					                            groupName={'Projects'}
 | 
				
			||||||
 | 
					                            icon={'flag'}
 | 
				
			||||||
 | 
					                            items={searchedProjects}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
                    </CommandResultsPaper>
 | 
					                    </CommandResultsPaper>
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                elseShow={
 | 
					                elseShow={
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,8 @@ import {
 | 
				
			|||||||
} from '@mui/material';
 | 
					} from '@mui/material';
 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
import type { Theme } from '@mui/material/styles/createTheme';
 | 
					import type { Theme } from '@mui/material/styles/createTheme';
 | 
				
			||||||
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
 | 
					import { StyledProjectIcon } from '../../layout/MainLayout/NavigationSidebar/IconRenderer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const listItemButtonStyle = (theme: Theme) => ({
 | 
					const listItemButtonStyle = (theme: Theme) => ({
 | 
				
			||||||
    borderRadius: theme.spacing(0.5),
 | 
					    borderRadius: theme.spacing(0.5),
 | 
				
			||||||
@ -49,6 +51,10 @@ export const CommandResultGroup = ({
 | 
				
			|||||||
    items,
 | 
					    items,
 | 
				
			||||||
}: CommandResultGroupProps) => {
 | 
					}: CommandResultGroupProps) => {
 | 
				
			||||||
    const slicedItems = items.slice(0, 3);
 | 
					    const slicedItems = items.slice(0, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (items.length === 0) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
            <StyledTypography color='textSecondary'>
 | 
					            <StyledTypography color='textSecondary'>
 | 
				
			||||||
@ -64,7 +70,11 @@ export const CommandResultGroup = ({
 | 
				
			|||||||
                        sx={listItemButtonStyle}
 | 
					                        sx={listItemButtonStyle}
 | 
				
			||||||
                    >
 | 
					                    >
 | 
				
			||||||
                        <StyledListItemIcon>
 | 
					                        <StyledListItemIcon>
 | 
				
			||||||
                            <Icon>{icon}</Icon>
 | 
					                            <ConditionallyRender
 | 
				
			||||||
 | 
					                                condition={groupName === 'Projects'}
 | 
				
			||||||
 | 
					                                show={<StyledProjectIcon />}
 | 
				
			||||||
 | 
					                                elseShow={<Icon>{icon}</Icon>}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
                        </StyledListItemIcon>
 | 
					                        </StyledListItemIcon>
 | 
				
			||||||
                        <StyledListItemText>
 | 
					                        <StyledListItemText>
 | 
				
			||||||
                            <Typography>{item.name}</Typography>
 | 
					                            <Typography>{item.name}</Typography>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user