Feat: IfElse node support variable reference (#5025)

* if else node support reference (#5016)

* if else node support reference

* optimize input render

* ui

* fix

---------

Co-authored-by: Archer <545436317@qq.com>

* fix: chat

* perf: download invoice

* optimize ifelse node ui (#5024)

* perf: ifelse node

* optimize type (#5027)

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2025-06-13 17:15:24 +08:00
committed by GitHub
parent 8acb16f9f2
commit 0914eacb5e
29 changed files with 393 additions and 276 deletions

View File

@@ -94,7 +94,7 @@ export const VariableInputItem = ({
step={1}
min={item.min}
max={item.max}
bg={'white'}
inputFieldProps={{ bg: 'white' }}
value={value}
onChange={onChange}
isInvalid={errors?.variables && Object.keys(errors.variables).includes(item.key)}
@@ -250,18 +250,16 @@ const VariableInput = ({
<ExternalVariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
))}
{variableList.length === 0 && !chatStarted && (
<Box>
<Button
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
size={'sm'}
maxW={'100px'}
onClick={handleSubmitChat(() => {
chatForm.setValue('chatStarted', true);
})}
>
{t('common:core.chat.Start Chat')}
</Button>
</Box>
<Button
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
size={'sm'}
maxW={'100px'}
onClick={handleSubmitChat(() => {
chatForm.setValue('chatStarted', true);
})}
>
{t('common:core.chat.Start Chat')}
</Button>
)}
</Card>
</Box>
@@ -287,7 +285,6 @@ const VariableInput = ({
size={'sm'}
maxW={'100px'}
onClick={handleSubmitChat(() => {
console.log('start chat');
chatForm.setValue('chatStarted', true);
})}
>

View File

@@ -198,7 +198,6 @@ const RenderPluginInput = ({
step={1}
min={input.min}
max={input.max}
bg={'myGray.50'}
isDisabled={isDisabled}
isInvalid={isInvalid}
value={value}

View File

@@ -146,10 +146,10 @@ export const FormInputComponent = React.memo(function FormInputComponent({
max={max}
defaultValue={defaultValue}
isDisabled={submitted}
bg={'white'}
register={register}
name={label}
isRequired={required}
inputFieldProps={{ bg: 'white' }}
/>
);
case FlowNodeInputTypeEnum.select:

View File

@@ -1,4 +1,4 @@
import { getInvoiceRecords, readInvoiceFile } from '@/web/support/wallet/bill/invoice/api';
import { getInvoiceRecords } from '@/web/support/wallet/bill/invoice/api';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { useTranslation } from 'next-i18next';
import { useState } from 'react';
@@ -23,6 +23,7 @@ import dayjs from 'dayjs';
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/usage/tools';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { downloadFetch } from '@/web/common/system/utils';
const InvoiceTable = () => {
const { t } = useTranslation();
@@ -138,25 +139,10 @@ function InvoiceDetailModal({
const { t } = useTranslation();
const { runAsync: handleDownloadInvoice } = useRequest2(async (id: string) => {
const fileInfo = await readInvoiceFile(id);
// Blob
const byteCharacters = atob(fileInfo.data);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: fileInfo.mimeType });
const fileUrl = URL.createObjectURL(blob);
// preview
window.open(fileUrl, '_blank');
// clean
setTimeout(() => {
URL.revokeObjectURL(fileUrl);
}, 1000);
await downloadFetch({
url: `/api/proApi/support/wallet/bill/invoice/downloadFile?id=${id}`,
filename: `${invoice.teamName}.pdf`
});
});
return (

View File

@@ -214,15 +214,7 @@ const RenderToolInput = ({
);
}
if (paramInfo.type === 'number') {
return (
<MyNumberInput
step={1}
bg={'myGray.50'}
isInvalid={isInvalid}
value={value}
onChange={onChange}
/>
);
return <MyNumberInput step={1} isInvalid={isInvalid} value={value} onChange={onChange} />;
}
if (paramInfo.type === 'boolean') {
return <Switch isChecked={value} onChange={onChange} isInvalid={isInvalid} />;

View File

@@ -39,7 +39,7 @@ const NodeCQNode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<MyIcon
mt={1}
mr={2}
name={'minus'}
name={'circleMinus'}
w={'12px'}
cursor={'pointer'}
color={'myGray.600'}

View File

@@ -85,7 +85,7 @@ const NodeDatasetConcat = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
step={100}
value={item.value}
name={NodeInputKeyEnum.datasetMaxTokens}
bg={'white'}
inputFieldProps={{ bg: 'white' }}
onChange={(e) => {
onChangeNode({
nodeId,

View File

@@ -1,16 +1,16 @@
import { Box, Button, Flex } from '@chakra-ui/react';
import { Box, Button, Flex, HStack } from '@chakra-ui/react';
import {
type DraggableProvided,
type DraggableStateSnapshot
} from '@fastgpt/web/components/common/DndDrag/index';
import Container from '../../components/Container';
import { MinusIcon, SmallAddIcon } from '@chakra-ui/icons';
import { MinusIcon } from '@chakra-ui/icons';
import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { type ReferenceItemValueType } from '@fastgpt/global/core/workflow/type/io';
import { useTranslation } from 'next-i18next';
import { ReferSelector, useReference } from '../render/RenderInput/templates/Reference';
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { VARIABLE_NODE_ID, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import {
VariableConditionEnum,
allConditionList,
@@ -18,6 +18,7 @@ import {
booleanConditionList,
numberConditionList,
objectConditionList,
renderNumberConditionList,
stringConditionList
} from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
import { useContextSelector } from 'use-context-selector';
@@ -28,9 +29,12 @@ import MyInput from '@/components/MyInput';
import { getElseIFLabel, getHandleId } from '@fastgpt/global/core/workflow/utils';
import { MySourceHandle } from '../render/Handle';
import { Position, useReactFlow } from 'reactflow';
import { getRefData } from '@/web/core/workflow/utils';
import { getRefData, getWorkflowGlobalVariables } from '@/web/core/workflow/utils';
import DragIcon from '@fastgpt/web/components/common/DndDrag/DragIcon';
import { AppContext } from '@/pageComponents/app/detail/context';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
const ListItem = ({
provided,
@@ -57,7 +61,6 @@ const ListItem = ({
const Render = useMemo(() => {
return (
<Flex
alignItems={'center'}
position={'relative'}
transform={snapshot.isDragging ? `scale(${getZoom()})` : ''}
transformOrigin={'top left'}
@@ -66,16 +69,20 @@ const ListItem = ({
<Container w={snapshot.isDragging ? '' : 'full'} className="nodrag">
<Flex mb={4} alignItems={'center'}>
{ifElseList.length > 1 && <DragIcon provided={provided} />}
<Box color={'black'} fontSize={'md'} ml={2}>
<Box color={'myGray.900'} fontWeight={'medium'} fontSize={'md'} ml={2}>
{getElseIFLabel(conditionIndex)}
</Box>
{conditionItem.list?.length > 1 && (
<Flex
px={'2.5'}
ml={1.5}
px={1}
color={'primary.600'}
fontWeight={'medium'}
alignItems={'center'}
cursor={'pointer'}
_hover={{
bg: 'myGray.200'
}}
rounded={'md'}
onClick={() => {
onUpdateIfElseList(
@@ -95,7 +102,7 @@ const ListItem = ({
<MyIcon ml={1} boxSize={5} name="change" />
</Flex>
)}
<Box flex={1}></Box>
<Box flex={1} />
{ifElseList.length > 1 && (
<MyIcon
ml={2}
@@ -103,7 +110,7 @@ const ListItem = ({
name="delete"
cursor={'pointer'}
_hover={{ color: 'red.600' }}
color={'myGray.400'}
color={'myGray.600'}
onClick={() => {
onUpdateIfElseList(ifElseList.filter((_, index) => index !== conditionIndex));
onDelEdge({
@@ -119,102 +126,96 @@ const ListItem = ({
return (
<Box key={i}>
{/* condition list */}
<Flex gap={2} mb={2} alignItems={'center'}>
<Flex gap={1.5} mb={2} alignItems={'center'}>
{/* variable reference */}
<Box minW={'250px'}>
<VariableSelector
nodeId={nodeId}
variable={item.variable}
onSelect={(e) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list: ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
variable: e,
condition: undefined
};
}
return item;
})
};
}
return ifElse;
})
);
}}
/>
</Box>
{/* condition select */}
<Box w={'130px'} flex={1}>
<ConditionSelect
condition={item.condition}
variable={item.variable}
onSelect={(e) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list: ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
condition: e
};
}
return item;
})
};
}
return ifElse;
})
);
}}
/>
</Box>
{/* value */}
<Box w={'200px'}>
<ConditionValueInput
value={item.value}
condition={item.condition}
variable={item.variable}
onChange={(e) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
<VariableSelector
nodeId={nodeId}
variable={item.variable}
onSelect={(e) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list:
index === conditionIndex
? ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
value: e
};
}
return item;
})
: ifElse.list
list: ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
variable: e,
condition: undefined
};
}
return item;
})
};
})
);
}}
/>
</Box>
}
return ifElse;
})
);
}}
/>
{/* condition select */}
<ConditionSelect
condition={item.condition}
variable={item.variable}
onSelect={(e) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list: ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
condition: e
};
}
return item;
})
};
}
return ifElse;
})
);
}}
/>
{/* value */}
<ConditionValueInput
value={item.value}
valueType={item.valueType}
condition={item.condition}
variable={item.variable}
nodeId={nodeId}
updateValue={(value, valueType) => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
return {
...ifElse,
list:
index === conditionIndex
? ifElse.list.map((item, index) => {
if (index === i) {
return {
...item,
value,
valueType
};
}
return item;
})
: ifElse.list
};
})
);
}}
/>
{/* delete */}
{conditionItem.list.length > 1 && (
<MinusIcon
ml={2}
boxSize={3}
name="delete"
cursor={'pointer'}
_hover={{ color: 'red.600' }}
color={'myGray.400'}
<MyIconButton
icon="minus"
hoverColor={'red.600'}
hoverBg="red.100"
onClick={() => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
@@ -235,30 +236,32 @@ const ListItem = ({
);
})}
</Box>
<Button
onClick={() => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list: ifElse.list.concat({
variable: undefined,
condition: undefined,
value: undefined
})
};
}
return ifElse;
})
);
}}
variant={'link'}
leftIcon={<SmallAddIcon />}
color={'primary.600'}
>
{t('common:core.module.input.add')}
</Button>
<Flex>
<Button
onClick={() => {
onUpdateIfElseList(
ifElseList.map((ifElse, index) => {
if (index === conditionIndex) {
return {
...ifElse,
list: ifElse.list.concat({
variable: undefined,
condition: undefined,
value: undefined
})
};
}
return ifElse;
})
);
}}
variant={'link'}
leftIcon={<MyIcon name={'common/addLight'} boxSize={4} mr={-1} />}
color={'primary.700'}
>
{t('common:core.module.input.add')}
</Button>
</Flex>
</Container>
{!snapshot.isDragging && (
<MySourceHandle
@@ -324,6 +327,11 @@ const VariableSelector = ({
value={variable}
onSelect={onSelect}
isArray={false}
ButtonProps={{
w: '14rem',
borderColor: 'myGray.200',
borderRadius: 'sm'
}}
/>
);
};
@@ -392,7 +400,9 @@ const ConditionSelect = ({
return (
<MySelect
className="nowheel"
w={'100%'}
w={'135px'}
h={10}
borderColor={'myGray.200'}
list={filterQuiredConditionList}
value={condition}
onChange={onSelect}
@@ -401,74 +411,192 @@ const ConditionSelect = ({
);
};
/*
Different condition can be entered differently
empty, notEmpty: forbid input
boolean type: select true/false
*/
const ConditionValueInput = ({
value = '',
value,
valueType: type,
variable,
condition,
onChange
updateValue,
nodeId
}: {
value?: string;
value?: string | ReferenceItemValueType;
valueType?: 'input' | 'reference';
variable?: ReferenceItemValueType;
condition?: VariableConditionEnum;
onChange: (e: string) => void;
updateValue: (value: string | ReferenceItemValueType, valueType: 'input' | 'reference') => void;
nodeId: string;
}) => {
const { t } = useTranslation();
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
const appDetail = useContextSelector(AppContext, (v) => v.appDetail);
const isReference = useMemo(() => type === 'reference', [type]);
const globalVariables = getWorkflowGlobalVariables({
nodes: nodeList,
chatConfig: appDetail.chatConfig
});
// get value type
const valueType = useMemo(() => {
if (!variable) return;
const node = nodeList.find((node) => node.nodeId === variable[0]);
if (variable?.[0] === VARIABLE_NODE_ID) {
return globalVariables.find((item) => item.key === variable[1])?.valueType;
} else {
const node = nodeList.find((node) => node.nodeId === variable?.[0]);
const output = node?.outputs.find((item) => item.id === variable?.[1]);
return output?.valueType;
}
}, [globalVariables, nodeList, variable]);
const { referenceList } = useReference({
nodeId,
valueType
});
if (!node) return WorkflowIOValueTypeEnum.any;
const output = node.outputs.find((item) => item.id === variable[1]);
const showBooleanSelect = useMemo(() => {
return (
valueType === WorkflowIOValueTypeEnum.boolean ||
(valueType === WorkflowIOValueTypeEnum.arrayBoolean &&
condition &&
!renderNumberConditionList.has(condition))
);
}, [condition, valueType]);
const showNumberInput = useMemo(() => {
return (
valueType === WorkflowIOValueTypeEnum.number ||
valueType === WorkflowIOValueTypeEnum.arrayNumber ||
(valueType?.includes('array') && condition && renderNumberConditionList.has(condition))
);
}, [condition, valueType]);
if (!output) return WorkflowIOValueTypeEnum.any;
return output.valueType;
}, [nodeList, variable]);
const Render = useMemo(() => {
if (valueType === WorkflowIOValueTypeEnum.boolean) {
const RenderInput = useMemo(() => {
if (showBooleanSelect) {
return (
<MySelect
list={[
{ label: 'True', value: 'true' },
{ label: 'False', value: 'false' }
]}
onChange={onChange}
value={value}
onChange={(e) => updateValue(e, 'input')}
value={value as string}
placeholder={t('workflow:ifelse.Select value')}
isDisabled={
condition === VariableConditionEnum.isEmpty ||
condition === VariableConditionEnum.isNotEmpty
}
borderLeftRadius={0}
h={10}
borderColor={'myGray.200'}
/>
);
} else if (showNumberInput) {
return (
<MyNumberInput
step={1}
inputFieldProps={{
bg: 'white',
borderLeftRadius: 'none'
}}
value={Number(value as string)}
onChange={(e) => updateValue(String(e), 'input')}
/>
);
} else {
return (
<MyInput
value={value}
value={value as string}
placeholder={
condition === VariableConditionEnum.reg
? '/^((+|00)86)?1[3-9]d{9}$/'
: t('workflow:ifelse.Input value')
}
w={'100%'}
w={'full'}
h={'full'}
bg={'white'}
isDisabled={
condition === VariableConditionEnum.isEmpty ||
condition === VariableConditionEnum.isNotEmpty
}
onChange={(e) => onChange(e.target.value)}
borderLeftRadius={0}
onChange={(e) => updateValue(e.target.value, 'input')}
/>
);
}
}, [condition, onChange, value, valueType, t]);
}, [showBooleanSelect, showNumberInput, value, t, condition, updateValue]);
return Render;
const RenderReference = useMemo(() => {
return (
<ReferSelector
placeholder={t('common:select_reference_variable')}
list={referenceList}
value={isReference ? (value as ReferenceItemValueType) : undefined}
onSelect={(e) => {
updateValue(e as ReferenceItemValueType, 'reference');
}}
isArray={false}
ButtonProps={{
borderRadius: 'sm',
borderLeftRadius: 'none',
borderColor: 'myGray.200',
w: '100%'
}}
/>
);
}, [t, referenceList, isReference, value, updateValue]);
const isDisabled =
condition === VariableConditionEnum.isEmpty || condition === VariableConditionEnum.isNotEmpty;
return (
<Flex position="relative">
<Flex>
<MyTooltip
label={
isReference
? t('workflow:click_to_change_reference')
: t('workflow:click_to_change_value')
}
>
<HStack
w={'4rem'}
h={10}
border={'1px solid'}
borderRight={'none'}
borderColor={'myGray.200'}
borderLeftRadius={'sm'}
justifyContent={'center'}
bg={'white'}
px={2}
spacing={2}
cursor={'pointer'}
_hover={{
bg: 'myGray.50'
}}
onClick={() => {
if (isDisabled) return;
if (isReference) {
updateValue('', 'input');
} else {
updateValue(['', undefined], 'reference');
}
}}
>
{isReference ? (
<MyIcon name={'core/workflow/inputType/reference'} w={4} color={'primary.600'} />
) : (
<MyIcon name={'core/app/variable/input'} w={4} color={'primary.600'} />
)}
<MyIcon name={'common/lineChange'} w={'14px'} color={'myGray.500'} />
</HStack>
</MyTooltip>
<Box w={'14rem'}>{isReference ? RenderReference : RenderInput}</Box>
</Flex>
{isDisabled && (
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
bg="whiteAlpha.700"
zIndex={1}
borderRadius="sm"
cursor="not-allowed"
/>
)}
</Flex>
);
};

View File

@@ -3,7 +3,7 @@ import NodeCard from '../render/NodeCard';
import { useTranslation } from 'next-i18next';
import { Box, Button, Flex } from '@chakra-ui/react';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { type NodeProps, Position, useViewport } from 'reactflow';
import { type NodeProps, Position } from 'reactflow';
import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
import { useContextSelector } from 'use-context-selector';
@@ -14,11 +14,11 @@ import { MySourceHandle } from '../render/Handle';
import { getHandleId } from '@fastgpt/global/core/workflow/utils';
import ListItem from './ListItem';
import { IfElseResultEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
import MyIcon from '@fastgpt/web/components/common/Icon';
const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { t } = useTranslation();
const { nodeId, inputs = [] } = data;
const { zoom } = useViewport();
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const elseHandleId = getHandleId(nodeId, 'source', IfElseResultEnum.ELSE);
@@ -108,6 +108,7 @@ const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<Button
variant={'whiteBase'}
w={'full'}
leftIcon={<MyIcon name={'common/addLight'} boxSize={4} mr={-1} />}
onClick={() => {
const ifElseListInput = inputs.find(
(input) => input.key === NodeInputKeyEnum.ifElseList

View File

@@ -157,7 +157,7 @@ const OptionItem = ({
<MyTooltip label={t('common:Delete')}>
<MyIcon
mt={0.5}
name={'minus'}
name={'circleMinus'}
w={'0.8rem'}
cursor={'pointer'}
color={'myGray.600'}

View File

@@ -249,7 +249,7 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) =>
if (valueType === WorkflowIOValueTypeEnum.number) {
return (
<MyNumberInput
bg={'white'}
inputFieldProps={{ bg: 'white' }}
value={Number(inputValue) || 0}
onChange={(e) => onUpdateNewValue(String(e || 0))}
/>

View File

@@ -13,7 +13,7 @@ const NumberInputRender = ({ item, nodeId }: RenderInputProps) => {
value={item.value}
min={item.min}
max={item.max}
bg={'white'}
inputFieldProps={{ bg: 'white' }}
rounded={'md'}
onChange={(e) => {
onChangeNode({

View File

@@ -47,7 +47,7 @@ type CommonSelectProps = {
}[];
}[];
popDirection?: 'top' | 'bottom';
styles?: ButtonProps;
ButtonProps?: ButtonProps;
};
type SelectProps<T extends boolean> = CommonSelectProps & {
isArray?: T;
@@ -87,7 +87,7 @@ export const useReference = ({
return {
label: (
<Flex alignItems={'center'}>
<Avatar src={node.avatar} w={isArray ? '1rem' : '1.25rem'} borderRadius={'xs'} />
<Avatar src={node.avatar} w={isArray ? '1rem' : '1.05rem'} borderRadius={'xs'} />
<Box ml={1}>{t(node.name as any)}</Box>
</Flex>
),
@@ -168,7 +168,8 @@ const SingleReferenceSelector = ({
value,
list = [],
onSelect,
popDirection
popDirection,
ButtonProps
}: SelectProps<false>) => {
const getSelectValue = useCallback(
(value: ReferenceValueType) => {
@@ -196,12 +197,10 @@ const SingleReferenceSelector = ({
<MultipleRowSelect
label={
isValidSelect ? (
<Flex gap={2} alignItems={'center'} fontSize={'sm'}>
<Flex py={1} pl={1} alignItems={'center'}>
{nodeName}
<MyIcon name={'common/rightArrowLight'} mx={1} w={'12px'} color={'myGray.500'} />
{outputName}
</Flex>
<Flex py={1} pl={1} alignItems={'center'} fontSize={'sm'}>
{nodeName}
<MyIcon name={'common/rightArrowLight'} mx={0.5} w={'12px'} color={'myGray.500'} />
{outputName}
</Flex>
) : (
<Box fontSize={'sm'} color={'myGray.400'}>
@@ -213,9 +212,10 @@ const SingleReferenceSelector = ({
list={list}
onSelect={onSelect as any}
popDirection={popDirection}
ButtonProps={ButtonProps}
/>
);
}, [getSelectValue, list, onSelect, placeholder, popDirection, value]);
}, [ButtonProps, getSelectValue, list, onSelect, placeholder, popDirection, value]);
return ItemSelector;
};
@@ -226,8 +226,6 @@ const MultipleReferenceSelector = ({
onSelect,
popDirection
}: SelectProps<true>) => {
const { t } = useTranslation();
const getSelectValue = useCallback(
(value: ReferenceValueType) => {
if (!value) return [];

View File

@@ -269,7 +269,7 @@ const CollectionChunkForm = ({ form }: { form: UseFormReturn<CollectionChunkForm
<Box flex={'1 0 0'}>
<MyNumberInput
h={'34px'}
bg={'white'}
inputFieldProps={{ bg: 'white' }}
min={100}
max={100000}
register={register}

View File

@@ -20,6 +20,3 @@ export const submitInvoice = (data: InvoiceType) =>
export const getInvoiceRecords = (data: PaginationProps) =>
POST<PaginationResponse<InvoiceSchemaType>>(`/proApi/support/wallet/bill/invoice/records`, data);
export const readInvoiceFile = (id: string) =>
GET<InvoiceFileInfo>(`/proApi/support/wallet/bill/invoice/file/read`, { id });