Feature: define a custom error message for allowed domains (#2194)

* Add a field for custom error message in allowed domains configuration

* enhance UI for more consistency

* update pnpm version

* update pnpm version

---------

Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
Ilango 2024-04-19 07:43:28 +05:30 committed by GitHub
parent b7e4fc9517
commit f4c7887e50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 66 additions and 19 deletions

View File

@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v3 - uses: pnpm/action-setup@v3
with: with:
version: 9.0.3 version: 9.0.4
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:

View File

@ -52,7 +52,7 @@
"turbo": "1.10.16", "turbo": "1.10.16",
"typescript": "^4.8.4" "typescript": "^4.8.4"
}, },
"packageManager": "pnpm@9.0.3", "packageManager": "pnpm@9.0.4",
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"faiss-node", "faiss-node",

View File

@ -4,11 +4,12 @@ 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 { Button, IconButton, OutlinedInput, Box, List, InputAdornment } from '@mui/material' import { Button, IconButton, OutlinedInput, Box, List, InputAdornment, Typography } from '@mui/material'
import { IconX, IconTrash, IconPlus } from '@tabler/icons' import { IconX, IconTrash, IconPlus } from '@tabler/icons'
// Project import // Project import
import { StyledButton } from '@/ui-component/button/StyledButton' import { StyledButton } from '@/ui-component/button/StyledButton'
import { TooltipWithParser } from '@/ui-component/tooltip/TooltipWithParser'
// store // store
import useNotifier from '@/utils/useNotifier' import useNotifier from '@/utils/useNotifier'
@ -25,6 +26,7 @@ const AllowedDomains = ({ dialogProps }) => {
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args)) const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
const [inputFields, setInputFields] = useState(['']) const [inputFields, setInputFields] = useState([''])
const [errorMessage, setErrorMessage] = useState('')
const [chatbotConfig, setChatbotConfig] = useState({}) const [chatbotConfig, setChatbotConfig] = useState({})
@ -47,9 +49,12 @@ const AllowedDomains = ({ dialogProps }) => {
const onSave = async () => { const onSave = async () => {
try { try {
let value = { let value = {
allowedOrigins: [...inputFields] allowedOrigins: [...inputFields],
allowedOriginsError: errorMessage
} }
chatbotConfig.allowedOrigins = value.allowedOrigins chatbotConfig.allowedOrigins = value.allowedOrigins
chatbotConfig.allowedOriginsError = value.allowedOriginsError
const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, { const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, {
chatbotConfig: JSON.stringify(chatbotConfig) chatbotConfig: JSON.stringify(chatbotConfig)
}) })
@ -98,8 +103,14 @@ const AllowedDomains = ({ dialogProps }) => {
} else { } else {
setInputFields(['']) setInputFields([''])
} }
if (chatbotConfig.allowedOriginsError) {
setErrorMessage(chatbotConfig.allowedOriginsError)
} else {
setErrorMessage('')
}
} catch (e) { } catch (e) {
setInputFields(['']) setInputFields([''])
setErrorMessage('')
} }
} }
@ -108,15 +119,21 @@ const AllowedDomains = ({ dialogProps }) => {
return ( return (
<> <>
<div <Box>
style={{ <Box
sx={{
display: 'flex', display: 'flex',
flexDirection: 'column' flexDirection: 'column'
}} }}
> >
<span>Your chatbot will only work when used from the following domains.</span> <Typography sx={{ mb: 1 }}>
</div> Allowed Domains
<Box sx={{ '& > :not(style)': { m: 1 }, pt: 2 }}> <TooltipWithParser
style={{ mb: 1, mt: 2, marginLeft: 10 }}
title={'Your chatbot will only work when used from the following domains.'}
/>
</Typography>
</Box>
<List> <List>
{inputFields.map((origin, index) => { {inputFields.map((origin, index) => {
return ( return (
@ -130,6 +147,7 @@ const AllowedDomains = ({ dialogProps }) => {
size='small' size='small'
value={origin} value={origin}
name='origin' name='origin'
placeholder='https://example.com'
endAdornment={ endAdornment={
<InputAdornment position='end' sx={{ padding: '2px' }}> <InputAdornment position='end' sx={{ padding: '2px' }}>
{inputFields.length > 1 && ( {inputFields.length > 1 && (
@ -160,6 +178,28 @@ const AllowedDomains = ({ dialogProps }) => {
})} })}
</List> </List>
</Box> </Box>
<Box sx={{ pt: 2, pb: 2 }}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
<Typography sx={{ mb: 1 }}>
Error Message
<TooltipWithParser
style={{ mb: 1, mt: 2, marginLeft: 10 }}
title={'Custom error message that will be shown when for unauthorized domain'}
/>
</Typography>
<OutlinedInput
sx={{ width: '100%' }}
type='text'
size='small'
fullWidth
placeholder='Unauthorized domain!'
value={errorMessage}
onChange={(e) => {
setErrorMessage(e.target.value)
}}
/>
</div>
</Box>
<StyledButton variant='contained' onClick={onSave}> <StyledButton variant='contained' onClick={onSave}>
Save Save
</StyledButton> </StyledButton>

View File

@ -7,6 +7,7 @@ import { Box, Typography, Button, OutlinedInput } from '@mui/material'
// Project import // Project import
import { StyledButton } from '@/ui-component/button/StyledButton' import { StyledButton } from '@/ui-component/button/StyledButton'
import { TooltipWithParser } from '@/ui-component/tooltip/TooltipWithParser'
// Icons // Icons
import { IconX } from '@tabler/icons' import { IconX } from '@tabler/icons'
@ -16,7 +17,6 @@ import chatflowsApi from '@/api/chatflows'
// utils // utils
import useNotifier from '@/utils/useNotifier' import useNotifier from '@/utils/useNotifier'
import { TooltipWithParser } from '@/ui-component/tooltip/TooltipWithParser'
const RateLimit = () => { const RateLimit = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
@ -117,6 +117,7 @@ const RateLimit = () => {
value={message} value={message}
placeholder={placeholder} placeholder={placeholder}
name={fieldName} name={fieldName}
size='small'
onChange={(e) => { onChange={(e) => {
onTextChanged(e.target.value, fieldName) onTextChanged(e.target.value, fieldName)
}} }}
@ -138,9 +139,9 @@ const RateLimit = () => {
} }
/> />
</Typography> </Typography>
{textField(limitMax, 'limitMax', 'Message Limit per Duration', 'number')} {textField(limitMax, 'limitMax', 'Message Limit per Duration', 'number', '5')}
{textField(limitDuration, 'limitDuration', 'Duration in Second', 'number')} {textField(limitDuration, 'limitDuration', 'Duration in Second', 'number', '60')}
{textField(limitMsg, 'limitMsg', 'Limit Message', 'string')} {textField(limitMsg, 'limitMsg', 'Limit Message', 'string', 'You have reached the quota')}
<StyledButton style={{ marginBottom: 10, marginTop: 10 }} variant='contained' onClick={() => onSave()}> <StyledButton style={{ marginBottom: 10, marginTop: 10 }} variant='contained' onClick={() => onSave()}>
Save Changes Save Changes

View File

@ -189,7 +189,7 @@ const SpeechToText = ({ dialogProps }) => {
Providers Providers
</Typography> </Typography>
<FormControl fullWidth> <FormControl fullWidth>
<Select value={selectedProvider} onChange={handleProviderChange}> <Select size='small' value={selectedProvider} onChange={handleProviderChange}>
<MenuItem value='none'>None</MenuItem> <MenuItem value='none'>None</MenuItem>
<MenuItem value='openAIWhisper'>OpenAI Whisper</MenuItem> <MenuItem value='openAIWhisper'>OpenAI Whisper</MenuItem>
<MenuItem value='assemblyAiTranscribe'>Assembly AI</MenuItem> <MenuItem value='assemblyAiTranscribe'>Assembly AI</MenuItem>
@ -198,7 +198,7 @@ const SpeechToText = ({ dialogProps }) => {
</Box> </Box>
{selectedProvider !== 'none' && ( {selectedProvider !== 'none' && (
<> <>
<ListItem style={{ padding: 0, margin: 0 }} alignItems='center'> <ListItem sx={{ mt: 3 }} alignItems='center'>
<ListItemAvatar> <ListItemAvatar>
<div <div
style={{ style={{

View File

@ -61,6 +61,7 @@ const ShareChatbot = ({ isSessionMemory }) => {
const [titleAvatarSrc, setTitleAvatarSrc] = useState(chatbotConfig?.titleAvatarSrc ?? '') const [titleAvatarSrc, setTitleAvatarSrc] = useState(chatbotConfig?.titleAvatarSrc ?? '')
const [welcomeMessage, setWelcomeMessage] = useState(chatbotConfig?.welcomeMessage ?? '') const [welcomeMessage, setWelcomeMessage] = useState(chatbotConfig?.welcomeMessage ?? '')
const [errorMessage, setErrorMessage] = useState(chatbotConfig?.errorMessage ?? '')
const [backgroundColor, setBackgroundColor] = useState(chatbotConfig?.backgroundColor ?? defaultConfig.backgroundColor) const [backgroundColor, setBackgroundColor] = useState(chatbotConfig?.backgroundColor ?? defaultConfig.backgroundColor)
const [fontSize, setFontSize] = useState(chatbotConfig?.fontSize ?? defaultConfig.fontSize) const [fontSize, setFontSize] = useState(chatbotConfig?.fontSize ?? defaultConfig.fontSize)
const [poweredByTextColor, setPoweredByTextColor] = useState(chatbotConfig?.poweredByTextColor ?? defaultConfig.poweredByTextColor) const [poweredByTextColor, setPoweredByTextColor] = useState(chatbotConfig?.poweredByTextColor ?? defaultConfig.poweredByTextColor)
@ -114,6 +115,7 @@ const ShareChatbot = ({ isSessionMemory }) => {
if (title) obj.title = title if (title) obj.title = title
if (titleAvatarSrc) obj.titleAvatarSrc = titleAvatarSrc if (titleAvatarSrc) obj.titleAvatarSrc = titleAvatarSrc
if (welcomeMessage) obj.welcomeMessage = welcomeMessage if (welcomeMessage) obj.welcomeMessage = welcomeMessage
if (errorMessage) obj.errorMessage = errorMessage
if (backgroundColor) obj.backgroundColor = backgroundColor if (backgroundColor) obj.backgroundColor = backgroundColor
if (fontSize) obj.fontSize = fontSize if (fontSize) obj.fontSize = fontSize
if (poweredByTextColor) obj.poweredByTextColor = poweredByTextColor if (poweredByTextColor) obj.poweredByTextColor = poweredByTextColor
@ -268,6 +270,9 @@ const ShareChatbot = ({ isSessionMemory }) => {
case 'welcomeMessage': case 'welcomeMessage':
setWelcomeMessage(value) setWelcomeMessage(value)
break break
case 'errorMessage':
setErrorMessage(value)
break
case 'fontSize': case 'fontSize':
setFontSize(value) setFontSize(value)
break break
@ -417,6 +422,7 @@ const ShareChatbot = ({ isSessionMemory }) => {
`https://raw.githubusercontent.com/FlowiseAI/Flowise/main/assets/FloWiseAI_dark.png` `https://raw.githubusercontent.com/FlowiseAI/Flowise/main/assets/FloWiseAI_dark.png`
)} )}
{textField(welcomeMessage, 'welcomeMessage', 'Welcome Message', 'string', 'Hello! This is custom welcome message')} {textField(welcomeMessage, 'welcomeMessage', 'Welcome Message', 'string', 'Hello! This is custom welcome message')}
{textField(errorMessage, 'errorMessage', 'Error Message', 'string', 'This is custom error message')}
{colorField(backgroundColor, 'backgroundColor', 'Background Color')} {colorField(backgroundColor, 'backgroundColor', 'Background Color')}
{textField(fontSize, 'fontSize', 'Font Size', 'number')} {textField(fontSize, 'fontSize', 'Font Size', 'number')}
{colorField(poweredByTextColor, 'poweredByTextColor', 'PoweredBy TextColor')} {colorField(poweredByTextColor, 'poweredByTextColor', 'PoweredBy TextColor')}