mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Add RunSheet component #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -5,7 +5,7 @@ import {
|
|||||||
ReactFlow,
|
ReactFlow,
|
||||||
} from '@xyflow/react';
|
} from '@xyflow/react';
|
||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
// import ChatDrawer from '../chat/drawer';
|
import { ChatSheet } from '../chat/chat-sheet';
|
||||||
import FormSheet from '../form-sheet/next';
|
import FormSheet from '../form-sheet/next';
|
||||||
import {
|
import {
|
||||||
useHandleDrop,
|
useHandleDrop,
|
||||||
@ -15,7 +15,7 @@ import {
|
|||||||
} from '../hooks';
|
} from '../hooks';
|
||||||
import { useBeforeDelete } from '../hooks/use-before-delete';
|
import { useBeforeDelete } from '../hooks/use-before-delete';
|
||||||
import { useShowDrawer } from '../hooks/use-show-drawer';
|
import { useShowDrawer } from '../hooks/use-show-drawer';
|
||||||
// import RunDrawer from '../run-drawer';
|
import RunSheet from '../run-sheet';
|
||||||
import { ButtonEdge } from './edge';
|
import { ButtonEdge } from './edge';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { RagNode } from './node';
|
import { RagNode } from './node';
|
||||||
@ -66,7 +66,7 @@ interface IProps {
|
|||||||
hideDrawer(): void;
|
hideDrawer(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function FlowCanvas({ drawerVisible, hideDrawer }: IProps) {
|
function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||||
const {
|
const {
|
||||||
nodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
@ -165,21 +165,21 @@ function FlowCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
showSingleDebugDrawer={showSingleDebugDrawer}
|
showSingleDebugDrawer={showSingleDebugDrawer}
|
||||||
></FormSheet>
|
></FormSheet>
|
||||||
)}
|
)}
|
||||||
{/* {chatVisible && (
|
{chatVisible && (
|
||||||
<ChatDrawer
|
<ChatSheet
|
||||||
visible={chatVisible}
|
visible={chatVisible}
|
||||||
hideModal={hideRunOrChatDrawer}
|
hideModal={hideRunOrChatDrawer}
|
||||||
></ChatDrawer>
|
></ChatSheet>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{runVisible && (
|
{runVisible && (
|
||||||
<RunDrawer
|
<RunSheet
|
||||||
hideModal={hideRunOrChatDrawer}
|
hideModal={hideRunOrChatDrawer}
|
||||||
showModal={showChatModal}
|
showModal={showChatModal}
|
||||||
></RunDrawer>
|
></RunSheet>
|
||||||
)} */}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FlowCanvas;
|
export default AgentCanvas;
|
||||||
|
|||||||
26
web/src/pages/agent/chat/chat-sheet.tsx
Normal file
26
web/src/pages/agent/chat/chat-sheet.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
Sheet,
|
||||||
|
SheetContent,
|
||||||
|
SheetDescription,
|
||||||
|
SheetHeader,
|
||||||
|
SheetTitle,
|
||||||
|
SheetTrigger,
|
||||||
|
} from '@/components/ui/sheet';
|
||||||
|
import { IModalProps } from '@/interfaces/common';
|
||||||
|
|
||||||
|
export function ChatSheet({ visible }: IModalProps<any>) {
|
||||||
|
return (
|
||||||
|
<Sheet open={visible} modal={false}>
|
||||||
|
<SheetTrigger>Open</SheetTrigger>
|
||||||
|
<SheetContent>
|
||||||
|
<SheetHeader>
|
||||||
|
<SheetTitle>Are you absolutely sure?</SheetTitle>
|
||||||
|
<SheetDescription>
|
||||||
|
This action cannot be undone. This will permanently delete your
|
||||||
|
account and remove your data from our servers.
|
||||||
|
</SheetDescription>
|
||||||
|
</SheetHeader>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,30 +1,27 @@
|
|||||||
import { Authorization } from '@/constants/authorization';
|
import { FileUploader } from '@/components/file-uploader';
|
||||||
|
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 { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
||||||
import { useHandleSubmittable } from '@/hooks/login-hooks';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import api from '@/utils/api';
|
|
||||||
import { getAuthorization } from '@/utils/authorization-util';
|
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Form,
|
|
||||||
FormItemProps,
|
|
||||||
Input,
|
|
||||||
InputNumber,
|
|
||||||
Select,
|
|
||||||
Switch,
|
|
||||||
Upload,
|
|
||||||
} from 'antd';
|
|
||||||
import { UploadChangeParam, UploadFile } from 'antd/es/upload';
|
import { UploadChangeParam, UploadFile } from 'antd/es/upload';
|
||||||
import { pick } from 'lodash';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { Link } from 'lucide-react';
|
import { useForm } from 'react-hook-form';
|
||||||
import React, { useCallback, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { z } from 'zod';
|
||||||
import { BeginQueryType } from '../constant';
|
import { BeginQueryType } from '../constant';
|
||||||
import { BeginQuery } from '../interface';
|
import { BeginQuery } from '../interface';
|
||||||
import { PopoverForm } from './popover-form';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
parameters: BeginQuery[];
|
parameters: BeginQuery[];
|
||||||
@ -34,6 +31,8 @@ interface IProps {
|
|||||||
submitButtonDisabled?: boolean;
|
submitButtonDisabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const values = {};
|
||||||
|
|
||||||
const DebugContent = ({
|
const DebugContent = ({
|
||||||
parameters,
|
parameters,
|
||||||
ok,
|
ok,
|
||||||
@ -42,7 +41,20 @@ const DebugContent = ({
|
|||||||
submitButtonDisabled = false,
|
submitButtonDisabled = false,
|
||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
|
||||||
|
const FormSchema = useMemo(() => {
|
||||||
|
const obj = parameters.reduce((pre, cur, idx) => {
|
||||||
|
pre[idx] = z.string().optional();
|
||||||
|
return pre;
|
||||||
|
}, {});
|
||||||
|
return z.object(obj);
|
||||||
|
}, [parameters]);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: values,
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
visible,
|
visible,
|
||||||
hideModal: hidePopover,
|
hideModal: hidePopover,
|
||||||
@ -50,7 +62,8 @@ const DebugContent = ({
|
|||||||
showModal: showPopover,
|
showModal: showPopover,
|
||||||
} = useSetModalState();
|
} = useSetModalState();
|
||||||
const { setRecord, currentRecord } = useSetSelectedRecord<number>();
|
const { setRecord, currentRecord } = useSetSelectedRecord<number>();
|
||||||
const { submittable } = useHandleSubmittable(form);
|
// const { submittable } = useHandleSubmittable(form);
|
||||||
|
const submittable = true;
|
||||||
const [isUploading, setIsUploading] = useState(false);
|
const [isUploading, setIsUploading] = useState(false);
|
||||||
|
|
||||||
const handleShowPopover = useCallback(
|
const handleShowPopover = useCallback(
|
||||||
@ -79,8 +92,8 @@ const DebugContent = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderWidget = useCallback(
|
const renderWidget = useCallback(
|
||||||
(q: BeginQuery, idx: number) => {
|
(q: BeginQuery, idx: string) => {
|
||||||
const props: FormItemProps & { key: number } = {
|
const props = {
|
||||||
key: idx,
|
key: idx,
|
||||||
label: q.name ?? q.key,
|
label: q.name ?? q.key,
|
||||||
name: idx,
|
name: idx,
|
||||||
@ -89,80 +102,119 @@ const DebugContent = ({
|
|||||||
props.rules = [{ required: true }];
|
props.rules = [{ required: true }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlList: { url: string; result: string }[] =
|
// const urlList: { url: string; result: string }[] =
|
||||||
form.getFieldValue(idx) || [];
|
// form.getFieldValue(idx) || [];
|
||||||
|
|
||||||
|
const urlList: { url: string; result: string }[] = [];
|
||||||
|
|
||||||
const BeginQueryTypeMap = {
|
const BeginQueryTypeMap = {
|
||||||
[BeginQueryType.Line]: (
|
[BeginQueryType.Line]: (
|
||||||
<Form.Item {...props}>
|
<FormField
|
||||||
<Input></Input>
|
control={form.control}
|
||||||
</Form.Item>
|
name={props.name}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormLabel>{props.label}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field}></Input>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
[BeginQueryType.Paragraph]: (
|
[BeginQueryType.Paragraph]: (
|
||||||
<Form.Item {...props}>
|
<FormField
|
||||||
<Input.TextArea rows={1}></Input.TextArea>
|
control={form.control}
|
||||||
</Form.Item>
|
name={props.name}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormLabel>{props.label}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea rows={1} {...field}></Textarea>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
[BeginQueryType.Options]: (
|
[BeginQueryType.Options]: (
|
||||||
<Form.Item {...props}>
|
<FormField
|
||||||
<Select
|
control={form.control}
|
||||||
allowClear
|
name={props.name}
|
||||||
options={q.options?.map((x) => ({ label: x, value: x })) ?? []}
|
render={({ field }) => (
|
||||||
></Select>
|
<FormItem className="flex-1">
|
||||||
</Form.Item>
|
<FormLabel>{props.label}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<RAGFlowSelect
|
||||||
|
allowClear
|
||||||
|
options={
|
||||||
|
q.options?.map((x) => ({ label: x, value: x })) ?? []
|
||||||
|
}
|
||||||
|
{...field}
|
||||||
|
></RAGFlowSelect>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
[BeginQueryType.File]: (
|
[BeginQueryType.File]: (
|
||||||
<React.Fragment key={idx}>
|
<React.Fragment key={idx}>
|
||||||
<Form.Item label={q.name ?? q.key} required={!q.optional}>
|
<FormField
|
||||||
<div className="relative">
|
control={form.control}
|
||||||
<Form.Item
|
name={'file'}
|
||||||
{...props}
|
render={({ field }) => (
|
||||||
valuePropName="fileList"
|
<div className="space-y-6">
|
||||||
getValueFromEvent={normFile}
|
<FormItem className="w-full">
|
||||||
noStyle
|
<FormLabel>{t('assistantAvatar')}</FormLabel>
|
||||||
>
|
<FormControl>
|
||||||
<Upload
|
<FileUploader
|
||||||
name="file"
|
value={field.value}
|
||||||
action={api.parse}
|
onValueChange={field.onChange}
|
||||||
multiple
|
maxFileCount={1}
|
||||||
headers={{ [Authorization]: getAuthorization() }}
|
maxSize={4 * 1024 * 1024}
|
||||||
onChange={onChange(q.optional)}
|
/>
|
||||||
>
|
</FormControl>
|
||||||
<Button icon={<UploadOutlined />}>
|
<FormMessage />
|
||||||
{t('common.upload')}
|
</FormItem>
|
||||||
</Button>
|
</div>
|
||||||
</Upload>
|
)}
|
||||||
</Form.Item>
|
/>
|
||||||
<Form.Item
|
|
||||||
{...pick(props, ['key', 'label', 'rules'])}
|
|
||||||
required={!q.optional}
|
|
||||||
className={urlList.length > 0 ? 'mb-1' : ''}
|
|
||||||
noStyle
|
|
||||||
>
|
|
||||||
<PopoverForm visible={visible} switchVisible={switchVisible}>
|
|
||||||
<Button
|
|
||||||
onClick={handleShowPopover(idx)}
|
|
||||||
className="absolute left-1/2 top-0"
|
|
||||||
icon={<Link className="size-3" />}
|
|
||||||
>
|
|
||||||
{t('flow.pasteFileLink')}
|
|
||||||
</Button>
|
|
||||||
</PopoverForm>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name={idx} noStyle {...pick(props, ['rules'])} />
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
),
|
),
|
||||||
[BeginQueryType.Integer]: (
|
[BeginQueryType.Integer]: (
|
||||||
<Form.Item {...props}>
|
<FormField
|
||||||
<InputNumber></InputNumber>
|
control={form.control}
|
||||||
</Form.Item>
|
name={props.name}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormLabel>{props.label}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input type="number" {...field}></Input>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
[BeginQueryType.Boolean]: (
|
[BeginQueryType.Boolean]: (
|
||||||
<Form.Item valuePropName={'checked'} {...props}>
|
<FormField
|
||||||
<Switch></Switch>
|
control={form.control}
|
||||||
</Form.Item>
|
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>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,11 +223,11 @@ const DebugContent = ({
|
|||||||
BeginQueryTypeMap[BeginQueryType.Paragraph]
|
BeginQueryTypeMap[BeginQueryType.Paragraph]
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[form, handleShowPopover, onChange, switchVisible, t, visible],
|
[form, t],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onOk = useCallback(async () => {
|
const onOk = useCallback(async () => {
|
||||||
const values = await form.validateFields();
|
// const values = await form.validateFields();
|
||||||
const nextValues = Object.entries(values).map(([key, value]) => {
|
const nextValues = Object.entries(values).map(([key, value]) => {
|
||||||
const item = parameters[Number(key)];
|
const item = parameters[Number(key)];
|
||||||
let nextValue = value;
|
let nextValue = value;
|
||||||
@ -193,44 +245,49 @@ const DebugContent = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
ok(nextValues);
|
ok(nextValues);
|
||||||
}, [form, ok, parameters]);
|
}, [ok, parameters]);
|
||||||
|
|
||||||
|
const onSubmit = useCallback(
|
||||||
|
(values: z.infer<typeof FormSchema>) => {
|
||||||
|
const nextValues = Object.entries(values).map(([key, value]) => {
|
||||||
|
const item = parameters[Number(key)];
|
||||||
|
let nextValue = value;
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
nextValue = ``;
|
||||||
|
|
||||||
|
value.forEach((x) => {
|
||||||
|
nextValue +=
|
||||||
|
x?.originFileObj instanceof File
|
||||||
|
? `${x.name}\n${x.response?.data}\n----\n`
|
||||||
|
: `${x.url}\n${x.result}\n----\n`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { ...item, value: nextValue };
|
||||||
|
});
|
||||||
|
|
||||||
|
ok(nextValues);
|
||||||
|
},
|
||||||
|
[ok, parameters],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className={styles.formWrapper}>
|
<section>
|
||||||
<Form.Provider
|
<Form {...form}>
|
||||||
onFormFinish={(name, { values, forms }) => {
|
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||||
if (name === 'urlForm') {
|
|
||||||
const { basicForm } = forms;
|
|
||||||
const urlInfo = basicForm.getFieldValue(currentRecord) || [];
|
|
||||||
basicForm.setFieldsValue({
|
|
||||||
[currentRecord]: [...urlInfo, { ...values, name: values.url }],
|
|
||||||
});
|
|
||||||
hidePopover();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form
|
|
||||||
name="basicForm"
|
|
||||||
autoComplete="off"
|
|
||||||
layout={'vertical'}
|
|
||||||
form={form}
|
|
||||||
>
|
|
||||||
{parameters.map((x, idx) => {
|
{parameters.map((x, idx) => {
|
||||||
return renderWidget(x, idx);
|
return <div key={idx}>{renderWidget(x, idx.toString())}</div>;
|
||||||
})}
|
})}
|
||||||
</Form>
|
</form>
|
||||||
</Form.Provider>
|
</Form>
|
||||||
</section>
|
</section>
|
||||||
<Button
|
<ButtonLoading
|
||||||
type={'primary'}
|
|
||||||
block
|
|
||||||
onClick={onOk}
|
onClick={onOk}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={!submittable || isUploading || submitButtonDisabled}
|
disabled={!submittable || isUploading || submitButtonDisabled}
|
||||||
>
|
>
|
||||||
{t(isNext ? 'common.next' : 'flow.run')}
|
{t(isNext ? 'common.next' : 'flow.run')}
|
||||||
</Button>
|
</ButtonLoading>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,74 +1,103 @@
|
|||||||
|
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 { useParseDocument } from '@/hooks/document-hooks';
|
||||||
import { useResetFormOnCloseModal } from '@/hooks/logic-hooks';
|
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
import { Button, Form, Input, Popover } from 'antd';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const reg =
|
const reg =
|
||||||
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
|
/^(((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 = ({
|
export const PopoverForm = ({
|
||||||
children,
|
children,
|
||||||
visible,
|
visible,
|
||||||
switchVisible,
|
switchVisible,
|
||||||
}: PropsWithChildren<IModalProps<any>>) => {
|
}: PropsWithChildren<IModalProps<any>>) => {
|
||||||
const [form] = Form.useForm();
|
const form = useForm({
|
||||||
|
defaultValues: values,
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
});
|
||||||
const { parseDocument, loading } = useParseDocument();
|
const { parseDocument, loading } = useParseDocument();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useResetFormOnCloseModal({
|
// useResetFormOnCloseModal({
|
||||||
form,
|
// form,
|
||||||
visible,
|
// visible,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const onOk = async () => {
|
async function onSubmit(values: z.infer<typeof FormSchema>) {
|
||||||
const values = await form.validateFields();
|
|
||||||
const val = values.url;
|
const val = values.url;
|
||||||
|
|
||||||
if (reg.test(val)) {
|
if (reg.test(val)) {
|
||||||
const ret = await parseDocument(val);
|
const ret = await parseDocument(val);
|
||||||
if (ret?.data?.code === 0) {
|
if (ret?.data?.code === 0) {
|
||||||
form.setFieldValue('result', ret?.data?.data);
|
form.setValue('result', ret?.data?.data);
|
||||||
form.submit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<Form form={form} name="urlForm">
|
<Form {...form}>
|
||||||
<Form.Item
|
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||||
name="url"
|
<FormField
|
||||||
rules={[{ required: true, type: 'url' }]}
|
control={form.control}
|
||||||
className="m-0"
|
name={`url`}
|
||||||
>
|
render={({ field }) => (
|
||||||
<Input
|
<FormItem className="flex-1">
|
||||||
onPressEnter={(e) => e.preventDefault()}
|
<FormControl>
|
||||||
placeholder={t('flow.pasteFileLink')}
|
<Input
|
||||||
suffix={
|
{...field}
|
||||||
<Button
|
// onPressEnter={(e) => e.preventDefault()}
|
||||||
type="primary"
|
placeholder={t('flow.pasteFileLink')}
|
||||||
onClick={onOk}
|
// suffix={
|
||||||
size={'small'}
|
// <Button
|
||||||
loading={loading}
|
// type="primary"
|
||||||
>
|
// onClick={onOk}
|
||||||
{t('common.submit')}
|
// size={'small'}
|
||||||
</Button>
|
// loading={loading}
|
||||||
}
|
// >
|
||||||
|
// {t('common.submit')}
|
||||||
|
// </Button>
|
||||||
|
// }
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
<FormField
|
||||||
<Form.Item name={'result'} noStyle />
|
control={form.control}
|
||||||
|
name={`result`}
|
||||||
|
render={() => <></>}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover open={visible} onOpenChange={switchVisible}>
|
||||||
content={content}
|
|
||||||
open={visible}
|
|
||||||
trigger={'click'}
|
|
||||||
onOpenChange={switchVisible}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
|
<PopoverContent>{content}</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,14 +12,19 @@ import { useSetModalState } from '@/hooks/common-hooks';
|
|||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { ReactFlowProvider } from '@xyflow/react';
|
import { ReactFlowProvider } from '@xyflow/react';
|
||||||
import { CodeXml, EllipsisVertical, Forward, Import, Key } from 'lucide-react';
|
import { CodeXml, EllipsisVertical, Forward, Import, Key } from 'lucide-react';
|
||||||
import { ComponentPropsWithoutRef } from 'react';
|
import { ComponentPropsWithoutRef, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AgentSidebar } from './agent-sidebar';
|
import { AgentSidebar } from './agent-sidebar';
|
||||||
import FlowCanvas from './canvas';
|
import AgentCanvas from './canvas';
|
||||||
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
|
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
|
||||||
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
||||||
|
import { useGetBeginNodeDataQuery } from './hooks/use-get-begin-query';
|
||||||
import { useOpenDocument } from './hooks/use-open-document';
|
import { useOpenDocument } from './hooks/use-open-document';
|
||||||
import { useSaveGraph } from './hooks/use-save-graph';
|
import {
|
||||||
|
useSaveGraph,
|
||||||
|
useSaveGraphBeforeOpeningDebugDrawer,
|
||||||
|
} from './hooks/use-save-graph';
|
||||||
|
import { BeginQuery } from './interface';
|
||||||
import { UploadAgentDialog } from './upload-agent-dialog';
|
import { UploadAgentDialog } from './upload-agent-dialog';
|
||||||
|
|
||||||
function AgentDropdownMenuItem({
|
function AgentDropdownMenuItem({
|
||||||
@ -52,6 +57,18 @@ export default function Agent() {
|
|||||||
const { saveGraph, loading } = useSaveGraph();
|
const { saveGraph, loading } = useSaveGraph();
|
||||||
|
|
||||||
const { flowDetail } = useFetchDataOnMount();
|
const { flowDetail } = useFetchDataOnMount();
|
||||||
|
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
||||||
|
|
||||||
|
const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
|
||||||
|
|
||||||
|
const handleRunAgent = useCallback(() => {
|
||||||
|
const query: BeginQuery[] = getBeginNodeDataQuery();
|
||||||
|
if (query.length > 0) {
|
||||||
|
showChatDrawer();
|
||||||
|
} else {
|
||||||
|
handleRun();
|
||||||
|
}
|
||||||
|
}, [getBeginNodeDataQuery, handleRun, showChatDrawer]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
@ -64,7 +81,9 @@ export default function Agent() {
|
|||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</ButtonLoading>
|
</ButtonLoading>
|
||||||
<Button variant={'outline'}>Run app</Button>
|
<Button variant={'outline'} onClick={handleRunAgent}>
|
||||||
|
Run app
|
||||||
|
</Button>
|
||||||
<Button variant={'outline'}>Publish</Button>
|
<Button variant={'outline'}>Publish</Button>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
@ -104,10 +123,10 @@ export default function Agent() {
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<SidebarTrigger />
|
<SidebarTrigger />
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<FlowCanvas
|
<AgentCanvas
|
||||||
drawerVisible={chatDrawerVisible}
|
drawerVisible={chatDrawerVisible}
|
||||||
hideDrawer={hideChatDrawer}
|
hideDrawer={hideChatDrawer}
|
||||||
></FlowCanvas>
|
></AgentCanvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
|
|||||||
62
web/src/pages/agent/run-sheet/index.tsx
Normal file
62
web/src/pages/agent/run-sheet/index.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { IModalProps } from '@/interfaces/common';
|
||||||
|
import { Drawer } from 'antd';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BeginId } from '../constant';
|
||||||
|
import DebugContent from '../debug-content';
|
||||||
|
import { useGetBeginNodeDataQuery } from '../hooks/use-get-begin-query';
|
||||||
|
import { useSaveGraphBeforeOpeningDebugDrawer } from '../hooks/use-save-graph';
|
||||||
|
import { BeginQuery } from '../interface';
|
||||||
|
import useGraphStore from '../store';
|
||||||
|
import { getDrawerWidth } from '../utils';
|
||||||
|
|
||||||
|
const RunSheet = ({
|
||||||
|
hideModal,
|
||||||
|
showModal: showChatModal,
|
||||||
|
}: IModalProps<any>) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
|
||||||
|
|
||||||
|
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
||||||
|
const query: BeginQuery[] = getBeginNodeDataQuery();
|
||||||
|
|
||||||
|
const { handleRun, loading } = useSaveGraphBeforeOpeningDebugDrawer(
|
||||||
|
showChatModal!,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleRunAgent = useCallback(
|
||||||
|
(nextValues: Record<string, any>) => {
|
||||||
|
const currentNodes = updateNodeForm(BeginId, nextValues, ['query']);
|
||||||
|
handleRun(currentNodes);
|
||||||
|
hideModal?.();
|
||||||
|
},
|
||||||
|
[handleRun, hideModal, updateNodeForm],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onOk = useCallback(
|
||||||
|
async (nextValues: any[]) => {
|
||||||
|
handleRunAgent(nextValues);
|
||||||
|
},
|
||||||
|
[handleRunAgent],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
title={t('flow.testRun')}
|
||||||
|
placement="right"
|
||||||
|
onClose={hideModal}
|
||||||
|
open
|
||||||
|
getContainer={false}
|
||||||
|
width={getDrawerWidth()}
|
||||||
|
mask={false}
|
||||||
|
>
|
||||||
|
<DebugContent
|
||||||
|
ok={onOk}
|
||||||
|
parameters={query}
|
||||||
|
loading={loading}
|
||||||
|
></DebugContent>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RunSheet;
|
||||||
Reference in New Issue
Block a user