mirror of
https://github.com/langgenius/dify.git
synced 2026-05-12 07:37:09 +08:00
feat(web): block selector in snippet
This commit is contained in:
parent
0f13aabea8
commit
a4ea33167d
@ -23,6 +23,8 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Evaluation from '@/app/components/evaluation'
|
||||
import { WorkflowWithInnerContext } from '@/app/components/workflow'
|
||||
import { useAvailableNodesMetaData } from '@/app/components/workflow-app/hooks'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { useConfigsMap } from '../hooks/use-configs-map'
|
||||
import { useNodesSyncDraft } from '../hooks/use-nodes-sync-draft'
|
||||
@ -66,6 +68,25 @@ const SnippetMain = ({
|
||||
} = useNodesSyncDraft(snippetId)
|
||||
const { handleRefreshWorkflowDraft } = useSnippetRefreshDraft(snippetId)
|
||||
const configsMap = useConfigsMap(snippetId)
|
||||
const workflowAvailableNodesMetaData = useAvailableNodesMetaData()
|
||||
const availableNodesMetaData = useMemo(() => {
|
||||
const nodes = workflowAvailableNodesMetaData.nodes.filter(node =>
|
||||
node.metaData.type !== BlockEnum.HumanInput && node.metaData.type !== BlockEnum.End)
|
||||
|
||||
if (!workflowAvailableNodesMetaData.nodesMap)
|
||||
return { nodes }
|
||||
|
||||
const {
|
||||
[BlockEnum.HumanInput]: _humanInput,
|
||||
[BlockEnum.End]: _end,
|
||||
...nodesMap
|
||||
} = workflowAvailableNodesMetaData.nodesMap
|
||||
|
||||
return {
|
||||
nodes,
|
||||
nodesMap,
|
||||
}
|
||||
}, [workflowAvailableNodesMetaData])
|
||||
const setAppSidebarExpand = useAppStore(state => state.setAppSidebarExpand)
|
||||
const {
|
||||
editingField,
|
||||
@ -150,9 +171,10 @@ const SnippetMain = ({
|
||||
doSyncWorkflowDraft,
|
||||
syncWorkflowDraftWhenPageClose,
|
||||
handleRefreshWorkflowDraft,
|
||||
availableNodesMetaData,
|
||||
configsMap,
|
||||
}
|
||||
}, [configsMap, doSyncWorkflowDraft, handleRefreshWorkflowDraft, syncWorkflowDraftWhenPageClose])
|
||||
}, [availableNodesMetaData, configsMap, doSyncWorkflowDraft, handleRefreshWorkflowDraft, syncWorkflowDraftWhenPageClose])
|
||||
|
||||
return (
|
||||
<div className="relative flex h-full overflow-hidden bg-background-body">
|
||||
@ -190,7 +212,7 @@ const SnippetMain = ({
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
viewport={viewport ?? graph.viewport}
|
||||
hooksStore={hooksStore}
|
||||
hooksStore={hooksStore as any}
|
||||
>
|
||||
<SnippetChildren
|
||||
snippetId={snippetId}
|
||||
|
||||
@ -40,6 +40,7 @@ export const useTabs = ({
|
||||
noStart = true,
|
||||
defaultActiveTab,
|
||||
hasUserInputNode = false,
|
||||
disableStartTab = false,
|
||||
forceEnableStartTab = false, // When true, Start tab remains enabled even if trigger/user input nodes already exist.
|
||||
}: {
|
||||
noBlocks?: boolean
|
||||
@ -48,11 +49,15 @@ export const useTabs = ({
|
||||
noStart?: boolean
|
||||
defaultActiveTab?: TabsEnum
|
||||
hasUserInputNode?: boolean
|
||||
disableStartTab?: boolean
|
||||
forceEnableStartTab?: boolean
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const shouldShowStartTab = !noStart
|
||||
const shouldDisableStartTab = !forceEnableStartTab && hasUserInputNode
|
||||
const shouldDisableStartTab = disableStartTab || (!forceEnableStartTab && hasUserInputNode)
|
||||
const startDisabledTip = disableStartTab
|
||||
? t('tabs.startNotSupportedTip', { ns: 'workflow' })
|
||||
: t('tabs.startDisabledTip', { ns: 'workflow' })
|
||||
const tabs = useMemo(() => {
|
||||
const tabConfigs = [{
|
||||
key: TabsEnum.Blocks,
|
||||
@ -71,6 +76,7 @@ export const useTabs = ({
|
||||
name: t('tabs.start', { ns: 'workflow' }),
|
||||
show: shouldShowStartTab,
|
||||
disabled: shouldDisableStartTab,
|
||||
disabledTip: shouldDisableStartTab ? startDisabledTip : undefined,
|
||||
}, {
|
||||
key: TabsEnum.Snippets,
|
||||
name: t('tabs.snippets', { ns: 'workflow' }),
|
||||
@ -78,7 +84,7 @@ export const useTabs = ({
|
||||
}]
|
||||
|
||||
return tabConfigs.filter(tab => tab.show)
|
||||
}, [t, noBlocks, noSources, noTools, shouldShowStartTab, shouldDisableStartTab])
|
||||
}, [t, noBlocks, noSources, noTools, shouldShowStartTab, shouldDisableStartTab, startDisabledTip])
|
||||
|
||||
const getValidTabKey = useCallback((targetKey?: TabsEnum) => {
|
||||
if (!targetKey)
|
||||
|
||||
@ -30,7 +30,9 @@ import {
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
||||
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||
import useNodes from '@/app/components/workflow/store/workflow/use-nodes'
|
||||
import { FlowType } from '@/types/common'
|
||||
import { BlockEnum, isTriggerNode } from '../types'
|
||||
import { useTabs } from './hooks'
|
||||
import Snippets from './snippets'
|
||||
@ -89,6 +91,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const nodes = useNodes()
|
||||
const flowType = useHooksStore(s => s.configsMap?.flowType)
|
||||
const [searchText, setSearchText] = useState('')
|
||||
const [snippetsLoading, setSnippetsLoading] = useState(() => Boolean(openFromProps) && defaultActiveTab === TabsEnum.Snippets)
|
||||
const [tags, setTags] = useState<string[]>([])
|
||||
@ -122,6 +125,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
// Default rule: user input option is only available when no Start node nor Trigger node exists on canvas.
|
||||
const defaultAllowUserInputSelection = !hasUserInputNode && !hasTriggerNode
|
||||
const canSelectUserInput = allowUserInputSelection ?? defaultAllowUserInputSelection
|
||||
const disableStartTab = flowType === FlowType.snippet
|
||||
const {
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
@ -133,6 +137,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
||||
noStart: !showStartTab,
|
||||
defaultActiveTab,
|
||||
hasUserInputNode,
|
||||
disableStartTab,
|
||||
forceEnableStartTab,
|
||||
})
|
||||
const open = openFromProps === undefined ? localOpen : openFromProps
|
||||
|
||||
@ -34,6 +34,7 @@ export type TabsProps = {
|
||||
key: TabsEnum
|
||||
name: string
|
||||
disabled?: boolean
|
||||
disabledTip?: string
|
||||
}>
|
||||
filterElem: React.ReactNode
|
||||
noBlocks?: boolean
|
||||
@ -225,7 +226,7 @@ const Tabs: FC<TabsProps> = ({
|
||||
tab={tab}
|
||||
activeTab={activeTab}
|
||||
onActiveTabChange={onActiveTabChange}
|
||||
disabledTip={disabledTip}
|
||||
disabledTip={tab.disabledTip || disabledTip}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@ -177,6 +177,11 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/(commonLayout)/snippets/[snippetId]/page.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/(humanInputLayout)/form/[token]/form.tsx": {
|
||||
"react/set-state-in-effect": {
|
||||
"count": 1
|
||||
@ -4917,6 +4922,11 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/components/evaluation/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/explore/banner/banner-item.tsx": {
|
||||
"react-hooks-extra/no-direct-set-state-in-use-effect": {
|
||||
"count": 1
|
||||
@ -6686,6 +6696,11 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/components/snippets/components/snippet-main.tsx": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/tools/edit-custom-collection-modal/config-credentials.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
@ -10487,6 +10502,11 @@
|
||||
"count": 7
|
||||
}
|
||||
},
|
||||
"service/use-evaluation.ts": {
|
||||
"no-barrel-files/no-barrel-files": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"service/use-flow.ts": {
|
||||
"react/no-unnecessary-use-prefix": {
|
||||
"count": 1
|
||||
|
||||
@ -1148,6 +1148,7 @@
|
||||
"tabs.sources": "Sources",
|
||||
"tabs.start": "Start",
|
||||
"tabs.startDisabledTip": "Trigger node and user input node are mutually exclusive.",
|
||||
"tabs.startNotSupportedTip": "The Start tab is not supported in snippets.",
|
||||
"tabs.tools": "Tools",
|
||||
"tabs.transform": "Transform",
|
||||
"tabs.usePlugin": "Select tool",
|
||||
|
||||
@ -1148,6 +1148,7 @@
|
||||
"tabs.sources": "数据源",
|
||||
"tabs.start": "开始",
|
||||
"tabs.startDisabledTip": "触发节点与用户输入节点互斥。",
|
||||
"tabs.startNotSupportedTip": "Snippet 暂不支持 Start 标签。",
|
||||
"tabs.tools": "工具",
|
||||
"tabs.transform": "转换",
|
||||
"tabs.usePlugin": "选择工具",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user