### What problem does this PR solve? Feat: Add RunSheet component #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.1
| @@ -5,7 +5,7 @@ import { | |||
| ReactFlow, | |||
| } from '@xyflow/react'; | |||
| import '@xyflow/react/dist/style.css'; | |||
| // import ChatDrawer from '../chat/drawer'; | |||
| import { ChatSheet } from '../chat/chat-sheet'; | |||
| import FormSheet from '../form-sheet/next'; | |||
| import { | |||
| useHandleDrop, | |||
| @@ -15,7 +15,7 @@ import { | |||
| } from '../hooks'; | |||
| import { useBeforeDelete } from '../hooks/use-before-delete'; | |||
| import { useShowDrawer } from '../hooks/use-show-drawer'; | |||
| // import RunDrawer from '../run-drawer'; | |||
| import RunSheet from '../run-sheet'; | |||
| import { ButtonEdge } from './edge'; | |||
| import styles from './index.less'; | |||
| import { RagNode } from './node'; | |||
| @@ -66,7 +66,7 @@ interface IProps { | |||
| hideDrawer(): void; | |||
| } | |||
| function FlowCanvas({ drawerVisible, hideDrawer }: IProps) { | |||
| function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { | |||
| const { | |||
| nodes, | |||
| edges, | |||
| @@ -165,21 +165,21 @@ function FlowCanvas({ drawerVisible, hideDrawer }: IProps) { | |||
| showSingleDebugDrawer={showSingleDebugDrawer} | |||
| ></FormSheet> | |||
| )} | |||
| {/* {chatVisible && ( | |||
| <ChatDrawer | |||
| {chatVisible && ( | |||
| <ChatSheet | |||
| visible={chatVisible} | |||
| hideModal={hideRunOrChatDrawer} | |||
| ></ChatDrawer> | |||
| ></ChatSheet> | |||
| )} | |||
| {runVisible && ( | |||
| <RunDrawer | |||
| <RunSheet | |||
| hideModal={hideRunOrChatDrawer} | |||
| showModal={showChatModal} | |||
| ></RunDrawer> | |||
| )} */} | |||
| ></RunSheet> | |||
| )} | |||
| </div> | |||
| ); | |||
| } | |||
| export default FlowCanvas; | |||
| export default AgentCanvas; | |||
| @@ -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 { useSetModalState } from '@/hooks/common-hooks'; | |||
| import { useSetSelectedRecord } from '@/hooks/logic-hooks'; | |||
| import { useHandleSubmittable } from '@/hooks/login-hooks'; | |||
| import api from '@/utils/api'; | |||
| import { getAuthorization } from '@/utils/authorization-util'; | |||
| import { UploadOutlined } from '@ant-design/icons'; | |||
| import { FileUploader } from '@/components/file-uploader'; | |||
| import { ButtonLoading } from '@/components/ui/button'; | |||
| import { | |||
| Button, | |||
| Form, | |||
| FormItemProps, | |||
| Input, | |||
| InputNumber, | |||
| Select, | |||
| Switch, | |||
| Upload, | |||
| } from 'antd'; | |||
| 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 { useSetSelectedRecord } from '@/hooks/logic-hooks'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { UploadChangeParam, UploadFile } from 'antd/es/upload'; | |||
| import { pick } from 'lodash'; | |||
| import { Link } from 'lucide-react'; | |||
| import React, { useCallback, useState } from 'react'; | |||
| import React, { useCallback, useMemo, useState } 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 { PopoverForm } from './popover-form'; | |||
| import styles from './index.less'; | |||
| interface IProps { | |||
| parameters: BeginQuery[]; | |||
| @@ -34,6 +31,8 @@ interface IProps { | |||
| submitButtonDisabled?: boolean; | |||
| } | |||
| const values = {}; | |||
| const DebugContent = ({ | |||
| parameters, | |||
| ok, | |||
| @@ -42,7 +41,20 @@ const DebugContent = ({ | |||
| submitButtonDisabled = false, | |||
| }: IProps) => { | |||
| 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 { | |||
| visible, | |||
| hideModal: hidePopover, | |||
| @@ -50,7 +62,8 @@ const DebugContent = ({ | |||
| showModal: showPopover, | |||
| } = useSetModalState(); | |||
| const { setRecord, currentRecord } = useSetSelectedRecord<number>(); | |||
| const { submittable } = useHandleSubmittable(form); | |||
| // const { submittable } = useHandleSubmittable(form); | |||
| const submittable = true; | |||
| const [isUploading, setIsUploading] = useState(false); | |||
| const handleShowPopover = useCallback( | |||
| @@ -79,8 +92,8 @@ const DebugContent = ({ | |||
| ); | |||
| const renderWidget = useCallback( | |||
| (q: BeginQuery, idx: number) => { | |||
| const props: FormItemProps & { key: number } = { | |||
| (q: BeginQuery, idx: string) => { | |||
| const props = { | |||
| key: idx, | |||
| label: q.name ?? q.key, | |||
| name: idx, | |||
| @@ -89,80 +102,119 @@ const DebugContent = ({ | |||
| props.rules = [{ required: true }]; | |||
| } | |||
| const urlList: { url: string; result: string }[] = | |||
| form.getFieldValue(idx) || []; | |||
| // const urlList: { url: string; result: string }[] = | |||
| // form.getFieldValue(idx) || []; | |||
| const urlList: { url: string; result: string }[] = []; | |||
| const BeginQueryTypeMap = { | |||
| [BeginQueryType.Line]: ( | |||
| <Form.Item {...props}> | |||
| <Input></Input> | |||
| </Form.Item> | |||
| <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]: ( | |||
| <Form.Item {...props}> | |||
| <Input.TextArea rows={1}></Input.TextArea> | |||
| </Form.Item> | |||
| <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]: ( | |||
| <Form.Item {...props}> | |||
| <Select | |||
| allowClear | |||
| options={q.options?.map((x) => ({ label: x, value: x })) ?? []} | |||
| ></Select> | |||
| </Form.Item> | |||
| <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 })) ?? [] | |||
| } | |||
| {...field} | |||
| ></RAGFlowSelect> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| ), | |||
| [BeginQueryType.File]: ( | |||
| <React.Fragment key={idx}> | |||
| <Form.Item label={q.name ?? q.key} required={!q.optional}> | |||
| <div className="relative"> | |||
| <Form.Item | |||
| {...props} | |||
| valuePropName="fileList" | |||
| getValueFromEvent={normFile} | |||
| noStyle | |||
| > | |||
| <Upload | |||
| name="file" | |||
| action={api.parse} | |||
| multiple | |||
| headers={{ [Authorization]: getAuthorization() }} | |||
| onChange={onChange(q.optional)} | |||
| > | |||
| <Button icon={<UploadOutlined />}> | |||
| {t('common.upload')} | |||
| </Button> | |||
| </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'])} /> | |||
| <FormField | |||
| control={form.control} | |||
| name={'file'} | |||
| render={({ field }) => ( | |||
| <div className="space-y-6"> | |||
| <FormItem className="w-full"> | |||
| <FormLabel>{t('assistantAvatar')}</FormLabel> | |||
| <FormControl> | |||
| <FileUploader | |||
| value={field.value} | |||
| onValueChange={field.onChange} | |||
| maxFileCount={1} | |||
| maxSize={4 * 1024 * 1024} | |||
| /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| </div> | |||
| )} | |||
| /> | |||
| </React.Fragment> | |||
| ), | |||
| [BeginQueryType.Integer]: ( | |||
| <Form.Item {...props}> | |||
| <InputNumber></InputNumber> | |||
| </Form.Item> | |||
| <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]: ( | |||
| <Form.Item valuePropName={'checked'} {...props}> | |||
| <Switch></Switch> | |||
| </Form.Item> | |||
| <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> | |||
| )} | |||
| /> | |||
| ), | |||
| }; | |||
| @@ -171,11 +223,11 @@ const DebugContent = ({ | |||
| BeginQueryTypeMap[BeginQueryType.Paragraph] | |||
| ); | |||
| }, | |||
| [form, handleShowPopover, onChange, switchVisible, t, visible], | |||
| [form, t], | |||
| ); | |||
| const onOk = useCallback(async () => { | |||
| const values = await form.validateFields(); | |||
| // const values = await form.validateFields(); | |||
| const nextValues = Object.entries(values).map(([key, value]) => { | |||
| const item = parameters[Number(key)]; | |||
| let nextValue = value; | |||
| @@ -193,44 +245,49 @@ const DebugContent = ({ | |||
| }); | |||
| 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 ( | |||
| <> | |||
| <section className={styles.formWrapper}> | |||
| <Form.Provider | |||
| onFormFinish={(name, { values, forms }) => { | |||
| 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} | |||
| > | |||
| <section> | |||
| <Form {...form}> | |||
| <form onSubmit={form.handleSubmit(onSubmit)}> | |||
| {parameters.map((x, idx) => { | |||
| return renderWidget(x, idx); | |||
| return <div key={idx}>{renderWidget(x, idx.toString())}</div>; | |||
| })} | |||
| </Form> | |||
| </Form.Provider> | |||
| </form> | |||
| </Form> | |||
| </section> | |||
| <Button | |||
| type={'primary'} | |||
| block | |||
| <ButtonLoading | |||
| onClick={onOk} | |||
| loading={loading} | |||
| disabled={!submittable || isUploading || submitButtonDisabled} | |||
| > | |||
| {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 { useResetFormOnCloseModal } from '@/hooks/logic-hooks'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| import { Button, Form, Input, Popover } from 'antd'; | |||
| 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] = Form.useForm(); | |||
| const form = useForm({ | |||
| defaultValues: values, | |||
| resolver: zodResolver(FormSchema), | |||
| }); | |||
| const { parseDocument, loading } = useParseDocument(); | |||
| const { t } = useTranslation(); | |||
| useResetFormOnCloseModal({ | |||
| form, | |||
| visible, | |||
| }); | |||
| // useResetFormOnCloseModal({ | |||
| // form, | |||
| // visible, | |||
| // }); | |||
| const onOk = async () => { | |||
| const values = await form.validateFields(); | |||
| 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.setFieldValue('result', ret?.data?.data); | |||
| form.submit(); | |||
| form.setValue('result', ret?.data?.data); | |||
| } | |||
| } | |||
| }; | |||
| } | |||
| const content = ( | |||
| <Form form={form} name="urlForm"> | |||
| <Form.Item | |||
| name="url" | |||
| rules={[{ required: true, type: 'url' }]} | |||
| className="m-0" | |||
| > | |||
| <Input | |||
| onPressEnter={(e) => e.preventDefault()} | |||
| placeholder={t('flow.pasteFileLink')} | |||
| suffix={ | |||
| <Button | |||
| type="primary" | |||
| onClick={onOk} | |||
| size={'small'} | |||
| loading={loading} | |||
| > | |||
| {t('common.submit')} | |||
| </Button> | |||
| } | |||
| <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.Item> | |||
| <Form.Item name={'result'} noStyle /> | |||
| </form> | |||
| </Form> | |||
| ); | |||
| return ( | |||
| <Popover | |||
| content={content} | |||
| open={visible} | |||
| trigger={'click'} | |||
| onOpenChange={switchVisible} | |||
| > | |||
| <Popover open={visible} onOpenChange={switchVisible}> | |||
| {children} | |||
| <PopoverContent>{content}</PopoverContent> | |||
| </Popover> | |||
| ); | |||
| }; | |||
| @@ -12,14 +12,19 @@ import { useSetModalState } from '@/hooks/common-hooks'; | |||
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | |||
| import { ReactFlowProvider } from '@xyflow/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 { AgentSidebar } from './agent-sidebar'; | |||
| import FlowCanvas from './canvas'; | |||
| import AgentCanvas from './canvas'; | |||
| import { useHandleExportOrImportJsonFile } from './hooks/use-export-json'; | |||
| import { useFetchDataOnMount } from './hooks/use-fetch-data'; | |||
| import { useGetBeginNodeDataQuery } from './hooks/use-get-begin-query'; | |||
| 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'; | |||
| function AgentDropdownMenuItem({ | |||
| @@ -52,6 +57,18 @@ export default function Agent() { | |||
| const { saveGraph, loading } = useSaveGraph(); | |||
| 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 ( | |||
| <section> | |||
| @@ -64,7 +81,9 @@ export default function Agent() { | |||
| > | |||
| Save | |||
| </ButtonLoading> | |||
| <Button variant={'outline'}>Run app</Button> | |||
| <Button variant={'outline'} onClick={handleRunAgent}> | |||
| Run app | |||
| </Button> | |||
| <Button variant={'outline'}>Publish</Button> | |||
| <DropdownMenu> | |||
| @@ -104,10 +123,10 @@ export default function Agent() { | |||
| <div className="w-full"> | |||
| <SidebarTrigger /> | |||
| <div className="w-full h-full"> | |||
| <FlowCanvas | |||
| <AgentCanvas | |||
| drawerVisible={chatDrawerVisible} | |||
| hideDrawer={hideChatDrawer} | |||
| ></FlowCanvas> | |||
| ></AgentCanvas> | |||
| </div> | |||
| </div> | |||
| </SidebarProvider> | |||
| @@ -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; | |||