mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-05-25 07:39:13 +08:00
### What problem does this PR solve? Feat: Render operator menu by category. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
f9f75aa119
commit
ca865df87f
@ -1,3 +1,4 @@
|
|||||||
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import {
|
import {
|
||||||
Collapsible,
|
Collapsible,
|
||||||
CollapsibleContent,
|
CollapsibleContent,
|
||||||
@ -11,81 +12,97 @@ import {
|
|||||||
SidebarGroupLabel,
|
SidebarGroupLabel,
|
||||||
SidebarHeader,
|
SidebarHeader,
|
||||||
SidebarMenu,
|
SidebarMenu,
|
||||||
SidebarMenuButton,
|
|
||||||
SidebarMenuItem,
|
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/components/ui/sidebar';
|
||||||
|
import { ChevronDown } from 'lucide-react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
Calendar,
|
AgentOperatorList,
|
||||||
ChevronDown,
|
Operator,
|
||||||
Home,
|
componentMenuList,
|
||||||
Inbox,
|
operatorMap,
|
||||||
Search,
|
} from './constant';
|
||||||
Settings,
|
import OperatorIcon from './operator-icon';
|
||||||
} from 'lucide-react';
|
|
||||||
|
|
||||||
// Menu items.
|
function SideDown() {
|
||||||
const items = [
|
return (
|
||||||
{
|
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
||||||
title: 'Home',
|
);
|
||||||
url: '#',
|
}
|
||||||
icon: Home,
|
|
||||||
},
|
type OperatorItem = {
|
||||||
{
|
name: Operator;
|
||||||
title: 'Inbox',
|
};
|
||||||
url: '#',
|
|
||||||
icon: Inbox,
|
function OperatorCard({ name }: OperatorItem) {
|
||||||
},
|
return (
|
||||||
{
|
<Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard">
|
||||||
title: 'Calendar',
|
<CardContent className="p-2 flex items-center gap-2">
|
||||||
url: '#',
|
<OperatorIcon
|
||||||
icon: Calendar,
|
name={name}
|
||||||
},
|
color={operatorMap[name].color}
|
||||||
{
|
></OperatorIcon>
|
||||||
title: 'Search',
|
{name}
|
||||||
url: '#',
|
</CardContent>
|
||||||
icon: Search,
|
</Card>
|
||||||
},
|
);
|
||||||
{
|
}
|
||||||
title: 'Settings',
|
|
||||||
url: '#',
|
type OperatorCollapsibleProps = { operatorList: OperatorItem[]; title: string };
|
||||||
icon: Settings,
|
|
||||||
},
|
function OperatorCollapsible({
|
||||||
];
|
operatorList,
|
||||||
|
title,
|
||||||
|
}: OperatorCollapsibleProps) {
|
||||||
|
return (
|
||||||
|
<Collapsible defaultOpen className="group/collapsible">
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupLabel asChild className="mb-1">
|
||||||
|
<CollapsibleTrigger>
|
||||||
|
<span className="font-bold text-base">{title}</span>
|
||||||
|
<SideDown />
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
</SidebarGroupLabel>
|
||||||
|
<CollapsibleContent className="px-2">
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu className="gap-2">
|
||||||
|
{operatorList.map((item) => (
|
||||||
|
<OperatorCard key={item.name} name={item.name}></OperatorCard>
|
||||||
|
))}
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
</Collapsible>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function AgentSidebar() {
|
export function AgentSidebar() {
|
||||||
|
const agentOperatorList = useMemo(() => {
|
||||||
|
return componentMenuList.filter((x) =>
|
||||||
|
AgentOperatorList.some((y) => y === x.name),
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const thirdOperatorList = useMemo(() => {
|
||||||
|
return componentMenuList.filter(
|
||||||
|
(x) => !AgentOperatorList.some((y) => y === x.name),
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar variant={'floating'} className="top-16">
|
<Sidebar variant={'floating'} className="top-16">
|
||||||
<SidebarHeader>
|
<SidebarHeader>
|
||||||
<p className="font-bold text-2xl">All nodes</p>
|
<p className="font-bold text-2xl">All nodes</p>
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<Collapsible defaultOpen className="group/collapsible">
|
<OperatorCollapsible
|
||||||
<SidebarGroup>
|
title="Agent operator"
|
||||||
<SidebarGroupLabel asChild>
|
operatorList={agentOperatorList}
|
||||||
<CollapsibleTrigger>
|
></OperatorCollapsible>
|
||||||
Help
|
<OperatorCollapsible
|
||||||
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
title="Third-party tools"
|
||||||
</CollapsibleTrigger>
|
operatorList={thirdOperatorList}
|
||||||
</SidebarGroupLabel>
|
></OperatorCollapsible>
|
||||||
<CollapsibleContent>
|
|
||||||
<SidebarGroupContent>
|
|
||||||
<SidebarMenu>
|
|
||||||
{items.map((item) => (
|
|
||||||
<SidebarMenuItem key={item.title}>
|
|
||||||
<SidebarMenuButton asChild>
|
|
||||||
<a href={item.url}>
|
|
||||||
<item.icon />
|
|
||||||
<span>{item.title}</span>
|
|
||||||
</a>
|
|
||||||
</SidebarMenuButton>
|
|
||||||
</SidebarMenuItem>
|
|
||||||
))}
|
|
||||||
</SidebarMenu>
|
|
||||||
</SidebarGroupContent>
|
|
||||||
</CollapsibleContent>
|
|
||||||
</SidebarGroup>
|
|
||||||
</Collapsible>
|
|
||||||
<SidebarGroup>yyy</SidebarGroup>
|
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
);
|
);
|
||||||
|
2985
web/src/pages/agent/constant.tsx
Normal file
2985
web/src/pages/agent/constant.tsx
Normal file
File diff suppressed because it is too large
Load Diff
22
web/src/pages/agent/operator-icon/index.tsx
Normal file
22
web/src/pages/agent/operator-icon/index.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Operator, operatorIconMap } from '../constant';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
name: Operator;
|
||||||
|
fontSize?: number;
|
||||||
|
width?: number;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OperatorIcon = ({ name, fontSize, width, color }: IProps) => {
|
||||||
|
const Icon = operatorIconMap[name] || React.Fragment;
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
className={'text-2xl max-h-6 max-w-6 text-[rgb(59, 118, 244)]'}
|
||||||
|
style={{ fontSize, color }}
|
||||||
|
width={width}
|
||||||
|
></Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OperatorIcon;
|
Loading…
x
Reference in New Issue
Block a user