| | |
| | | import Toast from '@/app/components/base/toast' |
| | | import { TransferMethod } from '@/types/app' |
| | | import { getProcessedFiles } from '@/app/components/base/file-uploader/utils' |
| | | import type { NodeTracing } from '@/types/workflow' |
| | | import RetryResultPanel from '@/app/components/workflow/run/retry-result-panel' |
| | | import type { BlockEnum } from '@/app/components/workflow/types' |
| | | import type { Emoji } from '@/app/components/tools/types' |
| | | import type { SpecialResultPanelProps } from '@/app/components/workflow/run/special-result-panel' |
| | | import SpecialResultPanel from '@/app/components/workflow/run/special-result-panel' |
| | | |
| | | const i18nPrefix = 'workflow.singleRun' |
| | | |
| | |
| | | onRun: (submitData: Record<string, any>) => void |
| | | onStop: () => void |
| | | runningStatus: NodeRunningStatus |
| | | result?: React.JSX.Element |
| | | result?: JSX.Element |
| | | forms: FormProps[] |
| | | showSpecialResultPanel?: boolean |
| | | } & Partial<SpecialResultPanelProps> |
| | | retryDetails?: NodeTracing[] |
| | | onRetryDetailBack?: any |
| | | } |
| | | |
| | | function formatValue(value: string | any, type: InputVarType) { |
| | | if (type === InputVarType.number) |
| | | return Number.parseFloat(value) |
| | | return parseFloat(value) |
| | | if (type === InputVarType.json) |
| | | return JSON.parse(value) |
| | | if (type === InputVarType.contexts) { |
| | |
| | | if (type === InputVarType.multiFiles) |
| | | return getProcessedFiles(value) |
| | | |
| | | if (type === InputVarType.singleFile) { |
| | | if (Array.isArray(value)) |
| | | return getProcessedFiles(value) |
| | | if (type === InputVarType.singleFile) |
| | | return getProcessedFiles([value])[0] |
| | | } |
| | | |
| | | return value |
| | | } |
| | |
| | | runningStatus, |
| | | result, |
| | | forms, |
| | | showSpecialResultPanel, |
| | | ...restResultPanelParams |
| | | retryDetails, |
| | | onRetryDetailBack = () => { }, |
| | | }) => { |
| | | const { t } = useTranslation() |
| | | |
| | |
| | | let errMsg = '' |
| | | forms.forEach((form) => { |
| | | form.inputs.forEach((input) => { |
| | | const value = form.values[input.variable] as any |
| | | const value = form.values[input.variable] |
| | | if (!errMsg && input.required && (value === '' || value === undefined || value === null || (input.type === InputVarType.files && value.length === 0))) |
| | | errMsg = t('workflow.errorMsg.fieldRequired', { field: typeof input.label === 'object' ? input.label.variable : input.label }) |
| | | |
| | | if (!errMsg && (input.type === InputVarType.singleFile || input.type === InputVarType.multiFiles) && value) { |
| | | let fileIsUploading = false |
| | | if (Array.isArray(value)) |
| | | fileIsUploading = value.find(item => item.transferMethod === TransferMethod.local_file && !item.uploadedId) |
| | | else |
| | | fileIsUploading = value.transferMethod === TransferMethod.local_file && !value.uploadedId |
| | | |
| | | if (fileIsUploading) |
| | | errMsg = t('appDebug.errorMessage.waitForFileUpload') |
| | | } |
| | | }) |
| | | }) |
| | | if (errMsg) { |
| | |
| | | const value = formatValue(form.values[input.variable], input.type) |
| | | submitData[input.variable] = value |
| | | } |
| | | catch { |
| | | catch (e) { |
| | | parseErrorJsonField = input.variable |
| | | } |
| | | }) |
| | |
| | | onRun(submitData) |
| | | }, [forms, onRun, t]) |
| | | return ( |
| | | <div className='absolute inset-0 z-10 rounded-2xl bg-background-overlay-alt pt-10'> |
| | | <div className='flex h-full flex-col rounded-2xl bg-components-panel-bg'> |
| | | <div className='flex h-8 shrink-0 items-center justify-between pl-4 pr-3 pt-3'> |
| | | <div className='truncate text-base font-semibold text-text-primary'> |
| | | <div className='absolute inset-0 z-10 rounded-2xl pt-10' style={{ |
| | | backgroundColor: 'rgba(16, 24, 40, 0.20)', |
| | | }}> |
| | | <div className='h-full rounded-2xl bg-white flex flex-col'> |
| | | <div className='shrink-0 flex justify-between items-center h-8 pl-4 pr-3 pt-3'> |
| | | <div className='text-base font-semibold text-gray-900 truncate'> |
| | | {t(`${i18nPrefix}.testRun`)} {nodeName} |
| | | </div> |
| | | <div className='ml-2 shrink-0 cursor-pointer p-1' onClick={() => { |
| | | <div className='ml-2 shrink-0 p-1 cursor-pointer' onClick={() => { |
| | | onHide() |
| | | }}> |
| | | <RiCloseLine className='h-4 w-4 text-text-tertiary ' /> |
| | | <RiCloseLine className='w-4 h-4 text-gray-500 ' /> |
| | | </div> |
| | | </div> |
| | | { |
| | | showSpecialResultPanel && ( |
| | | retryDetails?.length && ( |
| | | <div className='h-0 grow overflow-y-auto pb-4'> |
| | | <SpecialResultPanel {...restResultPanelParams} /> |
| | | <RetryResultPanel |
| | | list={retryDetails.map((item, index) => ({ |
| | | ...item, |
| | | title: `${t('workflow.nodes.common.retry.retry')} ${index + 1}`, |
| | | node_type: nodeType!, |
| | | extras: { |
| | | icon: toolIcon!, |
| | | }, |
| | | }))} |
| | | onBack={onRetryDetailBack} |
| | | /> |
| | | </div> |
| | | ) |
| | | } |
| | | { |
| | | !showSpecialResultPanel && ( |
| | | !retryDetails?.length && ( |
| | | <div className='h-0 grow overflow-y-auto pb-4'> |
| | | <div className='mt-3 space-y-4 px-4'> |
| | | <div className='mt-3 px-4 space-y-4'> |
| | | {forms.map((form, index) => ( |
| | | <div key={index}> |
| | | <Form |
| | |
| | | <div className='mt-4 flex justify-between space-x-2 px-4' > |
| | | {isRunning && ( |
| | | <div |
| | | className='cursor-pointer rounded-lg border border-divider-regular bg-components-button-secondary-bg p-2 shadow-xs' |
| | | className='p-2 rounded-lg border border-gray-200 bg-white shadow-xs cursor-pointer' |
| | | onClick={onStop} |
| | | > |
| | | <StopCircle className='h-4 w-4 text-text-tertiary' /> |
| | | <StopCircle className='w-4 h-4 text-gray-500' /> |
| | | </div> |
| | | )} |
| | | <Button disabled={!isFileLoaded || isRunning} variant='primary' className='w-0 grow space-x-2' onClick={handleRun}> |
| | | {isRunning && <RiLoader2Line className='h-4 w-4 animate-spin' />} |
| | | {isRunning && <RiLoader2Line className='animate-spin w-4 h-4 text-white' />} |
| | | <div>{t(`${i18nPrefix}.${isRunning ? 'running' : 'startRun'}`)}</div> |
| | | </Button> |
| | | </div> |