diff --git a/web/app/components/base/toast/index.tsx b/web/app/components/base/toast/index.tsx index 57f8c50439..b8636493c0 100644 --- a/web/app/components/base/toast/index.tsx +++ b/web/app/components/base/toast/index.tsx @@ -51,8 +51,9 @@ const Toast = ({ return
diff --git a/web/app/components/rag-pipeline/components/panel/input-field/editor/index.tsx b/web/app/components/rag-pipeline/components/panel/input-field/editor/index.tsx index 2e51d91806..67d589c3ff 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/editor/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/input-field/editor/index.tsx @@ -1,11 +1,13 @@ import { RiCloseLine } from '@remixicon/react' import InputFieldForm from './form' import { convertFormDataToINputField, convertToInputFieldFormData } from './utils' -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' import type { InputVar } from '@/models/pipeline' import type { FormData } from './form/types' import type { MoreInfo } from '@/app/components/workflow/types' +import { useFloatingRight } from '../hooks' +import cn from '@/utils/classnames' export type InputFieldEditorProps = { onClose: () => void @@ -19,7 +21,12 @@ const InputFieldEditorPanel = ({ initialData, }: InputFieldEditorProps) => { const { t } = useTranslation() - const formData = convertToInputFieldFormData(initialData) + + const { floatingRight, floatingRightWidth } = useFloatingRight(400) + + const formData = useMemo(() => { + return convertToInputFieldFormData(initialData) + }, [initialData]) const handleSubmit = useCallback((value: FormData, moreInfo?: MoreInfo) => { const inputFieldData = convertFormDataToINputField(value) @@ -27,7 +34,16 @@ const InputFieldEditorPanel = ({ }, [onSubmit]) return ( -
+
{initialData ? t('datasetPipeline.inputFieldPanel.editInputField') : t('datasetPipeline.inputFieldPanel.addInputField')}
diff --git a/web/app/components/rag-pipeline/components/panel/input-field/hooks.ts b/web/app/components/rag-pipeline/components/panel/input-field/hooks.ts new file mode 100644 index 0000000000..174d8741ee --- /dev/null +++ b/web/app/components/rag-pipeline/components/panel/input-field/hooks.ts @@ -0,0 +1,39 @@ +import { useEffect, useMemo, useState } from 'react' +import { useStore } from '@/app/components/workflow/store' +import { useStore as useReactflow } from 'reactflow' +import { useShallow } from 'zustand/react/shallow' + +export const useFloatingRight = (targetElementWidth: number) => { + const [floatingRight, setFloatingRight] = useState(false) + const nodePanelWidth = useStore(state => state.nodePanelWidth) + const workflowCanvasWidth = useStore(state => state.workflowCanvasWidth) + const otherPanelWidth = useStore(state => state.otherPanelWidth) + + const selectedNodeId = useReactflow(useShallow((s) => { + const nodes = s.getNodes() + const currentNode = nodes.find(node => node.data.selected) + + if (currentNode) + return currentNode.id + })) + + useEffect(() => { + if (typeof workflowCanvasWidth === 'number') { + const inputFieldPanelWidth = 400 + const marginRight = 4 + const leftWidth = workflowCanvasWidth - (selectedNodeId ? nodePanelWidth : 0) - otherPanelWidth - inputFieldPanelWidth - marginRight + setFloatingRight(leftWidth < targetElementWidth + marginRight) + } + }, [workflowCanvasWidth, nodePanelWidth, otherPanelWidth, selectedNodeId, targetElementWidth]) + + const floatingRightWidth = useMemo(() => { + if (!floatingRight) return targetElementWidth + const width = Math.min(targetElementWidth, (selectedNodeId ? nodePanelWidth : 0) + otherPanelWidth) + return width + }, [floatingRight, selectedNodeId, nodePanelWidth, otherPanelWidth, targetElementWidth]) + + return { + floatingRight, + floatingRightWidth, + } +} diff --git a/web/app/components/rag-pipeline/components/panel/input-field/preview/index.tsx b/web/app/components/rag-pipeline/components/panel/input-field/preview/index.tsx index 42fa0b6ddd..43b63b183a 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/preview/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/input-field/preview/index.tsx @@ -7,18 +7,31 @@ import Divider from '@/app/components/base/divider' import ProcessDocuments from './process-documents' import type { Datasource } from '../../test-run/types' import { useInputFieldPanel } from '@/app/components/rag-pipeline/hooks' +import cn from '@/utils/classnames' +import { useFloatingRight } from '../hooks' const PreviewPanel = () => { const { t } = useTranslation() const [datasource, setDatasource] = useState() const { toggleInputFieldPreviewPanel } = useInputFieldPanel() + const { floatingRight, floatingRightWidth } = useFloatingRight(480) + const handleClosePreviewPanel = useCallback(() => { toggleInputFieldPreviewPanel() }, [toggleInputFieldPreviewPanel]) return ( -
+
diff --git a/web/app/components/workflow/nodes/data-source/panel.tsx b/web/app/components/workflow/nodes/data-source/panel.tsx index 776ec7b6da..e6e3255dd5 100644 --- a/web/app/components/workflow/nodes/data-source/panel.tsx +++ b/web/app/components/workflow/nodes/data-source/panel.tsx @@ -15,6 +15,7 @@ import StructureOutputItem from '@/app/components/workflow/nodes/_base/component import TagInput from '@/app/components/base/tag-input' import { useNodesReadOnly } from '@/app/components/workflow/hooks' import { useConfig } from './hooks/use-config' +import type { StructuredOutput } from '@/app/components/workflow/nodes/llm/types' import { Type } from '@/app/components/workflow/nodes/llm/types' import { COMMON_OUTPUT, @@ -48,7 +49,24 @@ const Panel: FC> = ({ id, data }) => { const pipelineId = useStore(s => s.pipelineId) const setShowInputFieldPanel = useStore(s => s.setShowInputFieldPanel) - + const wrapStructuredVarItem = (outputItem: any): StructuredOutput => { + const dataType = outputItem.value?.properties?.dify_builtin_type ? outputItem.value?.properties?.dify_builtin_type.enum[0] : Type.object + const properties = Object.fromEntries( + Object.entries(outputItem.value?.properties || {}).filter(([key]) => key !== 'dify_builtin_type'), + ) as Record + return { + schema: { + type: dataType, + properties: { + [outputItem.name]: { + ...outputItem.value, + properties, + }, + }, + additionalProperties: false, + }, + } + } return (
{ @@ -123,15 +141,7 @@ const Panel: FC> = ({ id, data }) => { {outputItem.value?.type === 'object' ? ( + payload={wrapStructuredVarItem(outputItem)} /> ) : (