mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-25 15:01:03 +03:00
296 lines
9.2 KiB
JavaScript
296 lines
9.2 KiB
JavaScript
import { createPortal } from 'react-dom'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { useState, useEffect } from 'react'
|
|
import { useDispatch } from 'react-redux'
|
|
import PropTypes from 'prop-types'
|
|
|
|
import { Tabs, Tab, Dialog, DialogContent, DialogTitle, Box } from '@mui/material'
|
|
import { CopyBlock, atomOneDark } from 'react-code-blocks'
|
|
|
|
// Project import
|
|
import { Dropdown } from 'ui-component/dropdown/Dropdown'
|
|
|
|
// Const
|
|
import { baseURL } from 'store/constant'
|
|
import { SET_CHATFLOW } from 'store/actions'
|
|
|
|
// Images
|
|
import pythonSVG from 'assets/images/python.svg'
|
|
import javascriptSVG from 'assets/images/javascript.svg'
|
|
import cURLSVG from 'assets/images/cURL.svg'
|
|
|
|
// API
|
|
import apiKeyApi from 'api/apikey'
|
|
import chatflowsApi from 'api/chatflows'
|
|
|
|
// Hooks
|
|
import useApi from 'hooks/useApi'
|
|
|
|
function TabPanel(props) {
|
|
const { children, value, index, ...other } = props
|
|
return (
|
|
<div
|
|
role='tabpanel'
|
|
hidden={value !== index}
|
|
id={`attachment-tabpanel-${index}`}
|
|
aria-labelledby={`attachment-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: `attachment-tab-${index}`,
|
|
'aria-controls': `attachment-tabpanel-${index}`
|
|
}
|
|
}
|
|
|
|
const APICodeDialog = ({ show, dialogProps, onCancel }) => {
|
|
const portalElement = document.getElementById('portal')
|
|
const navigate = useNavigate()
|
|
const dispatch = useDispatch()
|
|
const codes = ['Python', 'JavaScript', 'cURL']
|
|
const [value, setValue] = useState(0)
|
|
const [keyOptions, setKeyOptions] = useState([])
|
|
const [apiKeys, setAPIKeys] = useState([])
|
|
const [chatflowApiKeyId, setChatflowApiKeyId] = useState('')
|
|
const [selectedApiKey, setSelectedApiKey] = useState({})
|
|
|
|
const getAllAPIKeysApi = useApi(apiKeyApi.getAllAPIKeys)
|
|
const updateChatflowApi = useApi(chatflowsApi.updateChatflow)
|
|
|
|
const onApiKeySelected = (keyValue) => {
|
|
if (keyValue === 'addnewkey') {
|
|
navigate('/apikey')
|
|
return
|
|
}
|
|
setChatflowApiKeyId(keyValue)
|
|
setSelectedApiKey(apiKeys.find((key) => key.id === keyValue))
|
|
const updateBody = {
|
|
apikeyid: keyValue
|
|
}
|
|
updateChatflowApi.request(dialogProps.chatflowid, updateBody)
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (updateChatflowApi.data) {
|
|
dispatch({ type: SET_CHATFLOW, chatflow: updateChatflowApi.data })
|
|
}
|
|
}, [updateChatflowApi.data, dispatch])
|
|
|
|
const handleChange = (event, newValue) => {
|
|
setValue(newValue)
|
|
}
|
|
|
|
const getCode = (codeLang) => {
|
|
if (codeLang === 'Python') {
|
|
return `import requests
|
|
|
|
API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}"
|
|
|
|
def query(payload):
|
|
response = requests.post(API_URL, json=payload)
|
|
return response.json()
|
|
|
|
output = query({
|
|
"question": "Hey, how are you?",
|
|
})
|
|
`
|
|
} else if (codeLang === 'JavaScript') {
|
|
return `async function query(data) {
|
|
const response = await fetch(
|
|
"${baseURL}/api/v1/prediction/${dialogProps.chatflowid}",
|
|
{
|
|
method: "POST",
|
|
body: {
|
|
"question": "Hey, how are you?"
|
|
},
|
|
}
|
|
);
|
|
const result = await response.json();
|
|
return result;
|
|
}
|
|
`
|
|
} else if (codeLang === 'cURL') {
|
|
return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
|
-X POST \\
|
|
-d '{"question": "Hey, how are you?"}'`
|
|
}
|
|
return ''
|
|
}
|
|
|
|
const getCodeWithAuthorization = (codeLang) => {
|
|
if (codeLang === 'Python') {
|
|
return `import requests
|
|
|
|
API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}"
|
|
headers = {"Authorization": "Bearer ${selectedApiKey?.apiKey}"}
|
|
|
|
def query(payload):
|
|
response = requests.post(API_URL, headers=headers, json=payload)
|
|
return response.json()
|
|
|
|
output = query({
|
|
"question": "Hey, how are you?",
|
|
})
|
|
`
|
|
} else if (codeLang === 'JavaScript') {
|
|
return `async function query(data) {
|
|
const response = await fetch(
|
|
"${baseURL}/api/v1/prediction/${dialogProps.chatflowid}",
|
|
{
|
|
headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" },
|
|
method: "POST",
|
|
body: {
|
|
"question": "Hey, how are you?"
|
|
},
|
|
}
|
|
);
|
|
const result = await response.json();
|
|
return result;
|
|
}
|
|
`
|
|
} else if (codeLang === 'cURL') {
|
|
return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
|
-X POST \\
|
|
-d '{"question": "Hey, how are you?"}'
|
|
-H "Authorization: Bearer ${selectedApiKey?.apiKey}"`
|
|
}
|
|
return ''
|
|
}
|
|
|
|
const getLang = (codeLang) => {
|
|
if (codeLang === 'Python') {
|
|
return 'python'
|
|
} else if (codeLang === 'JavaScript') {
|
|
return 'javascript'
|
|
} else if (codeLang === 'cURL') {
|
|
return 'bash'
|
|
}
|
|
return 'python'
|
|
}
|
|
|
|
const getSVG = (codeLang) => {
|
|
if (codeLang === 'Python') {
|
|
return pythonSVG
|
|
} else if (codeLang === 'JavaScript') {
|
|
return javascriptSVG
|
|
} else if (codeLang === 'cURL') {
|
|
return cURLSVG
|
|
}
|
|
return pythonSVG
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (getAllAPIKeysApi.data) {
|
|
const options = [
|
|
{
|
|
label: 'No Authorization',
|
|
name: ''
|
|
}
|
|
]
|
|
for (const key of getAllAPIKeysApi.data) {
|
|
options.push({
|
|
label: key.keyName,
|
|
name: key.id
|
|
})
|
|
}
|
|
options.push({
|
|
label: '- Add New Key -',
|
|
name: 'addnewkey'
|
|
})
|
|
setKeyOptions(options)
|
|
setAPIKeys(getAllAPIKeysApi.data)
|
|
|
|
if (dialogProps.chatflowApiKeyId) {
|
|
setChatflowApiKeyId(dialogProps.chatflowApiKeyId)
|
|
setSelectedApiKey(getAllAPIKeysApi.data.find((key) => key.id === dialogProps.chatflowApiKeyId))
|
|
}
|
|
}
|
|
}, [dialogProps, getAllAPIKeysApi.data])
|
|
|
|
useEffect(() => {
|
|
if (show) getAllAPIKeysApi.request()
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [show])
|
|
|
|
const component = show ? (
|
|
<Dialog
|
|
open={show}
|
|
fullWidth
|
|
maxWidth='md'
|
|
onClose={onCancel}
|
|
aria-labelledby='alert-dialog-title'
|
|
aria-describedby='alert-dialog-description'
|
|
>
|
|
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
|
|
{dialogProps.title}
|
|
</DialogTitle>
|
|
<DialogContent>
|
|
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
|
<div style={{ flex: 80 }}>
|
|
<Tabs value={value} onChange={handleChange} aria-label='tabs'>
|
|
{codes.map((codeLang, index) => (
|
|
<Tab
|
|
icon={
|
|
<img
|
|
style={{ objectFit: 'cover', height: 'auto', width: 'auto' }}
|
|
src={getSVG(codeLang)}
|
|
alt='code'
|
|
/>
|
|
}
|
|
iconPosition='start'
|
|
key={index}
|
|
label={codeLang}
|
|
{...a11yProps(index)}
|
|
></Tab>
|
|
))}
|
|
</Tabs>
|
|
</div>
|
|
<div style={{ flex: 20 }}>
|
|
<Dropdown
|
|
name='SelectKey'
|
|
disableClearable={true}
|
|
options={keyOptions}
|
|
onSelect={(newValue) => onApiKeySelected(newValue)}
|
|
value={dialogProps.chatflowApiKeyId ?? chatflowApiKeyId ?? 'Choose an API key'}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div style={{ marginTop: 10 }}></div>
|
|
{codes.map((codeLang, index) => (
|
|
<TabPanel key={index} value={value} index={index}>
|
|
<CopyBlock
|
|
theme={atomOneDark}
|
|
text={chatflowApiKeyId ? getCodeWithAuthorization(codeLang) : getCode(codeLang)}
|
|
language={getLang(codeLang)}
|
|
showLineNumbers={false}
|
|
wrapLines
|
|
/>
|
|
</TabPanel>
|
|
))}
|
|
</DialogContent>
|
|
</Dialog>
|
|
) : null
|
|
|
|
return createPortal(component, portalElement)
|
|
}
|
|
|
|
APICodeDialog.propTypes = {
|
|
show: PropTypes.bool,
|
|
dialogProps: PropTypes.object,
|
|
onCancel: PropTypes.func
|
|
}
|
|
|
|
export default APICodeDialog
|