feat: internal page links and mentions (#604)

* 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
This commit is contained in:
Philip Okugbe
2025-02-14 15:36:44 +00:00
committed by GitHub
parent 0ef6b1978a
commit e209aaa272
46 changed files with 1679 additions and 101 deletions

View File

@ -24,7 +24,8 @@ export function useSearchSuggestionsQuery(
params: SearchSuggestionParams,
): UseQueryResult<ISuggestionResult, Error> {
return useQuery({
queryKey: ["search-suggestion", params],
queryKey: ["search-suggestion", params.query],
staleTime: 60 * 1000, // 1min
queryFn: () => searchSuggestions(params),
enabled: !!params.query,
});

View File

@ -1,11 +1,12 @@
import { Group, Center, Text } from "@mantine/core";
import { Spotlight } from "@mantine/spotlight";
import { IconFileDescription, IconSearch } from "@tabler/icons-react";
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 {
@ -33,13 +34,7 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) {
}
>
<Group wrap="nowrap" w="100%">
<Center>
{page?.icon ? (
<span style={{ fontSize: "20px" }}>{page.icon}</span>
) : (
<IconFileDescription size={20} />
)}
</Center>
<Center>{getPageIcon(page?.icon)}</Center>
<div style={{ flex: 1 }}>
<Text>{page.title}</Text>

View File

@ -1,6 +1,7 @@
import { IUser } from "@/features/user/types/user.types.ts";
import { IGroup } from "@/features/group/types/group.types.ts";
import { ISpace } from "@/features/space/types/space.types.ts";
import { IPage } from "@/features/page/types/page.types.ts";
export interface IPageSearch {
id: string;
@ -20,11 +21,15 @@ export interface SearchSuggestionParams {
query: string;
includeUsers?: boolean;
includeGroups?: boolean;
includePages?: boolean;
spaceId?: string;
limit?: number;
}
export interface ISuggestionResult {
users?: Partial<IUser[]>;
groups?: Partial<IGroup[]>;
pages?: Partial<IPage[]>;
}
export interface IPageSearchParams {