mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Delete useless files from the data pipeline #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,58 +0,0 @@
|
||||
import OperateDropdown from '@/components/operate-dropdown';
|
||||
import { CopyOutlined } from '@ant-design/icons';
|
||||
import { Flex, MenuProps } from 'antd';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Operator } from '../../constant';
|
||||
import { useDuplicateNode } from '../../hooks';
|
||||
import useGraphStore from '../../store';
|
||||
|
||||
interface IProps {
|
||||
id: string;
|
||||
iconFontColor?: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const NodeDropdown = ({ id, iconFontColor, label }: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
const deleteNodeById = useGraphStore((store) => store.deleteNodeById);
|
||||
const deleteIterationNodeById = useGraphStore(
|
||||
(store) => store.deleteIterationNodeById,
|
||||
);
|
||||
|
||||
const deleteNode = useCallback(() => {
|
||||
if (label === Operator.Iteration) {
|
||||
deleteIterationNodeById(id);
|
||||
} else {
|
||||
deleteNodeById(id);
|
||||
}
|
||||
}, [label, deleteIterationNodeById, id, deleteNodeById]);
|
||||
|
||||
const duplicateNode = useDuplicateNode();
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: '2',
|
||||
onClick: () => duplicateNode(id, label),
|
||||
label: (
|
||||
<Flex justify={'space-between'}>
|
||||
{t('common.copy')}
|
||||
<CopyOutlined />
|
||||
</Flex>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<OperateDropdown
|
||||
iconFontSize={22}
|
||||
height={14}
|
||||
deleteItem={deleteNode}
|
||||
items={items}
|
||||
needsDeletionValidation={false}
|
||||
iconFontColor={iconFontColor}
|
||||
></OperateDropdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default NodeDropdown;
|
||||
@ -1,121 +0,0 @@
|
||||
import get from 'lodash/get';
|
||||
import React, { MouseEventHandler, useCallback, useMemo } from 'react';
|
||||
import JsonView from 'react18-json-view';
|
||||
import 'react18-json-view/src/style.css';
|
||||
import { useReplaceIdWithText } from '../../hooks';
|
||||
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/components/ui/popover';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useFetchAgent } from '@/hooks/use-agent-request';
|
||||
import { useGetComponentLabelByValue } from '../../hooks/use-get-begin-query';
|
||||
|
||||
interface IProps extends React.PropsWithChildren {
|
||||
nodeId: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export function NextNodePopover({ children, nodeId, name }: IProps) {
|
||||
const { t } = useTranslate('flow');
|
||||
|
||||
const { data } = useFetchAgent();
|
||||
const { theme } = useTheme();
|
||||
const component = useMemo(() => {
|
||||
return get(data, ['dsl', 'components', nodeId], {});
|
||||
}, [nodeId, data]);
|
||||
|
||||
const inputs: Array<{ component_id: string; content: string }> = get(
|
||||
component,
|
||||
['obj', 'inputs'],
|
||||
[],
|
||||
);
|
||||
const output = get(component, ['obj', 'output'], {});
|
||||
const { replacedOutput } = useReplaceIdWithText(output);
|
||||
const stopPropagation: MouseEventHandler = useCallback((e) => {
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
const getLabel = useGetComponentLabelByValue(nodeId);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger onClick={stopPropagation} asChild>
|
||||
{children}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
align={'start'}
|
||||
side={'right'}
|
||||
sideOffset={20}
|
||||
onClick={stopPropagation}
|
||||
className="w-[400px]"
|
||||
>
|
||||
<div className="mb-3 font-semibold text-[16px]">
|
||||
{name} {t('operationResults')}
|
||||
</div>
|
||||
<div className="flex w-full gap-4 flex-col">
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
<span className="font-semibold text-[14px]">{t('input')}</span>
|
||||
<div
|
||||
style={
|
||||
theme === 'dark'
|
||||
? {
|
||||
backgroundColor: 'rgba(150, 150, 150, 0.2)',
|
||||
}
|
||||
: {}
|
||||
}
|
||||
className={`bg-gray-100 p-1 rounded`}
|
||||
>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>{t('componentId')}</TableHead>
|
||||
<TableHead className="w-[60px]">{t('content')}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{inputs.map((x, idx) => (
|
||||
<TableRow key={idx}>
|
||||
<TableCell>{getLabel(x.component_id)}</TableCell>
|
||||
<TableCell className="truncate">{x.content}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
<span className="font-semibold text-[14px]">{t('output')}</span>
|
||||
<div
|
||||
style={
|
||||
theme === 'dark'
|
||||
? {
|
||||
backgroundColor: 'rgba(150, 150, 150, 0.2)',
|
||||
}
|
||||
: {}
|
||||
}
|
||||
className="bg-gray-100 p-1 rounded"
|
||||
>
|
||||
<JsonView
|
||||
src={replacedOutput}
|
||||
displaySize={30}
|
||||
className="w-full max-h-[300px] break-words overflow-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@ -2,8 +2,7 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { HandleType, Position } from '@xyflow/react';
|
||||
import { createContext } from 'react';
|
||||
import { useAddNode } from './hooks/use-add-node';
|
||||
import { useCacheChatLog } from './hooks/use-cache-chat-log';
|
||||
import { useShowFormDrawer, useShowLogSheet } from './hooks/use-show-drawer';
|
||||
import { useShowFormDrawer } from './hooks/use-show-drawer';
|
||||
|
||||
export const AgentFormContext = createContext<RAGFlowNodeType | undefined>(
|
||||
undefined,
|
||||
@ -19,24 +18,6 @@ export const AgentInstanceContext = createContext<AgentInstanceContextType>(
|
||||
{} as AgentInstanceContextType,
|
||||
);
|
||||
|
||||
type AgentChatContextType = Pick<
|
||||
ReturnType<typeof useShowLogSheet>,
|
||||
'showLogSheet'
|
||||
> & { setLastSendLoadingFunc: (loading: boolean, messageId: string) => void };
|
||||
|
||||
export const AgentChatContext = createContext<AgentChatContextType>(
|
||||
{} as AgentChatContextType,
|
||||
);
|
||||
|
||||
type AgentChatLogContextType = Pick<
|
||||
ReturnType<typeof useCacheChatLog>,
|
||||
'addEventList' | 'setCurrentMessageId'
|
||||
>;
|
||||
|
||||
export const AgentChatLogContext = createContext<AgentChatLogContextType>(
|
||||
{} as AgentChatLogContextType,
|
||||
);
|
||||
|
||||
export type HandleContextType = {
|
||||
nodeId?: string;
|
||||
id?: string;
|
||||
|
||||
@ -1,260 +0,0 @@
|
||||
import { ButtonLoading } from '@/components/ui/button';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { RAGFlowSelect } from '@/components/ui/select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { IMessage } from '@/pages/chat/interface';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import React, { ReactNode, useCallback, useMemo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
import { BeginQueryType } from '../constant';
|
||||
import { BeginQuery } from '../interface';
|
||||
import { FileUploadDirectUpload } from './uploader';
|
||||
|
||||
const StringFields = [
|
||||
BeginQueryType.Line,
|
||||
BeginQueryType.Paragraph,
|
||||
BeginQueryType.Options,
|
||||
];
|
||||
|
||||
interface IProps {
|
||||
parameters: BeginQuery[];
|
||||
message?: IMessage;
|
||||
ok(parameters: any[]): void;
|
||||
isNext?: boolean;
|
||||
loading?: boolean;
|
||||
submitButtonDisabled?: boolean;
|
||||
btnText?: ReactNode;
|
||||
}
|
||||
|
||||
const DebugContent = ({
|
||||
parameters,
|
||||
message,
|
||||
ok,
|
||||
isNext = true,
|
||||
loading = false,
|
||||
submitButtonDisabled = false,
|
||||
btnText,
|
||||
}: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchemaValues = useMemo(() => {
|
||||
const obj = parameters.reduce<{
|
||||
schema: Record<string, z.ZodType>;
|
||||
values: Record<string, any>;
|
||||
}>(
|
||||
(pre, cur, idx) => {
|
||||
const type = cur.type;
|
||||
let fieldSchema;
|
||||
let value;
|
||||
if (StringFields.some((x) => x === type)) {
|
||||
fieldSchema = z.string().trim().min(1);
|
||||
} else if (type === BeginQueryType.Boolean) {
|
||||
fieldSchema = z.boolean();
|
||||
value = false;
|
||||
} else if (type === BeginQueryType.Integer || type === 'float') {
|
||||
fieldSchema = z.coerce.number();
|
||||
} else {
|
||||
fieldSchema = z.record(z.any());
|
||||
}
|
||||
|
||||
if (cur.optional) {
|
||||
fieldSchema = fieldSchema.optional();
|
||||
}
|
||||
|
||||
const index = idx.toString();
|
||||
|
||||
pre.schema[index] = fieldSchema;
|
||||
pre.values[index] = value;
|
||||
|
||||
return pre;
|
||||
},
|
||||
{ schema: {}, values: {} },
|
||||
);
|
||||
|
||||
return { schema: z.object(obj.schema), values: obj.values };
|
||||
}, [parameters]);
|
||||
|
||||
const form = useForm<z.infer<typeof formSchemaValues.schema>>({
|
||||
defaultValues: formSchemaValues.values,
|
||||
resolver: zodResolver(formSchemaValues.schema),
|
||||
});
|
||||
|
||||
const submittable = true;
|
||||
|
||||
const renderWidget = useCallback(
|
||||
(q: BeginQuery, idx: string) => {
|
||||
const props = {
|
||||
key: idx,
|
||||
label: q.name ?? q.key,
|
||||
name: idx,
|
||||
};
|
||||
|
||||
const BeginQueryTypeMap = {
|
||||
[BeginQueryType.Line]: (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>{props.label}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field}></Input>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
[BeginQueryType.Paragraph]: (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>{props.label}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea rows={1} {...field}></Textarea>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
[BeginQueryType.Options]: (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>{props.label}</FormLabel>
|
||||
<FormControl>
|
||||
<RAGFlowSelect
|
||||
allowClear
|
||||
options={
|
||||
q.options?.map((x) => ({
|
||||
label: x,
|
||||
value: x as string,
|
||||
})) ?? []
|
||||
}
|
||||
{...field}
|
||||
></RAGFlowSelect>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
[BeginQueryType.File]: (
|
||||
<React.Fragment key={idx}>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<div className="space-y-6">
|
||||
<FormItem className="w-full">
|
||||
<FormLabel>{t('assistantAvatar')}</FormLabel>
|
||||
<FormControl>
|
||||
<FileUploadDirectUpload
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
></FileUploadDirectUpload>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</React.Fragment>
|
||||
),
|
||||
[BeginQueryType.Integer]: (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>{props.label}</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="number" {...field}></Input>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
[BeginQueryType.Boolean]: (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={props.name}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>{props.label}</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
BeginQueryTypeMap[q.type as BeginQueryType] ??
|
||||
BeginQueryTypeMap[BeginQueryType.Paragraph]
|
||||
);
|
||||
},
|
||||
[form, t],
|
||||
);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(values: z.infer<typeof formSchemaValues.schema>) => {
|
||||
const nextValues = Object.entries(values).map(([key, value]) => {
|
||||
const item = parameters[Number(key)];
|
||||
return { ...item, value };
|
||||
});
|
||||
|
||||
ok(nextValues);
|
||||
},
|
||||
[formSchemaValues, ok, parameters],
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<section>
|
||||
{message?.data?.tips && <div className="mb-2">{message.data.tips}</div>}
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
{parameters.map((x, idx) => {
|
||||
return <div key={idx}>{renderWidget(x, idx.toString())}</div>;
|
||||
})}
|
||||
<div>
|
||||
<ButtonLoading
|
||||
type="submit"
|
||||
loading={loading}
|
||||
disabled={!submittable || submitButtonDisabled}
|
||||
className="w-full mt-1"
|
||||
>
|
||||
{btnText || t(isNext ? 'common.next' : 'flow.run')}
|
||||
</ButtonLoading>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DebugContent;
|
||||
@ -1,103 +0,0 @@
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Popover, PopoverContent } from '@/components/ui/popover';
|
||||
import { useParseDocument } from '@/hooks/document-hooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
|
||||
const reg =
|
||||
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
|
||||
|
||||
const FormSchema = z.object({
|
||||
url: z.string(),
|
||||
result: z.any(),
|
||||
});
|
||||
|
||||
const values = {
|
||||
url: '',
|
||||
result: null,
|
||||
};
|
||||
|
||||
export const PopoverForm = ({
|
||||
children,
|
||||
visible,
|
||||
switchVisible,
|
||||
}: PropsWithChildren<IModalProps<any>>) => {
|
||||
const form = useForm({
|
||||
defaultValues: values,
|
||||
resolver: zodResolver(FormSchema),
|
||||
});
|
||||
const { parseDocument, loading } = useParseDocument();
|
||||
const { t } = useTranslation();
|
||||
|
||||
// useResetFormOnCloseModal({
|
||||
// form,
|
||||
// visible,
|
||||
// });
|
||||
|
||||
async function onSubmit(values: z.infer<typeof FormSchema>) {
|
||||
const val = values.url;
|
||||
|
||||
if (reg.test(val)) {
|
||||
const ret = await parseDocument(val);
|
||||
if (ret?.data?.code === 0) {
|
||||
form.setValue('result', ret?.data?.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const content = (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`url`}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
// onPressEnter={(e) => e.preventDefault()}
|
||||
placeholder={t('flow.pasteFileLink')}
|
||||
// suffix={
|
||||
// <Button
|
||||
// type="primary"
|
||||
// onClick={onOk}
|
||||
// size={'small'}
|
||||
// loading={loading}
|
||||
// >
|
||||
// {t('common.submit')}
|
||||
// </Button>
|
||||
// }
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`result`}
|
||||
render={() => <></>}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover open={visible} onOpenChange={switchVisible}>
|
||||
{children}
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
@ -1,116 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
FileUpload,
|
||||
FileUploadDropzone,
|
||||
FileUploadItem,
|
||||
FileUploadItemDelete,
|
||||
FileUploadItemMetadata,
|
||||
FileUploadItemPreview,
|
||||
FileUploadItemProgress,
|
||||
FileUploadList,
|
||||
FileUploadTrigger,
|
||||
type FileUploadProps,
|
||||
} from '@/components/file-upload';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useUploadCanvasFile } from '@/hooks/use-agent-request';
|
||||
import { Upload, X } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
type FileUploadDirectUploadProps = {
|
||||
value: Record<string, any>;
|
||||
onChange(value: Record<string, any>): void;
|
||||
};
|
||||
|
||||
export function FileUploadDirectUpload({
|
||||
onChange,
|
||||
}: FileUploadDirectUploadProps) {
|
||||
const [files, setFiles] = React.useState<File[]>([]);
|
||||
|
||||
const { uploadCanvasFile } = useUploadCanvasFile();
|
||||
|
||||
const onUpload: NonNullable<FileUploadProps['onUpload']> = React.useCallback(
|
||||
async (files, { onSuccess, onError }) => {
|
||||
try {
|
||||
const uploadPromises = files.map(async (file) => {
|
||||
const handleError = (error?: any) => {
|
||||
onError(
|
||||
file,
|
||||
error instanceof Error ? error : new Error('Upload failed'),
|
||||
);
|
||||
};
|
||||
try {
|
||||
const ret = await uploadCanvasFile([file]);
|
||||
if (ret.code === 0) {
|
||||
onSuccess(file);
|
||||
onChange(ret.data);
|
||||
} else {
|
||||
handleError();
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for all uploads to complete
|
||||
await Promise.all(uploadPromises);
|
||||
} catch (error) {
|
||||
// This handles any error that might occur outside the individual upload processes
|
||||
console.error('Unexpected error during upload:', error);
|
||||
}
|
||||
},
|
||||
[onChange, uploadCanvasFile],
|
||||
);
|
||||
|
||||
const onFileReject = React.useCallback((file: File, message: string) => {
|
||||
toast(message, {
|
||||
description: `"${file.name.length > 20 ? `${file.name.slice(0, 20)}...` : file.name}" has been rejected`,
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<FileUpload
|
||||
value={files}
|
||||
onValueChange={setFiles}
|
||||
onUpload={onUpload}
|
||||
onFileReject={onFileReject}
|
||||
maxFiles={1}
|
||||
className="w-full"
|
||||
multiple={false}
|
||||
>
|
||||
<FileUploadDropzone>
|
||||
<div className="flex flex-col items-center gap-1 text-center">
|
||||
<div className="flex items-center justify-center rounded-full border p-2.5">
|
||||
<Upload className="size-6 text-muted-foreground" />
|
||||
</div>
|
||||
<p className="font-medium text-sm">Drag & drop files here</p>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Or click to browse (max 2 files)
|
||||
</p>
|
||||
</div>
|
||||
<FileUploadTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="mt-2 w-fit">
|
||||
Browse files
|
||||
</Button>
|
||||
</FileUploadTrigger>
|
||||
</FileUploadDropzone>
|
||||
<FileUploadList>
|
||||
{files.map((file, index) => (
|
||||
<FileUploadItem key={index} value={file} className="flex-col">
|
||||
<div className="flex w-full items-center gap-2">
|
||||
<FileUploadItemPreview />
|
||||
<FileUploadItemMetadata />
|
||||
<FileUploadItemDelete asChild>
|
||||
<Button variant="ghost" size="icon" className="size-7">
|
||||
<X />
|
||||
</Button>
|
||||
</FileUploadItemDelete>
|
||||
</div>
|
||||
<FileUploadItemProgress />
|
||||
</FileUploadItem>
|
||||
))}
|
||||
</FileUploadList>
|
||||
</FileUpload>
|
||||
);
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Operator, RestrictedUpstreamMap } from './constant';
|
||||
import useGraphStore from './store';
|
||||
|
||||
export const useBuildFormSelectOptions = (
|
||||
operatorName: Operator,
|
||||
selfId?: string, // exclude the current node
|
||||
) => {
|
||||
const nodes = useGraphStore((state) => state.nodes);
|
||||
|
||||
const buildCategorizeToOptions = useCallback(
|
||||
(toList: string[]) => {
|
||||
const excludedNodes: Operator[] = [
|
||||
Operator.Note,
|
||||
...(RestrictedUpstreamMap[operatorName] ?? []),
|
||||
];
|
||||
return nodes
|
||||
.filter(
|
||||
(x) =>
|
||||
excludedNodes.every((y) => y !== x.data.label) &&
|
||||
x.id !== selfId &&
|
||||
!toList.some((y) => y === x.id), // filter out selected values in other to fields from the current drop-down box options
|
||||
)
|
||||
.map((x) => ({ label: x.data.name, value: x.id }));
|
||||
},
|
||||
[nodes, operatorName, selfId],
|
||||
);
|
||||
|
||||
return buildCategorizeToOptions;
|
||||
};
|
||||
|
||||
export const useBuildSortOptions = () => {
|
||||
const { t } = useTranslate('flow');
|
||||
|
||||
const options = useMemo(() => {
|
||||
return ['data', 'relevance'].map((x) => ({
|
||||
value: x,
|
||||
label: t(x),
|
||||
}));
|
||||
}, [t]);
|
||||
return options;
|
||||
};
|
||||
@ -1,12 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export function useOpenDocument() {
|
||||
const openDocument = useCallback(() => {
|
||||
window.open(
|
||||
'https://ragflow.io/docs/dev/category/agent-components',
|
||||
'_blank',
|
||||
);
|
||||
}, []);
|
||||
|
||||
return openDocument;
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
import { useFetchTokenListBeforeOtherStep } from '@/components/embed-dialog/use-show-embed-dialog';
|
||||
import { SharedFrom } from '@/constants/chat';
|
||||
import { useShowDeleteConfirm } from '@/hooks/common-hooks';
|
||||
import {
|
||||
useCreateSystemToken,
|
||||
useFetchSystemTokenList,
|
||||
useRemoveSystemToken,
|
||||
} from '@/hooks/user-setting-hooks';
|
||||
import { IStats } from '@/interfaces/database/chat';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const useOperateApiKey = (idKey: string, dialogId?: string) => {
|
||||
const { removeToken } = useRemoveSystemToken();
|
||||
const { createToken, loading: creatingLoading } = useCreateSystemToken();
|
||||
const { data: tokenList, loading: listLoading } = useFetchSystemTokenList();
|
||||
|
||||
const showDeleteConfirm = useShowDeleteConfirm();
|
||||
|
||||
const onRemoveToken = (token: string) => {
|
||||
showDeleteConfirm({
|
||||
onOk: () => removeToken(token),
|
||||
});
|
||||
};
|
||||
|
||||
const onCreateToken = useCallback(() => {
|
||||
createToken({ [idKey]: dialogId });
|
||||
}, [createToken, idKey, dialogId]);
|
||||
|
||||
return {
|
||||
removeToken: onRemoveToken,
|
||||
createToken: onCreateToken,
|
||||
tokenList,
|
||||
creatingLoading,
|
||||
listLoading,
|
||||
};
|
||||
};
|
||||
|
||||
type ChartStatsType = {
|
||||
[k in keyof IStats]: Array<{ xAxis: string; yAxis: number }>;
|
||||
};
|
||||
|
||||
export const useSelectChartStatsList = (): ChartStatsType => {
|
||||
const queryClient = useQueryClient();
|
||||
const data = queryClient.getQueriesData({ queryKey: ['fetchStats'] });
|
||||
const stats: IStats = (data.length > 0 ? data[0][1] : {}) as IStats;
|
||||
|
||||
return Object.keys(stats).reduce((pre, cur) => {
|
||||
const item = stats[cur as keyof IStats];
|
||||
if (item.length > 0) {
|
||||
pre[cur as keyof IStats] = item.map((x) => ({
|
||||
xAxis: x[0] as string,
|
||||
yAxis: x[1] as number,
|
||||
}));
|
||||
}
|
||||
return pre;
|
||||
}, {} as ChartStatsType);
|
||||
};
|
||||
|
||||
const getUrlWithToken = (token: string, from: string = 'chat') => {
|
||||
const { protocol, host } = window.location;
|
||||
return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
|
||||
};
|
||||
|
||||
export const usePreviewChat = (idKey: string) => {
|
||||
const { handleOperate } = useFetchTokenListBeforeOtherStep();
|
||||
|
||||
const open = useCallback(
|
||||
(t: string) => {
|
||||
window.open(
|
||||
getUrlWithToken(
|
||||
t,
|
||||
idKey === 'canvasId' ? SharedFrom.Agent : SharedFrom.Chat,
|
||||
),
|
||||
'_blank',
|
||||
);
|
||||
},
|
||||
[idKey],
|
||||
);
|
||||
|
||||
const handlePreview = useCallback(async () => {
|
||||
const token = await handleOperate();
|
||||
if (token) {
|
||||
open(token);
|
||||
}
|
||||
}, [handleOperate, open]);
|
||||
|
||||
return {
|
||||
handlePreview,
|
||||
};
|
||||
};
|
||||
@ -4,7 +4,6 @@ import get from 'lodash/get';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { BeginId, Operator } from '../constant';
|
||||
import useGraphStore from '../store';
|
||||
import { useCacheChatLog } from './use-cache-chat-log';
|
||||
import { useSaveGraph } from './use-save-graph';
|
||||
|
||||
export const useShowFormDrawer = () => {
|
||||
@ -135,26 +134,6 @@ export function useShowDrawer({
|
||||
};
|
||||
}
|
||||
|
||||
export function useShowLogSheet({
|
||||
setCurrentMessageId,
|
||||
}: Pick<ReturnType<typeof useCacheChatLog>, 'setCurrentMessageId'>) {
|
||||
const { visible, showModal, hideModal } = useSetModalState();
|
||||
|
||||
const handleShow = useCallback(
|
||||
(messageId: string) => {
|
||||
setCurrentMessageId(messageId);
|
||||
showModal();
|
||||
},
|
||||
[setCurrentMessageId, showModal],
|
||||
);
|
||||
|
||||
return {
|
||||
logSheetVisible: visible,
|
||||
hideLogSheet: hideModal,
|
||||
showLogSheet: handleShow,
|
||||
};
|
||||
}
|
||||
|
||||
export function useHideFormSheetOnNodeDeletion({
|
||||
hideFormDrawer,
|
||||
}: Pick<ReturnType<typeof useShowFormDrawer>, 'hideFormDrawer'>) {
|
||||
|
||||
Reference in New Issue
Block a user