mirror of
https://github.com/docmost/docmost.git
synced 2025-11-19 09:01:14 +10:00
fix search bug
This commit is contained in:
@ -4,6 +4,8 @@ import { IconSparkles, IconFileText } from "@tabler/icons-react";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { IAiSearchResponse } from "../services/ai-search-service";
|
import { IAiSearchResponse } from "../services/ai-search-service";
|
||||||
import { buildPageUrl } from "@/features/page/page.utils";
|
import { buildPageUrl } from "@/features/page/page.utils";
|
||||||
|
import { markdownToHtml } from "@docmost/editor-ext";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
|
|
||||||
interface AiSearchResultProps {
|
interface AiSearchResultProps {
|
||||||
result: IAiSearchResponse;
|
result: IAiSearchResponse;
|
||||||
@ -46,11 +48,17 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) {
|
|||||||
<Paper p="md" radius="md" withBorder>
|
<Paper p="md" radius="md" withBorder>
|
||||||
<Group gap="xs" mb="sm">
|
<Group gap="xs" mb="sm">
|
||||||
<IconSparkles size={20} color="var(--mantine-color-blue-6)" />
|
<IconSparkles size={20} color="var(--mantine-color-blue-6)" />
|
||||||
<Text fw={600} size="sm">AI Answer</Text>
|
<Text fw={600} size="sm">
|
||||||
</Group>
|
AI Answer
|
||||||
<Text size="sm" style={{ whiteSpace: "pre-wrap" }}>
|
|
||||||
{result.answer}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
</Group>
|
||||||
|
<Text
|
||||||
|
size="sm"
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: DOMPurify.sanitize(markdownToHtml(result.answer) as string),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
{deduplicatedSources.length > 0 && (
|
{deduplicatedSources.length > 0 && (
|
||||||
@ -66,7 +74,7 @@ export function AiSearchResult({ result, isLoading }: AiSearchResultProps) {
|
|||||||
style={{
|
style={{
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
color: "inherit",
|
color: "inherit",
|
||||||
display: "block"
|
display: "block",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paper
|
<Paper
|
||||||
|
|||||||
@ -28,7 +28,6 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) {
|
|||||||
contentType: "page",
|
contentType: "page",
|
||||||
});
|
});
|
||||||
const [isAiMode, setIsAiMode] = useState(false);
|
const [isAiMode, setIsAiMode] = useState(false);
|
||||||
const [triggerAiSearch, setTriggerAiSearch] = useState(false);
|
|
||||||
|
|
||||||
// Build unified search params
|
// Build unified search params
|
||||||
const searchParams = useMemo(() => {
|
const searchParams = useMemo(() => {
|
||||||
@ -49,10 +48,7 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) {
|
|||||||
searchParams,
|
searchParams,
|
||||||
!isAiMode // Disable regular search when in AI mode
|
!isAiMode // Disable regular search when in AI mode
|
||||||
);
|
);
|
||||||
const { data: aiSearchResult, isLoading: isAiLoading, refetch: refetchAiSearch } = useAiSearch(
|
const { data: aiSearchResult, isPending: isAiLoading, mutate: triggerAiSearchMutation } = useAiSearch();
|
||||||
searchParams,
|
|
||||||
isAiMode && triggerAiSearch
|
|
||||||
);
|
|
||||||
|
|
||||||
// Determine result type for rendering
|
// Determine result type for rendering
|
||||||
const isAttachmentSearch =
|
const isAttachmentSearch =
|
||||||
@ -72,16 +68,12 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAskClick = () => {
|
const handleAskClick = () => {
|
||||||
const newMode = !isAiMode;
|
setIsAiMode(!isAiMode);
|
||||||
setIsAiMode(newMode);
|
|
||||||
// Reset AI search state when toggling modes
|
|
||||||
setTriggerAiSearch(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAiSearchTrigger = () => {
|
const handleAiSearchTrigger = () => {
|
||||||
if (query.trim() && isAiMode) {
|
if (query.trim() && isAiMode) {
|
||||||
setTriggerAiSearch(true);
|
triggerAiSearchMutation(searchParams);
|
||||||
refetchAiSearch();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,11 @@
|
|||||||
import { useQuery, UseQueryResult } from "@tanstack/react-query";
|
import { useMutation, UseMutationResult } from "@tanstack/react-query";
|
||||||
import { askAi, IAiSearchResponse } from "@/features/search/services/ai-search-service";
|
import { askAi, IAiSearchResponse } from "@/features/search/services/ai-search-service";
|
||||||
import { IPageSearchParams } from "@/features/search/types/search.types";
|
import { IPageSearchParams } from "@/features/search/types/search.types";
|
||||||
import { useLicense } from "@/ee/hooks/use-license";
|
|
||||||
|
|
||||||
export function useAiSearch(
|
export function useAiSearch(): UseMutationResult<IAiSearchResponse, Error, IPageSearchParams> {
|
||||||
params: IPageSearchParams,
|
return useMutation({
|
||||||
enabled: boolean = false,
|
mutationFn: async (params: IPageSearchParams) => {
|
||||||
): UseQueryResult<IAiSearchResponse, Error> {
|
|
||||||
const { hasLicenseKey } = useLicense();
|
|
||||||
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ["ai-search", params],
|
|
||||||
queryFn: async () => {
|
|
||||||
return await askAi(params);
|
return await askAi(params);
|
||||||
},
|
},
|
||||||
enabled: !!params.query && hasLicenseKey && enabled,
|
|
||||||
staleTime: Infinity, // Don't refetch automatically
|
|
||||||
gcTime: 0, // Don't cache results when component unmounts
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ export class SearchService {
|
|||||||
)
|
)
|
||||||
.where('deletedAt', 'is', null)
|
.where('deletedAt', 'is', null)
|
||||||
.orderBy('rank', 'desc')
|
.orderBy('rank', 'desc')
|
||||||
.limit(searchParams.limit | 20)
|
.limit(searchParams.limit | 25)
|
||||||
.offset(searchParams.offset || 0);
|
.offset(searchParams.offset || 0);
|
||||||
|
|
||||||
if (!searchParams.shareId) {
|
if (!searchParams.shareId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user