Spaces:
Configuration error
Configuration error
| 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' | |
| import EmbedSVG from 'assets/images/embed.svg' | |
| // API | |
| import apiKeyApi from 'api/apikey' | |
| import chatflowsApi from 'api/chatflows' | |
| import configApi from 'api/config' | |
| // Hooks | |
| import useApi from 'hooks/useApi' | |
| import { CheckboxInput } from 'ui-component/checkbox/Checkbox' | |
| import { TableViewOnly } from 'ui-component/table/Table' | |
| 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 unshiftFiles = (configData) => { | |
| const filesConfig = configData.find((config) => config.name === 'files') | |
| if (filesConfig) { | |
| configData = configData.filter((config) => config.name !== 'files') | |
| configData.unshift(filesConfig) | |
| } | |
| return configData | |
| } | |
| const getConfigExamplesForJS = (configData, bodyType) => { | |
| let finalStr = '' | |
| configData = unshiftFiles(configData) | |
| const loop = Math.min(configData.length, 4) | |
| for (let i = 0; i < loop; i += 1) { | |
| const config = configData[i] | |
| let exampleVal = `"example"` | |
| if (config.type === 'string') exampleVal = `"example"` | |
| else if (config.type === 'boolean') exampleVal = `true` | |
| else if (config.type === 'number') exampleVal = `1` | |
| else if (config.name === 'files') exampleVal = `input.files[0]` | |
| finalStr += bodyType === 'json' ? `\n "${config.name}": ${exampleVal},` : `formData.append("${config.name}", ${exampleVal})\n` | |
| if (i === loop - 1 && bodyType !== 'json') `formData.append("question", "Hey, how are you?")\n` | |
| } | |
| return finalStr | |
| } | |
| const getConfigExamplesForPython = (configData, bodyType) => { | |
| let finalStr = '' | |
| configData = unshiftFiles(configData) | |
| const loop = Math.min(configData.length, 4) | |
| for (let i = 0; i < loop; i += 1) { | |
| const config = configData[i] | |
| let exampleVal = `"example"` | |
| if (config.type === 'string') exampleVal = `"example"` | |
| else if (config.type === 'boolean') exampleVal = `true` | |
| else if (config.type === 'number') exampleVal = `1` | |
| else if (config.name === 'files') exampleVal = `('example${config.type}', open('example${config.type}', 'rb'))` | |
| finalStr += bodyType === 'json' ? `\n "${config.name}": ${exampleVal},` : `\n "${config.name}": ${exampleVal},` | |
| if (i === loop - 1 && bodyType !== 'json') finalStr += `\n "question": "Hey, how are you?"\n` | |
| } | |
| return finalStr | |
| } | |
| const getConfigExamplesForCurl = (configData, bodyType) => { | |
| let finalStr = '' | |
| configData = unshiftFiles(configData) | |
| const loop = Math.min(configData.length, 4) | |
| for (let i = 0; i < loop; i += 1) { | |
| const config = configData[i] | |
| let exampleVal = `example` | |
| if (config.type === 'string') exampleVal = bodyType === 'json' ? `"example"` : `example` | |
| else if (config.type === 'boolean') exampleVal = `true` | |
| else if (config.type === 'number') exampleVal = `1` | |
| else if (config.name === 'files') exampleVal = `@/home/user1/Desktop/example${config.type}` | |
| finalStr += bodyType === 'json' ? `"${config.name}": ${exampleVal}` : `\n -F "${config.name}=${exampleVal}"` | |
| if (i === loop - 1) finalStr += bodyType === 'json' ? ` }` : ` \\\n -F "question=Hey, how are you?"` | |
| else finalStr += bodyType === 'json' ? `, ` : ` \\` | |
| } | |
| return finalStr | |
| } | |
| const embedCode = (chatflowid) => { | |
| return `<script type="module"> | |
| import Chatbot from "https://cdn.jsdelivr.net/npm/flowise-embed@latest/dist/web.js" | |
| Chatbot.init({ | |
| chatflowid: "${chatflowid}", | |
| apiHost: "${baseURL}", | |
| }) | |
| </script>` | |
| } | |
| const APICodeDialog = ({ show, dialogProps, onCancel }) => { | |
| const portalElement = document.getElementById('portal') | |
| const navigate = useNavigate() | |
| const dispatch = useDispatch() | |
| const codes = ['Embed', '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 [checkboxVal, setCheckbox] = useState(false) | |
| const getAllAPIKeysApi = useApi(apiKeyApi.getAllAPIKeys) | |
| const updateChatflowApi = useApi(chatflowsApi.updateChatflow) | |
| const getConfigApi = useApi(configApi.getConfig) | |
| const onCheckBoxChanged = (newVal) => { | |
| setCheckbox(newVal) | |
| if (newVal) { | |
| getConfigApi.request(dialogProps.chatflowid) | |
| } | |
| } | |
| 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: data | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query({"question": "Hey, how are you?"}).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } else if (codeLang === 'cURL') { | |
| return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\ | |
| -X POST \\ | |
| -d '{"question": "Hey, how are you?"}'` | |
| } else if (codeLang === 'Embed') { | |
| return embedCode(dialogProps.chatflowid) | |
| } | |
| 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: data | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query({"question": "Hey, how are you?"}).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } 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}"` | |
| } else if (codeLang === 'Embed') { | |
| return embedCode(dialogProps.chatflowid) | |
| } | |
| return '' | |
| } | |
| const getLang = (codeLang) => { | |
| if (codeLang === 'Python') { | |
| return 'python' | |
| } else if (codeLang === 'JavaScript' || codeLang === 'Embed') { | |
| 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 === 'Embed') { | |
| return EmbedSVG | |
| } else if (codeLang === 'cURL') { | |
| return cURLSVG | |
| } | |
| return pythonSVG | |
| } | |
| // ----------------------------CONFIG FORM DATA --------------------------// | |
| const getConfigCodeWithFormData = (codeLang, configData) => { | |
| if (codeLang === 'Python') { | |
| return `import requests | |
| API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}" | |
| # use form data to upload files | |
| form_data = {${getConfigExamplesForPython(configData, 'formData')}} | |
| def query(form_data): | |
| response = requests.post(API_URL, files=form_data) | |
| return response.json() | |
| output = query(form_data) | |
| ` | |
| } else if (codeLang === 'JavaScript') { | |
| return `// use FormData to upload files | |
| let formData = new FormData(); | |
| ${getConfigExamplesForJS(configData, 'formData')} | |
| async function query(formData) { | |
| const response = await fetch( | |
| "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}", | |
| { | |
| method: "POST", | |
| body: formData | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query(formData).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } else if (codeLang === 'cURL') { | |
| return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\ | |
| -X POST \\${getConfigExamplesForCurl(configData, 'formData')}` | |
| } | |
| return '' | |
| } | |
| // ----------------------------CONFIG FORM DATA with AUTH--------------------------// | |
| const getConfigCodeWithFormDataWithAuth = (codeLang, configData) => { | |
| if (codeLang === 'Python') { | |
| return `import requests | |
| API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}" | |
| headers = {"Authorization": "Bearer ${selectedApiKey?.apiKey}"} | |
| # use form data to upload files | |
| form_data = {${getConfigExamplesForPython(configData, 'formData')}} | |
| def query(form_data): | |
| response = requests.post(API_URL, headers=headers, files=form_data) | |
| return response.json() | |
| output = query(form_data) | |
| ` | |
| } else if (codeLang === 'JavaScript') { | |
| return `// use FormData to upload files | |
| let formData = new FormData(); | |
| ${getConfigExamplesForJS(configData, 'formData')} | |
| async function query(formData) { | |
| const response = await fetch( | |
| "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}", | |
| { | |
| headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" }, | |
| method: "POST", | |
| body: formData | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query(formData).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } else if (codeLang === 'cURL') { | |
| return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\ | |
| -X POST \\${getConfigExamplesForCurl(configData, 'formData')} \\ | |
| -H "Authorization: Bearer ${selectedApiKey?.apiKey}"` | |
| } | |
| return '' | |
| } | |
| // ----------------------------CONFIG JSON--------------------------// | |
| const getConfigCode = (codeLang, configData) => { | |
| 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?", | |
| "overrideConfig": {${getConfigExamplesForPython(configData, 'json')} | |
| } | |
| }) | |
| ` | |
| } else if (codeLang === 'JavaScript') { | |
| return `async function query(data) { | |
| const response = await fetch( | |
| "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}", | |
| { | |
| method: "POST", | |
| body: data | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query({ | |
| "question": "Hey, how are you?", | |
| "overrideConfig": {${getConfigExamplesForJS(configData, 'json')} | |
| } | |
| }).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } else if (codeLang === 'cURL') { | |
| return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\ | |
| -X POST \\ | |
| -d '{"question": "Hey, how are you?", "overrideConfig": {${getConfigExamplesForCurl(configData, 'json')}}'` | |
| } | |
| return '' | |
| } | |
| // ----------------------------CONFIG JSON with AUTH--------------------------// | |
| const getConfigCodeWithAuthorization = (codeLang, configData) => { | |
| 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?", | |
| "overrideConfig": {${getConfigExamplesForPython(configData, 'json')} | |
| } | |
| }) | |
| ` | |
| } 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: data | |
| } | |
| ); | |
| const result = await response.json(); | |
| return result; | |
| } | |
| query({ | |
| "question": "Hey, how are you?", | |
| "overrideConfig": {${getConfigExamplesForJS(configData, 'json')} | |
| } | |
| }).then((response) => { | |
| console.log(response); | |
| }); | |
| ` | |
| } else if (codeLang === 'cURL') { | |
| return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\ | |
| -X POST \\ | |
| -d '{"question": "Hey, how are you?", "overrideConfig": {${getConfigExamplesForCurl(configData, 'json')}}' \\ | |
| -H "Authorization: Bearer ${selectedApiKey?.apiKey}"` | |
| } | |
| return '' | |
| } | |
| 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: 15, width: 'auto' }} src={getSVG(codeLang)} alt='code' /> | |
| } | |
| iconPosition='start' | |
| key={index} | |
| label={codeLang} | |
| {...a11yProps(index)} | |
| ></Tab> | |
| ))} | |
| </Tabs> | |
| </div> | |
| {value !== 0 && ( | |
| <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}> | |
| {value === 0 && ( | |
| <> | |
| <span> | |
| Paste this anywhere in the <code>{`<body>`}</code> tag of your html file | |
| </span> | |
| <div style={{ height: 10 }}></div> | |
| </> | |
| )} | |
| <CopyBlock | |
| theme={atomOneDark} | |
| text={chatflowApiKeyId ? getCodeWithAuthorization(codeLang) : getCode(codeLang)} | |
| language={getLang(codeLang)} | |
| showLineNumbers={false} | |
| wrapLines | |
| /> | |
| {value !== 0 && <CheckboxInput label='Show Input Config' value={checkboxVal} onChange={onCheckBoxChanged} />} | |
| {value !== 0 && checkboxVal && getConfigApi.data && getConfigApi.data.length > 0 && ( | |
| <> | |
| <TableViewOnly rows={getConfigApi.data} columns={Object.keys(getConfigApi.data[0])} /> | |
| <CopyBlock | |
| theme={atomOneDark} | |
| text={ | |
| chatflowApiKeyId | |
| ? dialogProps.isFormDataRequired | |
| ? getConfigCodeWithFormDataWithAuth(codeLang, getConfigApi.data) | |
| : getConfigCodeWithAuthorization(codeLang, getConfigApi.data) | |
| : dialogProps.isFormDataRequired | |
| ? getConfigCodeWithFormData(codeLang, getConfigApi.data) | |
| : getConfigCode(codeLang, getConfigApi.data) | |
| } | |
| 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 | |