Update UI of speech to text dialog
This commit is contained in:
parent
10fc1bf08d
commit
81c07dc8c1
|
|
@ -13,14 +13,13 @@ import {
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
Accordion,
|
FormControl,
|
||||||
AccordionSummary,
|
|
||||||
AccordionDetails,
|
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
ListItemText
|
ListItemText,
|
||||||
|
MenuItem,
|
||||||
|
Select
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
|
||||||
import { IconX } from '@tabler/icons'
|
import { IconX } from '@tabler/icons'
|
||||||
|
|
||||||
// Project import
|
// Project import
|
||||||
|
|
@ -40,8 +39,8 @@ import useNotifier from 'utils/useNotifier'
|
||||||
// API
|
// API
|
||||||
import chatflowsApi from 'api/chatflows'
|
import chatflowsApi from 'api/chatflows'
|
||||||
|
|
||||||
const speechToTextProviders = [
|
const speechToTextProviders = {
|
||||||
{
|
openAIWhisper: {
|
||||||
label: 'OpenAI Whisper',
|
label: 'OpenAI Whisper',
|
||||||
name: 'openAIWhisper',
|
name: 'openAIWhisper',
|
||||||
icon: openAISVG,
|
icon: openAISVG,
|
||||||
|
|
@ -77,16 +76,10 @@ const speechToTextProviders = [
|
||||||
step: 0.1,
|
step: 0.1,
|
||||||
description: `The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.`,
|
description: `The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.`,
|
||||||
optional: true
|
optional: true
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'On/Off',
|
|
||||||
name: 'status',
|
|
||||||
type: 'boolean',
|
|
||||||
optional: true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
assemblyAiTranscribe: {
|
||||||
label: 'Assembly AI',
|
label: 'Assembly AI',
|
||||||
name: 'assemblyAiTranscribe',
|
name: 'assemblyAiTranscribe',
|
||||||
icon: assemblyAIPng,
|
icon: assemblyAIPng,
|
||||||
|
|
@ -97,16 +90,10 @@ const speechToTextProviders = [
|
||||||
name: 'credential',
|
name: 'credential',
|
||||||
type: 'credential',
|
type: 'credential',
|
||||||
credentialNames: ['assemblyAIApi']
|
credentialNames: ['assemblyAIApi']
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'On/Off',
|
|
||||||
name: 'status',
|
|
||||||
type: 'boolean',
|
|
||||||
optional: true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
|
|
||||||
const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
const portalElement = document.getElementById('portal')
|
const portalElement = document.getElementById('portal')
|
||||||
|
|
@ -118,7 +105,7 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
|
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
|
||||||
|
|
||||||
const [speechToText, setSpeechToText] = useState({})
|
const [speechToText, setSpeechToText] = useState({})
|
||||||
const [providerExpanded, setProviderExpanded] = useState({})
|
const [selectedProvider, setSelectedProvider] = useState('openAIWhisper')
|
||||||
|
|
||||||
const onSave = async () => {
|
const onSave = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -169,8 +156,9 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
|
|
||||||
newVal[providerName][inputParamName] = value
|
newVal[providerName][inputParamName] = value
|
||||||
if (inputParamName === 'status' && value === true) {
|
if (inputParamName === 'status' && value === true) {
|
||||||
//ensure that the others are turned off
|
// ensure that the others are turned off
|
||||||
speechToTextProviders.forEach((provider) => {
|
Object.keys(speechToTextProviders).forEach((key) => {
|
||||||
|
const provider = speechToTextProviders[key]
|
||||||
if (provider.name !== providerName) {
|
if (provider.name !== providerName) {
|
||||||
newVal[provider.name] = { ...speechToText[provider.name], status: false }
|
newVal[provider.name] = { ...speechToText[provider.name], status: false }
|
||||||
}
|
}
|
||||||
|
|
@ -179,10 +167,9 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
setSpeechToText(newVal)
|
setSpeechToText(newVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAccordionChange = (providerName) => (event, isExpanded) => {
|
const handleProviderChange = (event) => {
|
||||||
const accordionProviders = { ...providerExpanded }
|
setSelectedProvider(event.target.value)
|
||||||
accordionProviders[providerName] = isExpanded
|
setValue(true, event.target.value, 'status')
|
||||||
setProviderExpanded(accordionProviders)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -197,7 +184,6 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
setSpeechToText({})
|
setSpeechToText({})
|
||||||
setProviderExpanded({})
|
|
||||||
}
|
}
|
||||||
}, [dialogProps])
|
}, [dialogProps])
|
||||||
|
|
||||||
|
|
@ -220,136 +206,129 @@ const SpeechToTextDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
Speech To Text Configuration
|
Speech To Text Configuration
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
{speechToTextProviders.map((provider, index) => (
|
<Box fullWidth sx={{ my: 2, display: 'flex', flexDirection: 'column', gap: 1 }}>
|
||||||
<Accordion
|
<Typography>Speech To Text Providers</Typography>
|
||||||
expanded={providerExpanded[provider.name] || false}
|
<FormControl fullWidth>
|
||||||
onChange={handleAccordionChange(provider.name)}
|
<Select value={selectedProvider} onChange={handleProviderChange}>
|
||||||
disableGutters
|
<MenuItem value='openAIWhisper'>OpenAI Whisper</MenuItem>
|
||||||
key={index}
|
<MenuItem value='assemblyAiTranscribe'>Assembly AI</MenuItem>
|
||||||
>
|
</Select>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls={provider.name} id={provider.name}>
|
</FormControl>
|
||||||
<ListItem style={{ padding: 0, margin: 0 }} alignItems='center'>
|
</Box>
|
||||||
<ListItemAvatar>
|
<>
|
||||||
<div
|
<ListItem style={{ padding: 0, margin: 0 }} alignItems='center'>
|
||||||
style={{
|
<ListItemAvatar>
|
||||||
width: 50,
|
<div
|
||||||
height: 50,
|
style={{
|
||||||
borderRadius: '50%',
|
width: 50,
|
||||||
backgroundColor: 'white'
|
height: 50,
|
||||||
}}
|
borderRadius: '50%',
|
||||||
>
|
backgroundColor: 'white'
|
||||||
<img
|
}}
|
||||||
style={{
|
>
|
||||||
width: '100%',
|
<img
|
||||||
height: '100%',
|
style={{
|
||||||
padding: 10,
|
width: '100%',
|
||||||
objectFit: 'contain'
|
height: '100%',
|
||||||
}}
|
padding: 10,
|
||||||
alt='AI'
|
objectFit: 'contain'
|
||||||
src={provider.icon}
|
}}
|
||||||
/>
|
alt='AI'
|
||||||
</div>
|
src={speechToTextProviders[selectedProvider].icon}
|
||||||
</ListItemAvatar>
|
/>
|
||||||
<ListItemText
|
</div>
|
||||||
sx={{ ml: 1 }}
|
</ListItemAvatar>
|
||||||
primary={provider.label}
|
<ListItemText
|
||||||
secondary={
|
sx={{ ml: 1 }}
|
||||||
<a target='_blank' rel='noreferrer' href={provider.url}>
|
primary={speechToTextProviders[selectedProvider].label}
|
||||||
{provider.url}
|
secondary={
|
||||||
</a>
|
<a target='_blank' rel='noreferrer' href={speechToTextProviders[selectedProvider].url}>
|
||||||
|
{speechToTextProviders[selectedProvider].url}
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{speechToText[selectedProvider] && speechToText[selectedProvider].status && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
background: '#d8f3dc',
|
||||||
|
borderRadius: 15,
|
||||||
|
padding: 5,
|
||||||
|
paddingLeft: 7,
|
||||||
|
paddingRight: 7,
|
||||||
|
marginRight: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 15,
|
||||||
|
height: 15,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundColor: '#70e000'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ color: '#006400', marginLeft: 10 }}>ON</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ListItem>
|
||||||
|
{speechToTextProviders[selectedProvider].inputs.map((inputParam, index) => (
|
||||||
|
<Box key={index} sx={{ p: 2 }}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Typography>
|
||||||
|
{inputParam.label}
|
||||||
|
{!inputParam.optional && <span style={{ color: 'red' }}> *</span>}
|
||||||
|
{inputParam.description && (
|
||||||
|
<TooltipWithParser style={{ marginLeft: 10 }} title={inputParam.description} />
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
{inputParam.type === 'credential' && (
|
||||||
|
<CredentialInputHandler
|
||||||
|
data={speechToText[selectedProvider] ? { credential: speechToText[selectedProvider].credentialId } : {}}
|
||||||
|
inputParam={inputParam}
|
||||||
|
onSelect={(newValue) => setValue(newValue, selectedProvider, 'credentialId')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{inputParam.type === 'boolean' && (
|
||||||
|
<SwitchInput
|
||||||
|
onChange={(newValue) => setValue(newValue, selectedProvider, inputParam.name)}
|
||||||
|
value={
|
||||||
|
speechToText[selectedProvider]
|
||||||
|
? speechToText[selectedProvider][inputParam.name]
|
||||||
|
: inputParam.default ?? false
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{speechToText[provider.name] && speechToText[provider.name].status && (
|
)}
|
||||||
<div
|
{(inputParam.type === 'string' || inputParam.type === 'password' || inputParam.type === 'number') && (
|
||||||
style={{
|
<Input
|
||||||
display: 'flex',
|
inputParam={inputParam}
|
||||||
flexDirection: 'row',
|
onChange={(newValue) => setValue(newValue, selectedProvider, inputParam.name)}
|
||||||
alignContent: 'center',
|
value={
|
||||||
alignItems: 'center',
|
speechToText[selectedProvider]
|
||||||
background: '#d8f3dc',
|
? speechToText[selectedProvider][inputParam.name]
|
||||||
borderRadius: 15,
|
: inputParam.default ?? ''
|
||||||
padding: 5,
|
}
|
||||||
paddingLeft: 7,
|
/>
|
||||||
paddingRight: 7,
|
)}
|
||||||
marginRight: 10
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 15,
|
|
||||||
height: 15,
|
|
||||||
borderRadius: '50%',
|
|
||||||
backgroundColor: '#70e000'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span style={{ color: '#006400', marginLeft: 10 }}>ON</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ListItem>
|
|
||||||
</AccordionSummary>
|
|
||||||
<AccordionDetails>
|
|
||||||
{provider.inputs.map((inputParam, index) => (
|
|
||||||
<Box key={index} sx={{ p: 2 }}>
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
|
||||||
<Typography>
|
|
||||||
{inputParam.label}
|
|
||||||
{!inputParam.optional && <span style={{ color: 'red' }}> *</span>}
|
|
||||||
{inputParam.description && (
|
|
||||||
<TooltipWithParser style={{ marginLeft: 10 }} title={inputParam.description} />
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
{providerExpanded[provider.name] && inputParam.type === 'credential' && (
|
|
||||||
<CredentialInputHandler
|
|
||||||
data={
|
|
||||||
speechToText[provider.name] ? { credential: speechToText[provider.name].credentialId } : {}
|
|
||||||
}
|
|
||||||
inputParam={inputParam}
|
|
||||||
onSelect={(newValue) => setValue(newValue, provider.name, 'credentialId')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{inputParam.type === 'boolean' && (
|
|
||||||
<SwitchInput
|
|
||||||
onChange={(newValue) => setValue(newValue, provider.name, inputParam.name)}
|
|
||||||
value={
|
|
||||||
speechToText[provider.name]
|
|
||||||
? speechToText[provider.name][inputParam.name]
|
|
||||||
: inputParam.default ?? false
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{providerExpanded[provider.name] &&
|
|
||||||
(inputParam.type === 'string' ||
|
|
||||||
inputParam.type === 'password' ||
|
|
||||||
inputParam.type === 'number') && (
|
|
||||||
<Input
|
|
||||||
inputParam={inputParam}
|
|
||||||
onChange={(newValue) => setValue(newValue, provider.name, inputParam.name)}
|
|
||||||
value={
|
|
||||||
speechToText[provider.name]
|
|
||||||
? speechToText[provider.name][inputParam.name]
|
|
||||||
: inputParam.default ?? ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{providerExpanded[provider.name] && inputParam.type === 'options' && (
|
{inputParam.type === 'options' && (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
name={inputParam.name}
|
name={inputParam.name}
|
||||||
options={inputParam.options}
|
options={inputParam.options}
|
||||||
onSelect={(newValue) => setValue(newValue, provider.name, inputParam.name)}
|
onSelect={(newValue) => setValue(newValue, selectedProvider, inputParam.name)}
|
||||||
value={
|
value={
|
||||||
speechToText[provider.name]
|
speechToText[selectedProvider]
|
||||||
? speechToText[provider.name][inputParam.name]
|
? speechToText[selectedProvider][inputParam.name]
|
||||||
: inputParam.default ?? 'choose an option'
|
: inputParam.default ?? 'choose an option'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</AccordionDetails>
|
</>
|
||||||
</Accordion>
|
|
||||||
))}
|
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<StyledButton variant='contained' onClick={onSave}>
|
<StyledButton variant='contained' onClick={onSave}>
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,11 @@ export const AsyncDropdown = ({
|
||||||
})()
|
})()
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [credentialNames])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(value)
|
||||||
|
}, [value])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
|
||||||
// material-ui
|
// material-ui
|
||||||
import { IconButton } from '@mui/material'
|
import { IconButton } from '@mui/material'
|
||||||
|
|
@ -88,6 +88,10 @@ const CredentialInputHandler = ({ inputParam, data, onSelect, disabled = false }
|
||||||
setShowSpecificCredentialDialog(true)
|
setShowSpecificCredentialDialog(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCredentialId(data?.credential ?? '')
|
||||||
|
}, [data])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
{inputParam && (
|
{inputParam && (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue