onOpen(false)}
onChange={(v) => {
onChange?.(v)
diff --git a/web/app/components/base/features/new-feature-panel/image-upload/index.tsx b/web/app/components/base/features/new-feature-panel/image-upload/index.tsx
new file mode 100644
index 0000000000..f728520e9b
--- /dev/null
+++ b/web/app/components/base/features/new-feature-panel/image-upload/index.tsx
@@ -0,0 +1,114 @@
+import React, { useCallback, useMemo, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import produce from 'immer'
+import { RiEqualizer2Line, RiImage2Fill } from '@remixicon/react'
+import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card'
+import SettingModal from '@/app/components/base/features/new-feature-panel/file-upload/setting-modal'
+import Badge from '@/app/components/base/badge'
+import Button from '@/app/components/base/button'
+import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
+import type { OnFeaturesChange } from '@/app/components/base/features/types'
+import { FeatureEnum } from '@/app/components/base/features/types'
+
+type Props = {
+ disabled: boolean
+ onChange?: OnFeaturesChange
+}
+
+const FileUpload = ({
+ disabled,
+ onChange,
+}: Props) => {
+ const { t } = useTranslation()
+ const file = useFeatures(s => s.features.file)
+ const featuresStore = useFeaturesStore()
+ const [modalOpen, setModalOpen] = useState(false)
+ const [isHovering, setIsHovering] = useState(false)
+
+ const supportedTypes = useMemo(() => {
+ return file?.allowed_file_types?.join(',') || '-'
+ }, [file?.allowed_file_types])
+
+ const handleChange = useCallback((type: FeatureEnum, enabled: boolean) => {
+ const {
+ features,
+ setFeatures,
+ } = featuresStore!.getState()
+
+ const newFeatures = produce(features, (draft) => {
+ draft[type] = {
+ ...draft[type],
+ enabled,
+ image: { enabled },
+ }
+ })
+ setFeatures(newFeatures)
+ if (onChange)
+ onChange()
+ }, [featuresStore, onChange])
+
+ return (
+
+
+
+ }
+ title={
+
+ {t('appDebug.feature.imageUpload.title')}
+
+
+ }
+ value={file?.enabled}
+ onChange={state => handleChange(FeatureEnum.file, state)}
+ onMouseEnter={() => setIsHovering(true)}
+ onMouseLeave={() => setIsHovering(false)}
+ disabled={disabled}
+ >
+ <>
+ {!file?.enabled && (
+ {t('appDebug.feature.imageUpload.description')}
+ )}
+ {file?.enabled && (
+ <>
+ {!isHovering && !modalOpen && (
+
+
+
{t('appDebug.feature.imageUpload.supportedTypes')}
+
{supportedTypes}
+
+
+
+
{t('appDebug.feature.imageUpload.numberLimit')}
+
{file?.number_limits}
+
+
+ )}
+ {(isHovering || modalOpen) && (
+ {
+ setModalOpen(v)
+ setIsHovering(v)
+ }}
+ onChange={onChange}
+ >
+
+
+ )}
+ >
+ )}
+ >
+
+ )
+}
+
+export default FileUpload
diff --git a/web/app/components/base/features/new-feature-panel/index.tsx b/web/app/components/base/features/new-feature-panel/index.tsx
index 22a1f5a69f..519742442f 100644
--- a/web/app/components/base/features/new-feature-panel/index.tsx
+++ b/web/app/components/base/features/new-feature-panel/index.tsx
@@ -8,12 +8,13 @@ import type { OnFeaturesChange } from '@/app/components/base/features/types'
import MoreLikeThis from '@/app/components/base/features/new-feature-panel/more-like-this'
import ConversationOpener from '@/app/components/base/features/new-feature-panel/conversation-opener'
-import Moderation from '@/app/components/base/features/new-feature-panel/moderation'
+import FollowUp from '@/app/components/base/features/new-feature-panel/follow-up'
import SpeechToText from '@/app/components/base/features/new-feature-panel/speech-to-text'
import TextToSpeech from '@/app/components/base/features/new-feature-panel/text-to-speech'
import FileUpload from '@/app/components/base/features/new-feature-panel/file-upload'
-import FollowUp from '@/app/components/base/features/new-feature-panel/follow-up'
import Citation from '@/app/components/base/features/new-feature-panel/citation'
+import ImageUpload from '@/app/components/base/features/new-feature-panel/image-upload'
+import Moderation from '@/app/components/base/features/new-feature-panel/moderation'
import AnnotationReply from '@/app/components/base/features/new-feature-panel/annotation-reply'
import type { PromptVariable } from '@/models/debug'
@@ -82,6 +83,7 @@ const NewFeaturePanel = ({
)}
{showFileUpload && isChatMode && }
+ {showFileUpload && !isChatMode && }
{isChatMode && (
)}
diff --git a/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx b/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx
index df7a8f21d8..e0d545c83f 100644
--- a/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx
+++ b/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx
@@ -17,6 +17,7 @@ type Props = {
payload: UploadFileSetting
isMultiple: boolean
inFeaturePanel?: boolean
+ hideSupportFileType?: boolean
onChange: (payload: UploadFileSetting) => void
}
@@ -24,6 +25,7 @@ const FileUploadSetting: FC = ({
payload,
isMultiple,
inFeaturePanel = false,
+ hideSupportFileType = false,
onChange,
}) => {
const { t } = useTranslation()
@@ -93,7 +95,7 @@ const FileUploadSetting: FC = ({
>
{
- [SupportUploadFileTypes.image, SupportUploadFileTypes.document, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
+ [SupportUploadFileTypes.document, SupportUploadFileTypes.image, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
= ({
)}
- {inFeaturePanel && (
+ {inFeaturePanel && !hideSupportFileType && (
{
- [SupportUploadFileTypes.image, SupportUploadFileTypes.document, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
+ [SupportUploadFileTypes.document, SupportUploadFileTypes.image, SupportUploadFileTypes.audio, SupportUploadFileTypes.video].map((type: SupportUploadFileTypes) => (
void
rightContent?: JSX.Element
varKeys?: string[]
+ showLegacyBadge?: boolean
}
const VarItem: FC = ({
@@ -28,6 +30,7 @@ const VarItem: FC = ({
onRemove = () => { },
rightContent,
varKeys = [],
+ showLegacyBadge = false,
}) => {
const { t } = useTranslation()
@@ -50,6 +53,12 @@ const VarItem: FC = ({
{payload.label && (<>·
{payload.label as string}
>)}
+ {showLegacyBadge && (
+
+ )}
{rightContent || (<>
diff --git a/web/app/components/workflow/nodes/start/panel.tsx b/web/app/components/workflow/nodes/start/panel.tsx
index 94c348b371..275cb352a2 100644
--- a/web/app/components/workflow/nodes/start/panel.tsx
+++ b/web/app/components/workflow/nodes/start/panel.tsx
@@ -73,6 +73,7 @@ const Panel: FC> = ({