mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-29 01:40:51 +00:00
feat: plugin input type add select and custom var (#2571)
* feat: plugin input type add select and custom var * fix * fix ui * fix * fix
This commit is contained in:
@@ -108,15 +108,9 @@ const RenderInput = () => {
|
||||
<RenderPluginInput
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
label={input.label}
|
||||
description={input.description}
|
||||
isDisabled={isDisabledInput}
|
||||
valueType={input.valueType}
|
||||
placeholder={input.placeholder}
|
||||
required={input.required}
|
||||
min={input.min}
|
||||
max={input.max}
|
||||
isInvalid={errors && Object.keys(errors).includes(input.key)}
|
||||
input={input}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@@ -6,10 +6,14 @@ import {
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
Select,
|
||||
Switch,
|
||||
Textarea
|
||||
} from '@chakra-ui/react';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import dynamic from 'next/dynamic';
|
||||
@@ -18,58 +22,53 @@ const JsonEditor = dynamic(() => import('@fastgpt/web/components/common/Textarea
|
||||
|
||||
const RenderPluginInput = ({
|
||||
value,
|
||||
defaultValue,
|
||||
onChange,
|
||||
label,
|
||||
description,
|
||||
isDisabled,
|
||||
valueType,
|
||||
placeholder,
|
||||
required,
|
||||
min,
|
||||
max,
|
||||
isInvalid
|
||||
isInvalid,
|
||||
input
|
||||
}: {
|
||||
value: any;
|
||||
defaultValue?: any;
|
||||
onChange: () => void;
|
||||
label: string;
|
||||
description?: string;
|
||||
isDisabled?: boolean;
|
||||
valueType: WorkflowIOValueTypeEnum | undefined;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
min?: number;
|
||||
max?: number;
|
||||
isInvalid: boolean;
|
||||
input: FlowNodeInputItemType;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const inputType = input.renderTypeList[0];
|
||||
|
||||
const render = (() => {
|
||||
if (valueType === WorkflowIOValueTypeEnum.string) {
|
||||
if (inputType === FlowNodeInputTypeEnum.customVariable) {
|
||||
return null;
|
||||
}
|
||||
if (inputType === FlowNodeInputTypeEnum.select && input.list) {
|
||||
return (
|
||||
<MySelect list={input.list} value={value} onchange={onChange} isDisabled={isDisabled} />
|
||||
);
|
||||
}
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.string) {
|
||||
return (
|
||||
<Textarea
|
||||
value={value}
|
||||
defaultValue={defaultValue}
|
||||
defaultValue={input.defaultValue}
|
||||
onChange={onChange}
|
||||
isDisabled={isDisabled}
|
||||
placeholder={t(placeholder as any)}
|
||||
placeholder={t(input.placeholder as any)}
|
||||
bg={'myGray.50'}
|
||||
isInvalid={isInvalid}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (valueType === WorkflowIOValueTypeEnum.number) {
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.number) {
|
||||
return (
|
||||
<NumberInput
|
||||
step={1}
|
||||
min={min}
|
||||
max={max}
|
||||
min={input.min}
|
||||
max={input.max}
|
||||
bg={'myGray.50'}
|
||||
isDisabled={isDisabled}
|
||||
isInvalid={isInvalid}
|
||||
>
|
||||
<NumberInputField value={value} onChange={onChange} defaultValue={defaultValue} />
|
||||
<NumberInputField value={value} onChange={onChange} defaultValue={input.defaultValue} />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
@@ -77,14 +76,14 @@ const RenderPluginInput = ({
|
||||
</NumberInput>
|
||||
);
|
||||
}
|
||||
if (valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||
return (
|
||||
<Switch
|
||||
isChecked={value}
|
||||
onChange={onChange}
|
||||
isDisabled={isDisabled}
|
||||
isInvalid={isInvalid}
|
||||
defaultChecked={defaultValue}
|
||||
defaultChecked={!!input.defaultValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -92,12 +91,12 @@ const RenderPluginInput = ({
|
||||
return (
|
||||
<JsonEditor
|
||||
bg={'myGray.50'}
|
||||
placeholder={t(placeholder || ('' as any))}
|
||||
placeholder={t(input.placeholder as any)}
|
||||
resize
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
isInvalid={isInvalid}
|
||||
defaultValue={defaultValue}
|
||||
defaultValue={input.defaultValue}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
@@ -106,14 +105,14 @@ const RenderPluginInput = ({
|
||||
<Box _notLast={{ mb: 4 }} px={1}>
|
||||
<Flex alignItems={'center'} mb={1}>
|
||||
<Box position={'relative'}>
|
||||
{required && (
|
||||
{input.required && (
|
||||
<Box position={'absolute'} left={-2} top={'-1px'} color={'red.600'}>
|
||||
*
|
||||
</Box>
|
||||
)}
|
||||
{label}
|
||||
{input.label}
|
||||
</Box>
|
||||
{description && <QuestionTip ml={2} label={description} />}
|
||||
{input.description && <QuestionTip ml={2} label={input.description} />}
|
||||
</Flex>
|
||||
{render}
|
||||
</Box>
|
||||
|
@@ -378,15 +378,9 @@ const RenderList = React.memo(function RenderList({
|
||||
return (
|
||||
<RenderPluginInput
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
label={input.label}
|
||||
description={input.description}
|
||||
valueType={input.valueType}
|
||||
placeholder={input.placeholder}
|
||||
required={input.required}
|
||||
min={input.min}
|
||||
max={input.max}
|
||||
isInvalid={errors && Object.keys(errors).includes(input.key)}
|
||||
onChange={onChange}
|
||||
input={input}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@@ -38,7 +38,7 @@ const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
return (
|
||||
<Box>
|
||||
<Flex mb={1} alignItems={'flex-end'}>
|
||||
<Box flex={'1'}>Javascript{workflowT('Code')}</Box>
|
||||
<Box flex={'1'}>{'Javascript ' + workflowT('Code')}</Box>
|
||||
<Box
|
||||
cursor={'pointer'}
|
||||
color={'primary.500'}
|
||||
|
@@ -2,16 +2,15 @@ import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
Flex,
|
||||
Switch,
|
||||
Input,
|
||||
Textarea,
|
||||
Stack,
|
||||
HStack
|
||||
HStack,
|
||||
FormControl
|
||||
} from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useFieldArray, useForm } from 'react-hook-form';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { FlowValueTypeMap } from '@fastgpt/global/core/workflow/node/constant';
|
||||
@@ -19,9 +18,9 @@ import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/consta
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useI18n } from '@/web/context/I18n';
|
||||
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
@@ -39,7 +38,9 @@ export const defaultInput: FlowNodeInputItemType = {
|
||||
valueType: WorkflowIOValueTypeEnum.string,
|
||||
canEdit: true,
|
||||
key: '',
|
||||
label: ''
|
||||
label: '',
|
||||
description: '',
|
||||
defaultValue: ''
|
||||
};
|
||||
|
||||
const FieldEditModal = ({
|
||||
@@ -56,72 +57,118 @@ const FieldEditModal = ({
|
||||
onSubmit: (e: { data: FlowNodeInputItemType; isChangeKey: boolean }) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { workflowT } = useI18n();
|
||||
const { toast } = useToast();
|
||||
|
||||
const inputTypeList = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: t('common:core.workflow.inputType.Reference'),
|
||||
value: FlowNodeInputTypeEnum.reference,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.input'),
|
||||
value: FlowNodeInputTypeEnum.input,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.textarea'),
|
||||
value: FlowNodeInputTypeEnum.textarea,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.JSON Editor'),
|
||||
value: FlowNodeInputTypeEnum.JSONEditor,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.number input'),
|
||||
value: FlowNodeInputTypeEnum.numberInput,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.number
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.switch'),
|
||||
value: FlowNodeInputTypeEnum.switch,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.boolean
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.selectApp'),
|
||||
value: FlowNodeInputTypeEnum.selectApp,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.selectApp
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.selectLLMModel'),
|
||||
value: FlowNodeInputTypeEnum.selectLLMModel,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: t('common:core.workflow.inputType.selectDataset'),
|
||||
value: FlowNodeInputTypeEnum.selectDataset,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.selectDataset
|
||||
},
|
||||
...(hasDynamicInput
|
||||
? []
|
||||
: [
|
||||
{
|
||||
label: t('common:core.workflow.inputType.dynamicTargetInput'),
|
||||
value: FlowNodeInputTypeEnum.addInputParam,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.dynamic
|
||||
}
|
||||
])
|
||||
],
|
||||
() =>
|
||||
[
|
||||
[
|
||||
{
|
||||
icon: 'core/workflow/inputType/reference',
|
||||
label: t('common:core.workflow.inputType.Reference'),
|
||||
value: FlowNodeInputTypeEnum.reference,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/input',
|
||||
label: t('common:core.workflow.inputType.input'),
|
||||
value: FlowNodeInputTypeEnum.input,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/textarea',
|
||||
label: t('common:core.workflow.inputType.textarea'),
|
||||
value: FlowNodeInputTypeEnum.textarea,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/jsonEditor',
|
||||
label: t('common:core.workflow.inputType.JSON Editor'),
|
||||
value: FlowNodeInputTypeEnum.JSONEditor,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/numberInput',
|
||||
label: t('common:core.workflow.inputType.number input'),
|
||||
value: FlowNodeInputTypeEnum.numberInput,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.number
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/option',
|
||||
label: t('common:core.workflow.inputType.select'),
|
||||
value: FlowNodeInputTypeEnum.select,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/switch',
|
||||
label: t('common:core.workflow.inputType.switch'),
|
||||
value: FlowNodeInputTypeEnum.switch,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.boolean
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
icon: 'core/workflow/inputType/selectApp',
|
||||
label: t('common:core.workflow.inputType.selectApp'),
|
||||
value: FlowNodeInputTypeEnum.selectApp,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.selectApp
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/selectLLM',
|
||||
label: t('common:core.workflow.inputType.selectLLMModel'),
|
||||
value: FlowNodeInputTypeEnum.selectLLMModel,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
icon: 'core/workflow/inputType/selectDataset',
|
||||
label: t('common:core.workflow.inputType.selectDataset'),
|
||||
value: FlowNodeInputTypeEnum.selectDataset,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.selectDataset
|
||||
},
|
||||
...(hasDynamicInput
|
||||
? []
|
||||
: [
|
||||
{
|
||||
icon: 'core/workflow/inputType/dynamic',
|
||||
label: t('common:core.workflow.inputType.dynamicTargetInput'),
|
||||
value: FlowNodeInputTypeEnum.addInputParam,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.dynamic
|
||||
}
|
||||
])
|
||||
],
|
||||
[
|
||||
{
|
||||
icon: 'core/workflow/inputType/customVariable',
|
||||
label: t('common:core.workflow.inputType.custom'),
|
||||
value: FlowNodeInputTypeEnum.customVariable,
|
||||
defaultValueType: WorkflowIOValueTypeEnum.string,
|
||||
description: t('app:variable.select type_desc')
|
||||
}
|
||||
]
|
||||
] as {
|
||||
icon: string;
|
||||
label: string;
|
||||
value: FlowNodeInputTypeEnum;
|
||||
defaultValueType: WorkflowIOValueTypeEnum;
|
||||
description?: string;
|
||||
}[][],
|
||||
[hasDynamicInput, t]
|
||||
);
|
||||
|
||||
const isEdit = !!defaultValue.key;
|
||||
const { register, getValues, setValue, handleSubmit, watch } = useForm({
|
||||
defaultValues: defaultValue
|
||||
const { register, getValues, setValue, handleSubmit, watch, control, reset } = useForm({
|
||||
defaultValues: {
|
||||
...defaultValue,
|
||||
list: defaultValue.list?.length ? defaultValue.list : [{ label: '', value: '' }]
|
||||
}
|
||||
});
|
||||
const {
|
||||
fields: selectEnums,
|
||||
append: appendEnums,
|
||||
remove: removeEnums
|
||||
} = useFieldArray({
|
||||
control,
|
||||
name: 'list'
|
||||
});
|
||||
|
||||
const inputType = watch('renderTypeList.0') || FlowNodeInputTypeEnum.reference;
|
||||
@@ -134,11 +181,13 @@ const FieldEditModal = ({
|
||||
const min = watch('min');
|
||||
const selectValueTypeList = watch('customInputConfig.selectValueTypeList');
|
||||
|
||||
const showValueTypeSelect = inputType === FlowNodeInputTypeEnum.reference;
|
||||
const showValueTypeSelect =
|
||||
inputType === FlowNodeInputTypeEnum.reference ||
|
||||
inputType === FlowNodeInputTypeEnum.customVariable;
|
||||
|
||||
// input type config
|
||||
const showRequired = useMemo(() => {
|
||||
const list = [FlowNodeInputTypeEnum.addInputParam];
|
||||
const list = [FlowNodeInputTypeEnum.addInputParam, FlowNodeInputTypeEnum.customVariable];
|
||||
return !list.includes(inputType);
|
||||
}, [inputType]);
|
||||
const showDefaultValue = useMemo(() => {
|
||||
@@ -167,11 +216,11 @@ const FieldEditModal = ({
|
||||
value: item.value
|
||||
}));
|
||||
const defaultValueType =
|
||||
inputTypeList.find((item) => item.value === inputType)?.defaultValueType ||
|
||||
inputTypeList.flat().find((item) => item.value === inputType)?.defaultValueType ||
|
||||
WorkflowIOValueTypeEnum.string;
|
||||
|
||||
const onSubmitSuccess = useCallback(
|
||||
(data: FlowNodeInputItemType) => {
|
||||
(data: FlowNodeInputItemType, action: 'confirm' | 'continue') => {
|
||||
data.key = data?.key?.trim();
|
||||
|
||||
if (!data.key) {
|
||||
@@ -181,17 +230,27 @@ const FieldEditModal = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (data.renderTypeList[0] !== FlowNodeInputTypeEnum.reference) {
|
||||
if (
|
||||
data.renderTypeList[0] !== FlowNodeInputTypeEnum.reference &&
|
||||
data.renderTypeList[0] !== FlowNodeInputTypeEnum.customVariable
|
||||
) {
|
||||
data.valueType = defaultValueType;
|
||||
}
|
||||
|
||||
if (
|
||||
data.renderTypeList[0] === FlowNodeInputTypeEnum.addInputParam ||
|
||||
data.renderTypeList[0] === FlowNodeInputTypeEnum.customVariable
|
||||
) {
|
||||
data.required = false;
|
||||
}
|
||||
|
||||
const isChangeKey = defaultValue.key !== data.key;
|
||||
// create check key
|
||||
if (keys.includes(data.key)) {
|
||||
if (!isEdit || isChangeKey) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: workflowT('field_name_already_exists')
|
||||
title: t('workflow:field_name_already_exists')
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -205,11 +264,23 @@ const FieldEditModal = ({
|
||||
|
||||
data.label = data.key;
|
||||
|
||||
onSubmit({
|
||||
data,
|
||||
isChangeKey
|
||||
});
|
||||
onClose();
|
||||
if (action === 'confirm') {
|
||||
onSubmit({
|
||||
data,
|
||||
isChangeKey
|
||||
});
|
||||
onClose();
|
||||
} else if (action === 'continue') {
|
||||
onSubmit({
|
||||
data,
|
||||
isChangeKey
|
||||
});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('common:common.Add Success')
|
||||
});
|
||||
reset(defaultInput);
|
||||
}
|
||||
},
|
||||
[
|
||||
defaultValue.key,
|
||||
@@ -217,11 +288,11 @@ const FieldEditModal = ({
|
||||
isEdit,
|
||||
isToolInput,
|
||||
keys,
|
||||
onClose,
|
||||
onSubmit,
|
||||
t,
|
||||
toast,
|
||||
workflowT
|
||||
onClose,
|
||||
reset
|
||||
]
|
||||
);
|
||||
const onSubmitError = useCallback(
|
||||
@@ -242,206 +313,342 @@ const FieldEditModal = ({
|
||||
return (
|
||||
<MyModal
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
iconSrc="/imgs/workflow/extract.png"
|
||||
title={isEdit ? workflowT('edit_input') : workflowT('add_new_input')}
|
||||
maxW={['90vw', '800px']}
|
||||
title={isEdit ? t('workflow:edit_input') : t('workflow:add_new_input')}
|
||||
maxW={['90vw', '1028px']}
|
||||
w={'100%'}
|
||||
>
|
||||
<ModalBody display={'flex'} gap={8} flexDirection={['column', 'row']}>
|
||||
<Stack flex={1} gap={5}>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Input Type')}</FormLabel>
|
||||
<Box flex={1}>
|
||||
<MySelect<FlowNodeInputTypeEnum>
|
||||
list={inputTypeList}
|
||||
value={inputType}
|
||||
onchange={(e) => {
|
||||
setValue('renderTypeList.0', e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Field Name')}</FormLabel>
|
||||
<Input
|
||||
bg={'myGray.50'}
|
||||
placeholder="appointment/sql"
|
||||
{...register('key', {
|
||||
required: true
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
<Box alignItems={'flex-start'}>
|
||||
<FormLabel flex={'0 0 70px'} mb={'1px'}>
|
||||
{workflowT('field_description')}
|
||||
<Flex h={'560px'}>
|
||||
<Stack gap={4} p={8}>
|
||||
<Box alignItems={'center'}>
|
||||
<FormLabel color={'myGray.600'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Input Type')}
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
bg={'myGray.50'}
|
||||
placeholder={workflowT('field_description_placeholder')}
|
||||
rows={4}
|
||||
{...register('description', { required: isToolInput ? true : false })}
|
||||
/>
|
||||
<Flex flexDirection={'column'} gap={4}>
|
||||
{inputTypeList.map((list, index) => {
|
||||
return (
|
||||
<Box
|
||||
key={index}
|
||||
display={'grid'}
|
||||
gridTemplateColumns={'repeat(3, 1fr)'}
|
||||
gap={4}
|
||||
mt={5}
|
||||
>
|
||||
{list.map((item) => {
|
||||
const isSelected = inputType === item.value;
|
||||
return (
|
||||
<Box
|
||||
display={'flex'}
|
||||
key={item.label}
|
||||
border={isSelected ? '1px solid #3370FF' : '1px solid #DFE2EA'}
|
||||
p={3}
|
||||
rounded={'6px'}
|
||||
fontWeight={'medium'}
|
||||
fontSize={'14px'}
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
boxShadow={
|
||||
isSelected ? '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)' : 'none'
|
||||
}
|
||||
_hover={{
|
||||
'& > svg': {
|
||||
color: 'primary.600'
|
||||
},
|
||||
'& > span': {
|
||||
color: 'myGray.900'
|
||||
},
|
||||
border: '1px solid #3370FF',
|
||||
boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)'
|
||||
}}
|
||||
onClick={() => {
|
||||
setValue('renderTypeList.0', item.value);
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
name={item.icon as any}
|
||||
w={'20px'}
|
||||
mr={1.5}
|
||||
color={isSelected ? 'primary.600' : 'myGray.400'}
|
||||
/>
|
||||
<Box as="span" color={isSelected ? 'myGray.900' : 'inherit'}>
|
||||
{item.label}
|
||||
</Box>
|
||||
{item.description && <QuestionTip label={item.description} ml={1} />}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
</Stack>
|
||||
{/* input type config */}
|
||||
<Stack flex={1} gap={5}>
|
||||
{/* value type */}
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Data Type')}</FormLabel>
|
||||
{showValueTypeSelect ? (
|
||||
<Box flex={1}>
|
||||
<MySelect<WorkflowIOValueTypeEnum>
|
||||
list={valueTypeSelectList}
|
||||
value={valueType}
|
||||
onchange={(e) => {
|
||||
setValue('valueType', e);
|
||||
<Stack flex={1} borderLeft={'1px solid #F0F1F6'} justifyContent={'space-between'}>
|
||||
<Flex flexDirection={'column'} p={8} gap={4} flex={'1 0 0'} overflow={'auto'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Field Name')}
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={'myGray.50'}
|
||||
placeholder="appointment/sql"
|
||||
{...register('key', {
|
||||
required: true
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'flex-start'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('workflow:field_description')}
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
bg={'myGray.50'}
|
||||
placeholder={t('workflow:field_description_placeholder')}
|
||||
rows={4}
|
||||
{...register('description', { required: isToolInput ? true : false })}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
{/* value type */}
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Data Type')}
|
||||
</FormLabel>
|
||||
{showValueTypeSelect ? (
|
||||
<Box flex={1}>
|
||||
<MySelect<WorkflowIOValueTypeEnum>
|
||||
list={valueTypeSelectList}
|
||||
value={valueType}
|
||||
onchange={(e) => {
|
||||
setValue('valueType', e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Box fontSize={'14px'}>{defaultValueType}</Box>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{showRequired && (
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel flex={'1'} fontWeight={'medium'}>
|
||||
{t('workflow:field_required')}
|
||||
</FormLabel>
|
||||
<Switch {...register('required')} />
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{/* reference */}
|
||||
{inputType === FlowNodeInputTypeEnum.reference && (
|
||||
<>
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel flex={'1'} fontWeight={'medium'}>
|
||||
{t('workflow:field_used_as_tool_input')}
|
||||
</FormLabel>
|
||||
<Switch
|
||||
isChecked={isToolInput}
|
||||
onChange={(e) => {
|
||||
setIsToolInput();
|
||||
console.log(isToolInput);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
{showMaxLenInput && (
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Max Length')}
|
||||
</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
placeholder={t('common:core.module.Max Length placeholder')}
|
||||
value={maxLength}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('maxLength', e || '');
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
defaultValueType
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{showMinMaxInput && (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Max Value')}
|
||||
</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
value={watch('max')}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('max', e || '');
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Min Value')}
|
||||
</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
value={watch('min')}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('min', e || '');
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
{showDefaultValue && (
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel
|
||||
flex={inputType === FlowNodeInputTypeEnum.switch ? 1 : '0 0 100px'}
|
||||
fontWeight={'medium'}
|
||||
>
|
||||
{t('common:core.module.Default Value')}
|
||||
</FormLabel>
|
||||
{inputType === FlowNodeInputTypeEnum.numberInput && (
|
||||
<Input
|
||||
bg={'myGray.50'}
|
||||
max={max}
|
||||
min={min}
|
||||
type={'number'}
|
||||
{...register('defaultValue')}
|
||||
/>
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.input && (
|
||||
<Input bg={'myGray.50'} maxLength={maxLength} {...register('defaultValue')} />
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.textarea && (
|
||||
<Textarea bg={'myGray.50'} maxLength={maxLength} {...register('defaultValue')} />
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.JSONEditor && (
|
||||
<JsonEditor
|
||||
bg={'myGray.50'}
|
||||
resize
|
||||
w={'full'}
|
||||
onChange={(e) => {
|
||||
setValue('defaultValue', e);
|
||||
}}
|
||||
defaultValue={String(getValues('defaultValue'))}
|
||||
/>
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.switch && (
|
||||
<Switch {...register('defaultValue')} />
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{inputType === FlowNodeInputTypeEnum.addInputParam && (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{t('common:core.module.Input Type')}
|
||||
</FormLabel>
|
||||
<Box fontSize={'14px'}>{t('workflow:only_the_reference_type_is_supported')}</Box>
|
||||
</Flex>
|
||||
<Box>
|
||||
<HStack mb={1}>
|
||||
<FormLabel fontWeight={'medium'}>{t('workflow:optional_value_type')}</FormLabel>
|
||||
<QuestionTip label={t('workflow:optional_value_type_tip')} />
|
||||
</HStack>
|
||||
<MultipleSelect<WorkflowIOValueTypeEnum>
|
||||
list={valueTypeSelectList}
|
||||
bg={'myGray.50'}
|
||||
value={selectValueTypeList || []}
|
||||
onSelect={(e) => {
|
||||
setValue('customInputConfig.selectValueTypeList', e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
|
||||
{inputType === FlowNodeInputTypeEnum.select && (
|
||||
<>
|
||||
<Flex flexDirection={'column'} gap={4}>
|
||||
{selectEnums.map((item, i) => (
|
||||
<Flex key={item.id} alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 100px'} fontWeight={'medium'}>
|
||||
{`${t('common:core.module.variable.variable options')} ${i + 1}`}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
fontSize={'12px'}
|
||||
bg={'myGray.50'}
|
||||
placeholder={`${t('common:core.module.variable.variable options')} ${i + 1}`}
|
||||
{...register(`list.${i}.label`, {
|
||||
required: true,
|
||||
onChange: (e) => {
|
||||
setValue(`list.${i}.value`, e.target.value);
|
||||
}
|
||||
})}
|
||||
/>
|
||||
</FormControl>
|
||||
{selectEnums.length > 1 && (
|
||||
<MyIcon
|
||||
ml={3}
|
||||
name={'delete'}
|
||||
w={'16px'}
|
||||
cursor={'pointer'}
|
||||
p={2}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'red.100' }}
|
||||
onClick={() => removeEnums(i)}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
<Button
|
||||
variant={'whiteBase'}
|
||||
leftIcon={<MyIcon name={'common/addLight'} w={'16px'} />}
|
||||
onClick={() => appendEnums({ label: '', value: '' })}
|
||||
fontWeight={'medium'}
|
||||
fontSize={'12px'}
|
||||
w={'24'}
|
||||
py={2}
|
||||
>
|
||||
{t('common:core.module.variable add option')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{showRequired && (
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel flex={'1'}>{workflowT('field_required')}</FormLabel>
|
||||
<Switch {...register('required')} />
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{/* reference */}
|
||||
{inputType === FlowNodeInputTypeEnum.reference && (
|
||||
<>
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel flex={'1'}>{workflowT('field_used_as_tool_input')}</FormLabel>
|
||||
<Switch
|
||||
isChecked={isToolInput}
|
||||
onChange={(e) => {
|
||||
setIsToolInput();
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
{showMaxLenInput && (
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Max Length')}</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
placeholder={t('common:core.module.Max Length placeholder')}
|
||||
value={maxLength}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('maxLength', e || '');
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{showMinMaxInput && (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Max Value')}</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
value={watch('max')}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('max', e || '');
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Min Value')}</FormLabel>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
bg={'myGray.50'}
|
||||
value={watch('min')}
|
||||
onChange={(e) => {
|
||||
// @ts-ignore
|
||||
setValue('min', e || '');
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
{showDefaultValue && (
|
||||
<Flex alignItems={'center'} minH={'40px'}>
|
||||
<FormLabel flex={inputType === FlowNodeInputTypeEnum.switch ? 1 : '0 0 70px'}>
|
||||
{t('common:core.module.Default Value')}
|
||||
</FormLabel>
|
||||
{inputType === FlowNodeInputTypeEnum.numberInput && (
|
||||
<Input
|
||||
bg={'myGray.50'}
|
||||
max={max}
|
||||
min={min}
|
||||
type={'number'}
|
||||
{...register('defaultValue')}
|
||||
/>
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.input && (
|
||||
<Input bg={'myGray.50'} maxLength={maxLength} {...register('defaultValue')} />
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.textarea && (
|
||||
<Textarea bg={'myGray.50'} maxLength={maxLength} {...register('defaultValue')} />
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.JSONEditor && (
|
||||
<JsonEditor
|
||||
bg={'myGray.50'}
|
||||
resize
|
||||
w={'full'}
|
||||
onChange={(e) => {
|
||||
setValue('defaultValue', e);
|
||||
}}
|
||||
defaultValue={String(getValues('defaultValue'))}
|
||||
/>
|
||||
)}
|
||||
{inputType === FlowNodeInputTypeEnum.switch && (
|
||||
<Switch {...register('defaultValue')} />
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{inputType === FlowNodeInputTypeEnum.addInputParam && (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Input Type')}</FormLabel>
|
||||
<Box flex={1} fontWeight={'bold'}>
|
||||
{workflowT('only_the_reference_type_is_supported')}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box>
|
||||
<HStack mb={1}>
|
||||
<FormLabel>{workflowT('optional_value_type')}</FormLabel>
|
||||
<QuestionTip label={workflowT('optional_value_type_tip')} />
|
||||
</HStack>
|
||||
<MultipleSelect<WorkflowIOValueTypeEnum>
|
||||
list={valueTypeSelectList}
|
||||
bg={'myGray.50'}
|
||||
value={selectValueTypeList || []}
|
||||
onSelect={(e) => {
|
||||
setValue('customInputConfig.selectValueTypeList', e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
<Flex justify={'flex-end'} gap={3} pb={8} pr={8}>
|
||||
<Button variant={'whiteBase'} fontWeight={'medium'} onClick={onClose} w={20}>
|
||||
{t('common:common.Close')}
|
||||
</Button>
|
||||
<Button
|
||||
variant={'primaryOutline'}
|
||||
fontWeight={'medium'}
|
||||
onClick={handleSubmit((data) => onSubmitSuccess(data, 'confirm'), onSubmitError)}
|
||||
w={20}
|
||||
>
|
||||
{t('common:common.Confirm')}
|
||||
</Button>
|
||||
{!isEdit && (
|
||||
<Button
|
||||
fontWeight={'medium'}
|
||||
onClick={handleSubmit((data) => onSubmitSuccess(data, 'continue'), onSubmitError)}
|
||||
w={20}
|
||||
>
|
||||
{t('common:comon.Continue_Adding')}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
</Stack>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
|
||||
{t('common:common.Close')}
|
||||
</Button>
|
||||
<Button onClick={handleSubmit(onSubmitSuccess, onSubmitError)}>
|
||||
{t('common:common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Flex>
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
@@ -36,7 +36,9 @@ const VariableTable = ({
|
||||
<Tr key={item.key}>
|
||||
<Td>
|
||||
<Flex alignItems={'center'}>
|
||||
{!!item.icon && <MyIcon name={item.icon as any} w={'14px'} mr={1} />}
|
||||
{!!item.icon && (
|
||||
<MyIcon name={item.icon as any} w={'14px'} mr={1} color={'primary.600'} />
|
||||
)}
|
||||
{item.label || item.key}
|
||||
</Flex>
|
||||
</Td>
|
||||
@@ -48,6 +50,7 @@ const VariableTable = ({
|
||||
name={'common/settingLight'}
|
||||
w={'16px'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'primary.600' }}
|
||||
onClick={() => onEdit(item.key)}
|
||||
/>
|
||||
<MyIcon
|
||||
|
@@ -174,6 +174,7 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) =>
|
||||
bg={'white'}
|
||||
borderRadius={'xs'}
|
||||
mx={2}
|
||||
color={'primary.600'}
|
||||
onClick={() => {
|
||||
onUpdateList(
|
||||
updateList.map((update, i) => {
|
||||
|
Reference in New Issue
Block a user