mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-11 22:09:44 +00:00
Merge branch 'feat/sprint-web-flow' into feat/tags
This commit is contained in:
@@ -2,6 +2,9 @@ import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const en = {
|
||||
UploadData: 'Upload Data',
|
||||
CodeEditor: 'Code Editor:',
|
||||
openCodeEditor:'Open Code Editor',
|
||||
Knowledge_Space: 'Knowledge',
|
||||
space: 'space',
|
||||
Vector: 'Vector',
|
||||
@@ -234,6 +237,9 @@ export interface Resources {
|
||||
}
|
||||
|
||||
const zh: Resources['translation'] = {
|
||||
UploadData: '上传数据',
|
||||
CodeEditor: '代码编辑:',
|
||||
openCodeEditor: '打开代码编辑器',
|
||||
Knowledge_Space: '知识库',
|
||||
space: '知识库',
|
||||
Vector: '向量',
|
||||
|
@@ -15,10 +15,11 @@ import {
|
||||
RenderTreeSelect,
|
||||
RenderTimePicker,
|
||||
RenderTextArea,
|
||||
RenderUpload,
|
||||
RenderCodeEditor,
|
||||
RenderPassword,
|
||||
RenderVariables,
|
||||
} from './node-renderer';
|
||||
import { convertKeysToCamelCase } from '@/utils/flow';
|
||||
|
||||
interface NodeParamHandlerProps {
|
||||
node: IFlowNode;
|
||||
@@ -140,11 +141,13 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
|
||||
case 'time_picker':
|
||||
return <RenderTimePicker {...props} />;
|
||||
case 'tree_select':
|
||||
return <RenderPassword {...props} />;
|
||||
case 'password':
|
||||
return <RenderTreeSelect {...props} />;
|
||||
case 'variables':
|
||||
return <RenderVariables {...props} />;
|
||||
case 'password':
|
||||
return <RenderPassword {...props} />;
|
||||
case 'upload':
|
||||
return <RenderUpload {...props} />;
|
||||
case 'code_editor':
|
||||
return <RenderCodeEditor {...props} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
67
web/components/flow/node-renderer/codeEditor.tsx
Normal file
67
web/components/flow/node-renderer/codeEditor.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { Button, Modal } from 'antd';
|
||||
import Editor from '@monaco-editor/react';
|
||||
import { IFlowNodeParameter } from '@/types/flow';
|
||||
import { convertKeysToCamelCase } from '@/utils/flow';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type Props = {
|
||||
data: IFlowNodeParameter;
|
||||
defaultValue: any;
|
||||
onChange: (value: any) => void;
|
||||
};
|
||||
|
||||
export const RenderCodeEditor = (params: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { data, defaultValue, onChange } = params;
|
||||
const attr = convertKeysToCamelCase(data.ui?.attr || {});
|
||||
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const showModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
/**
|
||||
* 设置弹窗宽度
|
||||
*/
|
||||
const modalWidth = useMemo(() => {
|
||||
if (data?.ui?.editor?.width) {
|
||||
return data?.ui?.editor?.width + 100
|
||||
}
|
||||
return '80%';
|
||||
}, [data?.ui?.editor?.width]);
|
||||
|
||||
return (
|
||||
<div style={{ textAlign: 'center' }} className="p-2 text-sm">
|
||||
<Button type="primary" onClick={showModal}>
|
||||
{t('openCodeEditor')}
|
||||
</Button>
|
||||
<Modal title={t('openCodeEditor')} width={modalWidth} open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Editor
|
||||
{...data?.ui?.attr}
|
||||
width={data?.ui?.editor?.width || '100%'}
|
||||
value={defaultValue}
|
||||
style={{ padding: '10px' }}
|
||||
height={data?.ui?.editor?.height || 200}
|
||||
defaultLanguage={data?.ui?.language}
|
||||
onChange={onChange}
|
||||
theme='vs-dark'
|
||||
options={{
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
wordWrap: 'on',
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
@@ -11,7 +11,6 @@ type Props = {
|
||||
|
||||
export const RenderDatePicker = (params: Props) => {
|
||||
const { data, defaultValue, onChange } = params;
|
||||
console.log('data', data);
|
||||
|
||||
const attr = convertKeysToCamelCase(data.ui?.attr || {});
|
||||
|
||||
|
@@ -8,5 +8,7 @@ export * from './textarea';
|
||||
export * from './slider';
|
||||
export * from './time-picker';
|
||||
export * from './tree-select';
|
||||
export * from './codeEditor';
|
||||
export * from './upload';
|
||||
export * from './password';
|
||||
export * from './variables';
|
||||
|
@@ -25,14 +25,14 @@ export const RenderSlider = (params: TextAreaProps) => {
|
||||
{data?.ui?.show_input ? (
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Slider {...attr} onChange={onChangeSlider} value={typeof inputValue === 'number' ? inputValue : 0} />
|
||||
<Slider className="w-full nodrag" {...attr} onChange={onChangeSlider} value={typeof inputValue === 'number' ? inputValue : 0} />
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<InputNumber {...attr} style={{ margin: '0 16px' }} value={inputValue} onChange={onChangeSlider} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : (
|
||||
<Slider {...attr} onChange={onChangeSlider} value={typeof inputValue === 'number' ? inputValue : 0} />
|
||||
<Slider className="w-full nodrag" {...attr} onChange={onChangeSlider} value={typeof inputValue === 'number' ? inputValue : 0} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@@ -13,6 +13,7 @@ type TextAreaProps = {
|
||||
|
||||
export const RenderTextArea = (params: TextAreaProps) => {
|
||||
const { data, defaultValue, onChange } = params;
|
||||
|
||||
const attr = convertKeysToCamelCase(data.ui?.attr || {});
|
||||
|
||||
return (
|
||||
|
@@ -1,107 +1,29 @@
|
||||
import React, { useState } from 'react';
|
||||
import { TreeSelect } from 'antd';
|
||||
import type { TreeSelectProps } from 'antd';
|
||||
import { IFlowNodeParameter } from '@/types/flow';
|
||||
import { Label } from '@mui/icons-material';
|
||||
import { convertKeysToCamelCase } from '@/utils/flow';
|
||||
|
||||
type TextAreaProps = {
|
||||
data: IFlowNodeParameter;
|
||||
defaultValue: any;
|
||||
onChange: (value: any) => void;
|
||||
};
|
||||
const treeData = [
|
||||
{
|
||||
value: 'parent 1',
|
||||
title: 'parent 1',
|
||||
children: [
|
||||
{
|
||||
value: 'parent 1-0',
|
||||
title: 'parent 1-0',
|
||||
children: [
|
||||
{
|
||||
value: 'leaf1',
|
||||
title: 'leaf1',
|
||||
},
|
||||
{
|
||||
value: 'leaf2',
|
||||
title: 'leaf2',
|
||||
},
|
||||
{
|
||||
value: 'leaf3',
|
||||
title: 'leaf3',
|
||||
},
|
||||
{
|
||||
value: 'leaf4',
|
||||
title: 'leaf4',
|
||||
},
|
||||
{
|
||||
value: 'leaf5',
|
||||
title: 'leaf5',
|
||||
},
|
||||
{
|
||||
value: 'leaf6',
|
||||
title: 'leaf6',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'parent 1-1',
|
||||
title: 'parent 1-1',
|
||||
children: [
|
||||
{
|
||||
value: 'leaf11',
|
||||
title: <b style={{ color: '#08c' }}>leaf11</b>,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export const RenderTreeSelect = (params: TextAreaProps) => {
|
||||
const { data, defaultValue, onChange } = params;
|
||||
// console.log(data.options);
|
||||
// const [value, setValue] = useState<string>();
|
||||
|
||||
// const onChange = (newValue: string) => {
|
||||
// setValue(newValue);
|
||||
// };
|
||||
const [dropdownVisible, setDropdownVisible] = useState(false);
|
||||
|
||||
const handleDropdownVisibleChange = (visible: boolean | ((prevState: boolean) => boolean)) => {
|
||||
setDropdownVisible(visible);
|
||||
|
||||
// 你可以在这里执行更多的逻辑,比如发送请求、更新状态等
|
||||
console.log('Dropdown is now:', visible ? 'visible' : 'hidden');
|
||||
};
|
||||
|
||||
const focus = () => {
|
||||
// console.log('focus==========');
|
||||
};
|
||||
const attr = convertKeysToCamelCase(data.ui?.attr || {});
|
||||
|
||||
return (
|
||||
<div className="p-2 text-sm">
|
||||
<TreeSelect
|
||||
className="w-full nodrag"
|
||||
fieldNames={{ label: 'label', value: 'value', children: 'children' }}
|
||||
{...data.ui.attr}
|
||||
{...attr}
|
||||
style={{ width: '100%' }}
|
||||
value={defaultValue}
|
||||
treeDefaultExpandAll
|
||||
onChange={onChange}
|
||||
treeData={data.options}
|
||||
onDropdownVisibleChange={handleDropdownVisibleChange}
|
||||
/>
|
||||
|
||||
// TODO: Implement the TreeSelect component
|
||||
// <TreeSelect
|
||||
// showSearch
|
||||
// style={{ width: '100%' }}
|
||||
// value={value}
|
||||
// dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
// placeholder="Please select"
|
||||
// allowClear
|
||||
// treeDefaultExpandAll
|
||||
// onChange={onChange}
|
||||
// treeData={treeData}
|
||||
// getPopupContainer={() => document.body}
|
||||
// />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
40
web/components/flow/node-renderer/upload.tsx
Normal file
40
web/components/flow/node-renderer/upload.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import type { UploadProps } from 'antd';
|
||||
import { Button, message, Upload } from 'antd';
|
||||
import { convertKeysToCamelCase } from '@/utils/flow';
|
||||
import { IFlowNodeParameter } from '@/types/flow';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const props: UploadProps = {
|
||||
name: 'file',
|
||||
action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload',
|
||||
headers: {
|
||||
authorization: 'authorization-text',
|
||||
},
|
||||
};
|
||||
|
||||
type Props = {
|
||||
data: IFlowNodeParameter;
|
||||
defaultValue: any;
|
||||
onChange: (value: any) => void;
|
||||
};
|
||||
|
||||
export const RenderUpload = (params: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { data, defaultValue, onChange } = params;
|
||||
|
||||
const attr = convertKeysToCamelCase(data.ui?.attr || {});
|
||||
|
||||
return (
|
||||
<div style={{ textAlign: 'center' }} className="p-2 text-sm">
|
||||
<Upload {...attr} {...props}>
|
||||
<Button icon={<UploadOutlined />}>{t('UploadData')}</Button>
|
||||
</Upload>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
@@ -54,10 +54,15 @@ export type IFlowNodeParameter = {
|
||||
|
||||
export type IFlowNodeParameterUI = {
|
||||
ui_type: string;
|
||||
language: string;
|
||||
attr: {
|
||||
disabled: boolean;
|
||||
[key: string]: any;
|
||||
};
|
||||
editor: {
|
||||
width: Number;
|
||||
height: Number;
|
||||
};
|
||||
show_input: boolean;
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { message } from 'antd';
|
||||
import axios from './ctx-axios';
|
||||
import { isPlainObject } from 'lodash';
|
||||
|
||||
const DEFAULT_HEADERS = {
|
||||
'content-type': 'application/json',
|
||||
};
|
||||
|
Reference in New Issue
Block a user