1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00

feat: search features from command bar (#7378)

Now searching works in command bar

1. Currently piggybacking on the search hook, but I think it is not fast
enough, and also it is using the query params as the global search. This
causes some weird behaviour in UI. This probably means we will create
separate endpoint for this.


![image](https://github.com/Unleash/unleash/assets/964450/a24f41ae-93d7-4ebe-a92b-c20dfe7cb666)
This commit is contained in:
Jaanus Sellin 2024-06-12 21:24:22 +03:00 committed by GitHub
parent 702ee8cb12
commit 21088b745d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 99 additions and 4 deletions

View File

@ -16,6 +16,11 @@ import { useOnClickOutside } from 'hooks/useOnClickOutside';
import { useOnBlur } from 'hooks/useOnBlur';
import { RecentlyVisited } from './RecentlyVisited/RecentlyVisited';
import { useRecentlyVisited } from 'hooks/useRecentlyVisited';
import { useGlobalFeatureSearch } from '../feature/FeatureToggleList/useGlobalFeatureSearch';
import {
CommandResultGroup,
type CommandResultGroupItem,
} from './RecentlyVisited/CommandResultGroup';
export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
position: 'absolute',
@ -86,6 +91,7 @@ export const CommandBar = () => {
const [value, setValue] = useState<string>('');
const onSearchChange = (value: string) => {
setTableState({ query: value });
setValue(value);
};
@ -113,6 +119,13 @@ export const CommandBar = () => {
useOnClickOutside([searchContainerRef], hideSuggestions);
useOnBlur(searchContainerRef, hideSuggestions);
const { features, setTableState } = useGlobalFeatureSearch(3);
const flags: CommandResultGroupItem[] = features.map((feature) => ({
name: feature.name,
link: `/projects/${feature.project}/features/${feature.name}`,
}));
return (
<StyledContainer ref={searchContainerRef} active={showSuggestions}>
<StyledSearch>
@ -160,10 +173,14 @@ export const CommandBar = () => {
</StyledSearch>
<ConditionallyRender
condition={Boolean(value)}
condition={Boolean(value) && showSuggestions}
show={
<CommandResultsPaper className='dropdown-outline'>
<div>search result</div>
<CommandResultGroup
groupName={'Flags'}
icon={'flag'}
items={flags}
/>
</CommandResultsPaper>
}
elseShow={

View File

@ -0,0 +1,77 @@
import {
Icon,
List,
ListItemButton,
ListItemIcon,
ListItemText,
styled,
Typography,
} from '@mui/material';
import { Link } from 'react-router-dom';
import type { Theme } from '@mui/material/styles/createTheme';
const listItemButtonStyle = (theme: Theme) => ({
borderRadius: theme.spacing(0.5),
borderLeft: `${theme.spacing(0.5)} solid transparent`,
'&.Mui-selected': {
borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`,
},
});
const StyledTypography = styled(Typography)(({ theme }) => ({
fontSize: theme.fontSizes.bodySize,
padding: theme.spacing(0, 3),
}));
const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({
minWidth: theme.spacing(4),
margin: theme.spacing(0.25, 0),
}));
const StyledListItemText = styled(ListItemText)(({ theme }) => ({
margin: 0,
}));
export interface CommandResultGroupItem {
name: string;
link: string;
}
interface CommandResultGroupProps {
icon: string;
groupName: string;
items: CommandResultGroupItem[];
}
export const CommandResultGroup = ({
icon,
groupName,
items,
}: CommandResultGroupProps) => {
const slicedItems = items.slice(0, 3);
return (
<>
<StyledTypography color='textSecondary'>
{groupName}
</StyledTypography>
<List>
{slicedItems.map((item, index) => (
<ListItemButton
key={`command-result-group-${groupName}-${index}`}
dense={true}
component={Link}
to={item.link}
sx={listItemButtonStyle}
>
<StyledListItemIcon>
<Icon>{icon}</Icon>
</StyledListItemIcon>
<StyledListItemText>
<Typography>{item.name}</Typography>
</StyledListItemText>
</ListItemButton>
))}
</List>
</>
);
};

View File

@ -15,10 +15,11 @@ import {
import { usePersistentTableState } from 'hooks/usePersistentTableState';
import mapValues from 'lodash.mapvalues';
export const useGlobalFeatureSearch = (storageKey = 'features-list-table') => {
export const useGlobalFeatureSearch = (pageLimit = DEFAULT_PAGE_LIMIT) => {
const storageKey = 'features-list-table';
const stateConfig = {
offset: withDefault(NumberParam, 0),
limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
limit: withDefault(NumberParam, pageLimit),
query: StringParam,
favoritesFirst: withDefault(BooleansStringParam, true),
sortBy: withDefault(StringParam, 'createdAt'),