Feature/extract import all (#2796)

* use existing route to get all chatflows

* add export all chatflows functionality

* add read exported all chatflows json file functionality

* add save chatflows functionality in server

* chore rename saveChatflows to importChatflows and others

* chore rewrite snackbar message

* fix import chatflows when no data in chatflows db

* add handle when import file array length is 0

* chore update and add meaning comment in importChatflows

* update method of storing flowdata for importChatflows function

* Refresh/redirect to chatflows when import is successful

* fix lint

---------

Co-authored-by: Ilango <rajagopalilango@gmail.com>
This commit is contained in:
Ong Chung Yau
2024-07-16 09:47:41 +08:00
committed by GitHub
parent 074bb738a3
commit 95b2cf7b7f
7 changed files with 254 additions and 30 deletions
@@ -1,11 +1,11 @@
import { Request, Response, NextFunction } from 'express'
import chatflowsService from '../../services/chatflows'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { createRateLimiter } from '../../utils/rateLimit'
import { getApiKey } from '../../utils/apiKey'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { NextFunction, Request, Response } from 'express'
import { StatusCodes } from 'http-status-codes'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { ChatflowType } from '../../Interface'
import chatflowsService from '../../services/chatflows'
import { getApiKey } from '../../utils/apiKey'
import { createRateLimiter } from '../../utils/rateLimit'
const checkIfChatflowIsValidForStreaming = async (req: Request, res: Response, next: NextFunction) => {
try {
@@ -105,6 +105,16 @@ const saveChatflow = async (req: Request, res: Response, next: NextFunction) =>
}
}
const importChatflows = async (req: Request, res: Response, next: NextFunction) => {
try {
const chatflows: Partial<ChatFlow>[] = req.body.Chatflows
const apiResponse = await chatflowsService.importChatflows(chatflows)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const updateChatflow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
@@ -167,6 +177,7 @@ export default {
getChatflowByApiKey,
getChatflowById,
saveChatflow,
importChatflows,
updateChatflow,
getSinglePublicChatflow,
getSinglePublicChatbotConfig
@@ -4,6 +4,7 @@ const router = express.Router()
// CREATE
router.post('/', chatflowsController.saveChatflow)
router.post('/importchatflows', chatflowsController.importChatflows)
// READ
router.get('/', chatflowsController.getAllChatflows)
+5 -5
View File
@@ -1,10 +1,10 @@
import express from 'express'
import apikeyRouter from './apikey'
import assistantsRouter from './assistants'
import chatMessageRouter from './chat-messages'
import chatflowsRouter from './chatflows'
import chatflowsStreamingRouter from './chatflows-streaming'
import chatflowsUploadsRouter from './chatflows-uploads'
import chatMessageRouter from './chat-messages'
import componentsCredentialsRouter from './components-credentials'
import componentsCredentialsIconRouter from './components-credentials-icon'
import credentialsRouter from './credentials'
@@ -12,10 +12,10 @@ import documentStoreRouter from './documentstore'
import feedbackRouter from './feedback'
import fetchLinksRouter from './fetch-links'
import flowConfigRouter from './flow-config'
import internalChatmessagesRouter from './internal-chat-messages'
import internalPredictionRouter from './internal-predictions'
import getUploadFileRouter from './get-upload-file'
import getUploadPathRouter from './get-upload-path'
import internalChatmessagesRouter from './internal-chat-messages'
import internalPredictionRouter from './internal-predictions'
import leadsRouter from './leads'
import loadPromptRouter from './load-prompts'
import marketplacesRouter from './marketplaces'
@@ -27,18 +27,18 @@ import nodesRouter from './nodes'
import openaiAssistantsRouter from './openai-assistants'
import openaiAssistantsFileRouter from './openai-assistants-files'
import openaiAssistantsVectorStoreRouter from './openai-assistants-vector-store'
import pingRouter from './ping'
import predictionRouter from './predictions'
import promptListsRouter from './prompts-lists'
import publicChatbotRouter from './public-chatbots'
import publicChatflowsRouter from './public-chatflows'
import statsRouter from './stats'
import toolsRouter from './tools'
import upsertHistoryRouter from './upsert-history'
import variablesRouter from './variables'
import vectorRouter from './vectors'
import verifyRouter from './verify'
import versionRouter from './versions'
import upsertHistoryRouter from './upsert-history'
import pingRouter from './ping'
const router = express.Router()
+64 -10
View File
@@ -1,19 +1,18 @@
import { StatusCodes } from 'http-status-codes'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { ChatflowType, IChatFlow } from '../../Interface'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { getAppVersion, getTelemetryFlowObj, isFlowValidForStream, constructGraphs, getEndingNodes } from '../../utils'
import logger from '../../utils/logger'
import { removeFolderFromStorage } from 'flowise-components'
import { IReactFlowObject } from '../../Interface'
import { utilGetUploadsConfig } from '../../utils/getUploadsConfig'
import { StatusCodes } from 'http-status-codes'
import { ChatflowType, IChatFlow, IReactFlowObject } from '../../Interface'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { ChatMessage } from '../../database/entities/ChatMessage'
import { ChatMessageFeedback } from '../../database/entities/ChatMessageFeedback'
import { UpsertHistory } from '../../database/entities/UpsertHistory'
import { containsBase64File, updateFlowDataWithFilePaths } from '../../utils/fileRepository'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { getErrorMessage } from '../../errors/utils'
import documentStoreService from '../../services/documentstore'
import { constructGraphs, getAppVersion, getEndingNodes, getTelemetryFlowObj, isFlowValidForStream } from '../../utils'
import { containsBase64File, updateFlowDataWithFilePaths } from '../../utils/fileRepository'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { utilGetUploadsConfig } from '../../utils/getUploadsConfig'
import logger from '../../utils/logger'
// Check if chatflow valid for streaming
const checkIfChatflowIsValidForStreaming = async (chatflowId: string): Promise<any> => {
@@ -198,6 +197,60 @@ const saveChatflow = async (newChatFlow: ChatFlow): Promise<any> => {
}
}
const importChatflows = async (newChatflows: Partial<ChatFlow>[]): Promise<any> => {
try {
const appServer = getRunningExpressApp()
// step 1 - check whether file chatflows array is zero
if (newChatflows.length == 0) throw new Error('No chatflows in this file.')
// step 2 - check whether ids are duplicate in database
let ids = '('
let count: number = 0
const lastCount = newChatflows.length - 1
newChatflows.forEach((newChatflow) => {
ids += `'${newChatflow.id}'`
if (lastCount != count) ids += ','
if (lastCount == count) ids += ')'
count += 1
})
const selectResponse = await appServer.AppDataSource.getRepository(ChatFlow)
.createQueryBuilder('cf')
.select('cf.id')
.where(`cf.id IN ${ids}`)
.getMany()
const foundIds = selectResponse.map((response) => {
return response.id
})
// step 3 - remove ids that are only duplicate
const prepChatflows: Partial<ChatFlow>[] = newChatflows.map((newChatflow) => {
let id: string = ''
if (newChatflow.id) id = newChatflow.id
let flowData: string = ''
if (newChatflow.flowData) flowData = newChatflow.flowData
if (foundIds.includes(id)) {
newChatflow.id = undefined
newChatflow.name += ' with new id'
}
newChatflow.type = 'CHATFLOW'
newChatflow.flowData = JSON.stringify(JSON.parse(flowData))
return newChatflow
})
// step 4 - transactional insert array of entities
const insertResponse = await appServer.AppDataSource.getRepository(ChatFlow).insert(prepChatflows)
return insertResponse
} catch (error) {
throw new InternalFlowiseError(
StatusCodes.INTERNAL_SERVER_ERROR,
`Error: chatflowsService.saveChatflows - ${getErrorMessage(error)}`
)
}
}
const updateChatflow = async (chatflow: ChatFlow, updateChatFlow: ChatFlow): Promise<any> => {
try {
const appServer = getRunningExpressApp()
@@ -299,6 +352,7 @@ export default {
getChatflowByApiKey,
getChatflowById,
saveChatflow,
importChatflows,
updateChatflow,
getSinglePublicChatflow,
getSinglePublicChatbotConfig