Add chatflow config dialog

This commit is contained in:
Ilango
2024-03-05 16:25:35 +05:30
parent 8c65900bd2
commit 54c59024c5
6 changed files with 249 additions and 182 deletions
+14 -5
View File
@@ -7,11 +7,20 @@ import {
IconSearch, IconSearch,
IconMessage, IconMessage,
IconPictureInPictureOff, IconPictureInPictureOff,
IconMicrophone IconAdjustmentsHorizontal
} from '@tabler/icons' } from '@tabler/icons'
// constant // constant
const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch, IconMessage, IconPictureInPictureOff, IconMicrophone } const icons = {
IconTrash,
IconFileUpload,
IconFileExport,
IconCopy,
IconSearch,
IconMessage,
IconPictureInPictureOff,
IconAdjustmentsHorizontal
}
// ==============================|| SETTINGS MENU ITEMS ||============================== // // ==============================|| SETTINGS MENU ITEMS ||============================== //
@@ -35,11 +44,11 @@ const settings = {
icon: icons.IconMessage icon: icons.IconMessage
}, },
{ {
id: 'enableSpeechToText', id: 'chatflowConfiguration',
title: 'Speech to Text', title: 'Configuration',
type: 'item', type: 'item',
url: '', url: '',
icon: icons.IconMicrophone icon: icons.IconAdjustmentsHorizontal
}, },
{ {
id: 'duplicateChatflow', id: 'duplicateChatflow',
@@ -0,0 +1,102 @@
import PropTypes from 'prop-types'
import { useState } from 'react'
import { createPortal } from 'react-dom'
import { Box, Dialog, DialogContent, DialogTitle, Tabs, Tab } from '@mui/material'
import SpeechToText from './SpeechToTextDialog'
import Configuration from 'views/chatflows/Configuration'
const CHATFLOW_CONFIGURATION_TABS = [
{
label: 'Rate Limiting',
id: 'rateLimiting'
},
{
label: 'Speech to Text',
id: 'speechToText'
},
{
label: 'Chat Feedback',
id: 'chatFeedback'
},
{
label: 'Allowed Domains',
id: 'allowedDomains'
}
]
function TabPanel(props) {
const { children, value, index, ...other } = props
return (
<div
role='tabpanel'
hidden={value !== index}
id={`chatflow-config-tabpanel-${index}`}
aria-labelledby={`chatflow-config-tab-${index}`}
{...other}
>
{value === index && <Box sx={{ p: 1 }}>{children}</Box>}
</div>
)
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired
}
function a11yProps(index) {
return {
id: `chatflow-config-tab-${index}`,
'aria-controls': `chatflow-config-tabpanel-${index}`
}
}
const ChatflowConfigurationDialog = ({ show, dialogProps, onCancel }) => {
const portalElement = document.getElementById('portal')
const [tabValue, setTabValue] = useState(0)
const component = show ? (
<Dialog
onClose={onCancel}
open={show}
fullWidth
maxWidth={'md'}
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
<div style={{ display: 'flex', flexDirection: 'row' }}>{dialogProps.title}</div>
</DialogTitle>
<DialogContent>
<Tabs
sx={{ position: 'relative', minHeight: '50px', height: '50px' }}
variant='fullWidth'
value={tabValue}
onChange={(event, value) => setTabValue(value)}
aria-label='tabs'
>
{CHATFLOW_CONFIGURATION_TABS.map((item, index) => (
<Tab sx={{ minHeight: '50px', height: '50px' }} key={index} label={item.label} {...a11yProps(index)}></Tab>
))}
</Tabs>
{CHATFLOW_CONFIGURATION_TABS.map((item, index) => (
<TabPanel key={index} value={tabValue} index={index}>
{item.id === 'rateLimiting' && <Configuration />}
{item.id === 'speechToText' ? <SpeechToText dialogProps={dialogProps} /> : null}
</TabPanel>
))}
</DialogContent>
</Dialog>
) : null
return createPortal(component, portalElement)
}
ChatflowConfigurationDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func
}
export default ChatflowConfigurationDialog
@@ -1,25 +1,10 @@
import { createPortal } from 'react-dom'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions' import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions'
// material-ui // material-ui
import { import { Typography, Box, Button, FormControl, ListItem, ListItemAvatar, ListItemText, MenuItem, Select } from '@mui/material'
Typography,
Box,
Button,
Dialog,
DialogContent,
DialogTitle,
DialogActions,
FormControl,
ListItem,
ListItemAvatar,
ListItemText,
MenuItem,
Select
} from '@mui/material'
import { IconX } from '@tabler/icons' import { IconX } from '@tabler/icons'
// Project import // Project import
@@ -33,7 +18,6 @@ import openAISVG from 'assets/images/openai.svg'
import assemblyAIPng from 'assets/images/assemblyai.png' import assemblyAIPng from 'assets/images/assemblyai.png'
// store // store
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
import useNotifier from 'utils/useNotifier' import useNotifier from 'utils/useNotifier'
// API // API
@@ -95,8 +79,7 @@ const speechToTextProviders = {
} }
} }
const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => { const SpeechToText = ({ dialogProps }) => {
const portalElement = document.getElementById('portal')
const dispatch = useDispatch() const dispatch = useDispatch()
useNotifier() useNotifier()
@@ -128,7 +111,6 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
}) })
dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data }) dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data })
} }
onCancel()
} catch (error) { } catch (error) {
const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}` const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}`
enqueueSnackbar({ enqueueSnackbar({
@@ -199,25 +181,8 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
} }
}, [dialogProps]) }, [dialogProps])
useEffect(() => { return (
if (show) dispatch({ type: SHOW_CANVAS_DIALOG }) <>
else dispatch({ type: HIDE_CANVAS_DIALOG })
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
}, [show, dispatch])
const component = (
<Dialog
onClose={onCancel}
open={show}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
Speech To Text Configuration
</DialogTitle>
<DialogContent>
<Box fullWidth sx={{ my: 2, display: 'flex', flexDirection: 'column', gap: 1 }}> <Box fullWidth sx={{ my: 2, display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography>Speech To Text Providers</Typography> <Typography>Speech To Text Providers</Typography>
<FormControl fullWidth> <FormControl fullWidth>
@@ -323,8 +288,6 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
))} ))}
</> </>
)} )}
</DialogContent>
<DialogActions>
<StyledButton <StyledButton
disabled={selectedProvider !== 'none' && !speechToText[selectedProvider]?.credentialId} disabled={selectedProvider !== 'none' && !speechToText[selectedProvider]?.credentialId}
variant='contained' variant='contained'
@@ -332,17 +295,12 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
> >
Save Save
</StyledButton> </StyledButton>
</DialogActions> </>
</Dialog>
) )
return createPortal(component, portalElement)
} }
SpeechToTextDialog.propTypes = { SpeechToText.propTypes = {
show: PropTypes.bool, dialogProps: PropTypes.object
dialogProps: PropTypes.object,
onCancel: PropTypes.func
} }
export default SpeechToTextDialog export default SpeechToText
+14 -14
View File
@@ -28,7 +28,7 @@ import useApi from 'hooks/useApi'
import { generateExportFlowData } from 'utils/genericHelper' import { generateExportFlowData } from 'utils/genericHelper'
import { uiBaseURL } from 'store/constant' import { uiBaseURL } from 'store/constant'
import { SET_CHATFLOW } from 'store/actions' import { SET_CHATFLOW } from 'store/actions'
import SpeechToTextDialog from '../../ui-component/dialog/SpeechToTextDialog' import ChatflowConfigurationDialog from 'ui-component/dialog/ChatflowConfigurationDialog'
// ==============================|| CANVAS HEADER ||============================== // // ==============================|| CANVAS HEADER ||============================== //
@@ -47,12 +47,12 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
const [apiDialogProps, setAPIDialogProps] = useState({}) const [apiDialogProps, setAPIDialogProps] = useState({})
const [analyseDialogOpen, setAnalyseDialogOpen] = useState(false) const [analyseDialogOpen, setAnalyseDialogOpen] = useState(false)
const [analyseDialogProps, setAnalyseDialogProps] = useState({}) const [analyseDialogProps, setAnalyseDialogProps] = useState({})
const [speechToAudioDialogOpen, setSpeechToAudioDialogOpen] = useState(false)
const [speechToAudioDialogProps, setSpeechToAudioialogProps] = useState({})
const [conversationStartersDialogOpen, setConversationStartersDialogOpen] = useState(false) const [conversationStartersDialogOpen, setConversationStartersDialogOpen] = useState(false)
const [conversationStartersDialogProps, setConversationStartersDialogProps] = useState({}) const [conversationStartersDialogProps, setConversationStartersDialogProps] = useState({})
const [viewMessagesDialogOpen, setViewMessagesDialogOpen] = useState(false) const [viewMessagesDialogOpen, setViewMessagesDialogOpen] = useState(false)
const [viewMessagesDialogProps, setViewMessagesDialogProps] = useState({}) const [viewMessagesDialogProps, setViewMessagesDialogProps] = useState({})
const [chatflowConfigurationDialogOpen, setChatflowConfigurationDialogOpen] = useState(false)
const [chatflowConfigurationDialogProps, setChatflowConfigurationDialogProps] = useState({})
const updateChatflowApi = useApi(chatflowsApi.updateChatflow) const updateChatflowApi = useApi(chatflowsApi.updateChatflow)
const canvas = useSelector((state) => state.canvas) const canvas = useSelector((state) => state.canvas)
@@ -74,18 +74,18 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
chatflow: chatflow chatflow: chatflow
}) })
setAnalyseDialogOpen(true) setAnalyseDialogOpen(true)
} else if (setting === 'enableSpeechToText') {
setSpeechToAudioialogProps({
title: 'Speech to Text',
chatflow: chatflow
})
setSpeechToAudioDialogOpen(true)
} else if (setting === 'viewMessages') { } else if (setting === 'viewMessages') {
setViewMessagesDialogProps({ setViewMessagesDialogProps({
title: 'View Messages', title: 'View Messages',
chatflow: chatflow chatflow: chatflow
}) })
setViewMessagesDialogOpen(true) setViewMessagesDialogOpen(true)
} else if (setting === 'chatflowConfiguration') {
setChatflowConfigurationDialogProps({
title: 'Chatflow Configuration',
chatflow: chatflow
})
setChatflowConfigurationDialogOpen(true)
} else if (setting === 'duplicateChatflow') { } else if (setting === 'duplicateChatflow') {
try { try {
localStorage.setItem('duplicatedFlowData', chatflow.flowData) localStorage.setItem('duplicatedFlowData', chatflow.flowData)
@@ -394,11 +394,6 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
/> />
<APICodeDialog show={apiDialogOpen} dialogProps={apiDialogProps} onCancel={() => setAPIDialogOpen(false)} /> <APICodeDialog show={apiDialogOpen} dialogProps={apiDialogProps} onCancel={() => setAPIDialogOpen(false)} />
<AnalyseFlowDialog show={analyseDialogOpen} dialogProps={analyseDialogProps} onCancel={() => setAnalyseDialogOpen(false)} /> <AnalyseFlowDialog show={analyseDialogOpen} dialogProps={analyseDialogProps} onCancel={() => setAnalyseDialogOpen(false)} />
<SpeechToTextDialog
show={speechToAudioDialogOpen}
dialogProps={speechToAudioDialogProps}
onCancel={() => setSpeechToAudioDialogOpen(false)}
/>
<StarterPromptsDialog <StarterPromptsDialog
show={conversationStartersDialogOpen} show={conversationStartersDialogOpen}
dialogProps={conversationStartersDialogProps} dialogProps={conversationStartersDialogProps}
@@ -410,6 +405,11 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
dialogProps={viewMessagesDialogProps} dialogProps={viewMessagesDialogProps}
onCancel={() => setViewMessagesDialogOpen(false)} onCancel={() => setViewMessagesDialogOpen(false)}
/> />
<ChatflowConfigurationDialog
show={chatflowConfigurationDialogOpen}
dialogProps={chatflowConfigurationDialogProps}
onCancel={() => setChatflowConfigurationDialogOpen(false)}
/>
</> </>
) )
} }
@@ -23,7 +23,6 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { Dropdown } from 'ui-component/dropdown/Dropdown' import { Dropdown } from 'ui-component/dropdown/Dropdown'
import ShareChatbot from './ShareChatbot' import ShareChatbot from './ShareChatbot'
import EmbedChat from './EmbedChat' import EmbedChat from './EmbedChat'
import Configuration from './Configuration'
// Const // Const
import { baseURL } from 'store/constant' import { baseURL } from 'store/constant'
@@ -84,7 +83,7 @@ const APICodeDialog = ({ show, dialogProps, onCancel }) => {
const navigate = useNavigate() const navigate = useNavigate()
const dispatch = useDispatch() const dispatch = useDispatch()
const codes = ['Embed', 'Python', 'JavaScript', 'cURL', 'Share Chatbot', 'Configuration'] const codes = ['Embed', 'Python', 'JavaScript', 'cURL', 'Share Chatbot']
const [value, setValue] = useState(0) const [value, setValue] = useState(0)
const [keyOptions, setKeyOptions] = useState([]) const [keyOptions, setKeyOptions] = useState([])
const [apiKeys, setAPIKeys] = useState([]) const [apiKeys, setAPIKeys] = useState([])
@@ -721,7 +720,6 @@ formData.append("openAIApiKey[openAIEmbeddings_0]", "sk-my-openai-2nd-key")`
{codeLang === 'Share Chatbot' && !chatflowApiKeyId && ( {codeLang === 'Share Chatbot' && !chatflowApiKeyId && (
<ShareChatbot isSessionMemory={dialogProps.isSessionMemory} /> <ShareChatbot isSessionMemory={dialogProps.isSessionMemory} />
)} )}
{codeLang === 'Configuration' && <Configuration />}
</TabPanel> </TabPanel>
))} ))}
</DialogContent> </DialogContent>
+1 -1
View File
@@ -65,7 +65,7 @@ const Settings = ({ chatflow, isSettingsOpen, anchorEl, onSettingsItemClick, onU
width: customization.isOpen.findIndex((id) => id === menu?.id) > -1 ? 8 : 6, width: customization.isOpen.findIndex((id) => id === menu?.id) > -1 ? 8 : 6,
height: customization.isOpen.findIndex((id) => id === menu?.id) > -1 ? 8 : 6 height: customization.isOpen.findIndex((id) => id === menu?.id) > -1 ? 8 : 6
}} }}
fontSize={level > 0 ? 'inherit' : 'medium'} fontSize={'inherit'}
/> />
) )
return ( return (