diff --git a/packages/ui/src/menu-items/settings.js b/packages/ui/src/menu-items/settings.js index 3e43d0257..9b83aaa47 100644 --- a/packages/ui/src/menu-items/settings.js +++ b/packages/ui/src/menu-items/settings.js @@ -1,14 +1,5 @@ // assets -import { - IconTrash, - IconFileUpload, - IconFileExport, - IconCopy, - IconSearch, - IconMessage, - IconPictureInPictureOff, - IconAdjustmentsHorizontal -} from '@tabler/icons' +import { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconMessage, IconAdjustmentsHorizontal } from '@tabler/icons' // constant const icons = { @@ -16,9 +7,7 @@ const icons = { IconFileUpload, IconFileExport, IconCopy, - IconSearch, IconMessage, - IconPictureInPictureOff, IconAdjustmentsHorizontal } @@ -29,13 +18,6 @@ const settings = { title: '', type: 'group', children: [ - { - id: 'conversationStarters', - title: 'Starter Prompts', - type: 'item', - url: '', - icon: icons.IconPictureInPictureOff - }, { id: 'viewMessages', title: 'View Messages', @@ -71,13 +53,6 @@ const settings = { url: '', icon: icons.IconFileExport }, - { - id: 'analyseChatflow', - title: 'Analyse Chatflow', - type: 'item', - url: '', - icon: icons.IconSearch - }, { id: 'deleteChatflow', title: 'Delete Chatflow', diff --git a/packages/ui/src/ui-component/dialog/AllowedDomainsDialog.js b/packages/ui/src/ui-component/dialog/AllowedDomains.js similarity index 100% rename from packages/ui/src/ui-component/dialog/AllowedDomainsDialog.js rename to packages/ui/src/ui-component/dialog/AllowedDomains.js diff --git a/packages/ui/src/ui-component/dialog/AnalyseFlow.js b/packages/ui/src/ui-component/dialog/AnalyseFlow.js new file mode 100644 index 000000000..8bebea316 --- /dev/null +++ b/packages/ui/src/ui-component/dialog/AnalyseFlow.js @@ -0,0 +1,325 @@ +import { useDispatch } from 'react-redux' +import { useState, useEffect } from 'react' +import PropTypes from 'prop-types' +import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions' + +// material-ui +import { + Typography, + Box, + Button, + Accordion, + AccordionSummary, + AccordionDetails, + ListItem, + ListItemAvatar, + ListItemText +} from '@mui/material' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import { IconX } from '@tabler/icons' + +// Project import +import CredentialInputHandler from 'views/canvas/CredentialInputHandler' +import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser' +import { SwitchInput } from 'ui-component/switch/Switch' +import { Input } from 'ui-component/input/Input' +import { StyledButton } from 'ui-component/button/StyledButton' +import langsmithPNG from 'assets/images/langchain.png' +import langfuseSVG from 'assets/images/langfuse.svg' +import lunarySVG from 'assets/images/lunary.svg' + +// store +import useNotifier from 'utils/useNotifier' + +// API +import chatflowsApi from 'api/chatflows' + +const analyticProviders = [ + { + label: 'LangSmith', + name: 'langSmith', + icon: langsmithPNG, + url: 'https://smith.langchain.com', + inputs: [ + { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['langsmithApi'] + }, + { + label: 'Project Name', + name: 'projectName', + type: 'string', + optional: true, + description: 'If not provided, default will be used', + placeholder: 'default' + }, + { + label: 'On/Off', + name: 'status', + type: 'boolean', + optional: true + } + ] + }, + { + label: 'LangFuse', + name: 'langFuse', + icon: langfuseSVG, + url: 'https://langfuse.com', + inputs: [ + { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['langfuseApi'] + }, + { + label: 'Release', + name: 'release', + type: 'string', + optional: true, + description: 'The release number/hash of the application to provide analytics grouped by release' + }, + { + label: 'On/Off', + name: 'status', + type: 'boolean', + optional: true + } + ] + }, + { + label: 'Lunary', + name: 'lunary', + icon: lunarySVG, + url: 'https://lunary.ai', + inputs: [ + { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['lunaryApi'] + }, + { + label: 'On/Off', + name: 'status', + type: 'boolean', + optional: true + } + ] + } +] + +const AnalyseFlow = ({ dialogProps, onCancel }) => { + const dispatch = useDispatch() + + useNotifier() + + const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args)) + const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args)) + + const [analytic, setAnalytic] = useState({}) + const [providerExpanded, setProviderExpanded] = useState({}) + + const onSave = async () => { + try { + const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, { + analytic: JSON.stringify(analytic) + }) + if (saveResp.data) { + enqueueSnackbar({ + message: 'Analytic Configuration Saved', + options: { + key: new Date().getTime() + Math.random(), + variant: 'success', + action: (key) => ( + closeSnackbar(key)}> + + + ) + } + }) + dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data }) + } + onCancel() + } catch (error) { + const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}` + enqueueSnackbar({ + message: `Failed to save Analytic Configuration: ${errorData}`, + options: { + key: new Date().getTime() + Math.random(), + variant: 'error', + persist: true, + action: (key) => ( + closeSnackbar(key)}> + + + ) + } + }) + } + } + + const setValue = (value, providerName, inputParamName) => { + let newVal = {} + if (!Object.prototype.hasOwnProperty.call(analytic, providerName)) { + newVal = { ...analytic, [providerName]: {} } + } else { + newVal = { ...analytic } + } + + newVal[providerName][inputParamName] = value + setAnalytic(newVal) + } + + const handleAccordionChange = (providerName) => (event, isExpanded) => { + const accordianProviders = { ...providerExpanded } + accordianProviders[providerName] = isExpanded + setProviderExpanded(accordianProviders) + } + + useEffect(() => { + if (dialogProps.chatflow && dialogProps.chatflow.analytic) { + try { + setAnalytic(JSON.parse(dialogProps.chatflow.analytic)) + } catch (e) { + setAnalytic({}) + console.error(e) + } + } + + return () => { + setAnalytic({}) + setProviderExpanded({}) + } + }, [dialogProps]) + + return ( + <> + {analyticProviders.map((provider, index) => ( + + } aria-controls={provider.name} id={provider.name}> + + + + + + + + {provider.url} + + } + /> + {analytic[provider.name] && analytic[provider.name].status && ( + + + ON + + )} + + + + {provider.inputs.map((inputParam, index) => ( + + + + {inputParam.label} + {!inputParam.optional && *} + {inputParam.description && ( + + )} + + + {providerExpanded[provider.name] && inputParam.type === 'credential' && ( + setValue(newValue, provider.name, 'credentialId')} + /> + )} + {providerExpanded[provider.name] && inputParam.type === 'boolean' && ( + setValue(newValue, provider.name, inputParam.name)} + value={ + analytic[provider.name] ? analytic[provider.name][inputParam.name] : inputParam.default ?? false + } + /> + )} + {providerExpanded[provider.name] && + (inputParam.type === 'string' || inputParam.type === 'password' || inputParam.type === 'number') && ( + setValue(newValue, provider.name, inputParam.name)} + value={ + analytic[provider.name] + ? analytic[provider.name][inputParam.name] + : inputParam.default ?? '' + } + /> + )} + + ))} + + + ))} + + Save + + > + ) +} + +AnalyseFlow.propTypes = { + show: PropTypes.bool, + dialogProps: PropTypes.object, + onCancel: PropTypes.func +} + +export default AnalyseFlow diff --git a/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js b/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js deleted file mode 100644 index a326db9a5..000000000 --- a/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js +++ /dev/null @@ -1,358 +0,0 @@ -import { createPortal } from 'react-dom' -import { useDispatch } from 'react-redux' -import { useState, useEffect } from 'react' -import PropTypes from 'prop-types' -import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions' - -// material-ui -import { - Typography, - Box, - Button, - Dialog, - DialogContent, - DialogTitle, - DialogActions, - Accordion, - AccordionSummary, - AccordionDetails, - ListItem, - ListItemAvatar, - ListItemText -} from '@mui/material' -import ExpandMoreIcon from '@mui/icons-material/ExpandMore' -import { IconX } from '@tabler/icons' - -// Project import -import CredentialInputHandler from 'views/canvas/CredentialInputHandler' -import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser' -import { SwitchInput } from 'ui-component/switch/Switch' -import { Input } from 'ui-component/input/Input' -import { StyledButton } from 'ui-component/button/StyledButton' -import langsmithPNG from 'assets/images/langchain.png' -import langfuseSVG from 'assets/images/langfuse.svg' -import lunarySVG from 'assets/images/lunary.svg' - -// store -import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions' -import useNotifier from 'utils/useNotifier' - -// API -import chatflowsApi from 'api/chatflows' - -const analyticProviders = [ - { - label: 'LangSmith', - name: 'langSmith', - icon: langsmithPNG, - url: 'https://smith.langchain.com', - inputs: [ - { - label: 'Connect Credential', - name: 'credential', - type: 'credential', - credentialNames: ['langsmithApi'] - }, - { - label: 'Project Name', - name: 'projectName', - type: 'string', - optional: true, - description: 'If not provided, default will be used', - placeholder: 'default' - }, - { - label: 'On/Off', - name: 'status', - type: 'boolean', - optional: true - } - ] - }, - { - label: 'LangFuse', - name: 'langFuse', - icon: langfuseSVG, - url: 'https://langfuse.com', - inputs: [ - { - label: 'Connect Credential', - name: 'credential', - type: 'credential', - credentialNames: ['langfuseApi'] - }, - { - label: 'Release', - name: 'release', - type: 'string', - optional: true, - description: 'The release number/hash of the application to provide analytics grouped by release' - }, - { - label: 'On/Off', - name: 'status', - type: 'boolean', - optional: true - } - ] - }, - { - label: 'Lunary', - name: 'lunary', - icon: lunarySVG, - url: 'https://lunary.ai', - inputs: [ - { - label: 'Connect Credential', - name: 'credential', - type: 'credential', - credentialNames: ['lunaryApi'] - }, - { - label: 'On/Off', - name: 'status', - type: 'boolean', - optional: true - } - ] - } -] - -const AnalyseFlowDialog = ({ show, dialogProps, onCancel }) => { - const portalElement = document.getElementById('portal') - const dispatch = useDispatch() - - useNotifier() - - const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args)) - const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args)) - - const [analytic, setAnalytic] = useState({}) - const [providerExpanded, setProviderExpanded] = useState({}) - - const onSave = async () => { - try { - const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, { - analytic: JSON.stringify(analytic) - }) - if (saveResp.data) { - enqueueSnackbar({ - message: 'Analytic Configuration Saved', - options: { - key: new Date().getTime() + Math.random(), - variant: 'success', - action: (key) => ( - closeSnackbar(key)}> - - - ) - } - }) - dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data }) - } - onCancel() - } catch (error) { - const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}` - enqueueSnackbar({ - message: `Failed to save Analytic Configuration: ${errorData}`, - options: { - key: new Date().getTime() + Math.random(), - variant: 'error', - persist: true, - action: (key) => ( - closeSnackbar(key)}> - - - ) - } - }) - } - } - - const setValue = (value, providerName, inputParamName) => { - let newVal = {} - if (!Object.prototype.hasOwnProperty.call(analytic, providerName)) { - newVal = { ...analytic, [providerName]: {} } - } else { - newVal = { ...analytic } - } - - newVal[providerName][inputParamName] = value - setAnalytic(newVal) - } - - const handleAccordionChange = (providerName) => (event, isExpanded) => { - const accordianProviders = { ...providerExpanded } - accordianProviders[providerName] = isExpanded - setProviderExpanded(accordianProviders) - } - - useEffect(() => { - if (dialogProps.chatflow && dialogProps.chatflow.analytic) { - try { - setAnalytic(JSON.parse(dialogProps.chatflow.analytic)) - } catch (e) { - setAnalytic({}) - console.error(e) - } - } - - return () => { - setAnalytic({}) - setProviderExpanded({}) - } - }, [dialogProps]) - - useEffect(() => { - if (show) dispatch({ type: SHOW_CANVAS_DIALOG }) - else dispatch({ type: HIDE_CANVAS_DIALOG }) - return () => dispatch({ type: HIDE_CANVAS_DIALOG }) - }, [show, dispatch]) - - const component = show ? ( - - - Analyse Chatflow - - - {analyticProviders.map((provider, index) => ( - - } aria-controls={provider.name} id={provider.name}> - - - - - - - - {provider.url} - - } - /> - {analytic[provider.name] && analytic[provider.name].status && ( - - - ON - - )} - - - - {provider.inputs.map((inputParam, index) => ( - - - - {inputParam.label} - {!inputParam.optional && *} - {inputParam.description && ( - - )} - - - {providerExpanded[provider.name] && inputParam.type === 'credential' && ( - setValue(newValue, provider.name, 'credentialId')} - /> - )} - {providerExpanded[provider.name] && inputParam.type === 'boolean' && ( - setValue(newValue, provider.name, inputParam.name)} - value={ - analytic[provider.name] - ? analytic[provider.name][inputParam.name] - : inputParam.default ?? false - } - /> - )} - {providerExpanded[provider.name] && - (inputParam.type === 'string' || - inputParam.type === 'password' || - inputParam.type === 'number') && ( - setValue(newValue, provider.name, inputParam.name)} - value={ - analytic[provider.name] - ? analytic[provider.name][inputParam.name] - : inputParam.default ?? '' - } - /> - )} - - ))} - - - ))} - - - - Save - - - - ) : null - - return createPortal(component, portalElement) -} - -AnalyseFlowDialog.propTypes = { - show: PropTypes.bool, - dialogProps: PropTypes.object, - onCancel: PropTypes.func -} - -export default AnalyseFlowDialog diff --git a/packages/ui/src/ui-component/dialog/ChatFeedbackDialog.js b/packages/ui/src/ui-component/dialog/ChatFeedback.js similarity index 97% rename from packages/ui/src/ui-component/dialog/ChatFeedbackDialog.js rename to packages/ui/src/ui-component/dialog/ChatFeedback.js index 493f1031b..2ea2db38f 100644 --- a/packages/ui/src/ui-component/dialog/ChatFeedbackDialog.js +++ b/packages/ui/src/ui-component/dialog/ChatFeedback.js @@ -93,7 +93,7 @@ const ChatFeedback = ({ dialogProps }) => { - + Save > diff --git a/packages/ui/src/ui-component/dialog/ChatflowConfigurationDialog.js b/packages/ui/src/ui-component/dialog/ChatflowConfigurationDialog.js index 13ca4a15e..1c30aa0c0 100644 --- a/packages/ui/src/ui-component/dialog/ChatflowConfigurationDialog.js +++ b/packages/ui/src/ui-component/dialog/ChatflowConfigurationDialog.js @@ -2,16 +2,22 @@ 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 SpeechToText from './SpeechToText' import Configuration from 'views/chatflows/Configuration' -import AllowedDomains from './AllowedDomainsDialog' -import ChatFeedback from './ChatFeedbackDialog' +import AllowedDomains from './AllowedDomains' +import ChatFeedback from './ChatFeedback' +import AnalyseFlow from './AnalyseFlow' +import StarterPrompts from './StarterPrompts' const CHATFLOW_CONFIGURATION_TABS = [ { label: 'Rate Limiting', id: 'rateLimiting' }, + { + label: 'Starter Prompts', + id: 'conversationStarters' + }, { label: 'Speech to Text', id: 'speechToText' @@ -23,6 +29,10 @@ const CHATFLOW_CONFIGURATION_TABS = [ { label: 'Allowed Domains', id: 'allowedDomains' + }, + { + label: 'Analyse Chatflow', + id: 'analyseChatflow' } ] @@ -34,7 +44,7 @@ function TabPanel(props) { hidden={value !== index} id={`chatflow-config-tabpanel-${index}`} aria-labelledby={`chatflow-config-tab-${index}`} - style={{ paddingTop: '1rem' }} + style={{ width: '100%', paddingTop: '1rem' }} {...other} > {value === index && {children}} @@ -73,22 +83,28 @@ const ChatflowConfigurationDialog = ({ show, dialogProps, onCancel }) => { setTabValue(value)} aria-label='tabs' > {CHATFLOW_CONFIGURATION_TABS.map((item, index) => ( - + ))} {CHATFLOW_CONFIGURATION_TABS.map((item, index) => ( {item.id === 'rateLimiting' && } + {item.id === 'conversationStarters' ? : null} {item.id === 'speechToText' ? : null} {item.id === 'chatFeedback' ? : null} {item.id === 'allowedDomains' ? : null} + {item.id === 'analyseChatflow' ? : null} ))} diff --git a/packages/ui/src/ui-component/dialog/SpeechToTextDialog.js b/packages/ui/src/ui-component/dialog/SpeechToText.js similarity index 98% rename from packages/ui/src/ui-component/dialog/SpeechToTextDialog.js rename to packages/ui/src/ui-component/dialog/SpeechToText.js index 7199bf8c7..eb5e5af64 100644 --- a/packages/ui/src/ui-component/dialog/SpeechToTextDialog.js +++ b/packages/ui/src/ui-component/dialog/SpeechToText.js @@ -183,8 +183,10 @@ const SpeechToText = ({ dialogProps }) => { return ( <> - - Speech To Text Providers + + + Providers + None @@ -289,6 +291,7 @@ const SpeechToText = ({ dialogProps }) => { > )} { + const dispatch = useDispatch() + + useNotifier() + + const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args)) + const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args)) + + const [inputFields, setInputFields] = useState([ + { + prompt: '' + } + ]) + + const [chatbotConfig, setChatbotConfig] = useState({}) + + const addInputField = () => { + setInputFields([ + ...inputFields, + { + prompt: '' + } + ]) + } + const removeInputFields = (index) => { + const rows = [...inputFields] + rows.splice(index, 1) + setInputFields(rows) + } + + const handleChange = (index, evnt) => { + const { name, value } = evnt.target + const list = [...inputFields] + list[index][name] = value + setInputFields(list) + } + + const onSave = async () => { + try { + let value = { + starterPrompts: { + ...inputFields + } + } + chatbotConfig.starterPrompts = value.starterPrompts + const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, { + chatbotConfig: JSON.stringify(chatbotConfig) + }) + if (saveResp.data) { + enqueueSnackbar({ + message: 'Conversation Starter Prompts Saved', + options: { + key: new Date().getTime() + Math.random(), + variant: 'success', + action: (key) => ( + closeSnackbar(key)}> + + + ) + } + }) + dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data }) + } + onConfirm() + } catch (error) { + const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}` + enqueueSnackbar({ + message: `Failed to save Conversation Starter Prompts: ${errorData}`, + options: { + key: new Date().getTime() + Math.random(), + variant: 'error', + persist: true, + action: (key) => ( + closeSnackbar(key)}> + + + ) + } + }) + } + } + + useEffect(() => { + if (dialogProps.chatflow && dialogProps.chatflow.chatbotConfig) { + try { + let chatbotConfig = JSON.parse(dialogProps.chatflow.chatbotConfig) + setChatbotConfig(chatbotConfig || {}) + if (chatbotConfig.starterPrompts) { + let inputFields = [] + Object.getOwnPropertyNames(chatbotConfig.starterPrompts).forEach((key) => { + if (chatbotConfig.starterPrompts[key]) { + inputFields.push(chatbotConfig.starterPrompts[key]) + } + }) + setInputFields(inputFields) + } else { + setInputFields([ + { + prompt: '' + } + ]) + } + } catch (e) { + setInputFields([ + { + prompt: '' + } + ]) + } + } + + return () => {} + }, [dialogProps]) + + return ( + <> + + + + + Starter prompts will only be shown when there is no messages on the chat + + + + :not(style)': { m: 1 }, pt: 2 }}> + + {inputFields.map((data, index) => { + return ( + + + handleChange(index, e)} + size='small' + value={data.prompt} + name='prompt' + endAdornment={ + + {inputFields.length > 1 && ( + removeInputFields(index)} + edge='end' + > + + + )} + + } + /> + + + {index === inputFields.length - 1 && ( + + + + )} + + + ) + })} + + + + Save + + > + ) +} + +StarterPrompts.propTypes = { + show: PropTypes.bool, + dialogProps: PropTypes.object, + onCancel: PropTypes.func, + onConfirm: PropTypes.func +} + +export default StarterPrompts diff --git a/packages/ui/src/ui-component/dialog/StarterPromptsDialog.js b/packages/ui/src/ui-component/dialog/StarterPromptsDialog.js index 78866b4ca..3018b584d 100644 --- a/packages/ui/src/ui-component/dialog/StarterPromptsDialog.js +++ b/packages/ui/src/ui-component/dialog/StarterPromptsDialog.js @@ -1,149 +1,24 @@ import { createPortal } from 'react-dom' import { useDispatch } from 'react-redux' -import { useState, useEffect } from 'react' +import { useEffect } from 'react' import PropTypes from 'prop-types' -import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions' // material-ui -import { - Button, - IconButton, - Dialog, - DialogContent, - OutlinedInput, - DialogTitle, - DialogActions, - Box, - List, - InputAdornment -} from '@mui/material' -import { IconX, IconTrash, IconPlus, IconBulb } from '@tabler/icons' - -// Project import -import { StyledButton } from 'ui-component/button/StyledButton' +import { Dialog, DialogContent, DialogTitle } from '@mui/material' // store import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions' import useNotifier from 'utils/useNotifier' -// API -import chatflowsApi from 'api/chatflows' +// Project imports +import StarterPrompts from './StarterPrompts' -const StarterPromptsDialog = ({ show, dialogProps, onCancel, onConfirm }) => { +const StarterPromptsDialog = ({ show, dialogProps, onCancel }) => { const portalElement = document.getElementById('portal') const dispatch = useDispatch() useNotifier() - const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args)) - const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args)) - - const [inputFields, setInputFields] = useState([ - { - prompt: '' - } - ]) - - const [chatbotConfig, setChatbotConfig] = useState({}) - - const addInputField = () => { - setInputFields([ - ...inputFields, - { - prompt: '' - } - ]) - } - const removeInputFields = (index) => { - const rows = [...inputFields] - rows.splice(index, 1) - setInputFields(rows) - } - - const handleChange = (index, evnt) => { - const { name, value } = evnt.target - const list = [...inputFields] - list[index][name] = value - setInputFields(list) - } - - const onSave = async () => { - try { - let value = { - starterPrompts: { - ...inputFields - } - } - chatbotConfig.starterPrompts = value.starterPrompts - const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, { - chatbotConfig: JSON.stringify(chatbotConfig) - }) - if (saveResp.data) { - enqueueSnackbar({ - message: 'Conversation Starter Prompts Saved', - options: { - key: new Date().getTime() + Math.random(), - variant: 'success', - action: (key) => ( - closeSnackbar(key)}> - - - ) - } - }) - dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data }) - } - onConfirm() - } catch (error) { - const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}` - enqueueSnackbar({ - message: `Failed to save Conversation Starter Prompts: ${errorData}`, - options: { - key: new Date().getTime() + Math.random(), - variant: 'error', - persist: true, - action: (key) => ( - closeSnackbar(key)}> - - - ) - } - }) - } - } - - useEffect(() => { - if (dialogProps.chatflow && dialogProps.chatflow.chatbotConfig) { - try { - let chatbotConfig = JSON.parse(dialogProps.chatflow.chatbotConfig) - setChatbotConfig(chatbotConfig || {}) - if (chatbotConfig.starterPrompts) { - let inputFields = [] - Object.getOwnPropertyNames(chatbotConfig.starterPrompts).forEach((key) => { - if (chatbotConfig.starterPrompts[key]) { - inputFields.push(chatbotConfig.starterPrompts[key]) - } - }) - setInputFields(inputFields) - } else { - setInputFields([ - { - prompt: '' - } - ]) - } - } catch (e) { - setInputFields([ - { - prompt: '' - } - ]) - } - } - - return () => {} - }, [dialogProps]) - useEffect(() => { if (show) dispatch({ type: SHOW_CANVAS_DIALOG }) else dispatch({ type: HIDE_CANVAS_DIALOG }) @@ -163,79 +38,8 @@ const StarterPromptsDialog = ({ show, dialogProps, onCancel, onConfirm }) => { {dialogProps.title || 'Conversation Starter Prompts'} - - - - - Starter prompts will only be shown when there is no messages on the chat - - - - :not(style)': { m: 1 }, pt: 2 }}> - - {inputFields.map((data, index) => { - return ( - - - handleChange(index, e)} - size='small' - value={data.prompt} - name='prompt' - endAdornment={ - - {inputFields.length > 1 && ( - removeInputFields(index)} - edge='end' - > - - - )} - - } - /> - - - {index === inputFields.length - 1 && ( - - - - )} - - - ) - })} - - + - - Cancel - - Save - - ) : null diff --git a/packages/ui/src/views/canvas/CanvasHeader.js b/packages/ui/src/views/canvas/CanvasHeader.js index d9f54d19f..ef3ed1b1c 100644 --- a/packages/ui/src/views/canvas/CanvasHeader.js +++ b/packages/ui/src/views/canvas/CanvasHeader.js @@ -14,9 +14,7 @@ import { IconSettings, IconChevronLeft, IconDeviceFloppy, IconPencil, IconCheck, import Settings from 'views/settings' import SaveChatflowDialog from 'ui-component/dialog/SaveChatflowDialog' import APICodeDialog from 'views/chatflows/APICodeDialog' -import AnalyseFlowDialog from 'ui-component/dialog/AnalyseFlowDialog' import ViewMessagesDialog from 'ui-component/dialog/ViewMessagesDialog' -import StarterPromptsDialog from 'ui-component/dialog/StarterPromptsDialog' // API import chatflowsApi from 'api/chatflows' @@ -45,10 +43,6 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl const [flowDialogOpen, setFlowDialogOpen] = useState(false) const [apiDialogOpen, setAPIDialogOpen] = useState(false) const [apiDialogProps, setAPIDialogProps] = useState({}) - const [analyseDialogOpen, setAnalyseDialogOpen] = useState(false) - const [analyseDialogProps, setAnalyseDialogProps] = useState({}) - const [conversationStartersDialogOpen, setConversationStartersDialogOpen] = useState(false) - const [conversationStartersDialogProps, setConversationStartersDialogProps] = useState({}) const [viewMessagesDialogOpen, setViewMessagesDialogOpen] = useState(false) const [viewMessagesDialogProps, setViewMessagesDialogProps] = useState({}) const [chatflowConfigurationDialogOpen, setChatflowConfigurationDialogOpen] = useState(false) @@ -62,18 +56,6 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl if (setting === 'deleteChatflow') { handleDeleteFlow() - } else if (setting === 'conversationStarters') { - setConversationStartersDialogProps({ - title: 'Starter Prompts - ' + chatflow.name, - chatflow: chatflow - }) - setConversationStartersDialogOpen(true) - } else if (setting === 'analyseChatflow') { - setAnalyseDialogProps({ - title: 'Analyse Chatflow', - chatflow: chatflow - }) - setAnalyseDialogOpen(true) } else if (setting === 'viewMessages') { setViewMessagesDialogProps({ title: 'View Messages', @@ -393,13 +375,6 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl onConfirm={onConfirmSaveName} /> setAPIDialogOpen(false)} /> - setAnalyseDialogOpen(false)} /> - setConversationStartersDialogOpen(false)} - onCancel={() => setConversationStartersDialogOpen(false)} - />