Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
b75d8ca6
Unverified
Commit
b75d8ca6
authored
Mar 10, 2024
by
Rozstone
Committed by
GitHub
Mar 10, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: auto closing when close local image uploading (#2767)
parent
9beefd7d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
130 deletions
+158
-130
index.tsx
.../components/app/configuration/base/warning-mask/index.tsx
+1
-1
chat-image-uploader.tsx
...pp/components/base/image-uploader/chat-image-uploader.tsx
+53
-44
image-link-input.tsx
web/app/components/base/image-uploader/image-link-input.tsx
+1
-0
image-list.tsx
web/app/components/base/image-uploader/image-list.tsx
+93
-79
uploader.tsx
web/app/components/base/image-uploader/uploader.tsx
+10
-6
No files found.
web/app/components/app/configuration/base/warning-mask/index.tsx
View file @
b75d8ca6
...
...
@@ -24,7 +24,7 @@ const WarningMask: FC<IWarningMaskProps> = ({
return
(
<
div
className=
{
`${s.mask} absolute z-10 inset-0 pt-16`
}
>
<
div
className=
'mx-auto
w-[535px]
'
>
<
div
className=
'mx-auto
px-10
'
>
<
div
className=
{
`${s.icon} flex items-center justify-center w-11 h-11 rounded-xl bg-white`
}
>
{
warningIcon
}
</
div
>
<
div
className=
'mt-4 text-[24px] leading-normal font-semibold text-gray-800'
>
{
title
}
...
...
web/app/components/base/image-uploader/chat-image-uploader.tsx
View file @
b75d8ca6
import
type
{
FC
}
from
'react'
import
{
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
Uploader
from
'./uploader'
import
ImageLinkInput
from
'./image-link-input'
import
{
ImagePlus
}
from
'@/app/components/base/icons/src/vender/line/images'
...
...
@@ -25,16 +26,16 @@ const UploadOnlyFromLocal: FC<UploadOnlyFromLocalProps> = ({
})
=>
{
return
(
<
Uploader
onUpload=
{
onUpload
}
disabled=
{
disabled
}
limit=
{
limit
}
>
{
hovering
=>
(
<
div
className=
{
`
{
hovering
=>
(
<
div
className=
{
`
relative flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer
${hovering && 'bg-gray-100'}
`
}
>
<
ImagePlus
className=
'w-4 h-4 text-gray-500'
/
>
<
/
div
>
)
}
`
}
>
<
ImagePlus
className=
"w-4 h-4 text-gray-500"
/
>
</
div
>
)
}
</
Uploader
>
)
}
...
...
@@ -54,13 +55,16 @@ const UploaderButton: FC<UploaderButtonProps> = ({
const
{
t
}
=
useTranslation
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
hasUploadFromLocal
=
methods
.
find
(
method
=>
method
===
TransferMethod
.
local_file
)
const
hasUploadFromLocal
=
methods
.
find
(
method
=>
method
===
TransferMethod
.
local_file
,
)
const
handleUpload
=
(
imageFile
:
ImageFile
)
=>
{
setOpen
(
false
)
onUpload
(
imageFile
)
}
const
closePopover
=
()
=>
setOpen
(
false
)
const
handleToggle
=
()
=>
{
if
(
disabled
)
return
...
...
@@ -72,43 +76,46 @@ const UploaderButton: FC<UploaderButtonProps> = ({
<
PortalToFollowElem
open=
{
open
}
onOpenChange=
{
setOpen
}
placement=
'top-start'
placement=
"top-start"
>
<
PortalToFollowElemTrigger
onClick=
{
handleToggle
}
>
<
div
className=
{
`
relative flex items-center justify-center w-8 h-8 hover:bg-gray-100 rounded-lg
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
`
}
>
<
ImagePlus
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
<
button
type=
"button"
disabled=
{
disabled
}
className=
"relative flex items-center justify-center w-8 h-8 enabled:hover:bg-gray-100 rounded-lg disabled:cursor-not-allowed"
>
<
ImagePlus
className=
"w-4 h-4 text-gray-500"
/>
</
button
>
</
PortalToFollowElemTrigger
>
<
PortalToFollowElemContent
className=
'z-50'
>
<
div
className=
'p-2 w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'
>
<
PortalToFollowElemContent
className=
"z-50"
>
<
div
className=
"p-2 w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg"
>
<
ImageLinkInput
onUpload=
{
handleUpload
}
/>
{
hasUploadFromLocal
&&
(
<>
<
div
className=
'flex items-center mt-2 px-2 text-xs font-medium text-gray-400'
>
<
div
className=
'mr-3 w-[93px] h-[1px] bg-gradient-to-l from-[#F3F4F6]'
/>
OR
<
div
className=
'ml-3 w-[93px] h-[1px] bg-gradient-to-r from-[#F3F4F6]'
/>
</
div
>
<
Uploader
onUpload=
{
handleUpload
}
limit=
{
limit
}
>
{
hovering
=>
(
<
div
className=
{
`
flex items-center justify-center h-8 text-[13px] font-medium text-[#155EEF] rounded-lg cursor-pointer
${hovering && 'bg-primary-50'}
`
}
>
<
Upload03
className=
'mr-1 w-4 h-4'
/>
{
t
(
'common.imageUploader.uploadFromComputer'
)
}
</
div
>
)
}
</
Uploader
>
</>
)
}
{
hasUploadFromLocal
&&
(
<>
<
div
className=
"flex items-center mt-2 px-2 text-xs font-medium text-gray-400"
>
<
div
className=
"mr-3 w-[93px] h-[1px] bg-gradient-to-l from-[#F3F4F6]"
/>
OR
<
div
className=
"ml-3 w-[93px] h-[1px] bg-gradient-to-r from-[#F3F4F6]"
/>
</
div
>
<
Uploader
onUpload=
{
handleUpload
}
limit=
{
limit
}
closePopover=
{
closePopover
}
>
{
hovering
=>
(
<
div
className=
{
cn
(
'flex items-center justify-center h-8 text-[13px] font-medium text-[#155EEF] rounded-lg cursor-pointer'
,
hovering
&&
'bg-primary-50'
,
)
}
>
<
Upload03
className=
"mr-1 w-4 h-4"
/>
{
t
(
'common.imageUploader.uploadFromComputer'
)
}
</
div
>
)
}
</
Uploader
>
</>
)
}
</
div
>
</
PortalToFollowElemContent
>
</
PortalToFollowElem
>
...
...
@@ -125,7 +132,9 @@ const ChatImageUploader: FC<ChatImageUploaderProps> = ({
onUpload
,
disabled
,
})
=>
{
const
onlyUploadLocal
=
settings
.
transfer_methods
.
length
===
1
&&
settings
.
transfer_methods
[
0
]
===
TransferMethod
.
local_file
const
onlyUploadLocal
=
settings
.
transfer_methods
.
length
===
1
&&
settings
.
transfer_methods
[
0
]
===
TransferMethod
.
local_file
if
(
onlyUploadLocal
)
{
return
(
...
...
web/app/components/base/image-uploader/image-link-input.tsx
View file @
b75d8ca6
...
...
@@ -30,6 +30,7 @@ const ImageLinkInput: FC<ImageLinkInputProps> = ({
return
(
<
div
className=
'flex items-center pl-1.5 pr-1 h-8 border border-gray-200 bg-white shadow-xs rounded-lg'
>
<
input
type=
"text"
className=
'grow mr-0.5 px-1 h-[18px] text-[13px] outline-none appearance-none'
value=
{
imageLink
}
onChange=
{
e
=>
setImageLink
(
e
.
target
.
value
)
}
...
...
web/app/components/base/image-uploader/image-list.tsx
View file @
b75d8ca6
import
type
{
FC
}
from
'react'
import
{
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
Loading02
,
XClose
}
from
'@/app/components/base/icons/src/vender/line/general'
import
cn
from
'classnames'
import
{
Loading02
,
XClose
,
}
from
'@/app/components/base/icons/src/vender/line/general'
import
{
RefreshCcw01
}
from
'@/app/components/base/icons/src/vender/line/arrows'
import
{
AlertTriangle
}
from
'@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
import
TooltipPlus
from
'@/app/components/base/tooltip-plus'
...
...
@@ -30,7 +34,11 @@ const ImageList: FC<ImageListProps> = ({
const
[
imagePreviewUrl
,
setImagePreviewUrl
]
=
useState
(
''
)
const
handleImageLinkLoadSuccess
=
(
item
:
ImageFile
)
=>
{
if
(
item
.
type
===
TransferMethod
.
remote_url
&&
onImageLinkLoadSuccess
&&
item
.
progress
!==
-
1
)
if
(
item
.
type
===
TransferMethod
.
remote_url
&&
onImageLinkLoadSuccess
&&
item
.
progress
!==
-
1
)
onImageLinkLoadSuccess
(
item
.
_id
)
}
const
handleImageLinkLoadError
=
(
item
:
ImageFile
)
=>
{
...
...
@@ -39,89 +47,95 @@ const ImageList: FC<ImageListProps> = ({
}
return
(
<
div
className=
'flex flex-wrap'
>
{
list
.
map
(
item
=>
(
<
div
key=
{
item
.
_id
}
className=
'group relative mr-1 border-[0.5px] border-black/5 rounded-lg'
>
{
item
.
type
===
TransferMethod
.
local_file
&&
item
.
progress
!==
100
&&
(
<>
<
div
className=
'absolute inset-0 flex items-center justify-center z-[1] bg-black/30'
style=
{
{
left
:
item
.
progress
>
-
1
?
`${item.progress}%`
:
0
}
}
>
{
item
.
progress
===
-
1
&&
(
<
RefreshCcw01
className=
'w-5 h-5 text-white'
onClick=
{
()
=>
onReUpload
&&
onReUpload
(
item
.
_id
)
}
/>
)
}
</
div
>
{
item
.
progress
>
-
1
&&
(
<
span
className=
'absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] text-sm text-white mix-blend-lighten z-[1]'
>
{
item
.
progress
}
%
</
span
>
)
}
</>
)
}
{
item
.
type
===
TransferMethod
.
remote_url
&&
item
.
progress
!==
100
&&
(
<
div
className=
{
`
<
div
className=
"flex flex-wrap"
>
{
list
.
map
(
item
=>
(
<
div
key=
{
item
.
_id
}
className=
"group relative mr-1 border-[0.5px] border-black/5 rounded-lg"
>
{
item
.
type
===
TransferMethod
.
local_file
&&
item
.
progress
!==
100
&&
(
<>
<
div
className=
"absolute inset-0 flex items-center justify-center z-[1] bg-black/30"
style=
{
{
left
:
item
.
progress
>
-
1
?
`${item.progress}%`
:
0
}
}
>
{
item
.
progress
===
-
1
&&
(
<
RefreshCcw01
className=
"w-5 h-5 text-white"
onClick=
{
()
=>
onReUpload
&&
onReUpload
(
item
.
_id
)
}
/>
)
}
</
div
>
{
item
.
progress
>
-
1
&&
(
<
span
className=
"absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] text-sm text-white mix-blend-lighten z-[1]"
>
{
item
.
progress
}
%
</
span
>
)
}
</>
)
}
{
item
.
type
===
TransferMethod
.
remote_url
&&
item
.
progress
!==
100
&&
(
<
div
className=
{
`
absolute inset-0 flex items-center justify-center rounded-lg z-[1] border
${item.progress === -1 ? 'bg-[#FEF0C7] border-[#DC6803]' : 'bg-black/[0.16] border-transparent'}
`
}
>
{
item
.
progress
>
-
1
&&
(
<
Loading02
className=
'animate-spin w-5 h-5 text-white'
/>
)
}
{
item
.
progress
===
-
1
&&
(
<
TooltipPlus
popupContent=
{
t
(
'common.imageUploader.pasteImageLinkInvalid'
)
}
>
<
AlertTriangle
className=
'w-4 h-4 text-[#DC6803]'
/>
</
TooltipPlus
>
)
}
</
div
>
)
${
item.progress === -1
? 'bg-[#FEF0C7] border-[#DC6803]'
: 'bg-black/[0.16] border-transparent'
}
<
img
className=
'w-16 h-16 rounded-lg object-cover cursor-pointer border-[0.5px] border-black/5'
alt=
''
onLoad=
{
()
=>
handleImageLinkLoadSuccess
(
item
)
}
onError=
{
()
=>
handleImageLinkLoadError
(
item
)
}
src=
{
item
.
type
===
TransferMethod
.
remote_url
?
item
.
url
:
item
.
base64Url
}
onClick=
{
()
=>
item
.
progress
===
100
&&
setImagePreviewUrl
((
item
.
type
===
TransferMethod
.
remote_url
?
item
.
url
:
item
.
base64Url
)
as
string
)
}
/>
{
!
readonly
&&
(
<
div
className=
{
`
absolute z-10 -top-[9px] -right-[9px] items-center justify-center w-[18px] h-[18px]
bg-white hover:bg-gray-50 border-[0.5px] border-black/[0.02] rounded-2xl shadow-lg
cursor-pointer
${item.progress === -1 ? 'flex' : 'hidden group-hover:flex'}
`
}
onClick=
{
()
=>
onRemove
&&
onRemove
(
item
.
_id
)
}
`
}
>
{
item
.
progress
>
-
1
&&
(
<
Loading02
className=
"animate-spin w-5 h-5 text-white"
/>
)
}
{
item
.
progress
===
-
1
&&
(
<
TooltipPlus
popupContent=
{
t
(
'common.imageUploader.pasteImageLinkInvalid'
)
}
>
<
XClose
className=
'w-3 h-3 text-gray-500'
/>
</
div
>
<
AlertTriangle
className=
"w-4 h-4 text-[#DC6803]"
/>
</
TooltipPlus
>
)
}
</
div
>
)
}
<
img
className=
"w-16 h-16 rounded-lg object-cover cursor-pointer border-[0.5px] border-black/5"
alt=
{
item
.
file
?.
name
}
onLoad=
{
()
=>
handleImageLinkLoadSuccess
(
item
)
}
onError=
{
()
=>
handleImageLinkLoadError
(
item
)
}
src=
{
item
.
type
===
TransferMethod
.
remote_url
?
item
.
url
:
item
.
base64Url
}
onClick=
{
()
=>
item
.
progress
===
100
&&
setImagePreviewUrl
(
(
item
.
type
===
TransferMethod
.
remote_url
?
item
.
url
:
item
.
base64Url
)
as
string
,
)
}
</
div
>
))
}
{
imagePreviewUrl
&&
(
<
ImagePreview
url=
{
imagePreviewUrl
}
onCancel=
{
()
=>
setImagePreviewUrl
(
''
)
}
/>
)
}
{
!
readonly
&&
(
<
button
type=
"button"
className=
{
cn
(
'absolute z-10 -top-[9px] -right-[9px] items-center justify-center w-[18px] h-[18px]'
,
'bg-white hover:bg-gray-50 border-[0.5px] border-black/[0.02] rounded-2xl shadow-lg'
,
item
.
progress
===
-
1
?
'flex'
:
'hidden group-hover:flex'
,
)
}
onClick=
{
()
=>
onRemove
&&
onRemove
(
item
.
_id
)
}
>
<
XClose
className=
"w-3 h-3 text-gray-500"
/>
</
button
>
)
}
</
div
>
))
}
{
imagePreviewUrl
&&
(
<
ImagePreview
url=
{
imagePreviewUrl
}
onCancel=
{
()
=>
setImagePreviewUrl
(
''
)
}
/>
)
}
</
div
>
)
}
...
...
web/app/components/base/image-uploader/uploader.tsx
View file @
b75d8ca6
...
...
@@ -7,6 +7,7 @@ import { ALLOW_FILE_EXTENSIONS } from '@/types/app'
type
UploaderProps
=
{
children
:
(
hovering
:
boolean
)
=>
JSX
.
Element
onUpload
:
(
imageFile
:
ImageFile
)
=>
void
closePopover
?:
()
=>
void
limit
?:
number
disabled
?:
boolean
}
...
...
@@ -14,11 +15,16 @@ type UploaderProps = {
const
Uploader
:
FC
<
UploaderProps
>
=
({
children
,
onUpload
,
closePopover
,
limit
,
disabled
,
})
=>
{
const
[
hovering
,
setHovering
]
=
useState
(
false
)
const
{
handleLocalFileUpload
}
=
useLocalFileUploader
({
limit
,
onUpload
,
disabled
})
const
{
handleLocalFileUpload
}
=
useLocalFileUploader
({
limit
,
onUpload
,
disabled
,
})
const
handleChange
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
file
=
e
.
target
.
files
?.[
0
]
...
...
@@ -27,6 +33,7 @@ const Uploader: FC<UploaderProps> = ({
return
handleLocalFileUpload
(
file
)
closePopover
?.()
}
return
(
...
...
@@ -37,11 +44,8 @@ const Uploader: FC<UploaderProps> = ({
>
{
children
(
hovering
)
}
<
input
className=
{
`
absolute block inset-0 opacity-0 text-[0] w-full
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
`
}
onClick=
{
e
=>
(
e
.
target
as
HTMLInputElement
).
value
=
''
}
className=
'absolute block inset-0 opacity-0 text-[0] w-full disabled:cursor-not-allowed cursor-pointer'
onClick=
{
e
=>
((
e
.
target
as
HTMLInputElement
).
value
=
''
)
}
type=
'file'
accept=
{
ALLOW_FILE_EXTENSIONS
.
map
(
ext
=>
`.${ext}`
).
join
(
','
)
}
onChange=
{
handleChange
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment