mirror of
https://github.com/langgenius/dify.git
synced 2026-03-10 01:46:14 +08:00
Merge remote-tracking branch 'origin/main' into feat/trigger
This commit is contained in:
@ -14,10 +14,10 @@ import {
|
||||
import {
|
||||
useAvailableBlocks,
|
||||
useIsChatMode,
|
||||
useNodesMetaData,
|
||||
useNodesReadOnly,
|
||||
usePanelInteractions,
|
||||
} from '../hooks'
|
||||
import { NODES_INITIAL_DATA } from '../constants'
|
||||
import { useWorkflowStore } from '../store'
|
||||
import TipPopup from './tip-popup'
|
||||
import cn from '@/utils/classnames'
|
||||
@ -45,6 +45,7 @@ const AddBlock = ({
|
||||
const { handlePaneContextmenuCancel } = usePanelInteractions()
|
||||
const [open, setOpen] = useState(false)
|
||||
const { availableNextBlocks } = useAvailableBlocks(BlockEnum.Start, false)
|
||||
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
|
||||
|
||||
const handleOpenChange = useCallback((open: boolean) => {
|
||||
setOpen(open)
|
||||
@ -58,12 +59,15 @@ const AddBlock = ({
|
||||
} = store.getState()
|
||||
const nodes = getNodes()
|
||||
const nodesWithSameType = nodes.filter(node => node.data.type === type)
|
||||
const {
|
||||
defaultValue,
|
||||
} = nodesMetaDataMap![type]
|
||||
const { newNode } = generateNewNode({
|
||||
type: getNodeCustomTypeByNodeDataType(type),
|
||||
data: {
|
||||
...NODES_INITIAL_DATA[type],
|
||||
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${type}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${type}`),
|
||||
...(toolDefaultValue || {}),
|
||||
...(defaultValue as any),
|
||||
title: nodesWithSameType.length > 0 ? `${defaultValue.title} ${nodesWithSameType.length + 1}` : defaultValue.title,
|
||||
...toolDefaultValue,
|
||||
_isCandidate: true,
|
||||
},
|
||||
position: {
|
||||
@ -74,7 +78,7 @@ const AddBlock = ({
|
||||
workflowStore.setState({
|
||||
candidateNode: newNode,
|
||||
})
|
||||
}, [store, workflowStore, t])
|
||||
}, [store, workflowStore, nodesMetaDataMap])
|
||||
|
||||
const renderTriggerElement = useCallback((open: boolean) => {
|
||||
return (
|
||||
|
||||
@ -50,7 +50,7 @@ const Control = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-col items-center rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 text-text-tertiary shadow-lg'>
|
||||
<div className='pointer-events-auto flex flex-col items-center rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 text-text-tertiary shadow-lg'>
|
||||
<AddBlock />
|
||||
<TipPopup title={t('workflow.nodes.note.addNote')}>
|
||||
<div
|
||||
|
||||
@ -10,7 +10,6 @@ import { toJpeg, toPng, toSvg } from 'html-to-image'
|
||||
import { useNodesReadOnly } from '../hooks'
|
||||
import TipPopup from './tip-popup'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
@ -18,19 +17,21 @@ import {
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import { getNodesBounds, useReactFlow } from 'reactflow'
|
||||
import ImagePreview from '@/app/components/base/image-uploader/image-preview'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
|
||||
const MoreActions: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
const reactFlow = useReactFlow()
|
||||
|
||||
const appDetail = useAppStore(s => s.appDetail)
|
||||
const [open, setOpen] = useState(false)
|
||||
const [previewUrl, setPreviewUrl] = useState('')
|
||||
const [previewTitle, setPreviewTitle] = useState('')
|
||||
const knowledgeName = useStore(s => s.knowledgeName)
|
||||
const appName = useStore(s => s.appName)
|
||||
|
||||
const handleExportImage = useCallback(async (type: 'png' | 'jpeg' | 'svg', currentWorkflow = false) => {
|
||||
if (!appDetail)
|
||||
if (!appName && !knowledgeName)
|
||||
return
|
||||
|
||||
if (getNodesReadOnly())
|
||||
@ -41,6 +42,7 @@ const MoreActions: FC = () => {
|
||||
if (!flowElement) return
|
||||
|
||||
try {
|
||||
let filename = appName || knowledgeName
|
||||
const filter = (node: HTMLElement) => {
|
||||
if (node instanceof HTMLImageElement)
|
||||
return node.complete && node.naturalHeight !== 0
|
||||
@ -49,7 +51,6 @@ const MoreActions: FC = () => {
|
||||
}
|
||||
|
||||
let dataUrl
|
||||
let filename = `${appDetail.name}`
|
||||
|
||||
if (currentWorkflow) {
|
||||
const nodes = reactFlow.getNodes()
|
||||
@ -89,7 +90,8 @@ const MoreActions: FC = () => {
|
||||
style: {
|
||||
width: `${contentWidth}px`,
|
||||
height: `${contentHeight}px`,
|
||||
transform: `translate(${padding - nodesBounds.x}px, ${padding - nodesBounds.y}px) scale(${zoom})`,
|
||||
transform: `translate(${padding - nodesBounds.x}px, ${padding - nodesBounds.y}px)`,
|
||||
transformOrigin: 'top left',
|
||||
},
|
||||
}
|
||||
|
||||
@ -154,7 +156,7 @@ const MoreActions: FC = () => {
|
||||
catch (error) {
|
||||
console.error('Export image failed:', error)
|
||||
}
|
||||
}, [getNodesReadOnly, appDetail, reactFlow])
|
||||
}, [getNodesReadOnly, appName, reactFlow, knowledgeName])
|
||||
|
||||
const handleTrigger = useCallback(() => {
|
||||
if (getNodesReadOnly())
|
||||
|
||||
Reference in New Issue
Block a user