feat: update UI components for better user experience (#1850)

This commit is contained in:
Dreammy23
2024-08-20 11:26:50 +08:00
committed by GitHub
12 changed files with 93 additions and 47 deletions

View File

@@ -34,7 +34,7 @@ import {
SpaceConfig,
} from '@/types/knowledge';
import { UpdatePromptParams, IPrompt, PromptParams } from '@/types/prompt';
import { IFlow, IFlowNode, IFlowResponse, IFlowUpdateParam } from '@/types/flow';
import { IFlow, IFlowNode, IFlowResponse, IFlowUpdateParam, IFlowRefreshParams } from '@/types/flow';
import { IAgent, IApp, IAppData, ITeamModal } from '@/types/app';
/** App */
@@ -262,27 +262,31 @@ export const addPrompt = (data: UpdatePromptParams) => {
/** AWEL Flow */
export const addFlow = (data: IFlowUpdateParam) => {
return POST<IFlowUpdateParam, IFlow>('/api/v1/serve/awel/flows', data);
return POST<IFlowUpdateParam, IFlow>('/api/v2/serve/awel/flows', data);
};
export const getFlows = () => {
return GET<null, IFlowResponse>('/api/v1/serve/awel/flows');
return GET<null, IFlowResponse>('/api/v2/serve/awel/flows');
};
export const getFlowById = (id: string) => {
return GET<null, IFlow>(`/api/v1/serve/awel/flows/${id}`);
return GET<null, IFlow>(`/api/v2/serve/awel/flows/${id}`);
};
export const updateFlowById = (id: string, data: IFlowUpdateParam) => {
return PUT<IFlowUpdateParam, IFlow>(`/api/v1/serve/awel/flows/${id}`, data);
return PUT<IFlowUpdateParam, IFlow>(`/api/v2/serve/awel/flows/${id}`, data);
};
export const deleteFlowById = (id: string) => {
return DELETE<null, null>(`/api/v1/serve/awel/flows/${id}`);
return DELETE<null, null>(`/api/v2/serve/awel/flows/${id}`);
};
export const getFlowNodes = () => {
return GET<null, Array<IFlowNode>>(`/api/v1/serve/awel/nodes`);
return GET<null, Array<IFlowNode>>(`/api/v2/serve/awel/nodes`);
};
export const refreshFlowNodeById = (data: IFlowRefreshParams) => {
return POST<IFlowRefreshParams, IFlowNode>('/api/v2/serve/awel/nodes/refresh', data);
};
/** app */

View File

@@ -1,4 +1,5 @@
import { IFlowNode, IFlowNodeParameter } from '@/types/flow';
import { refreshFlowNodeById, apiInterceptors } from '@/client/api';
import { Checkbox, Input, InputNumber, Select, Tooltip } from 'antd';
import React from 'react';
import RequiredIcon from './required-icon';
@@ -51,6 +52,7 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
function renderNodeWithoutUiParam(data: IFlowNodeParameter) {
let defaultValue = data.value ?? data.default;
console.log('datacc', data);
switch (data.type_name) {
case 'int':
case 'float':
@@ -61,6 +63,8 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
className="w-full"
defaultValue={defaultValue}
onChange={(value: number | null) => {
console.log('value', value);
onChange(value);
}}
/>
@@ -106,6 +110,32 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
}
}
// TODO: refresh flow node
async function refreshFlowNode() {
// setLoading(true);
const params = {
id: '',
type_name: '',
type_cls: '',
flow_type: 'operator' as const,
refresh: [
{
name: '',
depends: [
{
name: '',
value: '',
has_value: true,
},
],
},
],
};
const [_, data] = await apiInterceptors(refreshFlowNodeById(params));
// setLoading(false);
// setFlowList(data?.items ?? []);
}
function renderComponentByType(type: string, props?: any) {
switch (type) {
case 'select':
@@ -146,6 +176,8 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
let defaultValue = data.value ?? data.default;
const props = { data, defaultValue, onChange };
console.log('xxx', props);
return (
<div>
{renderLabelWithTooltip(data)}
@@ -161,4 +193,4 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ node, data, label,
}
};
export default NodeParamHandler;
export default NodeParamHandler;

View File

@@ -22,19 +22,17 @@ export const RenderCodeEditor = (params: Props) => {
setIsModalOpen(true);
};
const handleOk = () => {
const onOk = () => {
setIsModalOpen(false);
};
const handleCancel = () => {
const onCancel = () => {
setIsModalOpen(false);
};
/**
* 设置弹窗宽度
*/
const modalWidth = useMemo(() => {
if (data?.ui?.editor?.width) {
return data?.ui?.editor?.width + 100
return data?.ui?.editor?.width + 100;
}
return '80%';
}, [data?.ui?.editor?.width]);
@@ -44,16 +42,16 @@ export const RenderCodeEditor = (params: Props) => {
<Button type="primary" onClick={showModal}>
{t('openCodeEditor')}
</Button>
<Modal title={t('openCodeEditor')} width={modalWidth} open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<Modal title={t('openCodeEditor')} width={modalWidth} open={isModalOpen} onOk={onOk} onCancel={onCancel}>
<Editor
{...data?.ui?.attr}
{...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'
theme="vs-dark"
options={{
minimap: {
enabled: false,

View File

@@ -11,7 +11,6 @@ type Props = {
export const RenderDatePicker = (params: Props) => {
const { data, defaultValue, onChange } = params;
const attr = convertKeysToCamelCase(data.ui?.attr || {});
const onChangeDate: DatePickerProps['onChange'] = (date, dateString) => {

View File

@@ -4,13 +4,13 @@ import { convertKeysToCamelCase } from '@/utils/flow';
const { Password } = Input;
type TextAreaProps = {
type Props = {
data: IFlowNodeParameter;
defaultValue: any;
onChange: (value: any) => void;
};
export const RenderPassword = (params: TextAreaProps) => {
export const RenderPassword = (params: Props) => {
const { data, defaultValue, onChange } = params;
const attr = convertKeysToCamelCase(data.ui?.attr || {});

View File

@@ -4,13 +4,13 @@ import { Col, InputNumber, Row, Slider, Space } from 'antd';
import type { InputNumberProps } from 'antd';
import React, { useState } from 'react';
type TextAreaProps = {
type Props = {
data: IFlowNodeParameter;
defaultValue: any;
onChange: (value: any) => void;
};
export const RenderSlider = (params: TextAreaProps) => {
export const RenderSlider = (params: Props) => {
const { data, defaultValue, onChange } = params;
const attr = convertKeysToCamelCase(data.ui?.attr || {});
const [inputValue, setInputValue] = useState(defaultValue);
@@ -18,7 +18,6 @@ export const RenderSlider = (params: TextAreaProps) => {
setInputValue(newValue);
onChange(newValue);
};
console.log(data);
return (
<>

View File

@@ -5,13 +5,13 @@ import classNames from 'classnames';
const { TextArea } = Input;
type TextAreaProps = {
type Props = {
data: IFlowNodeParameter;
defaultValue: any;
onChange: (value: any) => void;
};
export const RenderTextArea = (params: TextAreaProps) => {
export const RenderTextArea = (params: Props) => {
const { data, defaultValue, onChange } = params;
const attr = convertKeysToCamelCase(data.ui?.attr || {});

View File

@@ -1,15 +1,16 @@
import React, { useState } from 'react';
import React from 'react';
import type { TimePickerProps } from 'antd';
import { TimePicker } from 'antd';
import { IFlowNodeParameter } from '@/types/flow';
import { convertKeysToCamelCase } from '@/utils/flow';
type TextAreaProps = {
type Props = {
data: IFlowNodeParameter;
defaultValue: any;
onChange: (value: any) => void;
};
export const RenderTimePicker = (params: TextAreaProps) => {
export const RenderTimePicker = (params: Props) => {
const { data, defaultValue, onChange } = params;
const attr = convertKeysToCamelCase(data.ui?.attr || {});

View File

@@ -3,27 +3,24 @@ import { TreeSelect } from 'antd';
import { IFlowNodeParameter } from '@/types/flow';
import { convertKeysToCamelCase } from '@/utils/flow';
type TextAreaProps = {
type Props = {
data: IFlowNodeParameter;
defaultValue: any;
onChange: (value: any) => void;
};
export const RenderTreeSelect = (params: TextAreaProps) => {
export const RenderTreeSelect = (params: Props) => {
const { data, defaultValue, onChange } = params;
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' }}
{...attr}
style={{ width: '100%' }}
value={defaultValue}
treeDefaultExpandAll
onChange={onChange}
treeData={data.options}
/>
</div>
<TreeSelect
{...attr}
className="w-full nodrag"
fieldNames={{ label: 'label', value: 'value', children: 'children' }}
value={defaultValue}
treeDefaultExpandAll
onChange={onChange}
treeData={data.options}
/>
);
};

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { UploadOutlined } from '@ant-design/icons';
import type { UploadProps } from 'antd';
import { Button, message, Upload } from 'antd';
import { Button, Upload } from 'antd';
import { convertKeysToCamelCase } from '@/utils/flow';
import { IFlowNodeParameter } from '@/types/flow';
import { useTranslation } from 'react-i18next';
@@ -28,7 +28,7 @@ export const RenderUpload = (params: Props) => {
const attr = convertKeysToCamelCase(data.ui?.attr || {});
return (
<div style={{ textAlign: 'center' }} className="p-2 text-sm">
<div className="p-2 text-sm text-center">
<Upload {...attr} {...props}>
<Button icon={<UploadOutlined />}>{t('UploadData')}</Button>
</Upload>

View File

@@ -179,6 +179,7 @@ const Canvas: React.FC<Props> = () => {
const { name, label, description = '', editable = false, state = 'deployed' } = form.getFieldsValue();
console.log(form.getFieldsValue());
const reactFlowObject = mapHumpToUnderline(reactFlow.toObject() as IFlowData);
if (id) {
const [, , res] = await apiInterceptors(updateFlowById(id, { name, label, description, editable, uid: id, flow_data: reactFlowObject, state }));
setIsModalVisible(false);

View File

@@ -12,6 +12,21 @@ export type IFlowUpdateParam = {
state?: FlowState;
};
export type IFlowRefreshParams = {
id: string;
type_name: string;
type_cls: string;
flow_type: 'resource' | 'operator';
refresh: {
name: string;
depends?: Array<{
name: string;
value: string;
has_value: boolean;
}>;
}[];
};
export type IFlow = {
dag_id: string;
gmt_created: string;
@@ -60,8 +75,8 @@ export type IFlowNodeParameterUI = {
[key: string]: any;
};
editor: {
width: Number;
height: Number;
width: number;
height: number;
};
show_input: boolean;
};