mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-21 05:16:54 +08:00
### What problem does this PR solve? Feat: Create a folder #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -3,18 +3,19 @@ import React, {
|
||||
ChangeEventHandler,
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
import { Button, ButtonProps } from './ui/button';
|
||||
import { SearchInput } from './ui/input';
|
||||
|
||||
interface IProps {
|
||||
title: string;
|
||||
showDialog?: () => void;
|
||||
title?: string;
|
||||
FilterPopover?: FunctionComponent<any>;
|
||||
searchString?: string;
|
||||
onSearchChange?: ChangeEventHandler<HTMLInputElement>;
|
||||
count?: number;
|
||||
showFilter?: boolean;
|
||||
leftPanel?: ReactNode;
|
||||
}
|
||||
|
||||
const FilterButton = React.forwardRef<
|
||||
@ -31,16 +32,16 @@ const FilterButton = React.forwardRef<
|
||||
export default function ListFilterBar({
|
||||
title,
|
||||
children,
|
||||
showDialog,
|
||||
FilterPopover,
|
||||
searchString,
|
||||
onSearchChange,
|
||||
count,
|
||||
showFilter = true,
|
||||
leftPanel,
|
||||
}: PropsWithChildren<IProps>) {
|
||||
return (
|
||||
<div className="flex justify-between mb-6">
|
||||
<span className="text-3xl font-bold ">{title}</span>
|
||||
<div className="flex justify-between mb-6 items-center">
|
||||
<span className="text-3xl font-bold ">{leftPanel || title}</span>
|
||||
<div className="flex gap-4 items-center">
|
||||
{showFilter &&
|
||||
(FilterPopover ? (
|
||||
@ -55,9 +56,7 @@ export default function ListFilterBar({
|
||||
value={searchString}
|
||||
onChange={onSearchChange}
|
||||
></SearchInput>
|
||||
<Button variant={'tertiary'} size={'sm'} onClick={showDialog}>
|
||||
{children}
|
||||
</Button>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
95
web/src/components/ui/single-tree-select.tsx
Normal file
95
web/src/components/ui/single-tree-select.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { ChevronDown, X } from 'lucide-react';
|
||||
import React, { ReactNode, useState } from 'react';
|
||||
|
||||
export type TreeNode = {
|
||||
id: number;
|
||||
label: ReactNode;
|
||||
children?: TreeNode[];
|
||||
};
|
||||
|
||||
type SingleSelectTreeDropdownProps = {
|
||||
allowDelete?: boolean;
|
||||
treeData: TreeNode[];
|
||||
};
|
||||
|
||||
const SingleTreeSelect: React.FC<SingleSelectTreeDropdownProps> = ({
|
||||
allowDelete = false,
|
||||
treeData,
|
||||
}) => {
|
||||
const [selectedOption, setSelectedOption] = useState<TreeNode | null>(null);
|
||||
|
||||
const handleSelect = (option: TreeNode) => {
|
||||
setSelectedOption(option);
|
||||
};
|
||||
|
||||
const handleDelete = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
console.log(
|
||||
'Delete button clicked. Current selected option:',
|
||||
selectedOption,
|
||||
);
|
||||
setSelectedOption(null);
|
||||
console.log('After deletion, selected option:', selectedOption);
|
||||
};
|
||||
|
||||
const renderTree = (nodes: TreeNode[]) => {
|
||||
return nodes.map((node) => (
|
||||
<div key={node.id} className="pl-4">
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleSelect(node)}
|
||||
className={`flex items-center ${
|
||||
selectedOption?.id === node.id ? 'bg-gray-500' : ''
|
||||
}`}
|
||||
>
|
||||
<span>{node.label}</span>
|
||||
{node.children && (
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-gray-400" />
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
{node.children && renderTree(node.children)}
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center justify-between space-x-1 p-2 border rounded-md focus:outline-none w-full"
|
||||
>
|
||||
{selectedOption ? (
|
||||
<>
|
||||
<span>{selectedOption.label}</span>
|
||||
{allowDelete && (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-2 text-gray-500 hover:text-red-500 focus:outline-none"
|
||||
onClick={handleDelete}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
'Select an option'
|
||||
)}
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className=" mt-2 w-56 origin-top-right rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
{renderTree(treeData)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleTreeSelect;
|
||||
Reference in New Issue
Block a user