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 { HandleType, Position } from '@xyflow/react';
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { useAddNode } from './hooks/use-add-node';
|
import { useAddNode } from './hooks/use-add-node';
|
||||||
import { useCacheChatLog } from './hooks/use-cache-chat-log';
|
import { useShowFormDrawer } from './hooks/use-show-drawer';
|
||||||
import { useShowFormDrawer, useShowLogSheet } from './hooks/use-show-drawer';
|
|
||||||
|
|
||||||
export const AgentFormContext = createContext<RAGFlowNodeType | undefined>(
|
export const AgentFormContext = createContext<RAGFlowNodeType | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
@ -19,24 +18,6 @@ export const AgentInstanceContext = createContext<AgentInstanceContextType>(
|
|||||||
{} as 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 = {
|
export type HandleContextType = {
|
||||||
nodeId?: string;
|
nodeId?: string;
|
||||||
id?: 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 React, { useCallback, useEffect } from 'react';
|
||||||
import { BeginId, Operator } from '../constant';
|
import { BeginId, Operator } from '../constant';
|
||||||
import useGraphStore from '../store';
|
import useGraphStore from '../store';
|
||||||
import { useCacheChatLog } from './use-cache-chat-log';
|
|
||||||
import { useSaveGraph } from './use-save-graph';
|
import { useSaveGraph } from './use-save-graph';
|
||||||
|
|
||||||
export const useShowFormDrawer = () => {
|
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({
|
export function useHideFormSheetOnNodeDeletion({
|
||||||
hideFormDrawer,
|
hideFormDrawer,
|
||||||
}: Pick<ReturnType<typeof useShowFormDrawer>, 'hideFormDrawer'>) {
|
}: Pick<ReturnType<typeof useShowFormDrawer>, 'hideFormDrawer'>) {
|
||||||
|
|||||||
Reference in New Issue
Block a user