mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-26 15:00:20 +03:00
removed flow-config endpoint and resort to just prediction endpoint
This commit is contained in:
@@ -222,37 +222,12 @@ export class App {
|
||||
return res.json(availableConfigs)
|
||||
})
|
||||
|
||||
this.app.post('/api/v1/flow-config/:id', upload.array('files'), async (req: Request, res: Response) => {
|
||||
const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: req.params.id
|
||||
})
|
||||
if (!chatflow) return res.status(404).send(`Chatflow ${req.params.id} not found`)
|
||||
await this.validateKey(req, res, chatflow)
|
||||
|
||||
const overrideConfig: ICommonObject = { ...req.body }
|
||||
const files = req.files as any[]
|
||||
if (!files || !files.length) return
|
||||
|
||||
for (const file of files) {
|
||||
const fileData = fs.readFileSync(file.path, { encoding: 'base64' })
|
||||
const dataBase64String = `data:${file.mimetype};base64,${fileData},filename:${file.filename}`
|
||||
|
||||
const fileInputField = mapMimeTypeToInputField(file.mimetype)
|
||||
if (overrideConfig[fileInputField]) {
|
||||
overrideConfig[fileInputField] = JSON.stringify([...JSON.parse(overrideConfig[fileInputField]), dataBase64String])
|
||||
} else {
|
||||
overrideConfig[fileInputField] = JSON.stringify([dataBase64String])
|
||||
}
|
||||
}
|
||||
return res.json(overrideConfig)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Prediction
|
||||
// ----------------------------------------
|
||||
|
||||
// Send input message and get prediction result (External)
|
||||
this.app.post('/api/v1/prediction/:id', async (req: Request, res: Response) => {
|
||||
this.app.post('/api/v1/prediction/:id', upload.array('files'), async (req: Request, res: Response) => {
|
||||
await this.processPrediction(req, res)
|
||||
})
|
||||
|
||||
@@ -346,7 +321,7 @@ export class App {
|
||||
async processPrediction(req: Request, res: Response, isInternal = false) {
|
||||
try {
|
||||
const chatflowid = req.params.id
|
||||
const incomingInput: IncomingInput = req.body
|
||||
let incomingInput: IncomingInput = req.body
|
||||
|
||||
let nodeToExecuteData: INodeData
|
||||
|
||||
@@ -359,6 +334,28 @@ export class App {
|
||||
await this.validateKey(req, res, chatflow)
|
||||
}
|
||||
|
||||
const files = (req.files as any[]) || []
|
||||
|
||||
if (files.length) {
|
||||
const overrideConfig: ICommonObject = { ...req.body }
|
||||
for (const file of files) {
|
||||
const fileData = fs.readFileSync(file.path, { encoding: 'base64' })
|
||||
const dataBase64String = `data:${file.mimetype};base64,${fileData},filename:${file.filename}`
|
||||
|
||||
const fileInputField = mapMimeTypeToInputField(file.mimetype)
|
||||
if (overrideConfig[fileInputField]) {
|
||||
overrideConfig[fileInputField] = JSON.stringify([...JSON.parse(overrideConfig[fileInputField]), dataBase64String])
|
||||
} else {
|
||||
overrideConfig[fileInputField] = JSON.stringify([dataBase64String])
|
||||
}
|
||||
}
|
||||
incomingInput = {
|
||||
question: req.body.question ?? 'hello',
|
||||
overrideConfig,
|
||||
history: []
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't rebuild the flow (to avoid duplicated upsert, recomputation) when all these conditions met:
|
||||
* - Node Data already exists in pool
|
||||
* - Still in sync (i.e the flow has not been modified since)
|
||||
@@ -378,7 +375,6 @@ export class App {
|
||||
nodeToExecuteData = this.chatflowPool.activeChatflows[chatflowid].endingNodeData
|
||||
} else {
|
||||
/*** Get chatflows and prepare data ***/
|
||||
|
||||
const flowData = chatflow.flowData
|
||||
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
|
||||
const nodes = parsedFlowData.nodes
|
||||
|
||||
@@ -353,6 +353,12 @@ export const resolveVariables = (reactFlowNodeData: INodeData, reactFlowNodes: I
|
||||
return flowNodeData
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through each inputs and replace their value with override config values
|
||||
* @param {INodeData} flowNodeData
|
||||
* @param {ICommonObject} overrideConfig
|
||||
* @returns {INodeData}
|
||||
*/
|
||||
export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig: ICommonObject) => {
|
||||
const types = 'inputs'
|
||||
|
||||
@@ -560,12 +566,7 @@ export const findAvailableConfigs = (reactFlowNodes: IReactFlowNode[]) => {
|
||||
for (const inputParam of flowNode.data.inputParams) {
|
||||
let obj: IOverrideConfig
|
||||
if (inputParam.type === 'password' || inputParam.type === 'options') {
|
||||
obj = {
|
||||
node: flowNode.data.label,
|
||||
label: inputParam.label,
|
||||
name: inputParam.name,
|
||||
type: 'string'
|
||||
}
|
||||
continue
|
||||
} else if (inputParam.type === 'file') {
|
||||
obj = {
|
||||
node: flowNode.data.label,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// assets
|
||||
import { IconTrash, IconFileUpload, IconFileExport } from '@tabler/icons'
|
||||
import { IconTrash, IconFileUpload, IconFileExport, IconCopy } from '@tabler/icons'
|
||||
|
||||
// constant
|
||||
const icons = { IconTrash, IconFileUpload, IconFileExport }
|
||||
const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy }
|
||||
|
||||
// ==============================|| SETTINGS MENU ITEMS ||============================== //
|
||||
|
||||
@@ -11,6 +11,13 @@ const settings = {
|
||||
title: '',
|
||||
type: 'group',
|
||||
children: [
|
||||
{
|
||||
id: 'duplicateChatflow',
|
||||
title: 'Duplicate Chatflow',
|
||||
type: 'item',
|
||||
url: '',
|
||||
icon: icons.IconCopy
|
||||
},
|
||||
{
|
||||
id: 'loadChatflow',
|
||||
title: 'Load Chatflow',
|
||||
|
||||
@@ -4,3 +4,4 @@ export const drawerWidth = 260
|
||||
export const appDrawerWidth = 320
|
||||
export const maxScroll = 100000
|
||||
export const baseURL = process.env.NODE_ENV === 'production' ? window.location.origin : window.location.origin.replace(':8080', ':3000')
|
||||
export const uiBaseURL = window.location.origin
|
||||
|
||||
@@ -66,7 +66,7 @@ const unshiftFiles = (configData) => {
|
||||
return configData
|
||||
}
|
||||
|
||||
const getFormDataExamplesForJS = (configData) => {
|
||||
const getConfigExamplesForJS = (configData, bodyType) => {
|
||||
let finalStr = ''
|
||||
configData = unshiftFiles(configData)
|
||||
const loop = Math.min(configData.length, 4)
|
||||
@@ -77,12 +77,13 @@ const getFormDataExamplesForJS = (configData) => {
|
||||
else if (config.type === 'boolean') exampleVal = `true`
|
||||
else if (config.type === 'number') exampleVal = `1`
|
||||
else if (config.name === 'files') exampleVal = `input.files[0]`
|
||||
finalStr += `formData.append("${config.name}", ${exampleVal})\n`
|
||||
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 getFormDataExamplesForPython = (configData) => {
|
||||
const getConfigExamplesForPython = (configData, bodyType) => {
|
||||
let finalStr = ''
|
||||
configData = unshiftFiles(configData)
|
||||
const loop = Math.min(configData.length, 4)
|
||||
@@ -93,26 +94,26 @@ const getFormDataExamplesForPython = (configData) => {
|
||||
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 += `\n "${config.name}": ${exampleVal}`
|
||||
if (i === loop - 1) finalStr += `\n`
|
||||
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 getFormDataExamplesForCurl = (configData) => {
|
||||
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 = `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 += `\n -F "${config.name}=${exampleVal}"`
|
||||
if (i === loop - 1) finalStr += `)\n`
|
||||
else finalStr += ` \\`
|
||||
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
|
||||
}
|
||||
@@ -178,19 +179,21 @@ output = query({
|
||||
})
|
||||
`
|
||||
} else if (codeLang === 'JavaScript') {
|
||||
return `async function query() {
|
||||
return `async function query(data) {
|
||||
const response = await fetch(
|
||||
"${baseURL}/api/v1/prediction/${dialogProps.chatflowid}",
|
||||
{
|
||||
method: "POST",
|
||||
body: {
|
||||
"question": "Hey, how are you?"
|
||||
},
|
||||
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} \\
|
||||
@@ -222,14 +225,16 @@ output = query({
|
||||
{
|
||||
headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" },
|
||||
method: "POST",
|
||||
body: {
|
||||
"question": "Hey, how are you?"
|
||||
},
|
||||
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} \\
|
||||
@@ -262,143 +267,190 @@ output = query({
|
||||
return pythonSVG
|
||||
}
|
||||
|
||||
const getConfigCode = (codeLang, configData) => {
|
||||
// ----------------------------CONFIG FORM DATA --------------------------//
|
||||
|
||||
const getConfigCodeWithFormData = (codeLang, configData) => {
|
||||
if (codeLang === 'Python') {
|
||||
return `import requests
|
||||
form_data = {${getFormDataExamplesForPython(configData)}}
|
||||
|
||||
def setConfig():
|
||||
response = requests.post("${baseURL}/api/v1/flow-config/${dialogProps.chatflowid}", files=form_data)
|
||||
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()
|
||||
|
||||
def query(payload):
|
||||
response = requests.post("${baseURL}/api/v1/prediction/${dialogProps.chatflowid}", json=payload)
|
||||
return response.json()
|
||||
|
||||
# Set initial config
|
||||
config = setConfig()
|
||||
|
||||
# Run prediction with config
|
||||
output = query({
|
||||
"question": "Hey, how are you?",
|
||||
"overrideConfig": config
|
||||
})
|
||||
output = query(form_data)
|
||||
`
|
||||
} else if (codeLang === 'JavaScript') {
|
||||
return `let formData = new FormData();
|
||||
${getFormDataExamplesForJS(configData)}
|
||||
async function setConfig() {
|
||||
const response = await fetch(
|
||||
"${baseURL}/api/v1/flow-config/${dialogProps.chatflowid}",
|
||||
{
|
||||
method: "POST",
|
||||
body: formData
|
||||
}
|
||||
);
|
||||
const config = await response.json();
|
||||
return config; //Returns a config object
|
||||
}
|
||||
|
||||
async function query(config) {
|
||||
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: {
|
||||
"question": "Hey, how are you?",
|
||||
"overrideConfig": config
|
||||
},
|
||||
body: formData
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set initial config
|
||||
const config = await setConfig()
|
||||
|
||||
// Run prediction with config
|
||||
const res = await query(config)
|
||||
query(formData).then((response) => {
|
||||
console.log(response);
|
||||
});
|
||||
`
|
||||
} else if (codeLang === 'cURL') {
|
||||
return `CONFIG=$(curl ${baseURL}/api/v1/flow-config/${dialogProps.chatflowid} \\
|
||||
-X POST \\${getFormDataExamplesForCurl(configData)}
|
||||
curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
||||
-X POST \\
|
||||
-d '{"question": "Hey, how are you?", "overrideConfig": $CONFIG}'`
|
||||
return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
||||
-X POST \\${getConfigExamplesForCurl(configData, 'formData')}`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const getConfigCodeWithAuthorization = (codeLang, configData) => {
|
||||
// ----------------------------CONFIG FORM DATA with AUTH--------------------------//
|
||||
|
||||
const getConfigCodeWithFormDataWithAuth = (codeLang, configData) => {
|
||||
if (codeLang === 'Python') {
|
||||
return `import requests
|
||||
form_data = {${getFormDataExamplesForPython(configData)}}
|
||||
|
||||
API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}"
|
||||
headers = {"Authorization": "Bearer ${selectedApiKey?.apiKey}"}
|
||||
|
||||
def setConfig():
|
||||
response = requests.post("${baseURL}/api/v1/flow-config/${dialogProps.chatflowid}", headers=headers, files=form_data)
|
||||
# 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()
|
||||
|
||||
def query(payload):
|
||||
response = requests.post("${baseURL}/api/v1/prediction/${dialogProps.chatflowid}", headers=headers, json=payload)
|
||||
return response.json()
|
||||
|
||||
# Set initial config
|
||||
config = setConfig()
|
||||
|
||||
# Run prediction with config
|
||||
output = query({
|
||||
"question": "Hey, how are you?",
|
||||
"overrideConfig": config
|
||||
})
|
||||
output = query(form_data)
|
||||
`
|
||||
} else if (codeLang === 'JavaScript') {
|
||||
return `let formData = new FormData();
|
||||
${getFormDataExamplesForJS(configData)}
|
||||
async function setConfig() {
|
||||
return `// use FormData to upload files
|
||||
let formData = new FormData();
|
||||
${getConfigExamplesForJS(configData, 'formData')}
|
||||
async function query(formData) {
|
||||
const response = await fetch(
|
||||
"${baseURL}/api/v1/flow-config/${dialogProps.chatflowid}",
|
||||
"${baseURL}/api/v1/prediction/${dialogProps.chatflowid}",
|
||||
{
|
||||
headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" },
|
||||
method: "POST",
|
||||
body: formData
|
||||
}
|
||||
);
|
||||
const config = await response.json();
|
||||
return config; //Returns a config object
|
||||
const result = await response.json();
|
||||
return result;
|
||||
}
|
||||
|
||||
async function query(config) {
|
||||
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}",
|
||||
{
|
||||
headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" },
|
||||
method: "POST",
|
||||
body: {
|
||||
"question": "Hey, how are you?",
|
||||
"overrideConfig": config
|
||||
},
|
||||
body: data
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set initial config
|
||||
const config = await setConfig()
|
||||
|
||||
// Run prediction with config
|
||||
const res = await query(config)
|
||||
query({
|
||||
"question": "Hey, how are you?",
|
||||
"overrideConfig": {${getConfigExamplesForJS(configData, 'json')}
|
||||
}
|
||||
}).then((response) => {
|
||||
console.log(response);
|
||||
});
|
||||
`
|
||||
} else if (codeLang === 'cURL') {
|
||||
return `CONFIG=$(curl ${baseURL}/api/v1/flow-config/${dialogProps.chatflowid} \\
|
||||
return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
||||
-X POST \\
|
||||
-H "Authorization: Bearer ${selectedApiKey?.apiKey}"\\${getFormDataExamplesForCurl(configData)}
|
||||
curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
||||
-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 \\
|
||||
-H "Authorization: Bearer ${selectedApiKey?.apiKey}"
|
||||
-d '{"question": "Hey, how are you?", "overrideConfig": $CONFIG}'`
|
||||
-d '{"question": "Hey, how are you?", "overrideConfig": {${getConfigExamplesForCurl(configData, 'json')}}' \\
|
||||
-H "Authorization: Bearer ${selectedApiKey?.apiKey}"`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@@ -500,7 +552,11 @@ curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
|
||||
theme={atomOneDark}
|
||||
text={
|
||||
chatflowApiKeyId
|
||||
? getConfigCodeWithAuthorization(codeLang, getConfigApi.data)
|
||||
? dialogProps.isFormDataRequired
|
||||
? getConfigCodeWithFormDataWithAuth(codeLang, getConfigApi.data)
|
||||
: getConfigCodeWithAuthorization(codeLang, getConfigApi.data)
|
||||
: dialogProps.isFormDataRequired
|
||||
? getConfigCodeWithFormData(codeLang, getConfigApi.data)
|
||||
: getConfigCode(codeLang, getConfigApi.data)
|
||||
}
|
||||
language={getLang(codeLang)}
|
||||
|
||||
@@ -23,6 +23,7 @@ import useApi from 'hooks/useApi'
|
||||
|
||||
// utils
|
||||
import { generateExportFlowData } from 'utils/genericHelper'
|
||||
import { uiBaseURL } from 'store/constant'
|
||||
|
||||
// ==============================|| CANVAS HEADER ||============================== //
|
||||
|
||||
@@ -47,6 +48,13 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||
|
||||
if (setting === 'deleteChatflow') {
|
||||
handleDeleteFlow()
|
||||
} else if (setting === 'duplicateChatflow') {
|
||||
try {
|
||||
localStorage.setItem('duplicatedFlowData', chatflow.flowData)
|
||||
window.open(`${uiBaseURL}/canvas`, '_blank')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
} else if (setting === 'exportChatflow') {
|
||||
try {
|
||||
const flowData = JSON.parse(chatflow.flowData)
|
||||
@@ -80,10 +88,26 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||
}
|
||||
|
||||
const onAPIDialogClick = () => {
|
||||
let isFormDataRequired = false
|
||||
|
||||
try {
|
||||
const flowData = JSON.parse(chatflow.flowData)
|
||||
const nodes = flowData.nodes
|
||||
for (const node of nodes) {
|
||||
if (node.data.inputParams.find((param) => param.type === 'file')) {
|
||||
isFormDataRequired = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
setAPIDialogProps({
|
||||
title: 'Use this chatflow with API',
|
||||
chatflowid: chatflow.id,
|
||||
chatflowApiKeyId: chatflow.apikeyid
|
||||
chatflowApiKeyId: chatflow.apikeyid,
|
||||
isFormDataRequired
|
||||
})
|
||||
setAPIDialogOpen(true)
|
||||
}
|
||||
@@ -131,7 +155,9 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||
}
|
||||
}}
|
||||
color='inherit'
|
||||
onClick={() => navigate(-1)}
|
||||
onClick={() =>
|
||||
window.history.state && window.history.state.idx > 0 ? navigate(-1) : navigate('/', { replace: true })
|
||||
}
|
||||
>
|
||||
<IconChevronLeft stroke={1.5} size='1.3rem' />
|
||||
</Avatar>
|
||||
@@ -231,26 +257,28 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||
)}
|
||||
</Box>
|
||||
<Box>
|
||||
<ButtonBase title='API Endpoint' sx={{ borderRadius: '50%', mr: 2 }}>
|
||||
<Avatar
|
||||
variant='rounded'
|
||||
sx={{
|
||||
...theme.typography.commonAvatar,
|
||||
...theme.typography.mediumAvatar,
|
||||
transition: 'all .2s ease-in-out',
|
||||
background: theme.palette.canvasHeader.deployLight,
|
||||
color: theme.palette.canvasHeader.deployDark,
|
||||
'&:hover': {
|
||||
background: theme.palette.canvasHeader.deployDark,
|
||||
color: theme.palette.canvasHeader.deployLight
|
||||
}
|
||||
}}
|
||||
color='inherit'
|
||||
onClick={onAPIDialogClick}
|
||||
>
|
||||
<IconCode stroke={1.5} size='1.3rem' />
|
||||
</Avatar>
|
||||
</ButtonBase>
|
||||
{chatflow?.id && (
|
||||
<ButtonBase title='API Endpoint' sx={{ borderRadius: '50%', mr: 2 }}>
|
||||
<Avatar
|
||||
variant='rounded'
|
||||
sx={{
|
||||
...theme.typography.commonAvatar,
|
||||
...theme.typography.mediumAvatar,
|
||||
transition: 'all .2s ease-in-out',
|
||||
background: theme.palette.canvasHeader.deployLight,
|
||||
color: theme.palette.canvasHeader.deployDark,
|
||||
'&:hover': {
|
||||
background: theme.palette.canvasHeader.deployDark,
|
||||
color: theme.palette.canvasHeader.deployLight
|
||||
}
|
||||
}}
|
||||
color='inherit'
|
||||
onClick={onAPIDialogClick}
|
||||
>
|
||||
<IconCode stroke={1.5} size='1.3rem' />
|
||||
</Avatar>
|
||||
</ButtonBase>
|
||||
)}
|
||||
<ButtonBase title='Save Chatflow' sx={{ borderRadius: '50%', mr: 2 }}>
|
||||
<Avatar
|
||||
variant='rounded'
|
||||
|
||||
@@ -407,8 +407,13 @@ const Canvas = () => {
|
||||
if (chatflowId) {
|
||||
getSpecificChatflowApi.request(chatflowId)
|
||||
} else {
|
||||
setNodes([])
|
||||
setEdges([])
|
||||
if (localStorage.getItem('duplicatedFlowData')) {
|
||||
handleLoadFlow(localStorage.getItem('duplicatedFlowData'))
|
||||
setTimeout(() => localStorage.removeItem('duplicatedFlowData'), 0)
|
||||
} else {
|
||||
setNodes([])
|
||||
setEdges([])
|
||||
}
|
||||
dispatch({
|
||||
type: SET_CHATFLOW,
|
||||
chatflow: {
|
||||
|
||||
@@ -46,7 +46,6 @@ const MarketplaceCanvas = () => {
|
||||
}, [flowData])
|
||||
|
||||
const onChatflowCopy = (flowData) => {
|
||||
//navigator.clipboard.writeText(JSON.stringify(flowData))
|
||||
const templateFlowData = JSON.stringify(flowData)
|
||||
navigate(`/canvas`, { state: { templateFlowData } })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user