feat(web): http node config support editor
This commit is contained in:
@@ -30,7 +30,8 @@ export interface LexicalEditorProps {
|
|||||||
lineHeight?: number;
|
lineHeight?: number;
|
||||||
size?: 'default' | 'small';
|
size?: 'default' | 'small';
|
||||||
type?: 'input' | 'textarea',
|
type?: 'input' | 'textarea',
|
||||||
language?: 'string' | 'jinja2'
|
language?: 'string' | 'jinja2';
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
@@ -58,7 +59,9 @@ const Editor: FC<LexicalEditorProps> =({
|
|||||||
variant = 'borderless',
|
variant = 'borderless',
|
||||||
size = 'default',
|
size = 'default',
|
||||||
type = 'textarea',
|
type = 'textarea',
|
||||||
language = 'string'
|
language = 'string',
|
||||||
|
height,
|
||||||
|
className
|
||||||
}) => {
|
}) => {
|
||||||
const [_count, setCount] = useState(0);
|
const [_count, setCount] = useState(0);
|
||||||
const [enableJinja2, setEnableJinja2] = useState(false)
|
const [enableJinja2, setEnableJinja2] = useState(false)
|
||||||
@@ -156,23 +159,23 @@ const Editor: FC<LexicalEditorProps> =({
|
|||||||
};
|
};
|
||||||
const minheight = useMemo(() => {
|
const minheight = useMemo(() => {
|
||||||
if (type === 'input') {
|
if (type === 'input') {
|
||||||
return `${size === 'small' ? 26 : 30}px`
|
return `${height ? height : size === 'small' ? 28 : 30}px`
|
||||||
}
|
}
|
||||||
return `${size === 'small' ? 60 : 120}px`
|
return `${height ? height : size === 'small' ? 60 : 120}px`
|
||||||
}, [type, size])
|
}, [type, size, height])
|
||||||
const fontSize = useMemo(() => {
|
const fontSize = useMemo(() => {
|
||||||
return `${size === 'small' ? 12 : 14}px`
|
return `${size === 'small' ? 12 : 14}px`
|
||||||
}, [size])
|
}, [size])
|
||||||
const lineHeight = useMemo(() => {
|
const lineHeight = useMemo(() => {
|
||||||
return `${size === 'small' ? 16 : 20}px`
|
return `${height ? height : size === 'small' ? 16 : 20}px`
|
||||||
}, [size])
|
}, [size])
|
||||||
const placeHolderMinheight = useMemo(() => {
|
const placeHolderMinheight = useMemo(() => {
|
||||||
return `${size === 'small' ? 16 : 30}px`
|
return `${height ? height : size === 'small' ? 16 : 30}px`
|
||||||
}, [type, size])
|
}, [type, size, height])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LexicalComposer initialConfig={initialConfig}>
|
<LexicalComposer initialConfig={initialConfig}>
|
||||||
<div style={{ position: 'relative' }}>
|
<div style={{ position: 'relative' }} className={className}>
|
||||||
<RichTextPlugin
|
<RichTextPlugin
|
||||||
contentEditable={
|
contentEditable={
|
||||||
enableLineNumbers ? (
|
enableLineNumbers ? (
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { type FC, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Button, Select, Table, Form, type TableProps } from 'antd';
|
import { Button, Select, Table, Form, type TableProps } from 'antd';
|
||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin';
|
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin';
|
||||||
import Empty from '@/components/Empty';
|
import Empty from '@/components/Empty';
|
||||||
import VariableSelect from '../VariableSelect';
|
import Editor from '../../Editor'
|
||||||
|
|
||||||
export interface TableRow {
|
export interface TableRow {
|
||||||
key?: string;
|
key?: string;
|
||||||
@@ -21,7 +23,7 @@ interface EditableTableProps {
|
|||||||
size?: "small"
|
size?: "small"
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditableTable: React.FC<EditableTableProps> = ({
|
const EditableTable: FC<EditableTableProps> = ({
|
||||||
parentName,
|
parentName,
|
||||||
title,
|
title,
|
||||||
options = [],
|
options = [],
|
||||||
@@ -37,6 +39,13 @@ const EditableTable: React.FC<EditableTableProps> = ({
|
|||||||
...(typeOptions.length > 0 && { type: typeOptions[0].value })
|
...(typeOptions.length > 0 && { type: typeOptions[0].value })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Filter options based on boolean type if needed
|
||||||
|
const booleanFilterOptions = useMemo(() => {
|
||||||
|
return filterBooleanType
|
||||||
|
? options.filter(option => option.dataType !== 'boolean')
|
||||||
|
: options
|
||||||
|
}, [options, filterBooleanType])
|
||||||
|
|
||||||
const getColumns = (remove: (index: number) => void): TableProps<TableRow>['columns'] => {
|
const getColumns = (remove: (index: number) => void): TableProps<TableRow>['columns'] => {
|
||||||
const hasType = typeOptions.length > 0;
|
const hasType = typeOptions.length > 0;
|
||||||
const cellClassName="rb:p-1!"
|
const cellClassName="rb:p-1!"
|
||||||
@@ -49,14 +58,12 @@ const EditableTable: React.FC<EditableTableProps> = ({
|
|||||||
className: cellClassName,
|
className: cellClassName,
|
||||||
render: (_: any, __: TableRow, index: number) => (
|
render: (_: any, __: TableRow, index: number) => (
|
||||||
<Form.Item name={[index, 'name']} noStyle>
|
<Form.Item name={[index, 'name']} noStyle>
|
||||||
<VariableSelect
|
<Editor
|
||||||
placeholder={t('common.pleaseSelect')}
|
options={booleanFilterOptions}
|
||||||
// size="small"
|
type="input"
|
||||||
options={options}
|
|
||||||
filterBooleanType={filterBooleanType}
|
|
||||||
popupMatchSelectWidth={false}
|
|
||||||
className={contentClassName}
|
className={contentClassName}
|
||||||
size={size}
|
size={size}
|
||||||
|
height={16}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)
|
)
|
||||||
@@ -101,19 +108,17 @@ const EditableTable: React.FC<EditableTableProps> = ({
|
|||||||
{(form) => {
|
{(form) => {
|
||||||
const currentType = form.getFieldValue([...Array.isArray(parentName) ? parentName : [parentName], index, 'type']);
|
const currentType = form.getFieldValue([...Array.isArray(parentName) ? parentName : [parentName], index, 'type']);
|
||||||
const filteredOptions = currentType === 'file'
|
const filteredOptions = currentType === 'file'
|
||||||
? options.filter(option => option.dataType === 'file')
|
? booleanFilterOptions.filter(option => option.dataType.includes('file'))
|
||||||
: options;
|
: booleanFilterOptions;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form.Item name={[index, 'value']} noStyle>
|
<Form.Item name={[index, 'value']} noStyle>
|
||||||
<VariableSelect
|
<Editor
|
||||||
placeholder={t('common.pleaseSelect')}
|
|
||||||
// size="small"
|
|
||||||
options={filteredOptions}
|
options={filteredOptions}
|
||||||
filterBooleanType={filterBooleanType}
|
type="input"
|
||||||
popupMatchSelectWidth={false}
|
|
||||||
className={contentClassName}
|
className={contentClassName}
|
||||||
size={size}
|
size={size}
|
||||||
|
height={16}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-09 18:35:43
|
* @Date: 2026-02-09 18:35:43
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-09 18:35:43
|
* @Last Modified time: 2026-03-02 17:24:51
|
||||||
*/
|
*/
|
||||||
import { type FC, useRef, useState } from "react";
|
import { type FC, useRef, useState } from "react";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@@ -13,7 +13,6 @@ import Editor from '../../Editor'
|
|||||||
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin'
|
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin'
|
||||||
import AuthConfigModal from './AuthConfigModal'
|
import AuthConfigModal from './AuthConfigModal'
|
||||||
import type { AuthConfigModalRef, HttpRequestConfigForm } from './types'
|
import type { AuthConfigModalRef, HttpRequestConfigForm } from './types'
|
||||||
import VariableSelect from "../VariableSelect";
|
|
||||||
import MessageEditor from '../MessageEditor'
|
import MessageEditor from '../MessageEditor'
|
||||||
import EditableTable from './EditableTable'
|
import EditableTable from './EditableTable'
|
||||||
import { portTextAttrs } from '../../../constant'
|
import { portTextAttrs } from '../../../constant'
|
||||||
@@ -159,7 +158,7 @@ const HttpRequest: FC<{ options: Suggestion[]; selectedNode?: any; graphRef?: an
|
|||||||
<EditableTable
|
<EditableTable
|
||||||
size="small"
|
size="small"
|
||||||
parentName={['body', 'data']}
|
parentName={['body', 'data']}
|
||||||
options={options.filter(vo => vo.dataType === 'string' || vo.dataType === 'number')}
|
options={options.filter(vo => vo.dataType === 'string' || vo.dataType === 'number' || vo.dataType.includes('file'))}
|
||||||
typeOptions={[
|
typeOptions={[
|
||||||
{ label: 'text', value: 'text' },
|
{ label: 'text', value: 'text' },
|
||||||
{ label: 'file', value: 'file' }
|
{ label: 'file', value: 'file' }
|
||||||
@@ -201,10 +200,10 @@ const HttpRequest: FC<{ options: Suggestion[]; selectedNode?: any; graphRef?: an
|
|||||||
}
|
}
|
||||||
{values?.body?.content_type === 'binary' &&
|
{values?.body?.content_type === 'binary' &&
|
||||||
<Form.Item name={['body', 'data']} noStyle>
|
<Form.Item name={['body', 'data']} noStyle>
|
||||||
<VariableSelect
|
<Editor
|
||||||
placeholder={t('common.pleaseSelect')}
|
placeholder={t('common.pleaseSelect')}
|
||||||
options={options.filter(vo => vo.dataType.includes('file'))}
|
options={options.filter(vo => vo.dataType.includes('file'))}
|
||||||
filterBooleanType={true}
|
type="input"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
Reference in New Issue
Block a user