mirror of https://github.com/langgenius/dify.git
service
This commit is contained in:
parent
2f13d2775f
commit
a3d4befad4
|
|
@ -29,10 +29,10 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
|||
const detailParams = { url: '/apps', id: appId }
|
||||
const { data: response } = useSWR(detailParams, fetchAppDetail)
|
||||
|
||||
// redirection
|
||||
if ((response?.mode === 'workflow' || response?.mode === 'advanced-chat') && (pathname).endsWith('configuration'))
|
||||
// redirections
|
||||
if (response && (response?.mode === 'workflow' || response?.mode === 'advanced-chat') && (pathname).endsWith('configuration'))
|
||||
router.replace(`/app/${appId}/workflow`)
|
||||
if ((response?.mode !== 'workflow' && response?.mode !== 'advanced-chat') && (pathname).endsWith('workflow'))
|
||||
if (response && (response?.mode !== 'workflow' && response?.mode !== 'advanced-chat') && (pathname).endsWith('workflow'))
|
||||
router.replace(`/app/${appId}/configuration`)
|
||||
|
||||
const appModeName = (() => {
|
||||
|
|
@ -89,11 +89,12 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
|||
}, [response])
|
||||
if (!response)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className={cn(s.app, 'flex', 'overflow-hidden')}>
|
||||
<AppSideBar title={response.name} icon={response.icon} icon_background={response.icon_background} desc={appModeName} navigation={navigation} />
|
||||
<div className="bg-white grow overflow-hidden">
|
||||
{React.cloneElement(children as React.ReactElement<any>, { appMode: response.mode })}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,96 +1,14 @@
|
|||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import Workflow from '@/app/components/workflow'
|
||||
|
||||
const initialNodes = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'custom',
|
||||
position: { x: 180, y: 180 },
|
||||
data: { type: 'start' },
|
||||
},
|
||||
// {
|
||||
// id: '2',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: {
|
||||
// type: 'if-else',
|
||||
// branches: [
|
||||
// {
|
||||
// id: 'if-true',
|
||||
// name: 'IS TRUE',
|
||||
// },
|
||||
// {
|
||||
// id: 'if-false',
|
||||
// name: 'IS FALSE',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: '3',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: { type: 'question-classifier', sortIndexInBranches: 0 },
|
||||
// },
|
||||
// {
|
||||
// id: '4',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: {
|
||||
// type: 'if-else',
|
||||
// sortIndexInBranches: 1,
|
||||
// branches: [
|
||||
// {
|
||||
// id: 'if-true',
|
||||
// name: 'IS TRUE',
|
||||
// },
|
||||
// {
|
||||
// id: 'if-false',
|
||||
// name: 'IS FALSE',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
]
|
||||
|
||||
const initialEdges = [
|
||||
// {
|
||||
// id: '0',
|
||||
// type: 'custom',
|
||||
// source: '1',
|
||||
// sourceHandle: 'source',
|
||||
// target: '2',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
// {
|
||||
// id: '1',
|
||||
// type: 'custom',
|
||||
// source: '2',
|
||||
// sourceHandle: 'if-true',
|
||||
// target: '3',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
// {
|
||||
// id: '2',
|
||||
// type: 'custom',
|
||||
// source: '2',
|
||||
// sourceHandle: 'if-false',
|
||||
// target: '4',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
]
|
||||
|
||||
const Page: FC = () => {
|
||||
const Page = () => {
|
||||
return (
|
||||
<div className='min-w-[720px] w-full h-full overflow-x-auto'>
|
||||
<Workflow
|
||||
nodes={initialNodes}
|
||||
edges={initialEdges}
|
||||
/>
|
||||
</div>
|
||||
<Workflow
|
||||
nodes={[]}
|
||||
edges={[]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default memo(Page)
|
||||
|
|
|
|||
|
|
@ -1,96 +0,0 @@
|
|||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import Workflow from '@/app/components/workflow'
|
||||
|
||||
const initialNodes = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'custom',
|
||||
position: { x: 180, y: 180 },
|
||||
data: { type: 'start' },
|
||||
},
|
||||
// {
|
||||
// id: '2',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: {
|
||||
// type: 'if-else',
|
||||
// branches: [
|
||||
// {
|
||||
// id: 'if-true',
|
||||
// name: 'IS TRUE',
|
||||
// },
|
||||
// {
|
||||
// id: 'if-false',
|
||||
// name: 'IS FALSE',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: '3',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: { type: 'question-classifier', sortIndexInBranches: 0 },
|
||||
// },
|
||||
// {
|
||||
// id: '4',
|
||||
// type: 'custom',
|
||||
// position: { x: 0, y: 0 },
|
||||
// data: {
|
||||
// type: 'if-else',
|
||||
// sortIndexInBranches: 1,
|
||||
// branches: [
|
||||
// {
|
||||
// id: 'if-true',
|
||||
// name: 'IS TRUE',
|
||||
// },
|
||||
// {
|
||||
// id: 'if-false',
|
||||
// name: 'IS FALSE',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
]
|
||||
|
||||
const initialEdges = [
|
||||
// {
|
||||
// id: '0',
|
||||
// type: 'custom',
|
||||
// source: '1',
|
||||
// sourceHandle: 'source',
|
||||
// target: '2',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
// {
|
||||
// id: '1',
|
||||
// type: 'custom',
|
||||
// source: '2',
|
||||
// sourceHandle: 'if-true',
|
||||
// target: '3',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
// {
|
||||
// id: '2',
|
||||
// type: 'custom',
|
||||
// source: '2',
|
||||
// sourceHandle: 'if-false',
|
||||
// target: '4',
|
||||
// targetHandle: 'target',
|
||||
// },
|
||||
]
|
||||
|
||||
const Page: FC = () => {
|
||||
return (
|
||||
<div className='min-w-[720px] w-full h-full overflow-x-auto'>
|
||||
<Workflow
|
||||
nodes={initialNodes}
|
||||
edges={initialEdges}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default memo(Page)
|
||||
|
|
@ -3,6 +3,8 @@ import {
|
|||
memo,
|
||||
// useEffect,
|
||||
} from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import useSWR from 'swr'
|
||||
import { useKeyPress } from 'ahooks'
|
||||
import ReactFlow, {
|
||||
Background,
|
||||
|
|
@ -26,6 +28,12 @@ import CustomConnectionLine from './custom-connection-line'
|
|||
import Panel from './panel'
|
||||
import Features from './features'
|
||||
import { useStore } from './store'
|
||||
import { NodeInitialData } from './constants'
|
||||
import {
|
||||
fetchWorkflowDraft,
|
||||
syncWorkflowDraft,
|
||||
} from '@/service/workflow'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
|
||||
const nodeTypes = {
|
||||
custom: CustomNode,
|
||||
|
|
@ -112,6 +120,36 @@ const WorkflowWrap: FC<WorkflowProps> = ({
|
|||
nodes,
|
||||
edges,
|
||||
}) => {
|
||||
const appId = useParams().appId
|
||||
const { data, isLoading, error } = useSWR(`/apps/${appId}/workflows/draft`, fetchWorkflowDraft)
|
||||
// const { data: configsData } = useSWR(`/apps/${appId}/workflows/default-workflow-block-configs`, fetchNodesDefaultConfigs)
|
||||
|
||||
if (error) {
|
||||
syncWorkflowDraft({
|
||||
url: `/apps/${appId}/workflows/draft`,
|
||||
params: {
|
||||
graph: {
|
||||
nodes: [{
|
||||
id: `${Date.now()}`,
|
||||
data: NodeInitialData.start,
|
||||
position: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
}],
|
||||
edges: [],
|
||||
},
|
||||
features: {},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Loading />
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactFlowProvider>
|
||||
<Workflow
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ type IOtherOptions = {
|
|||
bodyStringify?: boolean
|
||||
needAllResponseContent?: boolean
|
||||
deleteContentType?: boolean
|
||||
silent?: boolean
|
||||
onData?: IOnData // for stream
|
||||
onThought?: IOnThought
|
||||
onFile?: IOnFile
|
||||
|
|
@ -176,6 +177,7 @@ const baseFetch = <T>(
|
|||
needAllResponseContent,
|
||||
deleteContentType,
|
||||
getAbortController,
|
||||
silent,
|
||||
}: IOtherOptions,
|
||||
): Promise<T> => {
|
||||
const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions)
|
||||
|
|
@ -250,13 +252,14 @@ const baseFetch = <T>(
|
|||
case 401: {
|
||||
if (isPublicAPI) {
|
||||
return bodyJson.then((data: ResponseError) => {
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
return Promise.reject(data)
|
||||
})
|
||||
}
|
||||
const loginUrl = `${globalThis.location.origin}/signin`
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
if (data.code === 'init_validate_failed' && IS_CE_EDITION)
|
||||
if (data.code === 'init_validate_failed' && IS_CE_EDITION && !silent)
|
||||
Toast.notify({ type: 'error', message: data.message, duration: 4000 })
|
||||
else if (data.code === 'not_init_validated' && IS_CE_EDITION)
|
||||
globalThis.location.href = `${globalThis.location.origin}/init`
|
||||
|
|
@ -264,7 +267,7 @@ const baseFetch = <T>(
|
|||
globalThis.location.href = `${globalThis.location.origin}/install`
|
||||
else if (location.pathname !== '/signin' || !IS_CE_EDITION)
|
||||
globalThis.location.href = loginUrl
|
||||
else
|
||||
else if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
}).catch(() => {
|
||||
// Handle any other errors
|
||||
|
|
@ -275,7 +278,8 @@ const baseFetch = <T>(
|
|||
}
|
||||
case 403:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (data.code === 'already_setup')
|
||||
globalThis.location.href = `${globalThis.location.origin}/signin`
|
||||
})
|
||||
|
|
@ -283,7 +287,8 @@ const baseFetch = <T>(
|
|||
// fall through
|
||||
default:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
})
|
||||
}
|
||||
return Promise.reject(resClone)
|
||||
|
|
@ -301,7 +306,8 @@ const baseFetch = <T>(
|
|||
resolve(needAllResponseContent ? resClone : data)
|
||||
})
|
||||
.catch((err) => {
|
||||
Toast.notify({ type: 'error', message: err })
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: err })
|
||||
reject(err)
|
||||
})
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import type { Fetcher } from 'swr'
|
||||
import { get, post } from './base'
|
||||
import type { CommonResponse } from '@/models/common'
|
||||
import type {
|
||||
FetchWorkflowDraftResponse,
|
||||
} from '@/types/workflow'
|
||||
|
||||
export const fetchWorkflowDraft: Fetcher<FetchWorkflowDraftResponse, string> = (url) => {
|
||||
return get<FetchWorkflowDraftResponse>(url, {}, { silent: true })
|
||||
}
|
||||
|
||||
export const syncWorkflowDraft: Fetcher<CommonResponse, { url: string; params: Pick<FetchWorkflowDraftResponse, 'graph' | 'features'> }> = ({ url, params }) => {
|
||||
return post<CommonResponse>(url, { body: params })
|
||||
}
|
||||
|
||||
export const fetchNodesDefaultConfigs: Fetcher<any, string> = (url) => {
|
||||
return get<any>(url)
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
} from '@/app/components/workflow/types'
|
||||
|
||||
export type FetchWorkflowDraftResponse = {
|
||||
id: string
|
||||
graph: {
|
||||
nodes: Node[]
|
||||
edges: Edge[]
|
||||
}
|
||||
features?: any
|
||||
}
|
||||
Loading…
Reference in New Issue