mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-27 08:25:07 +00:00
feat: http body type & http input support editor variable (#2603)
* feat: http body type & http input support editor variable * fix type * chore: code * code
This commit is contained in:
@@ -24,15 +24,18 @@ import {
|
||||
NumberDecrementStepper,
|
||||
NumberInput
|
||||
} from '@chakra-ui/react';
|
||||
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import {
|
||||
ContentTypes,
|
||||
NodeInputKeyEnum,
|
||||
WorkflowIOValueTypeEnum
|
||||
} from '@fastgpt/global/core/workflow/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io.d';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import JSONEditor from '@fastgpt/web/components/common/Textarea/JsonEditor';
|
||||
import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/workflow/utils';
|
||||
import { EditorVariablePickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
import { EditorVariableLabelPickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
import HttpInput from '@fastgpt/web/components/common/Input/HttpInput';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
@@ -40,52 +43,22 @@ import RenderToolInput from '../render/RenderToolInput';
|
||||
import IOTitle from '../../components/IOTitle';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { WorkflowContext } from '../../../context';
|
||||
import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { useCreation, useMemoizedFn } from 'ahooks';
|
||||
import { AppContext } from '@/pages/app/detail/components/context';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { getEditorVariables } from '../../../utils';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
const CurlImportModal = dynamic(() => import('./CurlImportModal'));
|
||||
|
||||
export const HttpHeaders = [
|
||||
{ key: 'A-IM', label: 'A-IM' },
|
||||
{ key: 'Accept', label: 'Accept' },
|
||||
{ key: 'Accept-Charset', label: 'Accept-Charset' },
|
||||
{ key: 'Accept-Encoding', label: 'Accept-Encoding' },
|
||||
{ key: 'Accept-Language', label: 'Accept-Language' },
|
||||
{ key: 'Accept-Datetime', label: 'Accept-Datetime' },
|
||||
{ key: 'Access-Control-Request-Method', label: 'Access-Control-Request-Method' },
|
||||
{ key: 'Access-Control-Request-Headers', label: 'Access-Control-Request-Headers' },
|
||||
{ key: 'Authorization', label: 'Authorization' },
|
||||
{ key: 'Cache-Control', label: 'Cache-Control' },
|
||||
{ key: 'Connection', label: 'Connection' },
|
||||
{ key: 'Content-Length', label: 'Content-Length' },
|
||||
{ key: 'Content-Type', label: 'Content-Type' },
|
||||
{ key: 'Cookie', label: 'Cookie' },
|
||||
{ key: 'Date', label: 'Date' },
|
||||
{ key: 'Expect', label: 'Expect' },
|
||||
{ key: 'Forwarded', label: 'Forwarded' },
|
||||
{ key: 'From', label: 'From' },
|
||||
{ key: 'Host', label: 'Host' },
|
||||
{ key: 'If-Match', label: 'If-Match' },
|
||||
{ key: 'If-Modified-Since', label: 'If-Modified-Since' },
|
||||
{ key: 'If-None-Match', label: 'If-None-Match' },
|
||||
{ key: 'If-Range', label: 'If-Range' },
|
||||
{ key: 'If-Unmodified-Since', label: 'If-Unmodified-Since' },
|
||||
{ key: 'Max-Forwards', label: 'Max-Forwards' },
|
||||
{ key: 'Origin', label: 'Origin' },
|
||||
{ key: 'Pragma', label: 'Pragma' },
|
||||
{ key: 'Proxy-Authorization', label: 'Proxy-Authorization' },
|
||||
{ key: 'Range', label: 'Range' },
|
||||
{ key: 'Referer', label: 'Referer' },
|
||||
{ key: 'TE', label: 'TE' },
|
||||
{ key: 'User-Agent', label: 'User-Agent' },
|
||||
{ key: 'Upgrade', label: 'Upgrade' },
|
||||
{ key: 'Via', label: 'Via' },
|
||||
{ key: 'Warning', label: 'Warning' },
|
||||
{ key: 'Dnt', label: 'Dnt' },
|
||||
{ key: 'X-Requested-With', label: 'X-Requested-With' },
|
||||
{ key: 'X-CSRF-Token', label: 'X-CSRF-Token' }
|
||||
];
|
||||
const defaultFormBody = {
|
||||
key: NodeInputKeyEnum.httpFormBody,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
valueType: WorkflowIOValueTypeEnum.any,
|
||||
value: [],
|
||||
label: '',
|
||||
required: false
|
||||
};
|
||||
|
||||
enum TabEnum {
|
||||
params = 'params',
|
||||
@@ -260,7 +233,7 @@ export function RenderHttpProps({
|
||||
const { t } = useTranslation();
|
||||
const [selectedTab, setSelectedTab] = useState(TabEnum.params);
|
||||
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
|
||||
const getNodeDynamicInputs = useContextSelector(WorkflowContext, (v) => v.getNodeDynamicInputs);
|
||||
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
|
||||
|
||||
const { appDetail } = useContextSelector(AppContext, (v) => v);
|
||||
|
||||
@@ -268,21 +241,23 @@ export function RenderHttpProps({
|
||||
const params = inputs.find((item) => item.key === NodeInputKeyEnum.httpParams);
|
||||
const headers = inputs.find((item) => item.key === NodeInputKeyEnum.httpHeaders);
|
||||
const jsonBody = inputs.find((item) => item.key === NodeInputKeyEnum.httpJsonBody);
|
||||
const formBody =
|
||||
inputs.find((item) => item.key === NodeInputKeyEnum.httpFormBody) || defaultFormBody;
|
||||
const contentType = inputs.find((item) => item.key === NodeInputKeyEnum.httpContentType);
|
||||
|
||||
const paramsLength = params?.value?.length || 0;
|
||||
const headersLength = headers?.value?.length || 0;
|
||||
|
||||
// get variable
|
||||
const variables = useMemo(() => {
|
||||
const globalVariables = getWorkflowGlobalVariables({
|
||||
nodes: nodeList,
|
||||
chatConfig: appDetail.chatConfig
|
||||
const variables = useCreation(() => {
|
||||
return getEditorVariables({
|
||||
nodeId,
|
||||
nodeList,
|
||||
edges,
|
||||
appDetail,
|
||||
t
|
||||
});
|
||||
|
||||
const nodeVariables = formatEditorVariablePickerIcon(getNodeDynamicInputs(nodeId));
|
||||
|
||||
return [...nodeVariables, ...globalVariables];
|
||||
}, [appDetail.chatConfig, getNodeDynamicInputs, nodeId, nodeList]);
|
||||
}, [nodeList, edges, inputs, t]);
|
||||
|
||||
const variableText = useMemo(() => {
|
||||
return variables
|
||||
@@ -310,10 +285,11 @@ export function RenderHttpProps({
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:core.module.http.Props tip', { variable: variableText })}
|
||||
></QuestionTip>
|
||||
/>
|
||||
</Flex>
|
||||
<LightRowTabs<TabEnum>
|
||||
width={'100%'}
|
||||
mb={selectedTab === TabEnum.body ? 1 : 2}
|
||||
list={[
|
||||
{ label: <RenderPropsItem text="Params" num={paramsLength} />, value: TabEnum.params },
|
||||
...(!['GET', 'DELETE'].includes(requestMethods)
|
||||
@@ -337,33 +313,31 @@ export function RenderHttpProps({
|
||||
value={selectedTab}
|
||||
onChange={setSelectedTab}
|
||||
/>
|
||||
<Box bg={'white'} borderRadius={'md'}>
|
||||
<Box bg={'white'} borderRadius={'md'} minW={'560px'}>
|
||||
{params &&
|
||||
headers &&
|
||||
jsonBody &&
|
||||
{
|
||||
[TabEnum.params]: (
|
||||
<RenderForm
|
||||
[TabEnum.params]: <RenderForm nodeId={nodeId} input={params} variables={variables} />,
|
||||
[TabEnum.body]: (
|
||||
<RenderBody
|
||||
nodeId={nodeId}
|
||||
input={params}
|
||||
variables={variables}
|
||||
tabType={TabEnum.params}
|
||||
jsonBody={jsonBody}
|
||||
formBody={formBody}
|
||||
typeInput={contentType}
|
||||
/>
|
||||
),
|
||||
[TabEnum.body]: <RenderJson nodeId={nodeId} variables={variables} input={jsonBody} />,
|
||||
[TabEnum.headers]: (
|
||||
<RenderForm
|
||||
nodeId={nodeId}
|
||||
input={headers}
|
||||
variables={variables}
|
||||
tabType={TabEnum.headers}
|
||||
/>
|
||||
<RenderForm nodeId={nodeId} input={headers} variables={variables} />
|
||||
)
|
||||
}[selectedTab]}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}, [
|
||||
contentType,
|
||||
formBody,
|
||||
headersLength,
|
||||
nodeId,
|
||||
paramsLength,
|
||||
@@ -433,13 +407,11 @@ const RenderHttpTimeout = ({
|
||||
const RenderForm = ({
|
||||
nodeId,
|
||||
input,
|
||||
variables,
|
||||
tabType
|
||||
variables
|
||||
}: {
|
||||
nodeId: string;
|
||||
input: FlowNodeInputItemType;
|
||||
variables: EditorVariablePickerType[];
|
||||
tabType?: TabEnum;
|
||||
variables: EditorVariableLabelPickerType[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
@@ -449,13 +421,6 @@ const RenderForm = ({
|
||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||
const [shouldUpdateNode, setShouldUpdateNode] = useState(false);
|
||||
|
||||
const leftVariables = useMemo(() => {
|
||||
return (tabType === TabEnum.headers ? HttpHeaders : variables).filter((variable) => {
|
||||
const existVariables = list.map((item) => item.key);
|
||||
return !existVariables.includes(variable.key);
|
||||
});
|
||||
}, [list, tabType, variables]);
|
||||
|
||||
useEffect(() => {
|
||||
setList(input.value || []);
|
||||
}, [input.value]);
|
||||
@@ -529,7 +494,7 @@ const RenderForm = ({
|
||||
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<Box mt={2} borderRadius={'md'} overflow={'hidden'} borderWidth={'1px'} borderBottom={'none'}>
|
||||
<Box borderRadius={'md'} overflow={'hidden'} borderWidth={'1px'} borderBottom={'none'}>
|
||||
<TableContainer overflowY={'visible'} overflowX={'unset'}>
|
||||
<Table>
|
||||
<Thead>
|
||||
@@ -545,29 +510,25 @@ const RenderForm = ({
|
||||
<Tbody>
|
||||
{list.map((item, index) => (
|
||||
<Tr key={`${input.key}${index}`}>
|
||||
<Td p={0} w={'150px'}>
|
||||
<Td p={0} w={'50%'}>
|
||||
<HttpInput
|
||||
hasVariablePlugin={false}
|
||||
hasDropDownPlugin={tabType === TabEnum.headers}
|
||||
setDropdownValue={(value) => {
|
||||
handleKeyChange(index, value);
|
||||
setUpdateTrigger((prev) => !prev);
|
||||
}}
|
||||
placeholder={t('common:core.module.http.Props name')}
|
||||
value={item.key}
|
||||
variables={leftVariables}
|
||||
variableLabels={variables}
|
||||
variables={variables}
|
||||
onBlur={(val) => {
|
||||
handleKeyChange(index, val);
|
||||
}}
|
||||
updateTrigger={updateTrigger}
|
||||
/>
|
||||
</Td>
|
||||
<Td p={0}>
|
||||
<Td p={0} w={'50%'}>
|
||||
<Box display={'flex'} alignItems={'center'}>
|
||||
<HttpInput
|
||||
placeholder={t('common:core.module.http.Props value')}
|
||||
value={item.value}
|
||||
variables={variables}
|
||||
variableLabels={variables}
|
||||
onBlur={(val) => {
|
||||
setList((prevList) =>
|
||||
prevList.map((item, i) =>
|
||||
@@ -592,17 +553,12 @@ const RenderForm = ({
|
||||
</Tr>
|
||||
))}
|
||||
<Tr>
|
||||
<Td p={0} w={'150px'}>
|
||||
<Td p={0} w={'50%'}>
|
||||
<HttpInput
|
||||
hasVariablePlugin={false}
|
||||
hasDropDownPlugin={tabType === TabEnum.headers}
|
||||
setDropdownValue={(val) => {
|
||||
handleAddNewProps(val);
|
||||
setUpdateTrigger((prev) => !prev);
|
||||
}}
|
||||
placeholder={t('common:core.module.http.Add props')}
|
||||
value={''}
|
||||
variables={leftVariables}
|
||||
variableLabels={variables}
|
||||
variables={variables}
|
||||
updateTrigger={updateTrigger}
|
||||
onBlur={(val) => {
|
||||
handleAddNewProps(val);
|
||||
@@ -610,7 +566,7 @@ const RenderForm = ({
|
||||
}}
|
||||
/>
|
||||
</Td>
|
||||
<Td p={0}>
|
||||
<Td p={0} w={'50%'}>
|
||||
<Box display={'flex'} alignItems={'center'}>
|
||||
<HttpInput />
|
||||
</Box>
|
||||
@@ -621,63 +577,158 @@ const RenderForm = ({
|
||||
</TableContainer>
|
||||
</Box>
|
||||
);
|
||||
}, [
|
||||
handleAddNewProps,
|
||||
handleKeyChange,
|
||||
input.key,
|
||||
leftVariables,
|
||||
list,
|
||||
t,
|
||||
tabType,
|
||||
updateTrigger,
|
||||
variables
|
||||
]);
|
||||
}, [handleAddNewProps, handleKeyChange, input.key, list, t, updateTrigger, variables]);
|
||||
|
||||
return Render;
|
||||
};
|
||||
const RenderJson = ({
|
||||
const RenderBody = ({
|
||||
nodeId,
|
||||
input,
|
||||
jsonBody,
|
||||
formBody,
|
||||
typeInput,
|
||||
variables
|
||||
}: {
|
||||
nodeId: string;
|
||||
input: FlowNodeInputItemType;
|
||||
variables: EditorVariablePickerType[];
|
||||
jsonBody: FlowNodeInputItemType;
|
||||
formBody: FlowNodeInputItemType;
|
||||
typeInput: FlowNodeInputItemType | undefined;
|
||||
variables: EditorVariableLabelPickerType[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
|
||||
const [_, startSts] = useTransition();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeInput === undefined) {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'addInput',
|
||||
value: {
|
||||
key: NodeInputKeyEnum.httpContentType,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
valueType: WorkflowIOValueTypeEnum.string,
|
||||
value: ContentTypes.json,
|
||||
label: '',
|
||||
required: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [nodeId, onChangeNode, typeInput]);
|
||||
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<Box mt={1}>
|
||||
<JSONEditor
|
||||
bg={'white'}
|
||||
defaultHeight={200}
|
||||
resize
|
||||
value={input.value}
|
||||
placeholder={t('common:core.module.template.http body placeholder')}
|
||||
onChange={(e) => {
|
||||
startSts(() => {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'updateInput',
|
||||
key: input.key,
|
||||
value: {
|
||||
...input,
|
||||
value: e
|
||||
}
|
||||
<Box>
|
||||
<Flex bg={'myGray.50'}>
|
||||
{Object.values(ContentTypes).map((item) => (
|
||||
<Box
|
||||
key={item}
|
||||
as={'span'}
|
||||
px={3}
|
||||
py={1.5}
|
||||
mb={2}
|
||||
borderRadius={'6px'}
|
||||
border={'1px solid'}
|
||||
{...(typeInput?.value === item
|
||||
? {
|
||||
bg: 'white',
|
||||
borderColor: 'myGray.200',
|
||||
color: 'primary.700'
|
||||
}
|
||||
: {
|
||||
bg: 'myGray.50',
|
||||
borderColor: 'transparent',
|
||||
color: 'myGray.500'
|
||||
})}
|
||||
_hover={{ bg: 'white', borderColor: 'myGray.200', color: 'primary.700' }}
|
||||
onClick={() => {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.httpContentType,
|
||||
value: {
|
||||
key: NodeInputKeyEnum.httpContentType,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
valueType: WorkflowIOValueTypeEnum.string,
|
||||
value: item,
|
||||
label: '',
|
||||
required: false
|
||||
}
|
||||
});
|
||||
}}
|
||||
cursor={'pointer'}
|
||||
whiteSpace={'nowrap'}
|
||||
>
|
||||
{item}
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
{typeInput?.value === ContentTypes.none && (
|
||||
<Box
|
||||
px={4}
|
||||
py={12}
|
||||
bg={'white'}
|
||||
color={'myGray.400'}
|
||||
borderRadius={'6px'}
|
||||
border={'1px solid'}
|
||||
borderColor={'myGray.200'}
|
||||
>
|
||||
{t('workflow:http.body_none')}
|
||||
</Box>
|
||||
)}
|
||||
{(typeInput?.value === ContentTypes.formData ||
|
||||
typeInput?.value === ContentTypes.xWwwFormUrlencoded) && (
|
||||
<RenderForm nodeId={nodeId} input={formBody} variables={variables} />
|
||||
)}
|
||||
{typeInput?.value === ContentTypes.json && (
|
||||
<JSONEditor
|
||||
bg={'white'}
|
||||
defaultHeight={200}
|
||||
resize
|
||||
value={jsonBody.value}
|
||||
placeholder={t('common:core.module.template.http body placeholder')}
|
||||
onChange={(e) => {
|
||||
startSts(() => {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'updateInput',
|
||||
key: jsonBody.key,
|
||||
value: {
|
||||
...jsonBody,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}}
|
||||
variables={variables}
|
||||
/>
|
||||
}}
|
||||
variables={variables}
|
||||
/>
|
||||
)}
|
||||
{(typeInput?.value === ContentTypes.xml || typeInput?.value === ContentTypes.raw) && (
|
||||
<PromptEditor
|
||||
value={jsonBody.value}
|
||||
onChange={(e) => {
|
||||
startSts(() => {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'updateInput',
|
||||
key: jsonBody.key,
|
||||
value: {
|
||||
...jsonBody,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
});
|
||||
}}
|
||||
showOpenModal={false}
|
||||
variableLabels={variables}
|
||||
h={200}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}, [input, nodeId, onChangeNode, t, variables]);
|
||||
|
||||
}, [typeInput?.value, t, nodeId, formBody, variables, jsonBody, onChangeNode]);
|
||||
return Render;
|
||||
};
|
||||
|
||||
const RenderPropsItem = ({ text, num }: { text: string; num: number }) => {
|
||||
return (
|
||||
<Flex alignItems={'center'}>
|
||||
@@ -709,7 +760,7 @@ const NodeHttp = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
[NodeInputKeyEnum.httpHeaders]: Headers,
|
||||
[NodeInputKeyEnum.httpTimeout]: HttpTimeout
|
||||
};
|
||||
}, [Headers, HttpMethodAndUrl]);
|
||||
}, [Headers, HttpMethodAndUrl, HttpTimeout]);
|
||||
|
||||
return (
|
||||
<NodeCard minW={'350px'} selected={selected} {...data}>
|
||||
|
@@ -34,7 +34,6 @@ import { str2OpenApiSchema } from '@fastgpt/global/core/app/httpPlugin/utils';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import HttpInput from '@fastgpt/web/components/common/Input/HttpInput';
|
||||
import { HttpHeaders } from '../../detail/components/WorkflowComponents/Flow/nodes/NodeHttp';
|
||||
import { OpenApiJsonSchema } from '@fastgpt/global/core/app/httpPlugin/type';
|
||||
import { AppSchema } from '@fastgpt/global/core/app/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -168,15 +167,6 @@ const HttpPluginEditModal = ({
|
||||
errorToast: t('common:plugin.Invalid Schema')
|
||||
});
|
||||
|
||||
const leftVariables = useMemo(
|
||||
() =>
|
||||
HttpHeaders.filter((variable) => {
|
||||
const existVariables = customHeaders.map((item) => item.key);
|
||||
return !existVariables.includes(variable.key);
|
||||
}),
|
||||
[customHeaders]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (!apiSchemaStr) {
|
||||
@@ -315,28 +305,8 @@ const HttpPluginEditModal = ({
|
||||
<Tr key={`${index}`}>
|
||||
<Td p={0} w={'150px'}>
|
||||
<HttpInput
|
||||
hasVariablePlugin={false}
|
||||
hasDropDownPlugin={true}
|
||||
setDropdownValue={(val) => {
|
||||
setCustomHeaders((prev) => {
|
||||
const newHeaders = prev.map((item, i) =>
|
||||
i === index ? { ...item, key: val } : item
|
||||
);
|
||||
setValue(
|
||||
'pluginData.customHeaders',
|
||||
'{\n' +
|
||||
newHeaders
|
||||
.map((item) => `"${item.key}":"${item.value}"`)
|
||||
.join(',\n') +
|
||||
'\n}'
|
||||
);
|
||||
return newHeaders;
|
||||
});
|
||||
setUpdateTrigger((prev) => !prev);
|
||||
}}
|
||||
placeholder={t('common:core.module.http.Props name')}
|
||||
value={item.key}
|
||||
variables={leftVariables}
|
||||
onBlur={(val) => {
|
||||
setCustomHeaders((prev) => {
|
||||
const newHeaders = prev.map((item, i) =>
|
||||
@@ -360,7 +330,6 @@ const HttpPluginEditModal = ({
|
||||
<Box display={'flex'} alignItems={'center'}>
|
||||
<HttpInput
|
||||
placeholder={t('common:core.module.http.Props value')}
|
||||
hasVariablePlugin={false}
|
||||
value={item.value}
|
||||
onBlur={(val) =>
|
||||
setCustomHeaders((prev) => {
|
||||
@@ -406,26 +375,8 @@ const HttpPluginEditModal = ({
|
||||
<Tr>
|
||||
<Td p={0} w={'150px'}>
|
||||
<HttpInput
|
||||
hasVariablePlugin={false}
|
||||
hasDropDownPlugin={true}
|
||||
setDropdownValue={(val) => {
|
||||
setCustomHeaders((prev) => {
|
||||
const newHeaders = [...prev, { key: val, value: '' }];
|
||||
setValue(
|
||||
'pluginData.customHeaders',
|
||||
'{\n' +
|
||||
newHeaders
|
||||
.map((item) => `"${item.key}":"${item.value}"`)
|
||||
.join(',\n') +
|
||||
'\n}'
|
||||
);
|
||||
return newHeaders;
|
||||
});
|
||||
setUpdateTrigger((prev) => !prev);
|
||||
}}
|
||||
placeholder={t('common:core.module.http.Add props')}
|
||||
value={''}
|
||||
variables={leftVariables}
|
||||
updateTrigger={updateTrigger}
|
||||
onBlur={(val) => {
|
||||
if (!val) return;
|
||||
|
Reference in New Issue
Block a user