mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 01:06:23 +02:00
feat: add connector filtering to InboxSidebar for enhanced item management
- Introduced a connector filter in the InboxSidebar to allow users to filter status items by connector type. - Implemented state management for selected connectors and reset functionality when switching tabs. - Enhanced the filtering logic to accommodate connector selection alongside existing filters. - Added UI elements for displaying available connectors as filter options in the status tab.
This commit is contained in:
parent
306a725b7c
commit
18319caca1
1 changed files with 81 additions and 3 deletions
|
|
@ -32,7 +32,9 @@ import { Input } from "@/components/ui/input";
|
|||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import type { InboxItem } from "@/hooks/use-inbox";
|
||||
import type { ConnectorIndexingMetadata } from "@/contracts/types/inbox.types";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
|
|
@ -84,6 +86,7 @@ export function InboxSidebar({
|
|||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [activeTab, setActiveTab] = useState<InboxTab>("mentions");
|
||||
const [activeFilter, setActiveFilter] = useState<InboxFilter>("all");
|
||||
const [selectedConnector, setSelectedConnector] = useState<string | null>(null);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
// Dropdown state for filter menu
|
||||
const [openDropdown, setOpenDropdown] = useState<"filter" | null>(null);
|
||||
|
|
@ -114,6 +117,13 @@ export function InboxSidebar({
|
|||
};
|
||||
}, [open]);
|
||||
|
||||
// Reset connector filter when switching away from status tab
|
||||
useEffect(() => {
|
||||
if (activeTab !== "status") {
|
||||
setSelectedConnector(null);
|
||||
}
|
||||
}, [activeTab]);
|
||||
|
||||
// Split items by type
|
||||
const mentionItems = useMemo(
|
||||
() => inboxItems.filter((item) => item.type === "new_mention"),
|
||||
|
|
@ -128,18 +138,48 @@ export function InboxSidebar({
|
|||
[inboxItems]
|
||||
);
|
||||
|
||||
// Get unique connectors from status items for filtering
|
||||
const uniqueConnectors = useMemo(() => {
|
||||
const connectorMap = new Map<string, { type: string; name: string }>();
|
||||
|
||||
statusItems
|
||||
.filter((item) => item.type === "connector_indexing")
|
||||
.forEach((item) => {
|
||||
const metadata = item.metadata as ConnectorIndexingMetadata;
|
||||
if (metadata?.connector_type && !connectorMap.has(metadata.connector_type)) {
|
||||
connectorMap.set(metadata.connector_type, {
|
||||
type: metadata.connector_type,
|
||||
name: metadata.connector_name || metadata.connector_type,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(connectorMap.values());
|
||||
}, [statusItems]);
|
||||
|
||||
// Get items for current tab
|
||||
const currentTabItems = activeTab === "mentions" ? mentionItems : statusItems;
|
||||
|
||||
// Filter items based on filter type and search query
|
||||
// Filter items based on filter type, connector filter, and search query
|
||||
const filteredItems = useMemo(() => {
|
||||
let items = currentTabItems;
|
||||
|
||||
// Apply filter
|
||||
// Apply read/unread filter
|
||||
if (activeFilter === "unread") {
|
||||
items = items.filter((item) => !item.read);
|
||||
}
|
||||
|
||||
// Apply connector filter (only for status tab)
|
||||
if (activeTab === "status" && selectedConnector) {
|
||||
items = items.filter((item) => {
|
||||
if (item.type === "connector_indexing") {
|
||||
const metadata = item.metadata as ConnectorIndexingMetadata;
|
||||
return metadata?.connector_type === selectedConnector;
|
||||
}
|
||||
return false; // Hide document_processing when a specific connector is selected
|
||||
});
|
||||
}
|
||||
|
||||
// Apply search query
|
||||
if (searchQuery.trim()) {
|
||||
const query = searchQuery.toLowerCase();
|
||||
|
|
@ -151,7 +191,7 @@ export function InboxSidebar({
|
|||
}
|
||||
|
||||
return items;
|
||||
}, [currentTabItems, activeFilter, searchQuery]);
|
||||
}, [currentTabItems, activeFilter, activeTab, selectedConnector, searchQuery]);
|
||||
|
||||
// Count unread items per tab
|
||||
const unreadMentionsCount = useMemo(() => {
|
||||
|
|
@ -441,6 +481,44 @@ export function InboxSidebar({
|
|||
</TabsList>
|
||||
</Tabs>
|
||||
|
||||
{/* Connector filter chips - only show in status tab when there are connectors */}
|
||||
{activeTab === "status" && uniqueConnectors.length > 0 && (
|
||||
<div className="shrink-0 py-2 border-b relative">
|
||||
{/* Left shadow indicator */}
|
||||
<div className="absolute left-0 top-0 bottom-0 w-6 bg-gradient-to-r from-background to-transparent pointer-events-none z-10" />
|
||||
{/* Right shadow indicator */}
|
||||
<div className="absolute right-0 top-0 bottom-0 w-6 bg-gradient-to-l from-background to-transparent pointer-events-none z-10" />
|
||||
<div className="flex items-center gap-1.5 overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden px-4">
|
||||
<Button
|
||||
variant={selectedConnector === null ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="h-7 px-2.5 text-xs shrink-0"
|
||||
onClick={() => setSelectedConnector(null)}
|
||||
>
|
||||
{t("all") || "All"}
|
||||
</Button>
|
||||
{uniqueConnectors.map((connector) => (
|
||||
<Tooltip key={connector.type}>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant={selectedConnector === connector.type ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="h-7 px-2.5 text-xs shrink-0 gap-1.5"
|
||||
onClick={() => setSelectedConnector(connector.type)}
|
||||
>
|
||||
{getConnectorIcon(connector.type, "h-3.5 w-3.5")}
|
||||
<span className="truncate max-w-20">{connector.name}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="z-80">
|
||||
{connector.name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-1 overflow-y-auto overflow-x-hidden p-2">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center py-8">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue