feat(web): Add Workflow
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { type FC, useEffect, useState, useRef, type Key } from 'react'
|
||||
import { type FC, useEffect, useState, useRef, forwardRef, useImperativeHandle, type Key } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useParams } from 'react-router-dom';
|
||||
import Card from './components/Card'
|
||||
@@ -11,17 +11,19 @@ import type {
|
||||
Config,
|
||||
SubAgentModalRef,
|
||||
ChatData,
|
||||
SubAgentItem
|
||||
SubAgentItem,
|
||||
ClusterRef
|
||||
} from './types'
|
||||
import Chat from './components/Chat'
|
||||
import RbCard from '@/components/RbCard/Card'
|
||||
import SubAgentModal from './components/SubAgentModal'
|
||||
import Empty from '@/components/Empty'
|
||||
import type { Application } from '@/views/ApplicationManagement/types'
|
||||
|
||||
|
||||
const tagColors = ['processing', 'warning', 'default']
|
||||
const MAX_LENGTH = 5;
|
||||
const Cluster: FC<{application: SubAgentItem}> = ({application}) => {
|
||||
const Cluster = forwardRef<ClusterRef, { application: Application }>(({application}, ref) => {
|
||||
const { t } = useTranslation()
|
||||
const { message } = App.useApp()
|
||||
const [form] = Form.useForm()
|
||||
@@ -113,6 +115,9 @@ const Cluster: FC<{application: SubAgentItem}> = ({application}) => {
|
||||
form.setFieldsValue({ master_agent_name: option.children })
|
||||
}
|
||||
}
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleSave
|
||||
}))
|
||||
|
||||
return (
|
||||
<Row className="rb:h-[calc(100vh-64px)]">
|
||||
@@ -210,6 +215,6 @@ const Cluster: FC<{application: SubAgentItem}> = ({application}) => {
|
||||
/>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Cluster
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type FC, useRef } from 'react';
|
||||
import { type FC, useEffect, useRef } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Layout, Tabs, Dropdown } from 'antd';
|
||||
import { Layout, Tabs, Dropdown, Button } from 'antd';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from '../index.module.css'
|
||||
@@ -11,7 +11,7 @@ import exportIcon from '@/assets/images/export_hover.svg'
|
||||
import deleteIcon from '@/assets/images/delete_hover.svg'
|
||||
import type { Application, ApplicationModalRef } from '@/views/ApplicationManagement/types';
|
||||
import ApplicationModal from '@/views/ApplicationManagement/components/ApplicationModal'
|
||||
import type { CopyModalRef } from '../types'
|
||||
import type { CopyModalRef, WorkflowRef } from '../types'
|
||||
import { deleteApplication } from '@/api/application'
|
||||
import CopyModal from './CopyModal'
|
||||
|
||||
@@ -29,8 +29,12 @@ interface ConfigHeaderProps {
|
||||
activeTab: string;
|
||||
handleChangeTab: (key: string) => void;
|
||||
refresh: () => void;
|
||||
workflowRef: React.RefObject<WorkflowRef>
|
||||
}
|
||||
const ConfigHeader: FC<ConfigHeaderProps> = ({ application, activeTab, handleChangeTab, refresh }) => {
|
||||
const ConfigHeader: FC<ConfigHeaderProps> = ({
|
||||
application, activeTab, handleChangeTab, refresh,
|
||||
workflowRef
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
@@ -46,7 +50,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({ application, activeTab, handleCha
|
||||
const formatMenuItems = () => {
|
||||
const items = ['edit', 'copy', 'delete'].map(key => ({
|
||||
key,
|
||||
icon: <img src={menuIcons[key]} className="rb:w-[16px] rb:h-[16px] rb:mr-[8px]" />,
|
||||
icon: <img src={menuIcons[key]} className="rb:w-4 rb:h-4 rb:mr-2" />,
|
||||
label: t(`common.${key}`),
|
||||
}))
|
||||
return {
|
||||
@@ -85,12 +89,23 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({ application, activeTab, handleCha
|
||||
const goToApplication = () => {
|
||||
navigate('/application', { replace: true })
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
workflowRef.current?.handleSave()
|
||||
}
|
||||
const run = () => {
|
||||
workflowRef.current?.handleSave(false)
|
||||
.then(() => {
|
||||
workflowRef.current?.handleRun()
|
||||
})
|
||||
}
|
||||
const clear = () => {
|
||||
workflowRef?.current?.graphRef?.current?.clearCells()
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Header className="rb:w-full rb:h-[64px] rb:grid rb:grid-cols-3 rb:p-[16px_16px_16px_24px]! rb:border-b rb:border-[#EAECEE] rb:leading-[32px]">
|
||||
<div className="rb:h-[32px] rb:flex rb:items-center rb:font-medium">
|
||||
<div className="rb:w-[32px] rb:h-[32px] rb:rounded-[8px] rb:mr-[13px] rb:bg-[#155eef] rb:flex rb:items-center rb:justify-center rb:text-[24px] rb:text-[#ffffff]">
|
||||
<Header className="rb:w-full rb:h-16 rb:grid rb:grid-cols-3 rb:p-[16px_16px_16px_24px]! rb:border-b rb:border-[#EAECEE] rb:leading-8">
|
||||
<div className="rb:h-8 rb:flex rb:items-center rb:font-medium">
|
||||
<div className="rb:w-8 rb:h-8 rb:rounded-lg rb:mr-3.25 rb:bg-[#155eef] rb:flex rb:items-center rb:justify-center rb:text-[24px] rb:text-[#ffffff]">
|
||||
{application?.name[0]}
|
||||
</div>
|
||||
|
||||
@@ -101,7 +116,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({ application, activeTab, handleCha
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div
|
||||
className="rb:w-[20px] rb:h-[20px] rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/edit.svg')] rb:hover:bg-[url('@/assets/images/edit_hover.svg')]"
|
||||
className="rb:w-5 rb:h-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/edit.svg')] rb:hover:bg-[url('@/assets/images/edit_hover.svg')]"
|
||||
></div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
@@ -114,10 +129,19 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({ application, activeTab, handleCha
|
||||
className={styles.tabs}
|
||||
/>
|
||||
</div>
|
||||
<div className="rb:h-[32px] rb:flex rb:items-center rb:justify-end rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={goToApplication}>
|
||||
<img src={logoutIcon} className="rb:mr-[8px]" />
|
||||
{application?.type === 'workflow'
|
||||
? <div className="rb:h-8 rb:flex rb:items-center rb:justify-end rb:gap-2.5">
|
||||
<Button onClick={clear}>{t('workflow.clear')}</Button>
|
||||
<Button onClick={run}>{t('workflow.run')}</Button>
|
||||
<Button type="primary" onClick={save}>{t('workflow.save')}</Button>
|
||||
{/* <Button type="primary">{t('workflow.export')}</Button> */}
|
||||
<img src={logoutIcon} className="rb:w-4 rb:h-4 rb:cursor-pointer" onClick={goToApplication} />
|
||||
</div>
|
||||
: <div className="rb:h-8 rb:flex rb:items-center rb:justify-end rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={goToApplication}>
|
||||
<img src={logoutIcon} className="rb:mr-2 rb:w-4 rb:h-4" />
|
||||
{t('application.returnToApplicationList')}
|
||||
</div>
|
||||
}
|
||||
</Header>
|
||||
<ApplicationModal
|
||||
ref={applicationModalRef}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import ConfigHeader from './components/ConfigHeader'
|
||||
import type { AgentRef } from './types'
|
||||
import type { AgentRef, ClusterRef, WorkflowRef } from './types'
|
||||
import type { Application } from '@/views/ApplicationManagement/types'
|
||||
import Agent from './Agent'
|
||||
import Api from './Api'
|
||||
import ReleasePage from './ReleasePage'
|
||||
import Cluster from './Cluster'
|
||||
import { getApplication } from '@/api/application'
|
||||
import Workflow from '@/views/Workflow';
|
||||
|
||||
const ApplicationConfig: React.FC = () => {
|
||||
const { id } = useParams();
|
||||
const agentRef = useRef<AgentRef>(null)
|
||||
const clusterRef = useRef<ClusterRef>(null)
|
||||
const workflowRef = useRef<WorkflowRef>(null)
|
||||
const [application, setApplication] = useState<Application | null>(null);
|
||||
const [activeTab, setActiveTab] = useState('arrangement');
|
||||
|
||||
@@ -21,6 +24,16 @@ const ApplicationConfig: React.FC = () => {
|
||||
.then(() => {
|
||||
setActiveTab(key)
|
||||
})
|
||||
} else if (activeTab === 'arrangement' && application?.type === 'multi_agent' && clusterRef.current) {
|
||||
clusterRef.current.handleSave(false)
|
||||
.then(() => {
|
||||
setActiveTab(key)
|
||||
})
|
||||
} else if (activeTab === 'arrangement' && application?.type === 'workflow' && workflowRef.current) {
|
||||
workflowRef.current.handleSave(false)
|
||||
.then(() => {
|
||||
setActiveTab(key)
|
||||
})
|
||||
} else {
|
||||
setActiveTab(key)
|
||||
}
|
||||
@@ -47,9 +60,11 @@ const ApplicationConfig: React.FC = () => {
|
||||
handleChangeTab={handleChangeTab}
|
||||
application={application as Application}
|
||||
refresh={getApplicationInfo}
|
||||
workflowRef={workflowRef}
|
||||
/>
|
||||
{activeTab === 'arrangement' && application?.type === 'agent' && <Agent ref={agentRef} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'multi_agent' && <Cluster application={application as Application} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'multi_agent' && <Cluster ref={clusterRef} application={application as Application} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'workflow' && <Workflow ref={workflowRef} />}
|
||||
{activeTab === 'api' && <Api application={application} />}
|
||||
{activeTab === 'release' && <ReleasePage data={application as Application} refresh={getApplicationInfo} />}
|
||||
</>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { KnowledgeBaseListItem } from '@/views/KnowledgeBase/types'
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
import type { GraphRef } from '@/views/Workflow/types';
|
||||
import type { ApiKey } from '@/views/ApiKeyManagement/types'
|
||||
|
||||
export interface ModelConfig {
|
||||
label?: string;
|
||||
@@ -116,6 +118,14 @@ export interface ApplicationModalData {
|
||||
export interface AgentRef {
|
||||
handleSave: (flag?: boolean) => Promise<any>;
|
||||
}
|
||||
export interface ClusterRef {
|
||||
handleSave: (flag?: boolean) => Promise<any>;
|
||||
}
|
||||
export interface WorkflowRef {
|
||||
handleSave: (flag?: boolean) => Promise<any>;
|
||||
handleRun: () => void;
|
||||
graphRef: GraphRef
|
||||
}
|
||||
export interface ApplicationModalRef {
|
||||
handleOpen: (application?: Config) => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user