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
f607a334
Commit
f607a334
authored
Feb 23, 2024
by
JzoNg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
create from DSL
parent
117b8411
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
277 additions
and
3 deletions
+277
-3
NewAppCard.tsx
web/app/(commonLayout)/apps/NewAppCard.tsx
+16
-3
index.tsx
web/app/components/app/create-from-dsl-modal/index.tsx
+198
-0
upload-cloud-01.svg
...base/icons/assets/vender/line/general/upload-cloud-01.svg
+4
-0
UploadCloud01.json
...nts/base/icons/src/vender/line/general/UploadCloud01.json
+42
-0
UploadCloud01.tsx
...ents/base/icons/src/vender/line/general/UploadCloud01.tsx
+16
-0
index.ts
...pp/components/base/icons/src/vender/line/general/index.ts
+1
-0
No files found.
web/app/(commonLayout)/apps/NewAppCard.tsx
View file @
f607a334
...
...
@@ -3,6 +3,7 @@
import
{
forwardRef
,
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
NewAppDialog
from
'./NewAppDialog'
import
CreateFromDSLModal
from
'@/app/components/app/create-from-dsl-modal'
import
{
useProviderContext
}
from
'@/context/provider-context'
import
{
Plus
}
from
'@/app/components/base/icons/src/vender/line/general'
import
{
ArrowUpRight
}
from
'@/app/components/base/icons/src/vender/line/arrows'
...
...
@@ -17,13 +18,13 @@ const CreateAppCard = forwardRef<HTMLAnchorElement, CreateAppCardProps>(({ onSuc
const
{
onPlanInfoChanged
}
=
useProviderContext
()
const
[
showNewAppDialog
,
setShowNewAppDialog
]
=
useState
(
false
)
const
[
showCreateFromDSLModal
,
setShowCreateFromDSLModal
]
=
useState
(
false
)
return
(
<
a
ref=
{
ref
}
onClick=
{
()
=>
setShowNewAppDialog
(
true
)
}
className=
'relative col-span-1 flex flex-col justify-between min-h-[160px] bg-gray-200 rounded-xl cursor-pointer duration-200 ease-in-out hover:bg-gray-50 hover:shadow-lg transition-colors'
>
<
div
className=
'grow rounded-t-xl group hover:bg-white'
>
<
div
className=
'grow rounded-t-xl group hover:bg-white'
onClick=
{
()
=>
setShowNewAppDialog
(
true
)
}
>
<
div
className=
'flex pt-4 px-4 pb-3 h-[66px] items-center gap-3 grow-0 shrink-0'
>
<
span
className=
'w-10 h-10 p-3 bg-gray-100 rounded-lg border border-gray-200 group-hover:bg-primary-50 group-hover:border-primary-100'
>
<
Plus
className=
'w-4 h-4 text-gray-500 group-hover:text-primary-600'
/>
...
...
@@ -33,10 +34,22 @@ const CreateAppCard = forwardRef<HTMLAnchorElement, CreateAppCardProps>(({ onSuc
</
div
>
</
div
>
</
div
>
<
div
className=
'flex items-center px-4 py-3 border-t-[0.5px] border-black/[.05] rounded-b-xl text-xs leading-[18px] text-gray-500 hover:bg-white hover:text-primary-600'
>
<
div
className=
'flex items-center px-4 py-3 border-t-[0.5px] border-black/[.05] rounded-b-xl text-xs leading-[18px] text-gray-500 hover:bg-white hover:text-primary-600'
onClick=
{
()
=>
setShowCreateFromDSLModal
(
true
)
}
>
{
t
(
'app.createFromConfigFile'
)
}
<
ArrowUpRight
className=
'ml-1 w-3 h-3'
/>
</
div
>
<
CreateFromDSLModal
show=
{
showCreateFromDSLModal
}
onClose=
{
()
=>
setShowCreateFromDSLModal
(
false
)
}
onSuccess=
{
()
=>
{
onPlanInfoChanged
()
if
(
onSuccess
)
onSuccess
()
}
}
/>
<
NewAppDialog
show=
{
showNewAppDialog
}
onSuccess=
{
()
=>
{
onPlanInfoChanged
()
...
...
web/app/components/app/create-from-dsl-modal/index.tsx
0 → 100644
View file @
f607a334
'use client'
import
type
{
MouseEventHandler
}
from
'react'
import
{
useCallback
,
useEffect
,
useRef
,
useState
}
from
'react'
// import useSWR from 'swr'
import
cn
from
'classnames'
import
{
useRouter
}
from
'next/navigation'
import
{
useContext
}
from
'use-context-selector'
import
{
useTranslation
}
from
'react-i18next'
import
Button
from
'@/app/components/base/button'
// import Dialog from '@/app/components/base/dialog'
import
Modal
from
'@/app/components/base/modal'
// import Input from '@/app/components/base/input'
// import type { AppMode } from '@/types/app'
import
{
ToastContext
}
from
'@/app/components/base/toast'
// import { createApp, fetchAppTemplates } from '@/service/apps'
import
{
useAppContext
}
from
'@/context/app-context'
import
{
useProviderContext
}
from
'@/context/provider-context'
import
AppsFull
from
'@/app/components/billing/apps-full-in-dialog'
import
{
Trash03
,
UploadCloud01
,
XClose
}
from
'@/app/components/base/icons/src/vender/line/general'
type
CreateFromDSLModalProps
=
{
show
:
boolean
onSuccess
?:
()
=>
void
onClose
:
()
=>
void
}
const
CreateFromDSLModal
=
({
show
,
onSuccess
,
onClose
}:
CreateFromDSLModalProps
)
=>
{
const
router
=
useRouter
()
const
{
t
}
=
useTranslation
()
const
{
notify
}
=
useContext
(
ToastContext
)
const
[
currentFile
,
setDSLFile
]
=
useState
<
File
|
null
>
()
const
[
dragging
,
setDragging
]
=
useState
(
false
)
const
dropRef
=
useRef
<
HTMLDivElement
>
(
null
)
const
dragRef
=
useRef
<
HTMLDivElement
>
(
null
)
const
fileUploader
=
useRef
<
HTMLInputElement
>
(
null
)
const
handleDragEnter
=
(
e
:
DragEvent
)
=>
{
e
.
preventDefault
()
e
.
stopPropagation
()
e
.
target
!==
dragRef
.
current
&&
setDragging
(
true
)
}
const
handleDragOver
=
(
e
:
DragEvent
)
=>
{
e
.
preventDefault
()
e
.
stopPropagation
()
}
const
handleDragLeave
=
(
e
:
DragEvent
)
=>
{
e
.
preventDefault
()
e
.
stopPropagation
()
e
.
target
===
dragRef
.
current
&&
setDragging
(
false
)
}
const
handleDrop
=
useCallback
((
e
:
DragEvent
)
=>
{
e
.
preventDefault
()
e
.
stopPropagation
()
setDragging
(
false
)
if
(
!
e
.
dataTransfer
)
return
const
files
=
[...
e
.
dataTransfer
.
files
]
as
File
[]
setDSLFile
(
files
[
0
])
},
[
setDSLFile
])
const
selectHandle
=
()
=>
{
if
(
fileUploader
.
current
)
fileUploader
.
current
.
click
()
}
const
fileChangeHandle
=
(
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
files
=
[...(
e
.
target
.
files
??
[])]
as
File
[]
console
.
log
(
files
[
0
])
setDSLFile
(
files
[
0
])
}
const
removeFile
=
()
=>
{
if
(
fileUploader
.
current
)
fileUploader
.
current
.
value
=
''
setDSLFile
(
null
)
}
// utils
// const getFileType = (currentFile: File) => {
// if (!currentFile)
// return ''
// const arr = currentFile.name.split('.')
// return arr[arr.length - 1]
// }
const
getFileSize
=
(
size
:
number
)
=>
{
if
(
size
/
1024
<
10
)
return
`
${(
size
/
1024
).
toFixed
(
2
)}
KB`
return
`
${(
size
/
1024
/
1024
).
toFixed
(
2
)}
MB`
}
useEffect
(()
=>
{
dropRef
.
current
?.
addEventListener
(
'dragenter'
,
handleDragEnter
)
dropRef
.
current
?.
addEventListener
(
'dragover'
,
handleDragOver
)
dropRef
.
current
?.
addEventListener
(
'dragleave'
,
handleDragLeave
)
dropRef
.
current
?.
addEventListener
(
'drop'
,
handleDrop
)
return
()
=>
{
dropRef
.
current
?.
removeEventListener
(
'dragenter'
,
handleDragEnter
)
dropRef
.
current
?.
removeEventListener
(
'dragover'
,
handleDragOver
)
dropRef
.
current
?.
removeEventListener
(
'dragleave'
,
handleDragLeave
)
dropRef
.
current
?.
removeEventListener
(
'drop'
,
handleDrop
)
}
},
[
handleDrop
])
const
{
isCurrentWorkspaceManager
}
=
useAppContext
()
const
{
plan
,
enableBilling
}
=
useProviderContext
()
const
isAppsFull
=
(
enableBilling
&&
plan
.
usage
.
buildApps
>=
plan
.
total
.
buildApps
)
const
isCreatingRef
=
useRef
(
false
)
// TODO
const
onCreate
:
MouseEventHandler
=
async
()
=>
{
if
(
isCreatingRef
.
current
)
return
isCreatingRef
.
current
=
true
try
{
// const app = await createApp()
if
(
onSuccess
)
onSuccess
()
if
(
onClose
)
onClose
()
notify
({
type
:
'success'
,
message
:
t
(
'app.newApp.appCreated'
)
})
// router.push(`/app/${app.id}/${isCurrentWorkspaceManager ? 'configuration' : 'overview'}`)
}
catch
(
e
)
{
notify
({
type
:
'error'
,
message
:
t
(
'app.newApp.appCreateFailed'
)
})
}
isCreatingRef
.
current
=
false
}
return
(
<
Modal
wrapperClassName=
'z-20'
className=
'px-8 py-6 max-w-[520px] w-[520px] rounded-xl'
isShow=
{
show
}
onClose=
{
()
=>
{}
}
>
<
div
className=
'relative pb-2 text-xl font-medium leading-[30px] text-gray-900'
>
Create from DSL file
</
div
>
<
div
className=
'absolute right-4 top-4 p-2 cursor-pointer'
onClick=
{
onClose
}
>
<
XClose
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
<
div
className=
'pt-5 pb-7'
>
<
input
ref=
{
fileUploader
}
id=
"fileUploader"
style=
{
{
display
:
'none'
}
}
type=
"file"
onChange=
{
fileChangeHandle
}
/>
<
div
ref=
{
dropRef
}
>
{
!
currentFile
&&
(
<
div
className=
{
cn
(
'relative flex justify-center items-center h-20 bg-gray-50 rounded-xl border border-dashed border-gray-200'
,
dragging
&&
'!bg-[#F5F8FF] !border-[#B2CCFF]'
,
)
}
>
<
div
className=
'flex justify-center items-center'
>
<
UploadCloud01
className=
'w-6 h-6 mr-2'
/>
<
span
className=
'text-sm text-gray-500'
>
{
t
(
'datasetCreation.stepOne.uploader.button'
)
}
<
label
className=
'pl-1 cursor-pointer text-[#155eef]'
onClick=
{
selectHandle
}
>
{
t
(
'datasetCreation.stepOne.uploader.browse'
)
}
</
label
>
</
span
>
</
div
>
</
div
>
)
}
{
dragging
&&
<
div
ref=
{
dragRef
}
className=
'absolute top-0 left-0 w-full h-full'
/>
}
</
div
>
{
currentFile
&&
(
<
div
className=
'group relative flex justify-center items-center justify-between h-20 pl-[64px] pr-6 bg-gray-50 rounded-xl border border-gray-100 cursor-pointer hover:bg-[#f5f8ff] hover:border-[#d1e0ff]'
>
{
/* TODO type icon */
}
<
div
className=
'absolute top-[24px] left-[24px] w-8 h-8'
/>
<
div
className=
'grow truncate'
>
<
div
className=
'truncate text-sm leading-[20px] font-medium text-gray-800'
>
{
currentFile
.
name
}
</
div
>
<
div
className=
'text-xs leading-[18px] text-gray-500'
>
{
getFileSize
(
currentFile
.
size
)
}
</
div
>
</
div
>
<
div
className=
'shrink-0 hidden group-hover:flex'
>
<
Trash03
className=
'w-4 h-4 text-gray-500 cursor-pointer'
onClick=
{
(
e
)
=>
{
e
.
stopPropagation
()
removeFile
()
}
}
/>
</
div
>
</
div
>
)
}
</
div
>
{
isAppsFull
&&
<
AppsFull
loc=
'app-create'
/>
}
<
div
className=
'pt-6 flex justify-end'
>
<
Button
className=
'mr-2 text-gray-700 text-sm font-medium'
onClick=
{
onClose
}
>
{
t
(
'app.newApp.Cancel'
)
}
</
Button
>
<
Button
className=
'text-sm font-medium'
disabled=
{
isAppsFull
||
!
currentFile
}
type=
"primary"
onClick=
{
onCreate
}
>
{
t
(
'app.newApp.Create'
)
}
</
Button
>
</
div
>
</
Modal
>
)
}
export
default
CreateFromDSLModal
web/app/components/base/icons/assets/vender/line/general/upload-cloud-01.svg
0 → 100644
View file @
f607a334
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
opacity=
"0.4"
d=
"M4 16.2422C2.79401 15.435 2 14.0602 2 12.5C2 10.1564 3.79151 8.23129 6.07974 8.01937C6.54781 5.17213 9.02024 3 12 3C14.9798 3 17.4522 5.17213 17.9203 8.01937C20.2085 8.23129 22 10.1564 22 12.5C22 14.0602 21.206 15.435 20 16.2422"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
<path
d=
"M8 16L12 12M12 12L16 16M12 12L12 21"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/icons/src/vender/line/general/UploadCloud01.json
0 → 100644
View file @
f607a334
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"24"
,
"height"
:
"24"
,
"viewBox"
:
"0 0 24 24"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"opacity"
:
"0.4"
,
"d"
:
"M4 16.2422C2.79401 15.435 2 14.0602 2 12.5C2 10.1564 3.79151 8.23129 6.07974 8.01937C6.54781 5.17213 9.02024 3 12 3C14.9798 3 17.4522 5.17213 17.9203 8.01937C20.2085 8.23129 22 10.1564 22 12.5C22 14.0602 21.206 15.435 20 16.2422"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
},
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M8 16L12 12M12 12L16 16M12 12L12 21"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
},
"name"
:
"UploadCloud01"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/general/UploadCloud01.tsx
0 → 100644
View file @
f607a334
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./UploadCloud01.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
Icon
.
displayName
=
'UploadCloud01'
export
default
Icon
web/app/components/base/icons/src/vender/line/general/index.ts
View file @
f607a334
...
...
@@ -28,5 +28,6 @@ export { default as Settings04 } from './Settings04'
export
{
default
as
Target04
}
from
'./Target04'
export
{
default
as
Trash03
}
from
'./Trash03'
export
{
default
as
Upload03
}
from
'./Upload03'
export
{
default
as
UploadCloud01
}
from
'./UploadCloud01'
export
{
default
as
XClose
}
from
'./XClose'
export
{
default
as
X
}
from
'./X'
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