mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
Fix: Refactoring and enhancing the functionality of the delete confirmation dialog component #10703 (#11542)
### What problem does this PR solve? Fix: Refactoring and enhancing the functionality of the delete confirmation dialog component - Refactoring and enhancing the functionality of the delete confirmation dialog component - Modifying the style of the user center ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -1,9 +1,13 @@
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { t } from 'i18next';
|
||||||
import { BrushCleaning } from 'lucide-react';
|
import { BrushCleaning } from 'lucide-react';
|
||||||
import { ReactNode, useCallback } from 'react';
|
import { ReactNode, useCallback } from 'react';
|
||||||
import { ConfirmDeleteDialog } from './confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from './confirm-delete-dialog';
|
||||||
import { Separator } from './ui/separator';
|
import { Separator } from './ui/separator';
|
||||||
|
|
||||||
export type BulkOperateItemType = {
|
export type BulkOperateItemType = {
|
||||||
@ -45,6 +49,15 @@ export function BulkOperateBar({
|
|||||||
<ConfirmDeleteDialog
|
<ConfirmDeleteDialog
|
||||||
hidden={!isDeleteItem(x.id)}
|
hidden={!isDeleteItem(x.id)}
|
||||||
onOk={x.onClick}
|
onOk={x.onClick}
|
||||||
|
title={t('deleteModal.delFiles')}
|
||||||
|
content={{
|
||||||
|
title: t('common.deleteThem'),
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
name={`${t('deleteModal.delFilesContent', { count })}`}
|
||||||
|
></ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
|
|||||||
@ -3,19 +3,30 @@ import {
|
|||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
AlertDialogCancel,
|
AlertDialogCancel,
|
||||||
AlertDialogContent,
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
AlertDialogFooter,
|
AlertDialogFooter,
|
||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from '@/components/ui/alert-dialog';
|
} from '@/components/ui/alert-dialog';
|
||||||
|
import { AlertDialogOverlay } from '@radix-ui/react-alert-dialog';
|
||||||
import { DialogProps } from '@radix-ui/react-dialog';
|
import { DialogProps } from '@radix-ui/react-dialog';
|
||||||
|
import { X } from 'lucide-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { RAGFlowAvatar } from './ragflow-avatar';
|
||||||
|
import { Separator } from './ui/separator';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
onOk?: (...args: any[]) => any;
|
onOk?: (...args: any[]) => any;
|
||||||
onCancel?: (...args: any[]) => any;
|
onCancel?: (...args: any[]) => any;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
content?: {
|
||||||
|
title?: string;
|
||||||
|
node?: React.ReactNode;
|
||||||
|
};
|
||||||
|
okButtonText?: string;
|
||||||
|
cancelButtonText?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ConfirmDeleteDialog({
|
export function ConfirmDeleteDialog({
|
||||||
@ -27,6 +38,9 @@ export function ConfirmDeleteDialog({
|
|||||||
onOpenChange,
|
onOpenChange,
|
||||||
open,
|
open,
|
||||||
defaultOpen,
|
defaultOpen,
|
||||||
|
content,
|
||||||
|
okButtonText,
|
||||||
|
cancelButtonText,
|
||||||
}: IProps & DialogProps) {
|
}: IProps & DialogProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -41,32 +55,78 @@ export function ConfirmDeleteDialog({
|
|||||||
defaultOpen={defaultOpen}
|
defaultOpen={defaultOpen}
|
||||||
>
|
>
|
||||||
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
|
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
|
||||||
<AlertDialogContent
|
<AlertDialogOverlay
|
||||||
onSelect={(e) => e.preventDefault()}
|
onClick={(e) => {
|
||||||
onClick={(e) => e.stopPropagation()}
|
e.stopPropagation();
|
||||||
className="bg-bg-base"
|
}}
|
||||||
>
|
>
|
||||||
<AlertDialogHeader>
|
<AlertDialogContent
|
||||||
<AlertDialogTitle>
|
onSelect={(e) => e.preventDefault()}
|
||||||
{title ?? t('common.deleteModalTitle')}
|
onClick={(e) => e.stopPropagation()}
|
||||||
</AlertDialogTitle>
|
className="bg-bg-base "
|
||||||
{/* <AlertDialogDescription>
|
>
|
||||||
This action cannot be undone. This will permanently delete your
|
<AlertDialogHeader className="space-y-5">
|
||||||
account and remove your data from our servers.
|
<AlertDialogTitle>
|
||||||
</AlertDialogDescription> */}
|
{title ?? t('common.deleteModalTitle')}
|
||||||
</AlertDialogHeader>
|
<AlertDialogCancel
|
||||||
<AlertDialogFooter>
|
onClick={onCancel}
|
||||||
<AlertDialogCancel onClick={onCancel}>
|
className="border-none bg-transparent hover:border-none hover:bg-transparent absolute right-3 top-3 hover:text-text-primary"
|
||||||
{t('common.no')}
|
>
|
||||||
</AlertDialogCancel>
|
<X size={16} />
|
||||||
<AlertDialogAction
|
</AlertDialogCancel>
|
||||||
className="bg-state-error text-text-primary hover:text-text-primary hover:bg-state-error"
|
</AlertDialogTitle>
|
||||||
onClick={onOk}
|
{content && (
|
||||||
>
|
<>
|
||||||
{t('common.yes')}
|
<Separator className="w-[calc(100%+48px)] -translate-x-6"></Separator>
|
||||||
</AlertDialogAction>
|
<AlertDialogDescription className="mt-5">
|
||||||
</AlertDialogFooter>
|
<div className="flex flex-col gap-5 text-base mb-10 px-5">
|
||||||
</AlertDialogContent>
|
<div className="text-text-primary">
|
||||||
|
{content.title || t('common.deleteModalTitle')}
|
||||||
|
</div>
|
||||||
|
{content.node}
|
||||||
|
</div>
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter className="px-5 flex items-center gap-2">
|
||||||
|
<AlertDialogCancel onClick={onCancel}>
|
||||||
|
{okButtonText || t('common.cancel')}
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
className="bg-state-error text-text-primary hover:text-text-primary hover:bg-state-error"
|
||||||
|
onClick={onOk}
|
||||||
|
>
|
||||||
|
{cancelButtonText || t('common.delete')}
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialogOverlay>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ConfirmDeleteDialogNode = ({
|
||||||
|
avatar,
|
||||||
|
name,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
avatar?: { avatar?: string; name?: string; isPerson?: boolean };
|
||||||
|
name?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center border-0.5 text-text-secondary border-border-button rounded-lg px-3 py-4">
|
||||||
|
{avatar && (
|
||||||
|
<RAGFlowAvatar
|
||||||
|
className="w-8 h-8"
|
||||||
|
avatar={avatar.avatar}
|
||||||
|
isPerson={avatar.isPerson}
|
||||||
|
name={avatar.name}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{name && <div className="ml-3">{name}</div>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@ -274,7 +274,7 @@ export function FileUploader(props: FileUploaderProps) {
|
|||||||
className={cn(
|
className={cn(
|
||||||
'group relative grid h-72 w-full cursor-pointer place-items-center rounded-lg border border-dashed border-border-default px-5 py-2.5 text-center transition hover:bg-border-button bg-bg-card',
|
'group relative grid h-72 w-full cursor-pointer place-items-center rounded-lg border border-dashed border-border-default px-5 py-2.5 text-center transition hover:bg-border-button bg-bg-card',
|
||||||
'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
||||||
isDragActive && 'border-muted-foreground/50',
|
isDragActive && 'border-border-button',
|
||||||
isDisabled && 'pointer-events-none opacity-60',
|
isDisabled && 'pointer-events-none opacity-60',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
@ -285,7 +285,7 @@ export function FileUploader(props: FileUploaderProps) {
|
|||||||
<div className="flex flex-col items-center justify-center gap-4 sm:px-5">
|
<div className="flex flex-col items-center justify-center gap-4 sm:px-5">
|
||||||
<div className="rounded-full border border-dashed p-3">
|
<div className="rounded-full border border-dashed p-3">
|
||||||
<Upload
|
<Upload
|
||||||
className="size-7 text-text-secondary"
|
className="size-7 text-text-secondary hover:text-text-primary"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -297,7 +297,7 @@ export function FileUploader(props: FileUploaderProps) {
|
|||||||
<div className="flex flex-col items-center justify-center gap-4 sm:px-5">
|
<div className="flex flex-col items-center justify-center gap-4 sm:px-5">
|
||||||
<div className="rounded-full border border-dashed p-3">
|
<div className="rounded-full border border-dashed p-3">
|
||||||
<Upload
|
<Upload
|
||||||
className="size-7 text-text-secondary"
|
className="size-7 text-text-secondary hover:text-text-primary"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -186,7 +186,9 @@ export const SelectWithSearch = forwardRef<
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<CommandList className="mt-2 outline-none">
|
<CommandList className="mt-2 outline-none">
|
||||||
<CommandEmpty>{emptyData}</CommandEmpty>
|
<CommandEmpty>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: emptyData }}></div>
|
||||||
|
</CommandEmpty>
|
||||||
{options.map((group, idx) => {
|
{options.map((group, idx) => {
|
||||||
if (group.options) {
|
if (group.options) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -53,6 +53,11 @@ const buttonVariants = cva(
|
|||||||
bg-text-primary text-bg-base border-b-4 border-b-accent-primary
|
bg-text-primary text-bg-base border-b-4 border-b-accent-primary
|
||||||
hover:bg-text-primary/90 focus-visible:bg-text-primary/90
|
hover:bg-text-primary/90 focus-visible:bg-text-primary/90
|
||||||
`,
|
`,
|
||||||
|
delete: `
|
||||||
|
text-text-secondary
|
||||||
|
hover:bg-state-error-5 hover:text-state-error
|
||||||
|
focus-visible:text-state-error focus-visible:bg-state-error-5
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: 'h-8 px-2.5 py-1.5 ',
|
default: 'h-8 px-2.5 py-1.5 ',
|
||||||
|
|||||||
@ -76,6 +76,7 @@ export function useDynamicSVGImport(
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
header?: string | ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
content?: ReactNode;
|
content?: ReactNode;
|
||||||
onOk?: (...args: any[]) => any;
|
onOk?: (...args: any[]) => any;
|
||||||
@ -85,19 +86,19 @@ interface IProps {
|
|||||||
export const useShowDeleteConfirm = () => {
|
export const useShowDeleteConfirm = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const showDeleteConfirm = useCallback(
|
const showDeleteConfirm = useCallback(
|
||||||
({ title, content, onOk, onCancel }: IProps): Promise<number> => {
|
({ title, content, onOk, onCancel, header }: IProps): Promise<number> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Modal.show({
|
Modal.show({
|
||||||
// title: title ?? t('common.deleteModalTitle'),
|
title: header,
|
||||||
closable: false,
|
closable: !!header,
|
||||||
visible: true,
|
visible: true,
|
||||||
onVisibleChange: () => {
|
onVisibleChange: () => {
|
||||||
Modal.hide();
|
Modal.destroy();
|
||||||
},
|
},
|
||||||
footer: null,
|
footer: null,
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
okText: t('common.yes'),
|
okText: t('common.delete'),
|
||||||
cancelText: t('common.no'),
|
cancelText: t('common.cancel'),
|
||||||
style: {
|
style: {
|
||||||
width: '450px',
|
width: '450px',
|
||||||
},
|
},
|
||||||
@ -114,7 +115,7 @@ export const useShowDeleteConfirm = () => {
|
|||||||
},
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
Modal.hide();
|
Modal.destroy();
|
||||||
},
|
},
|
||||||
children: (
|
children: (
|
||||||
<div className="flex flex-col justify-start items-start mt-3">
|
<div className="flex flex-col justify-start items-start mt-3">
|
||||||
|
|||||||
@ -7,7 +7,8 @@ export default {
|
|||||||
selectPlaceholder: 'select value',
|
selectPlaceholder: 'select value',
|
||||||
selectAll: 'Select all',
|
selectAll: 'Select all',
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
deleteModalTitle: 'Are you sure to delete this item?',
|
deleteModalTitle: 'Are you sure to delete it ?',
|
||||||
|
deleteThem: 'Are you sure to delete them ?',
|
||||||
ok: 'Ok',
|
ok: 'Ok',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
yes: 'Yes',
|
yes: 'Yes',
|
||||||
@ -59,6 +60,7 @@ export default {
|
|||||||
urlPlaceholder: 'https://api.example.com/v1/mcp',
|
urlPlaceholder: 'https://api.example.com/v1/mcp',
|
||||||
tokenPlaceholder: 'e.g. eyJhbGciOiJIUzI1Ni...',
|
tokenPlaceholder: 'e.g. eyJhbGciOiJIUzI1Ni...',
|
||||||
},
|
},
|
||||||
|
selected: 'Selected',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
loginTitle: 'Sign in to Your Account',
|
loginTitle: 'Sign in to Your Account',
|
||||||
@ -92,7 +94,7 @@ export default {
|
|||||||
home: 'Home',
|
home: 'Home',
|
||||||
setting: 'User settings',
|
setting: 'User settings',
|
||||||
logout: 'Log out',
|
logout: 'Log out',
|
||||||
fileManager: 'File Management',
|
fileManager: 'File',
|
||||||
flow: 'Agent',
|
flow: 'Agent',
|
||||||
search: 'Search',
|
search: 'Search',
|
||||||
welcome: 'Welcome to',
|
welcome: 'Welcome to',
|
||||||
@ -696,8 +698,9 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s
|
|||||||
tocEnhanceTip: ` During the parsing of the document, table of contents information was generated (see the 'Enable Table of Contents Extraction' option in the General method). This allows the large model to return table of contents items relevant to the user's query, thereby using these items to retrieve related chunks and apply weighting to these chunks during the sorting process. This approach is derived from mimicking the behavioral logic of how humans search for knowledge in books.`,
|
tocEnhanceTip: ` During the parsing of the document, table of contents information was generated (see the 'Enable Table of Contents Extraction' option in the General method). This allows the large model to return table of contents items relevant to the user's query, thereby using these items to retrieve related chunks and apply weighting to these chunks during the sorting process. This approach is derived from mimicking the behavioral logic of how humans search for knowledge in books.`,
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
|
deleteModel: 'Delete model',
|
||||||
modelEmptyTip:
|
modelEmptyTip:
|
||||||
'No models available. Please add models from the panel on the right.',
|
'No models available. <br>Please add models from the panel on the right.',
|
||||||
sourceEmptyTip: 'No data sources added yet. Select one below to connect.',
|
sourceEmptyTip: 'No data sources added yet. Select one below to connect.',
|
||||||
seconds: 'seconds',
|
seconds: 'seconds',
|
||||||
minutes: 'minutes',
|
minutes: 'minutes',
|
||||||
@ -1917,6 +1920,7 @@ Important structured information may include: names, dates, locations, events, k
|
|||||||
editMCP: 'Edit MCP',
|
editMCP: 'Edit MCP',
|
||||||
toolsAvailable: 'tools available',
|
toolsAvailable: 'tools available',
|
||||||
mcpServers: 'MCP servers',
|
mcpServers: 'MCP servers',
|
||||||
|
mcpServer: 'MCP server',
|
||||||
customizeTheListOfMcpServers: 'Customize the list of MCP servers',
|
customizeTheListOfMcpServers: 'Customize the list of MCP servers',
|
||||||
cachedTools: 'cached tools',
|
cachedTools: 'cached tools',
|
||||||
bulkManage: 'Bulk manage',
|
bulkManage: 'Bulk manage',
|
||||||
@ -2014,6 +2018,18 @@ Important structured information may include: names, dates, locations, events, k
|
|||||||
processingFailedTip: 'Total failed processes',
|
processingFailedTip: 'Total failed processes',
|
||||||
processing: 'Processing',
|
processing: 'Processing',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteModal: {
|
||||||
|
delAgent: 'Delete agent',
|
||||||
|
delDataset: 'Delete dataset',
|
||||||
|
delSearch: 'Delete search',
|
||||||
|
delFile: 'Delete file',
|
||||||
|
delFiles: 'Delete files',
|
||||||
|
delFilesContent: 'Selected {{count}} files',
|
||||||
|
delChat: 'Delete chat',
|
||||||
|
delMember: 'Delete member',
|
||||||
|
},
|
||||||
|
|
||||||
admin: {
|
admin: {
|
||||||
loginTitle: 'Admin Console',
|
loginTitle: 'Admin Console',
|
||||||
title: 'RAGFlow',
|
title: 'RAGFlow',
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export default {
|
|||||||
selectAll: '全选',
|
selectAll: '全选',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
deleteModalTitle: '确定删除吗?',
|
deleteModalTitle: '确定删除吗?',
|
||||||
|
deleteThem: '确定要删除吗?',
|
||||||
ok: '确认',
|
ok: '确认',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
@ -51,6 +52,7 @@ export default {
|
|||||||
noDataFound: '没有找到数据。',
|
noDataFound: '没有找到数据。',
|
||||||
noData: '暂无数据',
|
noData: '暂无数据',
|
||||||
promptPlaceholder: '请输入或使用 / 快速插入变量。',
|
promptPlaceholder: '请输入或使用 / 快速插入变量。',
|
||||||
|
selected: '已选择',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
loginTitle: '登录账户',
|
loginTitle: '登录账户',
|
||||||
@ -685,7 +687,8 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
tocEnhanceTip: `解析文档时生成了目录信息(见General方法的‘启用目录抽取’),让大模型返回和用户问题相关的目录项,从而利用目录项拿到相关chunk,对这些chunk在排序中进行加权。这种方法来源于模仿人类查询书本中知识的行为逻辑`,
|
tocEnhanceTip: `解析文档时生成了目录信息(见General方法的‘启用目录抽取’),让大模型返回和用户问题相关的目录项,从而利用目录项拿到相关chunk,对这些chunk在排序中进行加权。这种方法来源于模仿人类查询书本中知识的行为逻辑`,
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
modelEmptyTip: '暂无可用模型,请先在右侧面板添加模型。',
|
deleteModel: '删除模型',
|
||||||
|
modelEmptyTip: '暂无可用模型,<br>请先在右侧面板添加模型。',
|
||||||
sourceEmptyTip: '暂未添加任何数据源,请从下方选择一个进行连接。',
|
sourceEmptyTip: '暂未添加任何数据源,请从下方选择一个进行连接。',
|
||||||
seconds: '秒',
|
seconds: '秒',
|
||||||
minutes: '分',
|
minutes: '分',
|
||||||
@ -1770,6 +1773,7 @@ Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
|
|||||||
editMCP: '编辑 MCP',
|
editMCP: '编辑 MCP',
|
||||||
toolsAvailable: '可用的工具',
|
toolsAvailable: '可用的工具',
|
||||||
mcpServers: 'MCP 服务器',
|
mcpServers: 'MCP 服务器',
|
||||||
|
mcpServer: 'MCP 服务器',
|
||||||
customizeTheListOfMcpServers: '自定义 MCP 服务器列表',
|
customizeTheListOfMcpServers: '自定义 MCP 服务器列表',
|
||||||
cachedTools: '缓存工具',
|
cachedTools: '缓存工具',
|
||||||
selected: '已选择',
|
selected: '已选择',
|
||||||
@ -1866,5 +1870,16 @@ Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
|
|||||||
processingSuccessTip: '处理成功的文件总数',
|
processingSuccessTip: '处理成功的文件总数',
|
||||||
processingFailedTip: '处理失败的文件总数',
|
processingFailedTip: '处理失败的文件总数',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteModal: {
|
||||||
|
delAgent: '删除智能体',
|
||||||
|
delDataset: '删除知识库',
|
||||||
|
delSearch: '删除搜索',
|
||||||
|
delFile: '删除文件',
|
||||||
|
delFiles: '删除文件',
|
||||||
|
delFilesContent: '已选择 {{count}} 个文件',
|
||||||
|
delChat: '删除聊天',
|
||||||
|
delMember: '删除成员',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -45,7 +48,18 @@ export function AgentDropdown({
|
|||||||
{t('common.rename')} <PenLine />
|
{t('common.rename')} <PenLine />
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('deleteModal.delAgent')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
avatar={{ avatar: agent.avatar, name: agent.title }}
|
||||||
|
name={agent.title}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-state-error"
|
className="text-state-error"
|
||||||
onSelect={(e) => {
|
onSelect={(e) => {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import isEmpty from 'lodash/isEmpty';
|
|||||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import { buildNodesAndCombos } from './util';
|
import { buildNodesAndCombos } from './util';
|
||||||
|
|
||||||
|
import { useIsDarkTheme } from '@/components/theme-provider';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
const TooltipColorMap = {
|
const TooltipColorMap = {
|
||||||
@ -19,7 +20,7 @@ interface IProps {
|
|||||||
const ForceGraph = ({ data, show }: IProps) => {
|
const ForceGraph = ({ data, show }: IProps) => {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const graphRef = useRef<Graph | null>(null);
|
const graphRef = useRef<Graph | null>(null);
|
||||||
|
const isDark = useIsDarkTheme();
|
||||||
const nextData = useMemo(() => {
|
const nextData = useMemo(() => {
|
||||||
if (!isEmpty(data)) {
|
if (!isEmpty(data)) {
|
||||||
const graphData = data;
|
const graphData = data;
|
||||||
@ -80,8 +81,13 @@ const ForceGraph = ({ data, show }: IProps) => {
|
|||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
style: {
|
style: {
|
||||||
size: 150,
|
size: (d) => {
|
||||||
|
let size = 100 + ((d.rank as number) || 0) * 5;
|
||||||
|
size = size > 300 ? 300 : size;
|
||||||
|
return size;
|
||||||
|
},
|
||||||
labelText: (d) => d.id,
|
labelText: (d) => d.id,
|
||||||
|
labelFill: isDark ? 'rgba(255,255,255,1)' : 'rgba(0,0,0,1)',
|
||||||
// labelPadding: 30,
|
// labelPadding: 30,
|
||||||
labelFontSize: 40,
|
labelFontSize: 40,
|
||||||
// labelOffsetX: 20,
|
// labelOffsetX: 20,
|
||||||
@ -101,8 +107,9 @@ const ForceGraph = ({ data, show }: IProps) => {
|
|||||||
const weight: number = Number(model?.weight) || 2;
|
const weight: number = Number(model?.weight) || 2;
|
||||||
const lineWeight = weight * 4;
|
const lineWeight = weight * 4;
|
||||||
return {
|
return {
|
||||||
stroke: '#99ADD1',
|
stroke: isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.5)',
|
||||||
lineWidth: lineWeight > 10 ? 10 : lineWeight,
|
lineDash: [10, 10],
|
||||||
|
lineWidth: lineWeight > 8 ? 8 : lineWeight,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -45,7 +48,18 @@ export function DatasetDropdown({
|
|||||||
{t('common.rename')} <PenLine />
|
{t('common.rename')} <PenLine />
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('deleteModal.delDataset')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
avatar={{ avatar: dataset.avatar, name: dataset.name }}
|
||||||
|
name={dataset.name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-state-error"
|
className="text-state-error"
|
||||||
onSelect={(e) => {
|
onSelect={(e) => {
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
|
import { FileIcon } from '@/components/icon-font';
|
||||||
import NewDocumentLink from '@/components/new-document-link';
|
import NewDocumentLink from '@/components/new-document-link';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useDownloadFile } from '@/hooks/file-manager-hooks';
|
import { useDownloadFile } from '@/hooks/file-manager-hooks';
|
||||||
import { IFile } from '@/interfaces/database/file-manager';
|
import { IFile } from '@/interfaces/database/file-manager';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import {
|
import {
|
||||||
getExtension,
|
getExtension,
|
||||||
isSupportedPreviewDocumentType,
|
isSupportedPreviewDocumentType,
|
||||||
} from '@/utils/document-util';
|
} from '@/utils/document-util';
|
||||||
import { CellContext } from '@tanstack/react-table';
|
import { CellContext } from '@tanstack/react-table';
|
||||||
|
import { t } from 'i18next';
|
||||||
import {
|
import {
|
||||||
ArrowDownToLine,
|
ArrowDownToLine,
|
||||||
Eye,
|
Eye,
|
||||||
@ -38,6 +44,9 @@ export function ActionCell({
|
|||||||
}: IProps) {
|
}: IProps) {
|
||||||
const record = row.original;
|
const record = row.original;
|
||||||
const documentId = record.id;
|
const documentId = record.id;
|
||||||
|
const name: string = row.getValue('name');
|
||||||
|
const type = record.type;
|
||||||
|
|
||||||
const { downloadFile } = useDownloadFile();
|
const { downloadFile } = useDownloadFile();
|
||||||
const isFolder = isFolderType(record.type);
|
const isFolder = isFolderType(record.type);
|
||||||
const extension = getExtension(record.name);
|
const extension = getExtension(record.name);
|
||||||
@ -151,7 +160,28 @@ export function ActionCell({
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu> */}
|
</DropdownMenu> */}
|
||||||
{isKnowledgeBase || (
|
{isKnowledgeBase || (
|
||||||
<ConfirmDeleteDialog onOk={onRemoveFile}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={onRemoveFile}
|
||||||
|
title={t('deleteModal.delFile')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode>
|
||||||
|
<div className="flex items-center gap-2 text-text-secondary">
|
||||||
|
<span className="size-4">
|
||||||
|
<FileIcon name={name} type={type}></FileIcon>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className={cn('truncate text-xs', {
|
||||||
|
['cursor-pointer']: isFolder,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
className="border-none hover:bg-bg-card text-text-primary"
|
className="border-none hover:bg-bg-card text-text-primary"
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -45,7 +48,18 @@ export function ChatDropdown({
|
|||||||
{t('common.rename')} <PenLine />
|
{t('common.rename')} <PenLine />
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('deleteModal.delChat')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
avatar={{ avatar: chat.icon, name: chat.name }}
|
||||||
|
name={chat.name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-state-error"
|
className="text-state-error"
|
||||||
onSelect={(e) => {
|
onSelect={(e) => {
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -41,9 +44,20 @@ export function SearchDropdown({
|
|||||||
{t('common.rename')} <PenLine />
|
{t('common.rename')} <PenLine />
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('deleteModal.delSearch')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
avatar={{ avatar: dataset.avatar, name: dataset.name }}
|
||||||
|
name={dataset.name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-text-delete-red"
|
className="text-state-error"
|
||||||
onSelect={(e) => {
|
onSelect={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export const AddedSourceCard = (props: IAddedSourceCardProps) => {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
className="flex flex-row items-center justify-between rounded-md bg-bg-card px-[10px] py-4"
|
className="flex flex-row items-center justify-between rounded-md bg-bg-card px-[10px] py-4"
|
||||||
>
|
>
|
||||||
<div className="text-sm text-text-secondary ">{item.name}</div>
|
<div className="text-sm text-text-primary ">{item.name}</div>
|
||||||
<div className="text-sm text-text-secondary flex gap-2">
|
<div className="text-sm text-text-secondary flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
|
|||||||
@ -21,28 +21,33 @@ export const delSourceModal = <T extends IDataSourceBase>(
|
|||||||
? t('setting.deleteSourceModalTitle')
|
? t('setting.deleteSourceModalTitle')
|
||||||
: t('dataflowParser.unlinkSourceModalTitle'),
|
: t('dataflowParser.unlinkSourceModalTitle'),
|
||||||
content: (
|
content: (
|
||||||
<div className="px-2 py-6">
|
<div className="px-2 space-y-6 pt-5 pb-3">
|
||||||
<div className="flex items-center gap-1 p-2 border border-border-button rounded-md mb-3">
|
|
||||||
<div className="w-6 h-6 flex-shrink-0">
|
|
||||||
{data?.source ? DataSourceInfo[data?.source].icon : ''}
|
|
||||||
</div>
|
|
||||||
<div>{data?.name}</div>
|
|
||||||
</div>
|
|
||||||
{type === 'delete' ? (
|
{type === 'delete' ? (
|
||||||
<div
|
<div
|
||||||
className="text-sm text-text-secondary"
|
className="text-base text-text-primary"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('setting.deleteSourceModalContent'),
|
__html: t('setting.deleteSourceModalContent'),
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className="text-sm text-text-secondary"
|
className="text-base text-text-primary"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('dataflowParser.unlinkSourceModalContent'),
|
__html: t('dataflowParser.unlinkSourceModalContent'),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<div className="flex items-center gap-1 p-2 border border-border-button rounded-md mb-3">
|
||||||
|
<div className="w-6 h-6 flex-shrink-0">
|
||||||
|
{data?.source ? DataSourceInfo[data?.source].icon : ''}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-text-secondary text-xs">
|
||||||
|
{/* <div className="h-6 flex-shrink-0 text-text-primary text-base">
|
||||||
|
{data?.source ? DataSourceInfo[data?.source].name : ''}
|
||||||
|
</div> */}
|
||||||
|
{data?.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
confirmText:
|
confirmText:
|
||||||
@ -56,12 +61,13 @@ export const delSourceModal = <T extends IDataSourceBase>(
|
|||||||
...otherProps,
|
...otherProps,
|
||||||
title: config.title,
|
title: config.title,
|
||||||
children: config.content,
|
children: config.content,
|
||||||
|
titleClassName: 'border-b border-border-button',
|
||||||
onVisibleChange: () => {
|
onVisibleChange: () => {
|
||||||
Modal.hide();
|
Modal.destroy();
|
||||||
},
|
},
|
||||||
footer: (
|
footer: (
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<Button variant={'outline'} onClick={() => Modal.hide()}>
|
<Button variant={'outline'} onClick={() => Modal.destroy()}>
|
||||||
{t('dataflowParser.changeStepModalCancelText')}
|
{t('dataflowParser.changeStepModalCancelText')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -69,7 +75,7 @@ export const delSourceModal = <T extends IDataSourceBase>(
|
|||||||
className="!bg-state-error text-text-base"
|
className="!bg-state-error text-text-base"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onOk?.(data);
|
onOk?.(data);
|
||||||
Modal.hide();
|
Modal.destroy();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{config.confirmText}
|
{config.confirmText}
|
||||||
|
|||||||
@ -84,7 +84,7 @@ const DataSource = () => {
|
|||||||
>
|
>
|
||||||
<Spotlight />
|
<Spotlight />
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className=" flex flex-col gap-4 max-h-[calc(100vh-230px)] overflow-y-auto overflow-x-hidden scrollbar-auto">
|
<div className=" flex flex-col gap-4 max-h-[calc(100vh-235px)] overflow-y-auto overflow-x-hidden scrollbar-auto">
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
{categorizedList?.length <= 0 && (
|
{categorizedList?.length <= 0 && (
|
||||||
<div className="text-text-secondary w-full flex justify-center items-center h-20">
|
<div className="text-text-secondary w-full flex justify-center items-center h-20">
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import { CardContainer } from '@/components/card-container';
|
import { CardContainer } from '@/components/card-container';
|
||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import Spotlight from '@/components/spotlight';
|
import Spotlight from '@/components/spotlight';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
@ -110,7 +113,18 @@ export default function McpServer() {
|
|||||||
<Upload className="size-3.5"></Upload>
|
<Upload className="size-3.5"></Upload>
|
||||||
{t('mcp.export')}
|
{t('mcp.export')}
|
||||||
</Button>
|
</Button>
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('common.delete') + ' ' + t('mcp.mcpServers')}
|
||||||
|
content={{
|
||||||
|
title: t('common.deleteThem'),
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
name={`${t('mcp.selected')} ${selectedList.length} ${t('mcp.mcpServers')}`}
|
||||||
|
></ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Button variant={'danger'}>
|
<Button variant={'danger'}>
|
||||||
<Trash2 className="size-3.5 cursor-pointer" />
|
<Trash2 className="size-3.5 cursor-pointer" />
|
||||||
{t('common.delete')}
|
{t('common.delete')}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export function McpCard({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<McpOperation
|
<McpOperation
|
||||||
mcpId={data.id}
|
mcp={data}
|
||||||
showEditModal={showEditModal}
|
showEditModal={showEditModal}
|
||||||
></McpOperation>
|
></McpOperation>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import { useDeleteMcpServer } from '@/hooks/use-mcp-request';
|
import { useDeleteMcpServer } from '@/hooks/use-mcp-request';
|
||||||
|
import { IMcpServer } from '@/interfaces/database/mcp';
|
||||||
import { PenLine, Trash2, Upload } from 'lucide-react';
|
import { PenLine, Trash2, Upload } from 'lucide-react';
|
||||||
import { MouseEventHandler, useCallback } from 'react';
|
import { MouseEventHandler, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -7,33 +11,41 @@ import { UseEditMcpReturnType } from './use-edit-mcp';
|
|||||||
import { useExportMcp } from './use-export-mcp';
|
import { useExportMcp } from './use-export-mcp';
|
||||||
|
|
||||||
export function McpOperation({
|
export function McpOperation({
|
||||||
mcpId,
|
mcp,
|
||||||
showEditModal,
|
showEditModal,
|
||||||
}: { mcpId: string } & Pick<UseEditMcpReturnType, 'showEditModal'>) {
|
}: { mcp: IMcpServer } & Pick<UseEditMcpReturnType, 'showEditModal'>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { deleteMcpServer } = useDeleteMcpServer();
|
const { deleteMcpServer } = useDeleteMcpServer();
|
||||||
const { handleExportMcpJson } = useExportMcp();
|
const { handleExportMcpJson } = useExportMcp();
|
||||||
|
|
||||||
const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => {
|
const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => {
|
||||||
deleteMcpServer([mcpId]);
|
deleteMcpServer([mcp.id]);
|
||||||
}, [deleteMcpServer, mcpId]);
|
}, [deleteMcpServer, mcp.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="hidden gap-1 group-hover:flex text-text-secondary">
|
<div className="hidden gap-1 group-hover:flex text-text-secondary">
|
||||||
{/* <RAGFlowTooltip tooltip={t('mcp.export')}> */}
|
{/* <RAGFlowTooltip tooltip={t('mcp.export')}> */}
|
||||||
<Upload
|
<Upload
|
||||||
className="size-5 cursor-pointer p-1 rounded-sm hover:text-text-primary hover:bg-bg-card"
|
className="size-5 cursor-pointer p-1 rounded-sm hover:text-text-primary hover:bg-bg-card"
|
||||||
onClick={handleExportMcpJson([mcpId])}
|
onClick={handleExportMcpJson([mcp.id])}
|
||||||
/>
|
/>
|
||||||
{/* </RAGFlowTooltip>
|
{/* </RAGFlowTooltip>
|
||||||
<RAGFlowTooltip tooltip={t('common.edit')}> */}
|
<RAGFlowTooltip tooltip={t('common.edit')}> */}
|
||||||
<PenLine
|
<PenLine
|
||||||
className="size-5 cursor-pointer p-1 rounded-sm hover:text-text-primary hover:bg-bg-card"
|
className="size-5 cursor-pointer p-1 rounded-sm hover:text-text-primary hover:bg-bg-card"
|
||||||
onClick={showEditModal(mcpId)}
|
onClick={showEditModal(mcp.id)}
|
||||||
/>
|
/>
|
||||||
{/* </RAGFlowTooltip>
|
{/* </RAGFlowTooltip>
|
||||||
<RAGFlowTooltip tooltip={t('common.delete')}> */}
|
<RAGFlowTooltip tooltip={t('common.delete')}> */}
|
||||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
<ConfirmDeleteDialog
|
||||||
|
onOk={handleDelete}
|
||||||
|
title={t('common.delete') + ' ' + t('mcp.mcpServer')}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode name={mcp.name}></ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Trash2 className="size-5 cursor-pointer p-1 rounded-sm hover:text-state-error hover:bg-state-error-5" />
|
<Trash2 className="size-5 cursor-pointer p-1 rounded-sm hover:text-state-error hover:bg-state-error-5" />
|
||||||
</ConfirmDeleteDialog>
|
</ConfirmDeleteDialog>
|
||||||
{/* </RAGFlowTooltip> */}
|
{/* </RAGFlowTooltip> */}
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
// src/components/ModelProviderCard.tsx
|
// src/components/ModelProviderCard.tsx
|
||||||
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import { LlmIcon } from '@/components/svg-icon';
|
import { LlmIcon } from '@/components/svg-icon';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
@ -54,7 +58,7 @@ export const ModelProviderCard: FC<IModelCardProps> = ({
|
|||||||
const { visible, switchVisible } = useSetModalState();
|
const { visible, switchVisible } = useSetModalState();
|
||||||
const { t } = useTranslate('setting');
|
const { t } = useTranslate('setting');
|
||||||
const { handleEnableLlm } = useHandleEnableLlm(item.name);
|
const { handleEnableLlm } = useHandleEnableLlm(item.name);
|
||||||
const { handleDeleteFactory } = useHandleDeleteFactory(item.name);
|
const { deleteFactory } = useHandleDeleteFactory(item.name);
|
||||||
|
|
||||||
const handleApiKeyClick = () => {
|
const handleApiKeyClick = () => {
|
||||||
clickApiKey(item.name);
|
clickApiKey(item.name);
|
||||||
@ -102,16 +106,31 @@ export const ModelProviderCard: FC<IModelCardProps> = ({
|
|||||||
{!visible ? <ChevronsDown /> : <ChevronsUp />}
|
{!visible ? <ChevronsDown /> : <ChevronsUp />}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<ConfirmDeleteDialog
|
||||||
variant={'ghost'}
|
onOk={() => deleteFactory({ llm_factory: item.name })}
|
||||||
onClick={(e) => {
|
title={t('deleteModel')}
|
||||||
e.stopPropagation();
|
content={{
|
||||||
handleDeleteFactory();
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<LlmIcon name={item.name} />
|
||||||
|
{item.name}
|
||||||
|
</div>
|
||||||
|
</ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
className=" hover:text-state-error hover:bg-state-error-5 transition-colors border border-border-default"
|
|
||||||
>
|
>
|
||||||
<Trash2 />
|
<Button
|
||||||
</Button>
|
variant={'ghost'}
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.stopPropagation();
|
||||||
|
// handleDeleteFactory(item);
|
||||||
|
// }}
|
||||||
|
className=" hover:text-state-error hover:bg-state-error-5 transition-colors border border-border-default"
|
||||||
|
>
|
||||||
|
<Trash2 />
|
||||||
|
</Button>
|
||||||
|
</ConfirmDeleteDialog>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
// src/components/AvailableModels.tsx
|
// src/components/AvailableModels.tsx
|
||||||
import { LlmIcon } from '@/components/svg-icon';
|
import { LlmIcon } from '@/components/svg-icon';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { SearchInput } from '@/components/ui/input';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import { useSelectLlmList } from '@/hooks/llm-hooks';
|
import { useSelectLlmList } from '@/hooks/llm-hooks';
|
||||||
import { Plus, Search } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
import { FC, useMemo, useState } from 'react';
|
import { FC, useMemo, useState } from 'react';
|
||||||
|
|
||||||
type TagType =
|
type TagType =
|
||||||
@ -77,16 +77,16 @@ export const AvailableModels: FC<{
|
|||||||
</div>
|
</div>
|
||||||
{/* Search Bar */}
|
{/* Search Bar */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="relative">
|
{/* <div className="relative"> */}
|
||||||
<Input
|
<SearchInput
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={t('search')}
|
placeholder={t('search')}
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
className="w-full px-4 py-2 pl-10 bg-bg-input border border-border-default rounded-lg focus:outline-none focus:ring-1 focus:ring-border-button transition-colors"
|
className="w-full px-4 py-2 pl-10 bg-bg-input border border-border-default rounded-lg focus:outline-none focus:ring-1 focus:ring-border-button transition-colors"
|
||||||
/>
|
/>
|
||||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-text-secondary" />
|
{/* <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-text-secondary" /> */}
|
||||||
</div>
|
{/* </div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tags Filter */}
|
{/* Tags Filter */}
|
||||||
|
|||||||
@ -457,5 +457,5 @@ export const useHandleDeleteFactory = (llmFactory: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return { handleDeleteFactory };
|
return { handleDeleteFactory, deleteFactory };
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ export const useHandleDeleteUser = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return { handleDeleteTenantUser, loading };
|
return { handleDeleteTenantUser, deleteTenantUser, loading };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHandleAgreeTenant = () => {
|
export const useHandleAgreeTenant = () => {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
ConfirmDeleteDialog,
|
||||||
|
ConfirmDeleteDialogNode,
|
||||||
|
} from '@/components/confirm-delete-dialog';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@ -26,7 +30,7 @@ const ColorMap: Record<string, string> = {
|
|||||||
|
|
||||||
const UserTable = ({ searchUser }: { searchUser: string }) => {
|
const UserTable = ({ searchUser }: { searchUser: string }) => {
|
||||||
const { data, loading } = useListTenantUser();
|
const { data, loading } = useListTenantUser();
|
||||||
const { handleDeleteTenantUser } = useHandleDeleteUser();
|
const { deleteTenantUser } = useHandleDeleteUser();
|
||||||
const [sortOrder, setSortOrder] = useState<'asc' | 'desc' | null>(null);
|
const [sortOrder, setSortOrder] = useState<'asc' | 'desc' | null>(null);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const sortedData = useMemo(() => {
|
const sortedData = useMemo(() => {
|
||||||
@ -134,14 +138,35 @@ const UserTable = ({ searchUser }: { searchUser: string }) => {
|
|||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="p-4">
|
<TableCell className="p-4">
|
||||||
<Button
|
<ConfirmDeleteDialog
|
||||||
variant="ghost"
|
title={t('deleteModal.delMember')}
|
||||||
size="icon"
|
onOk={async () => {
|
||||||
className="h-8 w-8 p-0 hover:bg-state-error-5 hover:text-state-error"
|
await deleteTenantUser({
|
||||||
onClick={handleDeleteTenantUser(record.user_id)}
|
userId: record.user_id,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
content={{
|
||||||
|
node: (
|
||||||
|
<ConfirmDeleteDialogNode
|
||||||
|
avatar={{
|
||||||
|
avatar: record.avatar,
|
||||||
|
name: record.nickname,
|
||||||
|
isPerson: true,
|
||||||
|
}}
|
||||||
|
name={record.email}
|
||||||
|
></ConfirmDeleteDialogNode>
|
||||||
|
),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Trash2 className="h-4 w-4" />
|
<Button
|
||||||
</Button>
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-8 w-8 p-0 hover:bg-state-error-5 hover:text-state-error"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</ConfirmDeleteDialog>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in New Issue
Block a user