mirror of
https://github.com/docmost/docmost.git
synced 2026-08-25 15:57:11 +08:00
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.
This commit is contained in:
@@ -21,6 +21,8 @@ type CreatorFilterMenuProps = {
|
|||||||
| "top-end"
|
| "top-end"
|
||||||
| "top";
|
| "top";
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
|
opened?: boolean;
|
||||||
|
onOpenChange?: (opened: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function CreatorFilterMenu({
|
export function CreatorFilterMenu({
|
||||||
@@ -30,6 +32,8 @@ export function CreatorFilterMenu({
|
|||||||
width = 280,
|
width = 280,
|
||||||
position = "bottom-end",
|
position = "bottom-end",
|
||||||
zIndex,
|
zIndex,
|
||||||
|
opened,
|
||||||
|
onOpenChange,
|
||||||
}: CreatorFilterMenuProps) {
|
}: CreatorFilterMenuProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
@@ -46,7 +50,14 @@ export function CreatorFilterMenu({
|
|||||||
const users: IUser[] = (suggestion?.users as IUser[]) ?? [];
|
const users: IUser[] = (suggestion?.users as IUser[]) ?? [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu shadow="md" width={width} position={position} zIndex={zIndex}>
|
<Menu
|
||||||
|
shadow="md"
|
||||||
|
width={width}
|
||||||
|
position={position}
|
||||||
|
zIndex={zIndex}
|
||||||
|
opened={opened}
|
||||||
|
onChange={onOpenChange}
|
||||||
|
>
|
||||||
<Menu.Target>{children}</Menu.Target>
|
<Menu.Target>{children}</Menu.Target>
|
||||||
<Menu.Dropdown>
|
<Menu.Dropdown>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ type LabelFilterMenuProps = {
|
|||||||
| "top-end"
|
| "top-end"
|
||||||
| "top";
|
| "top";
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
|
opened?: boolean;
|
||||||
|
onOpenChange?: (opened: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function LabelFilterMenu({
|
export function LabelFilterMenu({
|
||||||
@@ -36,6 +38,8 @@ export function LabelFilterMenu({
|
|||||||
width = 280,
|
width = 280,
|
||||||
position = "bottom-end",
|
position = "bottom-end",
|
||||||
zIndex,
|
zIndex,
|
||||||
|
opened,
|
||||||
|
onOpenChange,
|
||||||
}: LabelFilterMenuProps) {
|
}: LabelFilterMenuProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const scheme = useComputedColorScheme("light");
|
const scheme = useComputedColorScheme("light");
|
||||||
@@ -61,6 +65,8 @@ export function LabelFilterMenu({
|
|||||||
width={width}
|
width={width}
|
||||||
position={position}
|
position={position}
|
||||||
zIndex={zIndex}
|
zIndex={zIndex}
|
||||||
|
opened={opened}
|
||||||
|
onChange={onOpenChange}
|
||||||
closeOnItemClick={false}
|
closeOnItemClick={false}
|
||||||
>
|
>
|
||||||
<Menu.Target>{children}</Menu.Target>
|
<Menu.Target>{children}</Menu.Target>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
IconChevronDown,
|
IconChevronDown,
|
||||||
IconBuilding,
|
IconBuilding,
|
||||||
|
IconPlus,
|
||||||
IconFileDescription,
|
IconFileDescription,
|
||||||
IconCheck,
|
IconCheck,
|
||||||
IconUser,
|
IconUser,
|
||||||
@@ -52,6 +53,7 @@ export function SearchSpotlightFilters({
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [selectedLabelIds, setSelectedLabelIds] = useState<string[]>([]);
|
const [selectedLabelIds, setSelectedLabelIds] = useState<string[]>([]);
|
||||||
|
const [openedFilter, setOpenedFilter] = useState<string | null>(null);
|
||||||
const [workspace] = useAtom(workspaceAtom);
|
const [workspace] = useAtom(workspaceAtom);
|
||||||
|
|
||||||
const { data: spacesData } = useGetSpacesQuery({ limit: 100 });
|
const { data: spacesData } = useGetSpacesQuery({ limit: 100 });
|
||||||
@@ -104,6 +106,24 @@ export function SearchSpotlightFilters({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showCreatorFilter = !!selectedCreatorId || openedFilter === "creator";
|
||||||
|
const showLabelFilter =
|
||||||
|
contentType !== "attachment" &&
|
||||||
|
(selectedLabelIds.length > 0 || openedFilter === "labels");
|
||||||
|
|
||||||
|
const addableFilters: { key: string; label: string; icon: typeof IconUser }[] =
|
||||||
|
[];
|
||||||
|
if (!showCreatorFilter) {
|
||||||
|
addableFilters.push({
|
||||||
|
key: "creator",
|
||||||
|
label: t("Created by"),
|
||||||
|
icon: IconUser,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (contentType !== "attachment" && !showLabelFilter) {
|
||||||
|
addableFilters.push({ key: "labels", label: t("Labels"), icon: IconTag });
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.filtersContainer}>
|
<div className={classes.filtersContainer}>
|
||||||
{workspace?.settings?.ai?.search === true && (
|
{workspace?.settings?.ai?.search === true && (
|
||||||
@@ -219,35 +239,41 @@ export function SearchSpotlightFilters({
|
|||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
<CreatorFilterMenu
|
{showCreatorFilter && (
|
||||||
value={selectedCreatorId}
|
<CreatorFilterMenu
|
||||||
onChange={handleCreatorSelect}
|
value={selectedCreatorId}
|
||||||
position="bottom-start"
|
onChange={handleCreatorSelect}
|
||||||
width={250}
|
position="bottom-start"
|
||||||
zIndex={getDefaultZIndex("max")}
|
width={250}
|
||||||
>
|
zIndex={getDefaultZIndex("max")}
|
||||||
<Button
|
opened={openedFilter === "creator"}
|
||||||
variant="subtle"
|
onOpenChange={(opened) => setOpenedFilter(opened ? "creator" : null)}
|
||||||
color="gray"
|
|
||||||
size="sm"
|
|
||||||
rightSection={<IconChevronDown size={14} />}
|
|
||||||
leftSection={<IconUser size={16} />}
|
|
||||||
className={classes.filterButton}
|
|
||||||
fw={500}
|
|
||||||
>
|
>
|
||||||
{selectedCreatorId
|
<Button
|
||||||
? `${t("Created by")}: ${selectedCreatorName || t("Unknown")}`
|
variant="subtle"
|
||||||
: `${t("Created by")}: ${t("Anyone")}`}
|
color="gray"
|
||||||
</Button>
|
size="sm"
|
||||||
</CreatorFilterMenu>
|
rightSection={<IconChevronDown size={14} />}
|
||||||
|
leftSection={<IconUser size={16} />}
|
||||||
|
className={classes.filterButton}
|
||||||
|
fw={500}
|
||||||
|
>
|
||||||
|
{selectedCreatorId
|
||||||
|
? `${t("Created by")}: ${selectedCreatorName || t("Unknown")}`
|
||||||
|
: `${t("Created by")}: ${t("Anyone")}`}
|
||||||
|
</Button>
|
||||||
|
</CreatorFilterMenu>
|
||||||
|
)}
|
||||||
|
|
||||||
{contentType !== "attachment" && (
|
{showLabelFilter && (
|
||||||
<LabelFilterMenu
|
<LabelFilterMenu
|
||||||
value={selectedLabelIds}
|
value={selectedLabelIds}
|
||||||
onChange={handleLabelsSelect}
|
onChange={handleLabelsSelect}
|
||||||
position="bottom-start"
|
position="bottom-start"
|
||||||
width={250}
|
width={250}
|
||||||
zIndex={getDefaultZIndex("max")}
|
zIndex={getDefaultZIndex("max")}
|
||||||
|
opened={openedFilter === "labels"}
|
||||||
|
onOpenChange={(opened) => setOpenedFilter(opened ? "labels" : null)}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
@@ -264,6 +290,40 @@ export function SearchSpotlightFilters({
|
|||||||
</Button>
|
</Button>
|
||||||
</LabelFilterMenu>
|
</LabelFilterMenu>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{addableFilters.length > 0 && (
|
||||||
|
<Menu
|
||||||
|
shadow="md"
|
||||||
|
width={200}
|
||||||
|
position="bottom-end"
|
||||||
|
zIndex={getDefaultZIndex("max")}
|
||||||
|
>
|
||||||
|
<Menu.Target>
|
||||||
|
<Button
|
||||||
|
variant="subtle"
|
||||||
|
color="gray"
|
||||||
|
size="sm"
|
||||||
|
leftSection={<IconPlus size={16} />}
|
||||||
|
className={classes.filterButton}
|
||||||
|
style={{ marginLeft: "auto" }}
|
||||||
|
fw={500}
|
||||||
|
>
|
||||||
|
{t("Filter")}
|
||||||
|
</Button>
|
||||||
|
</Menu.Target>
|
||||||
|
<Menu.Dropdown>
|
||||||
|
{addableFilters.map((filter) => (
|
||||||
|
<Menu.Item
|
||||||
|
key={filter.key}
|
||||||
|
leftSection={<filter.icon size={16} />}
|
||||||
|
onClick={() => setOpenedFilter(filter.key)}
|
||||||
|
>
|
||||||
|
{filter.label}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu.Dropdown>
|
||||||
|
</Menu>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user