balibabu commited on
Commit
9ee6e3a
·
1 Parent(s): 591888d

feat: add CreateFlowModal #918 (#1343)

Browse files

### What problem does this PR solve?

feat: add CreateFlowModal #918

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

web/src/hooks/flow-hooks.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { DSL, IFlow } from '@/interfaces/database/flow';
 
2
  import i18n from '@/locales/config';
3
  import flowService from '@/services/flow-service';
4
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
5
  import { message } from 'antd';
6
  import { useParams } from 'umi';
7
 
8
- export const useFetchFlowTemplates = () => {
9
  const { data } = useQuery({
10
  queryKey: ['fetchFlowTemplates'],
11
  initialData: [],
 
1
+ import { ResponseType } from '@/interfaces/database/base';
2
+ import { DSL, IFlow, IFlowTemplate } from '@/interfaces/database/flow';
3
  import i18n from '@/locales/config';
4
  import flowService from '@/services/flow-service';
5
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
6
  import { message } from 'antd';
7
  import { useParams } from 'umi';
8
 
9
+ export const useFetchFlowTemplates = (): ResponseType<IFlowTemplate[]> => {
10
  const { data } = useQuery({
11
  queryKey: ['fetchFlowTemplates'],
12
  initialData: [],
web/src/hooks/logicHooks.ts CHANGED
@@ -244,3 +244,28 @@ export const useHandleMessageInputChange = () => {
244
  };
245
 
246
  // #endregion
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  };
245
 
246
  // #endregion
247
+
248
+ /**
249
+ *
250
+ * @param defaultId
251
+ * used to switch between different items, similar to radio
252
+ * @returns
253
+ */
254
+ export const useSelectItem = (defaultId?: string) => {
255
+ const [selectedId, setSelectedId] = useState('');
256
+
257
+ const handleItemClick = useCallback(
258
+ (id: string) => () => {
259
+ setSelectedId(id);
260
+ },
261
+ [],
262
+ );
263
+
264
+ useEffect(() => {
265
+ if (defaultId) {
266
+ setSelectedId(defaultId);
267
+ }
268
+ }, [defaultId]);
269
+
270
+ return { selectedId, handleItemClick };
271
+ };
web/src/interfaces/database/base.ts CHANGED
@@ -1,6 +1,6 @@
1
- export interface ResponseType {
2
  retcode: number;
3
- data: any;
4
  retmsg: string;
5
  status: number;
6
  }
 
1
+ export interface ResponseType<T = any> {
2
  retcode: number;
3
+ data: T;
4
  retmsg: string;
5
  status: number;
6
  }
web/src/interfaces/database/flow.ts CHANGED
@@ -42,3 +42,16 @@ export interface IFlow {
42
  update_time: number;
43
  user_id: string;
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  update_time: number;
43
  user_id: string;
44
  }
45
+
46
+ export interface IFlowTemplate {
47
+ avatar: string;
48
+ canvas_type: string;
49
+ create_date: string;
50
+ create_time: number;
51
+ description: string;
52
+ dsl: DSL;
53
+ id: string;
54
+ title: string;
55
+ update_date: string;
56
+ update_time: number;
57
+ }
web/src/locales/en.ts CHANGED
@@ -557,6 +557,7 @@ The above is the content you need to summarize.`,
557
  messageMsg: 'Please input message or delete this field.',
558
  addField: 'Add field',
559
  loop: 'Loop',
 
560
  },
561
  footer: {
562
  profile: 'All rights reserved @ React',
 
557
  messageMsg: 'Please input message or delete this field.',
558
  addField: 'Add field',
559
  loop: 'Loop',
560
+ createFlow: 'Create a workflow',
561
  },
562
  footer: {
563
  profile: 'All rights reserved @ React',
web/src/locales/zh.ts CHANGED
@@ -524,6 +524,7 @@ export default {
524
  fileError: '文件错误',
525
  },
526
  flow: {
 
527
  cite: '引用',
528
  citeTip: 'citeTip',
529
  name: '名称',
 
524
  fileError: '文件错误',
525
  },
526
  flow: {
527
+ flow: '工作流',
528
  cite: '引用',
529
  citeTip: 'citeTip',
530
  name: '名称',
web/src/pages/flow/hooks.ts CHANGED
@@ -1,9 +1,5 @@
1
  import { useSetModalState } from '@/hooks/commonHooks';
2
- import {
3
- useFetchFlow,
4
- useFetchFlowTemplates,
5
- useSetFlow,
6
- } from '@/hooks/flow-hooks';
7
  import { useFetchLlmList } from '@/hooks/llmHooks';
8
  import { IGraph } from '@/interfaces/database/flow';
9
  import { useIsFetching } from '@tanstack/react-query';
@@ -221,7 +217,6 @@ export const useFetchDataOnMount = () => {
221
 
222
  useWatchGraphChange();
223
 
224
- useFetchFlowTemplates();
225
  useFetchLlmList();
226
 
227
  return { loading, flowDetail: data };
 
1
  import { useSetModalState } from '@/hooks/commonHooks';
2
+ import { useFetchFlow, useSetFlow } from '@/hooks/flow-hooks';
 
 
 
 
3
  import { useFetchLlmList } from '@/hooks/llmHooks';
4
  import { IGraph } from '@/interfaces/database/flow';
5
  import { useIsFetching } from '@tanstack/react-query';
 
217
 
218
  useWatchGraphChange();
219
 
 
220
  useFetchLlmList();
221
 
222
  return { loading, flowDetail: data };
web/src/pages/flow/list/create-flow-modal.tsx ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { IModalManagerChildrenProps } from '@/components/modal-manager';
2
+ import { useTranslate } from '@/hooks/commonHooks';
3
+ import { useFetchFlowTemplates } from '@/hooks/flow-hooks';
4
+ import { useSelectItem } from '@/hooks/logicHooks';
5
+ import { UserOutlined } from '@ant-design/icons';
6
+ import {
7
+ Avatar,
8
+ Card,
9
+ Flex,
10
+ Form,
11
+ Input,
12
+ Modal,
13
+ Space,
14
+ Typography,
15
+ } from 'antd';
16
+ import classNames from 'classnames';
17
+ import { useEffect } from 'react';
18
+ import styles from './index.less';
19
+
20
+ const { Title } = Typography;
21
+ interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
22
+ loading: boolean;
23
+ initialName: string;
24
+ onOk: (name: string, templateId: string) => void;
25
+ showModal?(): void;
26
+ }
27
+
28
+ const CreateFlowModal = ({
29
+ visible,
30
+ hideModal,
31
+ loading,
32
+ initialName,
33
+ onOk,
34
+ }: IProps) => {
35
+ const [form] = Form.useForm();
36
+ const { t } = useTranslate('common');
37
+ const { data: list } = useFetchFlowTemplates();
38
+ const { selectedId, handleItemClick } = useSelectItem(list?.at(0)?.id);
39
+
40
+ type FieldType = {
41
+ name?: string;
42
+ };
43
+
44
+ const handleOk = async () => {
45
+ const ret = await form.validateFields();
46
+
47
+ return onOk(ret.name, selectedId);
48
+ };
49
+
50
+ useEffect(() => {
51
+ if (visible) {
52
+ form.setFieldValue('name', initialName);
53
+ }
54
+ }, [initialName, form, visible]);
55
+
56
+ return (
57
+ <Modal
58
+ title={t('createFlow', { keyPrefix: 'flow' })}
59
+ open={visible}
60
+ onOk={handleOk}
61
+ width={600}
62
+ onCancel={hideModal}
63
+ okButtonProps={{ loading }}
64
+ confirmLoading={loading}
65
+ >
66
+ <Form
67
+ name="basic"
68
+ labelCol={{ span: 4 }}
69
+ wrapperCol={{ span: 20 }}
70
+ autoComplete="off"
71
+ layout={'vertical'}
72
+ form={form}
73
+ >
74
+ <Form.Item<FieldType>
75
+ label={<b>{t('name')}</b>}
76
+ name="name"
77
+ rules={[{ required: true, message: t('namePlaceholder') }]}
78
+ >
79
+ <Input />
80
+ </Form.Item>
81
+ </Form>
82
+ <Title level={5}>Choose from templates</Title>
83
+ <Flex vertical gap={16}>
84
+ {list?.map((x) => (
85
+ <Card
86
+ key={x.id}
87
+ className={classNames(styles.flowTemplateCard, {
88
+ [styles.selectedFlowTemplateCard]: selectedId === x.id,
89
+ })}
90
+ onClick={handleItemClick(x.id)}
91
+ >
92
+ <Space size={'middle'}>
93
+ <Avatar size={40} icon={<UserOutlined />} src={x.avatar} />
94
+ <b>{x.title}</b>
95
+ </Space>
96
+ <p>{x.description}</p>
97
+ </Card>
98
+ ))}
99
+ </Flex>
100
+ </Modal>
101
+ );
102
+ };
103
+
104
+ export default CreateFlowModal;
web/src/pages/flow/list/hooks.ts CHANGED
@@ -1,10 +1,14 @@
1
  import { useSetModalState } from '@/hooks/commonHooks';
2
- import { useFetchFlowList, useSetFlow } from '@/hooks/flow-hooks';
 
 
 
 
3
  import { useCallback, useState } from 'react';
4
  import { useNavigate } from 'umi';
5
  // import { dsl } from '../mock';
6
- import headhunterZhComponents from '../../../../../graph/test/dsl_examples/headhunter_zh.json';
7
- import headhunter_zh from '../headhunter_zh.json';
8
 
9
  export const useFetchDataOnMount = () => {
10
  const { data, loading } = useFetchFlowList();
@@ -21,12 +25,19 @@ export const useSaveFlow = () => {
21
  } = useSetModalState();
22
  const { loading, setFlow } = useSetFlow();
23
  const navigate = useNavigate();
 
24
 
25
  const onFlowOk = useCallback(
26
- async (title: string) => {
 
 
 
 
 
 
27
  const ret = await setFlow({
28
  title,
29
- dsl: { ...headhunterZhComponents, graph: headhunter_zh },
30
  });
31
 
32
  if (ret?.retcode === 0) {
@@ -34,7 +45,7 @@ export const useSaveFlow = () => {
34
  navigate(`/flow/${ret.data.id}`);
35
  }
36
  },
37
- [setFlow, hideFlowSettingModal, navigate],
38
  );
39
 
40
  const handleShowFlowSettingModal = useCallback(
 
1
  import { useSetModalState } from '@/hooks/commonHooks';
2
+ import {
3
+ useFetchFlowList,
4
+ useFetchFlowTemplates,
5
+ useSetFlow,
6
+ } from '@/hooks/flow-hooks';
7
  import { useCallback, useState } from 'react';
8
  import { useNavigate } from 'umi';
9
  // import { dsl } from '../mock';
10
+ // import headhunterZhComponents from '../../../../../graph/test/dsl_examples/headhunter_zh.json';
11
+ import dslJson from '../../../../../dls.json';
12
 
13
  export const useFetchDataOnMount = () => {
14
  const { data, loading } = useFetchFlowList();
 
25
  } = useSetModalState();
26
  const { loading, setFlow } = useSetFlow();
27
  const navigate = useNavigate();
28
+ const { data: list } = useFetchFlowTemplates();
29
 
30
  const onFlowOk = useCallback(
31
+ async (title: string, templateId: string) => {
32
+ const templateItem = list.find((x) => x.id === templateId);
33
+
34
+ let dsl = templateItem?.dsl;
35
+ // if (dsl) {
36
+ // dsl.graph = headhunter_zh;
37
+ // }
38
  const ret = await setFlow({
39
  title,
40
+ dsl: dslJson,
41
  });
42
 
43
  if (ret?.retcode === 0) {
 
45
  navigate(`/flow/${ret.data.id}`);
46
  }
47
  },
48
+ [setFlow, hideFlowSettingModal, navigate, list],
49
  );
50
 
51
  const handleShowFlowSettingModal = useCallback(
web/src/pages/flow/list/index.less CHANGED
@@ -46,3 +46,11 @@
46
  width: 100%;
47
  }
48
  }
 
 
 
 
 
 
 
 
 
46
  width: 100%;
47
  }
48
  }
49
+
50
+ .flowTemplateCard {
51
+ cursor: pointer;
52
+ }
53
+
54
+ .selectedFlowTemplateCard {
55
+ background-color: @selectedBackgroundColor;
56
+ }
web/src/pages/flow/list/index.tsx CHANGED
@@ -1,6 +1,6 @@
1
- import RenameModal from '@/components/rename-modal';
2
  import { PlusOutlined } from '@ant-design/icons';
3
  import { Button, Empty, Flex, Spin } from 'antd';
 
4
  import FlowCard from './flow-card';
5
  import { useFetchDataOnMount, useSaveFlow } from './hooks';
6
 
@@ -39,13 +39,15 @@ const FlowList = () => {
39
  )}
40
  </Flex>
41
  </Spin>
42
- <RenameModal
43
- visible={flowSettingVisible}
44
- onOk={onFlowOk}
45
- loading={flowSettingLoading}
46
- hideModal={hideFlowSettingModal}
47
- initialName=""
48
- ></RenameModal>
 
 
49
  </Flex>
50
  );
51
  };
 
 
1
  import { PlusOutlined } from '@ant-design/icons';
2
  import { Button, Empty, Flex, Spin } from 'antd';
3
+ import CreateFlowModal from './create-flow-modal';
4
  import FlowCard from './flow-card';
5
  import { useFetchDataOnMount, useSaveFlow } from './hooks';
6
 
 
39
  )}
40
  </Flex>
41
  </Spin>
42
+ {flowSettingVisible && (
43
+ <CreateFlowModal
44
+ visible={flowSettingVisible}
45
+ onOk={onFlowOk}
46
+ loading={flowSettingLoading}
47
+ hideModal={hideFlowSettingModal}
48
+ initialName=""
49
+ ></CreateFlowModal>
50
+ )}
51
  </Flex>
52
  );
53
  };