mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-04 17:45:07 +08:00
### What problem does this PR solve? feat: Added UI functions related to data-flow knowledge base #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
128 lines
3.5 KiB
TypeScript
128 lines
3.5 KiB
TypeScript
import Image from '@/components/image';
|
|
import { useTheme } from '@/components/theme-provider';
|
|
import { Card } from '@/components/ui/card';
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import {
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
} from '@/components/ui/popover';
|
|
import { Switch } from '@/components/ui/switch';
|
|
import { IChunk } from '@/interfaces/database/knowledge';
|
|
import { CheckedState } from '@radix-ui/react-checkbox';
|
|
import classNames from 'classnames';
|
|
import DOMPurify from 'dompurify';
|
|
import { useEffect, useState } from 'react';
|
|
import { ChunkTextMode } from '../../constant';
|
|
import styles from './index.less';
|
|
|
|
interface IProps {
|
|
item: IChunk;
|
|
checked: boolean;
|
|
switchChunk: (available?: number, chunkIds?: string[]) => void;
|
|
editChunk: (chunkId: string) => void;
|
|
handleCheckboxClick: (chunkId: string, checked: boolean) => void;
|
|
selected: boolean;
|
|
clickChunkCard: (chunkId: string) => void;
|
|
textMode: ChunkTextMode;
|
|
}
|
|
|
|
const ChunkCard = ({
|
|
item,
|
|
checked,
|
|
handleCheckboxClick,
|
|
editChunk,
|
|
switchChunk,
|
|
selected,
|
|
clickChunkCard,
|
|
textMode,
|
|
}: IProps) => {
|
|
const available = Number(item.available_int);
|
|
const [enabled, setEnabled] = useState(false);
|
|
const { theme } = useTheme();
|
|
|
|
const onChange = (checked: boolean) => {
|
|
setEnabled(checked);
|
|
switchChunk(available === 0 ? 1 : 0, [item.chunk_id]);
|
|
};
|
|
|
|
const handleCheck = (e: CheckedState) => {
|
|
handleCheckboxClick(item.chunk_id, e === 'indeterminate' ? false : e);
|
|
};
|
|
|
|
const handleContentDoubleClick = () => {
|
|
editChunk(item.chunk_id);
|
|
};
|
|
|
|
const handleContentClick = () => {
|
|
clickChunkCard(item.chunk_id);
|
|
};
|
|
|
|
useEffect(() => {
|
|
setEnabled(available === 1);
|
|
}, [available]);
|
|
const [open, setOpen] = useState<boolean>(false);
|
|
return (
|
|
<Card
|
|
className={classNames('rounded-lg w-full py-3 px-3', {
|
|
'bg-bg-title': selected,
|
|
'bg-bg-input': !selected,
|
|
})}
|
|
>
|
|
<div className="flex items-start justify-between gap-2">
|
|
<Checkbox onCheckedChange={handleCheck} checked={checked}></Checkbox>
|
|
{item.image_id && (
|
|
<Popover open={open}>
|
|
<PopoverTrigger
|
|
asChild
|
|
onMouseEnter={() => setOpen(true)}
|
|
onMouseLeave={() => setOpen(false)}
|
|
>
|
|
<div>
|
|
<Image id={item.image_id} className={styles.image}></Image>
|
|
</div>
|
|
</PopoverTrigger>
|
|
<PopoverContent
|
|
className="p-0"
|
|
align={'start'}
|
|
side={'right'}
|
|
sideOffset={-20}
|
|
>
|
|
<div>
|
|
<Image
|
|
id={item.image_id}
|
|
className={styles.imagePreview}
|
|
></Image>
|
|
</div>
|
|
</PopoverContent>
|
|
</Popover>
|
|
)}
|
|
<section
|
|
onDoubleClick={handleContentDoubleClick}
|
|
onClick={handleContentClick}
|
|
className={styles.content}
|
|
>
|
|
<div
|
|
dangerouslySetInnerHTML={{
|
|
__html: DOMPurify.sanitize(item.content_with_weight),
|
|
}}
|
|
className={classNames(styles.contentText, {
|
|
[styles.contentEllipsis]: textMode === ChunkTextMode.Ellipse,
|
|
})}
|
|
></div>
|
|
</section>
|
|
<div>
|
|
<Switch
|
|
checked={enabled}
|
|
onCheckedChange={onChange}
|
|
aria-readonly
|
|
className="!m-0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default ChunkCard;
|