mirror of
https://github.com/docmost/docmost.git
synced 2026-08-30 18:36:26 +08:00
feat: enhanced search filters (#2398)
* advanced search filters * improve labelId filtering in query * index label ids on typesense * index label ids on typesense * filters on AI search * refactor: detect typesense schema drift from the declared collection schema * feat: show secondary search filters only when applied Created by and Labels now stay hidden until they hold a value; a Filter button at the right end of the bar lists the hidden ones and opens the picked filter's dropdown immediately. * fix: keep applied search filters in the order they were added * feat: add title-only search mode Adds a titleOnly flag to page search: the Postgres driver matches titles via trigram-indexed unaccented LIKE ranked by word_similarity, and a Match filter in the search spotlight switches between everything and title-only matching. * refactor: make title-only search a toggle chip * fix: drop stale results when the search content type changes * feat: add trigram index on attachment file names * feat: extend title-only search to attachments The titleOnly flag now matches attachment file names via the separator-normalized trigram expression, and the toggle chip stays available in attachment mode as File name only. * refactor: keep the title-only label uniform across search modes * feat: index txt attachments for content search * feat: pin the current user at the top of the creator filter * refactor: dim the you suffix in the creator filter * feat: browse label-filtered pages without a query Selecting labels now lists their pages newest-first before any text is typed, on both the Postgres and Typesense drivers. * fix: match any selected label instead of requiring all * fix: use a gray spotlight selection instead of primary blue * feat: include search results in the spotlight tab order * feat: show last updated time on search results * fix: stop empty-state flicker while the search query debounces * feat: browse creator-filtered results without a query Selecting a creator with an empty query now lists their pages (or attachments in attachment mode) newest-first, with the same space and page permission filtering as typed search. * fix: show Untitled for pages without a title in search results * quick page sharing fix * minor search filter fixes --------- Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
} from "@/features/search/types/search.types";
|
||||
import DOMPurify from "dompurify";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { timeAgo } from "@/lib/time.ts";
|
||||
|
||||
interface SearchResultItemProps {
|
||||
result: IPageSearch | IAttachmentSearch;
|
||||
@@ -26,6 +27,14 @@ interface SearchResultItemProps {
|
||||
showSpace?: boolean;
|
||||
}
|
||||
|
||||
// Spotlight hardcodes tabIndex={-1} after spreading props; a ref wins and
|
||||
// React never writes -1 back because the prop value never changes
|
||||
const makeActionTabbable = (el: HTMLElement | null) => {
|
||||
if (el) {
|
||||
el.tabIndex = 0;
|
||||
}
|
||||
};
|
||||
|
||||
export function SearchResultItem({
|
||||
result,
|
||||
isAttachmentResult,
|
||||
@@ -46,6 +55,7 @@ export function SearchResultItem({
|
||||
return (
|
||||
<Spotlight.Action
|
||||
component={Link}
|
||||
ref={makeActionTabbable}
|
||||
//@ts-ignore
|
||||
to={buildPageUrl(
|
||||
attachmentResult.space.slug,
|
||||
@@ -59,8 +69,13 @@ export function SearchResultItem({
|
||||
<IconFile size={16} />
|
||||
</Center>
|
||||
|
||||
<div style={{ flex: 1 }}>
|
||||
<Text>{attachmentResult.fileName}</Text>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<Group justify="space-between" wrap="nowrap" gap="xs">
|
||||
<Text truncate>{attachmentResult.fileName}</Text>
|
||||
<Text size="xs" c="dimmed" style={{ flexShrink: 0 }}>
|
||||
{timeAgo(attachmentResult.updatedAt)}
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="xs" opacity={0.6}>
|
||||
{attachmentResult.space.name} • {attachmentResult.page.title}
|
||||
</Text>
|
||||
@@ -96,6 +111,7 @@ export function SearchResultItem({
|
||||
return (
|
||||
<Spotlight.Action
|
||||
component={Link}
|
||||
ref={makeActionTabbable}
|
||||
//@ts-ignore
|
||||
to={buildPageUrl(
|
||||
pageResult.space.slug,
|
||||
@@ -107,8 +123,13 @@ export function SearchResultItem({
|
||||
<Group wrap="nowrap" w="100%">
|
||||
<Center>{getPageIcon(pageResult?.icon)}</Center>
|
||||
|
||||
<div style={{ flex: 1 }}>
|
||||
<Text>{pageResult.title}</Text>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<Group justify="space-between" wrap="nowrap" gap="xs">
|
||||
<Text truncate>{pageResult.title || t("Untitled")}</Text>
|
||||
<Text size="xs" c="dimmed" style={{ flexShrink: 0 }}>
|
||||
{timeAgo(pageResult.updatedAt)}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
{showSpace && pageResult.space && (
|
||||
<Badge variant="light" size="xs" color="gray">
|
||||
|
||||
Reference in New Issue
Block a user