Skip to content

Commit

Permalink
Merge pull request #581 from sickelap/site_search_people
Browse files Browse the repository at this point in the history
restore site search functionality
  • Loading branch information
derneuere authored Dec 6, 2024
2 parents 8b68bb9 + 6f7b46a commit cb21c8f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 24 deletions.
1 change: 0 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@
- low: dark mode visibility text sidemenu
- low: refactor sidebar with NavLink
- low: notifications not visible
- optional: refactor site search with combobox
- optional: refactor tree with latest mantine tree (and remove existing one)
- optional: move color theme switch to top menu for convenience
71 changes: 52 additions & 19 deletions src/components/SiteSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Combobox, Group, InputBase, Loader, Text, useCombobox } from "@mantine/core";
import { ActionIcon, Combobox, Group, Image, InputBase, Loader, Popover, Text, useCombobox } from "@mantine/core";
import { useViewportSize } from "@mantine/hooks";
import { IconAlbum, IconMap, IconSearch, IconTag, IconUser, IconX } from "@tabler/icons-react";
import React from "react";
Expand All @@ -7,6 +7,7 @@ import { push } from "redux-first-history";

import { SearchOption, SearchOptionType, useSearch } from "../service/use-search";
import { useAppDispatch } from "../store/store";
import classes from "./SiteSearch.module.css";

const ICON_SIZE = 20;

Expand Down Expand Up @@ -34,13 +35,14 @@ export function SiteSearch() {
const dispatch = useAppDispatch();
const searchWidth = width ? width - width / 1.8 : 200;
const [value, setValue] = React.useState("");
const [personToBeSelected, setPersonToBeSelected] = React.useState<string | null>(null);

function getSearchRightIcon() {
if (isLoading) return <Loader size="xs" type="dots" />;
if (value) {
return (
<IconX
size="sm"
className={classes.clearSearch}
onMouseDown={event => event.preventDefault()}
onClick={() => {
setValue("");
Expand All @@ -53,6 +55,10 @@ export function SiteSearch() {
return null;
}

function showPersonNameToBeSelected(name: string): boolean {
return name === personToBeSelected;
}

function search(query: string) {
const item = options.find(i => i.value === query);
switch (item?.type) {
Expand All @@ -77,26 +83,53 @@ export function SiteSearch() {
}
}

const searchOptions = options.map(item => (
<Combobox.Option value={item.value} key={item.value}>
<Group wrap="nowrap">
{getIconForItem(item)}
<Text>{item.value}</Text>
</Group>
</Combobox.Option>
));
function onOptionSubmit(val: string) {
setValue(val);
search(val);
combobox.closeDropdown();
}

const searchOptionsDefault = options.filter(option => option.type !== SearchOptionType.PEOPLE);
const searchOptionsPeople = options.filter(option => option.type === SearchOptionType.PEOPLE);
const searchOptions = searchOptionsDefault
.map(item => (
<Combobox.Option value={item.value} key={item.value}>
<Group wrap="nowrap">
{getIconForItem(item)}
<Text>{item.value}</Text>
</Group>
</Combobox.Option>
))
.concat([
<Combobox.Empty className={classes.people}>
<Group wrap="nowrap">
{searchOptionsPeople.map(person => (
<Popover withArrow opened={showPersonNameToBeSelected(person.value)}>
<Popover.Target>
<ActionIcon
className={classes.person}
onMouseEnter={() => setPersonToBeSelected(person.value)}
onMouseLeave={() => setPersonToBeSelected(null)}
size="xl"
radius="xl"
variant="transparent"
onClick={() => onOptionSubmit(person.value)}
>
<Image src={person.thumbnail} />
</ActionIcon>
</Popover.Target>
<Popover.Dropdown p="xs">
<Text size="xs">{person.value}</Text>
</Popover.Dropdown>
</Popover>
))}
</Group>
</Combobox.Empty>,
]);

return (
<div style={{ width: searchWidth }}>
<Combobox
store={combobox}
withinPortal
onOptionSubmit={val => {
setValue(val);
search(val);
combobox.closeDropdown();
}}
>
<Combobox store={combobox} withinPortal onOptionSubmit={option => onOptionSubmit(option)}>
<Combobox.Target>
<InputBase
leftSection={<IconSearch size={16} />}
Expand Down
7 changes: 4 additions & 3 deletions src/service/use-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type SearchOption = {
value: string;
type: SearchOptionType;
data: string | null;
thumbnail?: string;
};

function toExampleOption(item: string): SearchOption {
Expand All @@ -41,7 +42,7 @@ function toUserAlbumOption(item: any): SearchOption {
}

function toPersonOption(item: any): SearchOption {
return { value: item.value, type: SearchOptionType.PEOPLE, data: item.key };
return { value: item.name, type: SearchOptionType.PEOPLE, data: item.id, thumbnail: item.face_url };
}

export function useSearch() {
Expand Down Expand Up @@ -78,8 +79,8 @@ export function useSearch() {
.slice(0, 2)
.map(toUserAlbumOption),
...people
.filter((item: any) => fuzzyMatch(q, item.value))
.slice(0, 2)
.filter((item: any) => fuzzyMatch(q, item.name))
.slice(0, 9)
.map(toPersonOption),
]);
},
Expand Down
2 changes: 1 addition & 1 deletion src/ui-constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const TOP_MENU_HEIGHT = 45; // don't change this
export const TOP_MENU_HEIGHT = 55; // don't change this
export const LEFT_MENU_WIDTH = 200; // don't change this
export const FOOTER_HEIGHT = 50;
export const MIN_VIEWPORT_WODTH = 350;
Expand Down

0 comments on commit cb21c8f

Please sign in to comment.