mirror of
https://github.com/docmost/docmost.git
synced 2026-05-17 23:14:07 +08:00
full implementation
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
import React, { useState, useMemo, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
Button,
|
||||
Menu,
|
||||
Text,
|
||||
TextInput,
|
||||
Divider,
|
||||
Badge,
|
||||
ScrollArea,
|
||||
Avatar,
|
||||
Group,
|
||||
Switch,
|
||||
getDefaultZIndex,
|
||||
@@ -16,12 +12,11 @@ import {
|
||||
IconChevronDown,
|
||||
IconBuilding,
|
||||
IconFileDescription,
|
||||
IconSearch,
|
||||
IconCheck,
|
||||
} from "@tabler/icons-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDebouncedValue } from "@mantine/hooks";
|
||||
import { useGetSpacesQuery } from "@/features/space/queries/space-query";
|
||||
import { SpaceFilterMenu } from "@/features/space/components/space-filter-menu";
|
||||
import { useHasFeature } from "@/ee/hooks/use-feature";
|
||||
import { Feature } from "@/ee/features";
|
||||
import classes from "./search-spotlight-filters.module.css";
|
||||
@@ -46,32 +41,13 @@ export function SearchSpotlightFilters({
|
||||
const [selectedSpaceId, setSelectedSpaceId] = useState<string | null>(
|
||||
spaceId || null,
|
||||
);
|
||||
const [spaceSearchQuery, setSpaceSearchQuery] = useState("");
|
||||
const [debouncedSpaceQuery] = useDebouncedValue(spaceSearchQuery, 300);
|
||||
const [contentType, setContentType] = useState<string | null>("page");
|
||||
const [workspace] = useAtom(workspaceAtom);
|
||||
|
||||
const { data: spacesData } = useGetSpacesQuery({
|
||||
limit: 100,
|
||||
query: debouncedSpaceQuery,
|
||||
});
|
||||
|
||||
const selectedSpaceData = useMemo(() => {
|
||||
if (!spacesData?.items || !selectedSpaceId) return null;
|
||||
return spacesData.items.find((space) => space.id === selectedSpaceId);
|
||||
}, [spacesData?.items, selectedSpaceId]);
|
||||
|
||||
const availableSpaces = useMemo(() => {
|
||||
const spaces = spacesData?.items || [];
|
||||
if (!selectedSpaceId) return spaces;
|
||||
|
||||
// Sort to put selected space first
|
||||
return [...spaces].sort((a, b) => {
|
||||
if (a.id === selectedSpaceId) return -1;
|
||||
if (b.id === selectedSpaceId) return 1;
|
||||
return 0;
|
||||
});
|
||||
}, [spacesData?.items, selectedSpaceId]);
|
||||
const { data: spacesData } = useGetSpacesQuery({ limit: 100 });
|
||||
const selectedSpaceData = selectedSpaceId
|
||||
? spacesData?.items.find((space) => space.id === selectedSpaceId)
|
||||
: null;
|
||||
|
||||
useEffect(() => {
|
||||
if (onFiltersChange) {
|
||||
@@ -152,86 +128,27 @@ export function SearchSpotlightFilters({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Menu
|
||||
shadow="md"
|
||||
width={250}
|
||||
<SpaceFilterMenu
|
||||
value={selectedSpaceId}
|
||||
onChange={handleSpaceSelect}
|
||||
position="bottom-start"
|
||||
width={250}
|
||||
zIndex={getDefaultZIndex("max")}
|
||||
>
|
||||
<Menu.Target>
|
||||
<Button
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
size="sm"
|
||||
rightSection={<IconChevronDown size={14} />}
|
||||
leftSection={<IconBuilding size={16} />}
|
||||
className={classes.filterButton}
|
||||
fw={500}
|
||||
>
|
||||
{selectedSpaceId
|
||||
? `${t("Space")}: ${selectedSpaceData?.name || t("Unknown")}`
|
||||
: `${t("Space")}: ${t("All spaces")}`}
|
||||
</Button>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<TextInput
|
||||
placeholder={t("Find a space")}
|
||||
data-autofocus
|
||||
autoFocus
|
||||
leftSection={<IconSearch size={16} />}
|
||||
value={spaceSearchQuery}
|
||||
onChange={(e) => setSpaceSearchQuery(e.target.value)}
|
||||
size="sm"
|
||||
variant="filled"
|
||||
radius="sm"
|
||||
styles={{ input: { marginBottom: 8 } }}
|
||||
/>
|
||||
|
||||
<ScrollArea.Autosize mah={280}>
|
||||
<Menu.Item onClick={() => handleSpaceSelect(null)}>
|
||||
<Group flex="1" gap="xs">
|
||||
<Avatar
|
||||
color="initials"
|
||||
variant="filled"
|
||||
name={t("All spaces")}
|
||||
size={20}
|
||||
/>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Text size="sm" fw={500}>
|
||||
{t("All spaces")}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{t("Search in all your spaces")}
|
||||
</Text>
|
||||
</div>
|
||||
{!selectedSpaceId && <IconCheck size={20} />}
|
||||
</Group>
|
||||
</Menu.Item>
|
||||
|
||||
<Divider my="xs" />
|
||||
|
||||
{availableSpaces.map((space) => (
|
||||
<Menu.Item
|
||||
key={space.id}
|
||||
onClick={() => handleSpaceSelect(space.id)}
|
||||
>
|
||||
<Group flex="1" gap="xs">
|
||||
<Avatar
|
||||
color="initials"
|
||||
variant="filled"
|
||||
name={space.name}
|
||||
size={20}
|
||||
/>
|
||||
<Text size="sm" fw={500} style={{ flex: 1 }} truncate>
|
||||
{space.name}
|
||||
</Text>
|
||||
{selectedSpaceId === space.id && <IconCheck size={20} />}
|
||||
</Group>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</ScrollArea.Autosize>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Button
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
size="sm"
|
||||
rightSection={<IconChevronDown size={14} />}
|
||||
leftSection={<IconBuilding size={16} />}
|
||||
className={classes.filterButton}
|
||||
fw={500}
|
||||
>
|
||||
{selectedSpaceId
|
||||
? `${t("Space")}: ${selectedSpaceData?.name || t("Unknown")}`
|
||||
: `${t("Space")}: ${t("All spaces")}`}
|
||||
</Button>
|
||||
</SpaceFilterMenu>
|
||||
|
||||
<Menu
|
||||
shadow="md"
|
||||
|
||||
Reference in New Issue
Block a user