mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-11 13:58:58 +00:00
feat(web): AWEL flow 2.0 frontend codes (#1898)
Co-authored-by: Fangyin Cheng <staneyffer@gmail.com> Co-authored-by: 谨欣 <echo.cmy@antgroup.com> Co-authored-by: 严志勇 <yanzhiyong@tiansuixiansheng.com> Co-authored-by: yanzhiyong <932374019@qq.com>
This commit is contained in:
@@ -1,12 +1,31 @@
|
||||
import BlurredCard, { ChatButton, InnerDropdown } from '@/new-components/common/blurredCard';
|
||||
import BlurredCard, {
|
||||
ChatButton,
|
||||
InnerDropdown,
|
||||
} from '@/new-components/common/blurredCard';
|
||||
import ConstructLayout from '@/new-components/layout/Construct';
|
||||
import { ChatContext } from '@/app/chat-context';
|
||||
import { apiInterceptors, deleteFlowById, getFlows, newDialogue, updateFlowAdmins, addFlow } from '@/client/api';
|
||||
import {
|
||||
apiInterceptors,
|
||||
deleteFlowById,
|
||||
getFlows,
|
||||
newDialogue,
|
||||
addFlow,
|
||||
} from '@/client/api';
|
||||
import MyEmpty from '@/components/common/MyEmpty';
|
||||
import { IFlow, IFlowUpdateParam } from '@/types/flow';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Button, Modal, Popconfirm, Select, Spin, Tag, message, Form, Input, Checkbox } from 'antd';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
Popconfirm,
|
||||
Spin,
|
||||
Tag,
|
||||
message,
|
||||
Form,
|
||||
Input,
|
||||
Checkbox,
|
||||
} from 'antd';
|
||||
import { t } from 'i18next';
|
||||
import { concat, debounce } from 'lodash';
|
||||
import moment from 'moment';
|
||||
@@ -19,18 +38,14 @@ function Flow() {
|
||||
const router = useRouter();
|
||||
const { model } = useContext(ChatContext);
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [form] = Form.useForm<Pick<IFlow, 'label' | 'name'>>();
|
||||
|
||||
const [flowList, setFlowList] = useState<Array<IFlow>>([]);
|
||||
const [adminOpen, setAdminOpen] = useState<boolean>(false);
|
||||
const [curFlow, setCurFLow] = useState<IFlow>();
|
||||
const [admins, setAdmins] = useState<string[]>([]);
|
||||
const copyFlowTemp = useRef<IFlow>();
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [deploy, setDeploy] = useState(false);
|
||||
const [editable, setEditable] = useState(false);
|
||||
|
||||
const [form] = Form.useForm<Pick<IFlow, 'label' | 'name'>>();
|
||||
|
||||
// 分页信息
|
||||
const totalRef = useRef<{
|
||||
current_page: number;
|
||||
@@ -41,18 +56,14 @@ function Flow() {
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// 获取列表
|
||||
const {
|
||||
run: getFlowListRun,
|
||||
loading,
|
||||
refresh: refreshFlowList,
|
||||
} = useRequest(
|
||||
const { run: getFlowListRun, loading } = useRequest(
|
||||
async (params: any) =>
|
||||
await apiInterceptors(
|
||||
getFlows({
|
||||
page: 1,
|
||||
page_size: 12,
|
||||
...params,
|
||||
}),
|
||||
})
|
||||
),
|
||||
{
|
||||
cacheKey: 'query-flow-list',
|
||||
@@ -66,7 +77,7 @@ function Flow() {
|
||||
};
|
||||
},
|
||||
throttleWait: 300,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const { i18n } = useTranslation();
|
||||
@@ -112,7 +123,9 @@ function Flow() {
|
||||
}, [loading, handleScroll, loadMoreData]);
|
||||
|
||||
const handleChat = async (flow: IFlow) => {
|
||||
const [, res] = await apiInterceptors(newDialogue({ chat_mode: 'chat_agent' }));
|
||||
const [, res] = await apiInterceptors(
|
||||
newDialogue({ chat_mode: 'chat_agent' })
|
||||
);
|
||||
if (res) {
|
||||
const queryStr = qs.stringify({
|
||||
scene: 'chat_flow',
|
||||
@@ -131,30 +144,6 @@ function Flow() {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (curFlow?.admins?.length) {
|
||||
setAdmins(curFlow?.admins);
|
||||
} else {
|
||||
setAdmins([]);
|
||||
}
|
||||
}, [curFlow]);
|
||||
|
||||
// 更新管理员
|
||||
const { run: updateAdmins, loading: adminLoading } = useRequest(
|
||||
async (value: string[]) => await apiInterceptors(updateFlowAdmins({ uid: curFlow?.uid || '', admins: value })),
|
||||
{
|
||||
manual: true,
|
||||
onSuccess: (data) => {
|
||||
const [error] = data;
|
||||
if (!error) {
|
||||
message.success('更新成功');
|
||||
} else {
|
||||
message.error('更新失败');
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const handleCopy = (flow: IFlow) => {
|
||||
copyFlowTemp.current = flow;
|
||||
form.setFieldValue('label', `${flow.label} Copy`);
|
||||
@@ -166,7 +155,8 @@ function Flow() {
|
||||
|
||||
const onFinish = async (val: { name: string; label: string }) => {
|
||||
if (!copyFlowTemp.current) return;
|
||||
const { source, uid, dag_id, gmt_created, gmt_modified, state, ...params } = copyFlowTemp.current;
|
||||
const { source, uid, dag_id, gmt_created, gmt_modified, state, ...params } =
|
||||
copyFlowTemp.current;
|
||||
const data: IFlowUpdateParam = {
|
||||
...params,
|
||||
editable,
|
||||
@@ -181,18 +171,15 @@ function Flow() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = async (value: string[]) => {
|
||||
setAdmins(value);
|
||||
await updateAdmins(value);
|
||||
await refreshFlowList();
|
||||
};
|
||||
|
||||
return (
|
||||
<ConstructLayout>
|
||||
<Spin spinning={loading}>
|
||||
<div className="relative h-screen w-full p-4 md:p-6 overflow-y-auto" ref={scrollRef}>
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div
|
||||
className='relative h-screen w-full p-4 md:p-6 overflow-y-auto'
|
||||
ref={scrollRef}
|
||||
>
|
||||
<div className='flex justify-between items-center mb-6'>
|
||||
<div className='flex items-center gap-4'>
|
||||
{/* <Input
|
||||
variant="filled"
|
||||
prefix={<SearchOutlined />}
|
||||
@@ -204,9 +191,9 @@ function Flow() {
|
||||
/> */}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className='flex items-center gap-4'>
|
||||
<Button
|
||||
className="border-none text-white bg-button-gradient"
|
||||
className='border-none text-white bg-button-gradient'
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => {
|
||||
router.push('/construct/flow/canvas');
|
||||
@@ -216,13 +203,13 @@ function Flow() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap mx-[-8px] pb-12 justify-start items-stretch">
|
||||
<div className='flex flex-wrap mx-[-8px] pb-12 justify-start items-stretch'>
|
||||
{flowList.map((flow) => (
|
||||
<BlurredCard
|
||||
description={flow.description}
|
||||
name={flow.name}
|
||||
key={flow.uid}
|
||||
logo="/pictures/flow.png"
|
||||
logo='/pictures/flow.png'
|
||||
onClick={() => {
|
||||
router.push('/construct/flow/canvas?id=' + flow.uid);
|
||||
}}
|
||||
@@ -230,19 +217,6 @@ function Flow() {
|
||||
<InnerDropdown
|
||||
menu={{
|
||||
items: [
|
||||
// {
|
||||
// key: 'edit',
|
||||
// label: (
|
||||
// <span
|
||||
// onClick={() => {
|
||||
// setAdminOpen(true);
|
||||
// setCurFLow(flow);
|
||||
// }}
|
||||
// >
|
||||
// 权限管理
|
||||
// </span>
|
||||
// ),
|
||||
// },
|
||||
{
|
||||
key: 'copy',
|
||||
label: (
|
||||
@@ -251,15 +225,20 @@ function Flow() {
|
||||
handleCopy(flow);
|
||||
}}
|
||||
>
|
||||
{t('copy')}
|
||||
{t('Copy_Btn')}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'del',
|
||||
label: (
|
||||
<Popconfirm title="Are you sure to delete this flow?" onConfirm={() => deleteFlow(flow)}>
|
||||
<span className="text-red-400">删除</span>
|
||||
<Popconfirm
|
||||
title='Are you sure to delete this flow?'
|
||||
onConfirm={() => deleteFlow(flow)}
|
||||
>
|
||||
<span className='text-red-400'>
|
||||
{t('Delete_Btn')}
|
||||
</span>
|
||||
</Popconfirm>
|
||||
),
|
||||
},
|
||||
@@ -270,16 +249,36 @@ function Flow() {
|
||||
rightTopHover={false}
|
||||
Tags={
|
||||
<div>
|
||||
<Tag color={flow.source === 'DBGPT-WEB' ? 'green' : 'blue'}>{flow.source}</Tag>
|
||||
<Tag color={flow.editable ? 'green' : 'gray'}>{flow.editable ? 'Editable' : 'Can not Edit'}</Tag>
|
||||
<Tag color={flow.state === 'load_failed' ? 'red' : flow.state === 'running' ? 'green' : 'blue'}>{flow.state}</Tag>
|
||||
<Tag color={flow.source === 'DBGPT-WEB' ? 'green' : 'blue'}>
|
||||
{flow.source}
|
||||
</Tag>
|
||||
<Tag color={flow.editable ? 'green' : 'gray'}>
|
||||
{flow.editable ? 'Editable' : 'Can not Edit'}
|
||||
</Tag>
|
||||
<Tag
|
||||
color={
|
||||
flow.state === 'load_failed'
|
||||
? 'red'
|
||||
: flow.state === 'running'
|
||||
? 'green'
|
||||
: 'blue'
|
||||
}
|
||||
>
|
||||
{flow.state}
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
LeftBottom={
|
||||
<div key={i18n.language + 'flow'} className="flex gap-2">
|
||||
<div key={i18n.language + 'flow'} className='flex gap-2'>
|
||||
<span>{flow?.nick_name}</span>
|
||||
<span>•</span>
|
||||
{flow?.gmt_modified && <span>{moment(flow?.gmt_modified).fromNow() + ' ' + t('update')}</span>}
|
||||
{flow?.gmt_modified && (
|
||||
<span>
|
||||
{moment(flow?.gmt_modified).fromNow() +
|
||||
' ' +
|
||||
t('update')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
RightBottom={
|
||||
@@ -292,40 +291,26 @@ function Flow() {
|
||||
}
|
||||
/>
|
||||
))}
|
||||
{flowList.length === 0 && <MyEmpty description="No flow found" />}
|
||||
{flowList.length === 0 && <MyEmpty description='No flow found' />}
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
<Modal title="权限管理" open={adminOpen} onCancel={() => setAdminOpen(false)} footer={null}>
|
||||
<div className="py-4">
|
||||
<div className="mb-1">管理员(工号,去前缀0):</div>
|
||||
<Select
|
||||
mode="tags"
|
||||
value={admins}
|
||||
style={{ width: '100%' }}
|
||||
onChange={handleChange}
|
||||
tokenSeparators={[',']}
|
||||
options={admins?.map((item: string) => ({ label: item, value: item }))}
|
||||
loading={adminLoading}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal
|
||||
open={showModal}
|
||||
title="Copy AWEL Flow"
|
||||
title='Copy AWEL Flow'
|
||||
onCancel={() => {
|
||||
setShowModal(false);
|
||||
}}
|
||||
footer={false}
|
||||
>
|
||||
<Form form={form} onFinish={onFinish} className="mt-6">
|
||||
<Form.Item name="name" label="Name" rules={[{ required: true }]}>
|
||||
<Form form={form} onFinish={onFinish} className='mt-6'>
|
||||
<Form.Item name='name' label='Name' rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="label" label="Label" rules={[{ required: true }]}>
|
||||
<Form.Item name='label' label='Label' rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label="editable">
|
||||
<Form.Item label='editable'>
|
||||
<Checkbox
|
||||
value={editable}
|
||||
checked={editable}
|
||||
@@ -335,7 +320,7 @@ function Flow() {
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="deploy">
|
||||
<Form.Item label='deploy'>
|
||||
<Checkbox
|
||||
value={deploy}
|
||||
checked={deploy}
|
||||
@@ -345,8 +330,8 @@ function Flow() {
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<div className="flex justify-end">
|
||||
<Button type="primary" htmlType="submit">
|
||||
<div className='flex justify-end'>
|
||||
<Button type='primary' htmlType='submit'>
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user