Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion packages/ui/src/views/agentflowsv2/Canvas.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import ConfirmDialog from '@/ui-component/dialog/ConfirmDialog'
import EditNodeDialog from '@/views/agentflowsv2/EditNodeDialog'
import ChatPopUp from '@/views/chatmessage/ChatPopUp'
import ValidationPopUp from '@/views/chatmessage/ValidationPopUp'
import SaveChatflowDialog from '@/ui-component/dialog/SaveChatflowDialog'
import { flowContext } from '@/store/context/ReactFlowContext'

// API
Expand Down Expand Up @@ -100,6 +101,7 @@ const AgentflowCanvas = () => {
const [isSyncNodesButtonEnabled, setIsSyncNodesButtonEnabled] = useState(false)
const [editNodeDialogOpen, setEditNodeDialogOpen] = useState(false)
const [editNodeDialogProps, setEditNodeDialogProps] = useState({})
const [flowDialogOpen, setFlowDialogOpen] = useState(false)
const [isSnappingEnabled, setIsSnappingEnabled] = useState(false)

const reactFlowWrapper = useRef(null)
Expand Down Expand Up @@ -240,6 +242,15 @@ const AgentflowCanvas = () => {
}
}

const onConfirmSaveName = (flowName) => {
setFlowDialogOpen(false)
handleSaveFlow(flowName)
}

const openSaveDialog = () => {
setFlowDialogOpen(true)
}

// eslint-disable-next-line
const onNodeClick = useCallback((event, clickedNode) => {
setSelectedNode(clickedNode)
Expand Down Expand Up @@ -785,13 +796,28 @@ const AgentflowCanvas = () => {
<IconRefreshAlert />
</Fab>
)}
<ChatPopUp isAgentCanvas={true} chatflowid={chatflowId} onOpenChange={setChatPopupOpen} />
<ChatPopUp
isAgentCanvas={true}
chatflowid={chatflowId}
onOpenChange={setChatPopupOpen}
onOpenSaveDialog={openSaveDialog}
/>
{!chatPopupOpen && <ValidationPopUp isAgentCanvas={true} chatflowid={chatflowId} />}
</ReactFlow>
</div>
</div>
</Box>
<ConfirmDialog />
<SaveChatflowDialog
show={flowDialogOpen}
dialogProps={{
title: 'Save New Agent Flow',
confirmButtonName: 'Save',
cancelButtonName: 'Cancel'
}}
onCancel={() => setFlowDialogOpen(false)}
onConfirm={onConfirmSaveName}
/>
</Box>
</>
)
Expand Down
27 changes: 25 additions & 2 deletions packages/ui/src/views/canvas/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import StickyNote from './StickyNote'
import CanvasHeader from './CanvasHeader'
import AddNodes from './AddNodes'
import ConfirmDialog from '@/ui-component/dialog/ConfirmDialog'
import SaveChatflowDialog from '@/ui-component/dialog/SaveChatflowDialog'
import ChatPopUp from '@/views/chatmessage/ChatPopUp'
import VectorStorePopUp from '@/views/vectorstore/VectorStorePopUp'
import { flowContext } from '@/store/context/ReactFlowContext'
Expand Down Expand Up @@ -104,6 +105,7 @@ const Canvas = () => {
const [lastUpdatedDateTime, setLasUpdatedDateTime] = useState('')
const [chatflowName, setChatflowName] = useState('')
const [flowData, setFlowData] = useState('')
const [flowDialogOpen, setFlowDialogOpen] = useState(false)

// ==============================|| Chatflow API ||============================== //

Expand Down Expand Up @@ -243,6 +245,16 @@ const Canvas = () => {
}
}

const openSaveDialog = () => {
if (chatflow?.id) {
// If chatflow has an ID, save directly using the flow name
handleSaveFlow(chatflow.name)
} else {
// If no ID, open the save dialog
setFlowDialogOpen(true)
}
}

// eslint-disable-next-line
const onNodeClick = useCallback((event, clickedNode) => {
setSelectedNode(clickedNode)
Expand Down Expand Up @@ -431,7 +443,8 @@ const Canvas = () => {
const chatflow = createNewChatflowApi.data
dispatch({ type: SET_CHATFLOW, chatflow })
saveChatflowSuccess()
window.history.replaceState(state, null, `/${isAgentCanvas ? 'agentcanvas' : 'canvas'}/${chatflow.id}`)
setFlowDialogOpen(false) // Close the save dialog
navigate(`/${isAgentCanvas ? 'agentcanvas' : 'canvas'}/${chatflow.id}`)
} else if (createNewChatflowApi.error) {
errorFailed(`Failed to retrieve ${canvasTitle}: ${createNewChatflowApi.error.response.data.message}`)
}
Expand Down Expand Up @@ -645,12 +658,22 @@ const Canvas = () => {
</Fab>
)}
{isUpsertButtonEnabled && <VectorStorePopUp chatflowid={chatflowId} />}
<ChatPopUp isAgentCanvas={isAgentCanvas} chatflowid={chatflowId} />
<ChatPopUp isAgentCanvas={isAgentCanvas} chatflowid={chatflowId} onOpenSaveDialog={openSaveDialog} />
</ReactFlow>
</div>
</div>
</Box>
<ConfirmDialog />
<SaveChatflowDialog
show={flowDialogOpen}
dialogProps={{
title: 'Save Flow',
cancelButtonName: 'Cancel',
confirmButtonName: 'Save'
}}
onCancel={() => setFlowDialogOpen(false)}
onConfirm={(name) => handleSaveFlow(name)}
/>
</Box>
</>
)
Expand Down
45 changes: 42 additions & 3 deletions packages/ui/src/views/chatmessage/ChatMessage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import {
IconSquareFilled,
IconCheck,
IconPaperclip,
IconSparkles
IconSparkles,
IconDeviceFloppy
} from '@tabler/icons-react'
import robotPNG from '@/assets/images/robot.png'
import userPNG from '@/assets/images/account.png'
Expand Down Expand Up @@ -162,7 +163,7 @@ CardWithDeleteOverlay.propTypes = {
onDelete: PropTypes.func
}

const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setPreviews }) => {
const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setPreviews, onOpenSaveDialog }) => {
const theme = useTheme()
const customization = useSelector((state) => state.customization)

Expand Down Expand Up @@ -1672,6 +1673,43 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
}
}

// If no chatflowid and this is an agent canvas, show save prompt
if (!chatflowid) {
const handleSaveFlow = () => {
// Use the proper Flowise save dialog
if (onOpenSaveDialog) {
onOpenSaveDialog()
}
}

return (
<Box
sx={{
width: '100%',
height: '100%',
position: 'relative',
backgroundColor: theme.palette.background.paper,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
p: 3
}}
>
<IconDeviceFloppy size={48} style={{ marginBottom: 16, color: theme.palette.text.secondary }} />
<Typography variant='h6' gutterBottom>
Save Flow to Continue
</Typography>
<Typography variant='body2' color='text.secondary' align='center' sx={{ mb: 3 }}>
You need to save this {isAgentCanvas ? 'agent flow' : 'chatflow'} before you can test it with messages.
</Typography>
<Button variant='contained' color='primary' onClick={handleSaveFlow} startIcon={<IconDeviceFloppy size={16} />}>
Save Flow
</Button>
</Box>
)
}

if (isConfigLoading) {
return (
<Box
Expand Down Expand Up @@ -2507,7 +2545,8 @@ ChatMessage.propTypes = {
isAgentCanvas: PropTypes.bool,
isDialog: PropTypes.bool,
previews: PropTypes.array,
setPreviews: PropTypes.func
setPreviews: PropTypes.func,
onOpenSaveDialog: PropTypes.func
}

export default memo(ChatMessage)
6 changes: 4 additions & 2 deletions packages/ui/src/views/chatmessage/ChatPopUp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackba
// Utils
import { getLocalStorageChatflow, removeLocalStorageChatHistory } from '@/utils/genericHelper'

const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange, onOpenSaveDialog }) => {
const theme = useTheme()
const { confirm } = useConfirm()
const dispatch = useDispatch()
Expand Down Expand Up @@ -215,6 +215,7 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
open={open}
previews={previews}
setPreviews={setPreviews}
onOpenSaveDialog={onOpenSaveDialog}
/>
</MainCard>
</ClickAwayListener>
Expand All @@ -238,7 +239,8 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
ChatPopUp.propTypes = {
chatflowid: PropTypes.string,
isAgentCanvas: PropTypes.bool,
onOpenChange: PropTypes.func
onOpenChange: PropTypes.func,
onOpenSaveDialog: PropTypes.func
}

export default memo(ChatPopUp)