mirror of
https://github.com/docmost/docmost.git
synced 2026-05-18 23:44:24 +08:00
e209aaa272
* Work on mentions * fix: properly parse page slug * fix editor suggestion bugs * mentions must start with whitespace * add icon to page mention render * feat: backlinks - WIP * UI - WIP * permissions check * use FTS for page suggestion * cleanup * WIP * page title fallback * feat: handle internal link paste * link styling * WIP * Switch back to LIKE operator for search suggestion * WIP * scope to workspaceId * still create link for pages not found * select necessary columns * cleanups
83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
import { Group, Center, Text } from "@mantine/core";
|
|
import { Spotlight } from "@mantine/spotlight";
|
|
import { IconSearch } from "@tabler/icons-react";
|
|
import React, { useState } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useDebouncedValue } from "@mantine/hooks";
|
|
import { usePageSearchQuery } from "@/features/search/queries/search-query";
|
|
import { buildPageUrl } from "@/features/page/page.utils.ts";
|
|
import { getPageIcon } from "@/lib";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
interface SearchSpotlightProps {
|
|
spaceId?: string;
|
|
}
|
|
export function SearchSpotlight({ spaceId }: SearchSpotlightProps) {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const [query, setQuery] = useState("");
|
|
const [debouncedSearchQuery] = useDebouncedValue(query, 300);
|
|
|
|
const {
|
|
data: searchResults,
|
|
isLoading,
|
|
error,
|
|
} = usePageSearchQuery({ query: debouncedSearchQuery, spaceId });
|
|
|
|
const pages = (
|
|
searchResults && searchResults.length > 0 ? searchResults : []
|
|
).map((page) => (
|
|
<Spotlight.Action
|
|
key={page.id}
|
|
onClick={() =>
|
|
navigate(buildPageUrl(page.space.slug, page.slugId, page.title))
|
|
}
|
|
>
|
|
<Group wrap="nowrap" w="100%">
|
|
<Center>{getPageIcon(page?.icon)}</Center>
|
|
|
|
<div style={{ flex: 1 }}>
|
|
<Text>{page.title}</Text>
|
|
|
|
{page?.highlight && (
|
|
<Text
|
|
opacity={0.6}
|
|
size="xs"
|
|
dangerouslySetInnerHTML={{ __html: page.highlight }}
|
|
/>
|
|
)}
|
|
</div>
|
|
</Group>
|
|
</Spotlight.Action>
|
|
));
|
|
|
|
return (
|
|
<>
|
|
<Spotlight.Root
|
|
query={query}
|
|
onQueryChange={setQuery}
|
|
scrollable
|
|
overlayProps={{
|
|
backgroundOpacity: 0.55,
|
|
}}
|
|
>
|
|
<Spotlight.Search
|
|
placeholder={t("Search...")}
|
|
leftSection={<IconSearch size={20} stroke={1.5} />}
|
|
/>
|
|
<Spotlight.ActionsList>
|
|
{query.length === 0 && pages.length === 0 && (
|
|
<Spotlight.Empty>{t("Start typing to search...")}</Spotlight.Empty>
|
|
)}
|
|
|
|
{query.length > 0 && pages.length === 0 && (
|
|
<Spotlight.Empty>{t("No results found...")}</Spotlight.Empty>
|
|
)}
|
|
|
|
{pages.length > 0 && pages}
|
|
</Spotlight.ActionsList>
|
|
</Spotlight.Root>
|
|
</>
|
|
);
|
|
}
|