Feature/Add auto sync nodes (#2307)

add auto sync nodes
This commit is contained in:
Henry Heng
2024-05-02 18:40:10 +01:00
committed by GitHub
parent d5a97060e2
commit c5e06bce6d
3 changed files with 143 additions and 5 deletions
+4 -2
View File
@@ -70,6 +70,8 @@ const CanvasNode = ({ data }) => {
componentNode?.deprecateMessage ??
'This node will be deprecated in the next release. Change to a new node tagged with NEW'
)
} else {
setWarningMessage('')
}
}
}, [canvas.componentNodes, data.name, data.version])
@@ -241,8 +243,8 @@ const CanvasNode = ({ data }) => {
</Typography>
</Box>
<Divider />
{data.outputAnchors.map((outputAnchor, index) => (
<NodeOutputHandler key={index} outputAnchor={outputAnchor} data={data} />
{data.outputAnchors.map((outputAnchor) => (
<NodeOutputHandler key={JSON.stringify(data)} outputAnchor={outputAnchor} data={data} />
))}
</Box>
</NodeTooltip>
+73 -3
View File
@@ -15,7 +15,7 @@ import {
import { omit, cloneDeep } from 'lodash'
// material-ui
import { Toolbar, Box, AppBar, Button } from '@mui/material'
import { Toolbar, Box, AppBar, Button, Fab } from '@mui/material'
import { useTheme } from '@mui/material/styles'
// project imports
@@ -38,10 +38,17 @@ import useApi from '@/hooks/useApi'
import useConfirm from '@/hooks/useConfirm'
// icons
import { IconX } from '@tabler/icons'
import { IconX, IconRefreshAlert } from '@tabler/icons'
// utils
import { getUniqueNodeId, initNode, rearrangeToolsOrdering, getUpsertDetails } from '@/utils/genericHelper'
import {
getUniqueNodeId,
initNode,
rearrangeToolsOrdering,
getUpsertDetails,
updateOutdatedNodeData,
updateOutdatedNodeEdge
} from '@/utils/genericHelper'
import useNotifier from '@/utils/useNotifier'
// const
@@ -84,6 +91,7 @@ const Canvas = () => {
const [selectedNode, setSelectedNode] = useState(null)
const [isUpsertButtonEnabled, setIsUpsertButtonEnabled] = useState(false)
const [isSyncNodesButtonEnabled, setIsSyncNodesButtonEnabled] = useState(false)
const reactFlowWrapper = useRef(null)
@@ -305,6 +313,28 @@ const Canvas = () => {
[reactFlowInstance]
)
const syncNodes = () => {
const componentNodes = canvas.componentNodes
const cloneNodes = cloneDeep(nodes)
const cloneEdges = cloneDeep(edges)
let toBeRemovedEdges = []
for (let i = 0; i < cloneNodes.length; i++) {
const node = cloneNodes[i]
const componentNode = componentNodes.find((cn) => cn.name === node.data.name)
if (componentNode && componentNode.version > node.data.version) {
cloneNodes[i].data = updateOutdatedNodeData(componentNode, node.data)
toBeRemovedEdges.push(...updateOutdatedNodeEdge(cloneNodes[i].data, cloneEdges))
}
}
setNodes(cloneNodes)
setEdges(cloneEdges.filter((edge) => !toBeRemovedEdges.includes(edge)))
setDirty()
setIsSyncNodesButtonEnabled(false)
}
const saveChatflowSuccess = () => {
dispatch({ type: REMOVE_DIRTY })
enqueueSnackbar({
@@ -347,6 +377,21 @@ const Canvas = () => {
else setIsUpsertButtonEnabled(false)
}
const checkIfSyncNodesAvailable = (nodes) => {
const componentNodes = canvas.componentNodes
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i]
const componentNode = componentNodes.find((cn) => cn.name === node.data.name)
if (componentNode && componentNode.version > node.data.version) {
setIsSyncNodesButtonEnabled(true)
return
}
}
setIsSyncNodesButtonEnabled(false)
}
// ==============================|| useEffect ||============================== //
// Get specific chatflow successful
@@ -416,11 +461,16 @@ const Canvas = () => {
if (canvasDataStore.chatflow) {
const flowData = canvasDataStore.chatflow.flowData ? JSON.parse(canvasDataStore.chatflow.flowData) : []
checkIfUpsertAvailable(flowData.nodes || [], flowData.edges || [])
checkIfSyncNodesAvailable(flowData.nodes || [])
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [canvasDataStore.chatflow])
// Initialization
useEffect(() => {
setIsSyncNodesButtonEnabled(false)
setIsUpsertButtonEnabled(false)
if (chatflowId) {
getSpecificChatflowApi.request(chatflowId)
} else {
@@ -532,6 +582,26 @@ const Canvas = () => {
/>
<Background color='#aaa' gap={16} />
<AddNodes nodesData={getNodesApi.data} node={selectedNode} />
{isSyncNodesButtonEnabled && (
<Fab
sx={{
left: 40,
top: 20,
color: 'white',
background: 'orange',
'&:hover': {
background: 'orange',
backgroundImage: `linear-gradient(rgb(0 0 0/10%) 0 0)`
}
}}
size='small'
aria-label='sync'
title='Sync Nodes'
onClick={() => syncNodes()}
>
<IconRefreshAlert />
</Fab>
)}
{isUpsertButtonEnabled && <VectorStorePopUp chatflowid={chatflowId} />}
<ChatPopUp chatflowid={chatflowId} />
</ReactFlow>