Browse Source

Feat: Displays the output variable type selected by the loop operator #3221 (#8515)

### What problem does this PR solve?

Feat: Displays the output variable type selected by the loop operator
#3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
tags/v0.20.0
balibabu 4 months ago
parent
commit
05bf01b058
No account linked to committer's email address

+ 33
- 3
web/src/pages/agent/form/iteration-form/dynamic-output.tsx View File

@@ -13,7 +13,7 @@ import { Input } from '@/components/ui/input';
import { Separator } from '@/components/ui/separator';
import { RAGFlowNodeType } from '@/interfaces/database/flow';
import { X } from 'lucide-react';
import { ReactNode } from 'react';
import { ReactNode, useCallback, useMemo } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useBuildSubNodeOutputOptions } from './use-build-options';
@@ -28,6 +28,26 @@ export function DynamicOutputForm({ node }: IProps) {
const options = useBuildSubNodeOutputOptions(node?.id);
const name = 'outputs';

const flatOptions = useMemo(() => {
return options.reduce<{ label: string; value: string; type: string }[]>(
(pre, cur) => {
pre.push(...cur.options);
return pre;
},
[],
);
}, [options]);

const findType = useCallback(
(val: string) => {
const type = flatOptions.find((x) => x.value === val)?.type;
if (type) {
return `Array<${type}>`;
}
},
[flatOptions],
);

const { fields, remove, append } = useFieldArray({
name: name,
control: form.control,
@@ -36,12 +56,13 @@ export function DynamicOutputForm({ node }: IProps) {
return (
<div className="space-y-5">
{fields.map((field, index) => {
const typeField = `${name}.${index}.name`;
const nameField = `${name}.${index}.name`;
const typeField = `${name}.${index}.type`;
return (
<div key={field.id} className="flex items-center gap-2">
<FormField
control={form.control}
name={typeField}
name={nameField}
render={({ field }) => (
<FormItem className="flex-1">
<FormControl>
@@ -64,12 +85,21 @@ export function DynamicOutputForm({ node }: IProps) {
<SelectWithSearch
options={options}
{...field}
onChange={(val) => {
form.setValue(typeField, findType(val));
field.onChange(val);
}}
></SelectWithSearch>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={typeField}
render={() => <div></div>}
/>
<Button variant={'ghost'} onClick={() => remove(index)}>
<X className="text-text-sub-title-invert " />
</Button>

+ 1
- 1
web/src/pages/agent/form/iteration-form/interface.ts View File

@@ -1,2 +1,2 @@
export type OutputArray = Array<{ name: string; ref: string; type?: string }>;
export type OutputObject = Record<string, { ref: string }>;
export type OutputObject = Record<string, { ref: string; type?: string }>;

+ 1
- 0
web/src/pages/agent/form/iteration-form/use-values.ts View File

@@ -8,6 +8,7 @@ function convertToArray(outputObject: OutputObject) {
return Object.entries(outputObject).map(([key, value]) => ({
name: key,
ref: value.ref,
type: value.type,
}));
}


+ 2
- 1
web/src/pages/agent/form/iteration-form/use-watch-form-change.ts View File

@@ -5,7 +5,7 @@ import { OutputArray, OutputObject } from './interface';

function transferToObject(list: OutputArray) {
return list.reduce<OutputObject>((pre, cur) => {
pre[cur.name] = { ref: cur.ref };
pre[cur.name] = { ref: cur.ref, type: cur.type };
return pre;
}, {});
}
@@ -18,6 +18,7 @@ export function useWatchFormChange(id?: string, form?: UseFormReturn) {
// Manually triggered form updates are synchronized to the canvas
if (id && form?.formState.isDirty) {
values = form?.getValues();
console.log('🚀 ~ useEffect ~ values:', values);
let nextValues: any = {
...values,
outputs: transferToObject(values.outputs),

+ 1
- 4
web/src/pages/agent/index.tsx View File

@@ -7,14 +7,13 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
import { SidebarProvider } from '@/components/ui/sidebar';
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, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { AgentSidebar } from './agent-sidebar';
import AgentCanvas from './canvas';
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
import { useFetchDataOnMount } from './hooks/use-fetch-data';
@@ -119,9 +118,7 @@ export default function Agent() {
<ReactFlowProvider>
<div>
<SidebarProvider>
<AgentSidebar />
<div className="w-full">
<SidebarTrigger />
<div className="w-full h-full">
<AgentCanvas
drawerVisible={chatDrawerVisible}

Loading…
Cancel
Save