From a3d4befad40f4dac082fc7019a09e791afd41a99 Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Mon, 4 Mar 2024 16:52:35 +0800 Subject: [PATCH] service --- .../app/(appDetailLayout)/[appId]/layout.tsx | 9 +- .../[appId]/workflow/page.tsx | 92 +----------------- web/app/(commonLayout)/workflow/page.tsx | 96 ------------------- web/app/components/workflow/index.tsx | 38 ++++++++ web/service/base.ts | 18 ++-- web/service/workflow.ts | 18 ++++ web/types/workflow.ts | 13 +++ 7 files changed, 91 insertions(+), 193 deletions(-) delete mode 100644 web/app/(commonLayout)/workflow/page.tsx create mode 100644 web/service/workflow.ts create mode 100644 web/types/workflow.ts diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx index 12c9e88c90..8e98927cf2 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx @@ -29,10 +29,10 @@ const AppDetailLayout: FC = (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 = (props) => { }, [response]) if (!response) return null + return (
- {React.cloneElement(children as React.ReactElement, { appMode: response.mode })} + {children}
) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx index 245e172940..6f532baa7c 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx @@ -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 ( -
- -
+ ) } export default memo(Page) diff --git a/web/app/(commonLayout)/workflow/page.tsx b/web/app/(commonLayout)/workflow/page.tsx deleted file mode 100644 index 245e172940..0000000000 --- a/web/app/(commonLayout)/workflow/page.tsx +++ /dev/null @@ -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 ( -
- -
- ) -} -export default memo(Page) diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 9da7a25c6a..074e7458c1 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -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 = ({ 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 ( + + ) + } + return ( ( needAllResponseContent, deleteContentType, getAbortController, + silent, }: IOtherOptions, ): Promise => { const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions) @@ -250,13 +252,14 @@ const baseFetch = ( 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 = ( 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 = ( } 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 = ( // 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 = ( resolve(needAllResponseContent ? resClone : data) }) .catch((err) => { - Toast.notify({ type: 'error', message: err }) + if (!silent) + Toast.notify({ type: 'error', message: err }) reject(err) }) }), diff --git a/web/service/workflow.ts b/web/service/workflow.ts new file mode 100644 index 0000000000..35be70912d --- /dev/null +++ b/web/service/workflow.ts @@ -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 = (url) => { + return get(url, {}, { silent: true }) +} + +export const syncWorkflowDraft: Fetcher }> = ({ url, params }) => { + return post(url, { body: params }) +} + +export const fetchNodesDefaultConfigs: Fetcher = (url) => { + return get(url) +} diff --git a/web/types/workflow.ts b/web/types/workflow.ts new file mode 100644 index 0000000000..45b4828456 --- /dev/null +++ b/web/types/workflow.ts @@ -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 +}