Commit a3d4befa authored by StyleZhang's avatar StyleZhang

service

parent 2f13d277
...@@ -29,10 +29,10 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => { ...@@ -29,10 +29,10 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
const detailParams = { url: '/apps', id: appId } const detailParams = { url: '/apps', id: appId }
const { data: response } = useSWR(detailParams, fetchAppDetail) const { data: response } = useSWR(detailParams, fetchAppDetail)
// redirection // redirections
if ((response?.mode === 'workflow' || response?.mode === 'advanced-chat') && (pathname).endsWith('configuration')) if (response && (response?.mode === 'workflow' || response?.mode === 'advanced-chat') && (pathname).endsWith('configuration'))
router.replace(`/app/${appId}/workflow`) 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`) router.replace(`/app/${appId}/configuration`)
const appModeName = (() => { const appModeName = (() => {
...@@ -89,11 +89,12 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => { ...@@ -89,11 +89,12 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
}, [response]) }, [response])
if (!response) if (!response)
return null return null
return ( return (
<div className={cn(s.app, 'flex', 'overflow-hidden')}> <div className={cn(s.app, 'flex', 'overflow-hidden')}>
<AppSideBar title={response.name} icon={response.icon} icon_background={response.icon_background} desc={appModeName} navigation={navigation} /> <AppSideBar title={response.name} icon={response.icon} icon_background={response.icon_background} desc={appModeName} navigation={navigation} />
<div className="bg-white grow overflow-hidden"> <div className="bg-white grow overflow-hidden">
{React.cloneElement(children as React.ReactElement<any>, { appMode: response.mode })} {children}
</div> </div>
</div> </div>
) )
......
'use client' 'use client'
import type { FC } from 'react'
import { memo } from 'react' import { memo } from 'react'
import Workflow from '@/app/components/workflow' import Workflow from '@/app/components/workflow'
const initialNodes = [ const Page = () => {
{
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 ( return (
<div className='min-w-[720px] w-full h-full overflow-x-auto'> <Workflow
<Workflow nodes={[]}
nodes={initialNodes} edges={[]}
edges={initialEdges} />
/>
</div>
) )
} }
export default memo(Page) export default memo(Page)
'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 { ...@@ -3,6 +3,8 @@ import {
memo, memo,
// useEffect, // useEffect,
} from 'react' } from 'react'
import { useParams } from 'next/navigation'
import useSWR from 'swr'
import { useKeyPress } from 'ahooks' import { useKeyPress } from 'ahooks'
import ReactFlow, { import ReactFlow, {
Background, Background,
...@@ -26,6 +28,12 @@ import CustomConnectionLine from './custom-connection-line' ...@@ -26,6 +28,12 @@ import CustomConnectionLine from './custom-connection-line'
import Panel from './panel' import Panel from './panel'
import Features from './features' import Features from './features'
import { useStore } from './store' import { useStore } from './store'
import { NodeInitialData } from './constants'
import {
fetchWorkflowDraft,
syncWorkflowDraft,
} from '@/service/workflow'
import Loading from '@/app/components/base/loading'
const nodeTypes = { const nodeTypes = {
custom: CustomNode, custom: CustomNode,
...@@ -112,6 +120,36 @@ const WorkflowWrap: FC<WorkflowProps> = ({ ...@@ -112,6 +120,36 @@ const WorkflowWrap: FC<WorkflowProps> = ({
nodes, nodes,
edges, 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 ( return (
<ReactFlowProvider> <ReactFlowProvider>
<Workflow <Workflow
......
...@@ -44,6 +44,7 @@ type IOtherOptions = { ...@@ -44,6 +44,7 @@ type IOtherOptions = {
bodyStringify?: boolean bodyStringify?: boolean
needAllResponseContent?: boolean needAllResponseContent?: boolean
deleteContentType?: boolean deleteContentType?: boolean
silent?: boolean
onData?: IOnData // for stream onData?: IOnData // for stream
onThought?: IOnThought onThought?: IOnThought
onFile?: IOnFile onFile?: IOnFile
...@@ -176,6 +177,7 @@ const baseFetch = <T>( ...@@ -176,6 +177,7 @@ const baseFetch = <T>(
needAllResponseContent, needAllResponseContent,
deleteContentType, deleteContentType,
getAbortController, getAbortController,
silent,
}: IOtherOptions, }: IOtherOptions,
): Promise<T> => { ): Promise<T> => {
const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions) const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions)
...@@ -250,13 +252,14 @@ const baseFetch = <T>( ...@@ -250,13 +252,14 @@ const baseFetch = <T>(
case 401: { case 401: {
if (isPublicAPI) { if (isPublicAPI) {
return bodyJson.then((data: ResponseError) => { 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) return Promise.reject(data)
}) })
} }
const loginUrl = `${globalThis.location.origin}/signin` const loginUrl = `${globalThis.location.origin}/signin`
bodyJson.then((data: ResponseError) => { 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 }) Toast.notify({ type: 'error', message: data.message, duration: 4000 })
else if (data.code === 'not_init_validated' && IS_CE_EDITION) else if (data.code === 'not_init_validated' && IS_CE_EDITION)
globalThis.location.href = `${globalThis.location.origin}/init` globalThis.location.href = `${globalThis.location.origin}/init`
...@@ -264,7 +267,7 @@ const baseFetch = <T>( ...@@ -264,7 +267,7 @@ const baseFetch = <T>(
globalThis.location.href = `${globalThis.location.origin}/install` globalThis.location.href = `${globalThis.location.origin}/install`
else if (location.pathname !== '/signin' || !IS_CE_EDITION) else if (location.pathname !== '/signin' || !IS_CE_EDITION)
globalThis.location.href = loginUrl globalThis.location.href = loginUrl
else else if (!silent)
Toast.notify({ type: 'error', message: data.message }) Toast.notify({ type: 'error', message: data.message })
}).catch(() => { }).catch(() => {
// Handle any other errors // Handle any other errors
...@@ -275,7 +278,8 @@ const baseFetch = <T>( ...@@ -275,7 +278,8 @@ const baseFetch = <T>(
} }
case 403: case 403:
bodyJson.then((data: ResponseError) => { 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') if (data.code === 'already_setup')
globalThis.location.href = `${globalThis.location.origin}/signin` globalThis.location.href = `${globalThis.location.origin}/signin`
}) })
...@@ -283,7 +287,8 @@ const baseFetch = <T>( ...@@ -283,7 +287,8 @@ const baseFetch = <T>(
// fall through // fall through
default: default:
bodyJson.then((data: ResponseError) => { bodyJson.then((data: ResponseError) => {
Toast.notify({ type: 'error', message: data.message }) if (!silent)
Toast.notify({ type: 'error', message: data.message })
}) })
} }
return Promise.reject(resClone) return Promise.reject(resClone)
...@@ -301,7 +306,8 @@ const baseFetch = <T>( ...@@ -301,7 +306,8 @@ const baseFetch = <T>(
resolve(needAllResponseContent ? resClone : data) resolve(needAllResponseContent ? resClone : data)
}) })
.catch((err) => { .catch((err) => {
Toast.notify({ type: 'error', message: err }) if (!silent)
Toast.notify({ type: 'error', message: err })
reject(err) reject(err)
}) })
}), }),
......
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)
}
import type {
Edge,
Node,
} from '@/app/components/workflow/types'
export type FetchWorkflowDraftResponse = {
id: string
graph: {
nodes: Node[]
edges: Edge[]
}
features?: any
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment