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:
Dreammy23
2024-08-28 12:39:13 +08:00
committed by GitHub
parent 9502251c08
commit 131bc7b89b
60 changed files with 2334 additions and 2243 deletions

View File

@@ -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>