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
4edaa95c
Commit
4edaa95c
authored
Mar 06, 2024
by
JzoNg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
app menu
parent
067e6b5a
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
367 additions
and
58 deletions
+367
-58
layout.tsx
...p/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx
+1
-14
AppCard.tsx
web/app/(commonLayout)/apps/AppCard.tsx
+13
-7
Apps.tsx
web/app/(commonLayout)/apps/Apps.tsx
+1
-2
app-info.tsx
web/app/components/app-sidebar/app-info.tsx
+301
-0
index.tsx
web/app/components/app-sidebar/index.tsx
+14
-8
index.tsx
web/app/components/explore/app-list/index.tsx
+3
-0
index.tsx
web/app/components/explore/create-app-modal/index.tsx
+19
-18
app.ts
web/i18n/en-US/app.ts
+4
-3
app.ts
web/i18n/zh-Hans/app.ts
+4
-3
explore.ts
web/models/explore.ts
+2
-2
apps.ts
web/service/apps.ts
+5
-1
No files found.
web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx
View file @
4edaa95c
...
...
@@ -31,19 +31,6 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
const
{
appDetail
,
setAppDetail
}
=
useStore
()
const
{
data
:
response
}
=
useSWR
(
detailParams
,
fetchAppDetail
)
const
appModeName
=
(()
=>
{
if
(
response
?.
mode
===
'chat'
||
response
?.
mode
===
'advanced-chat'
)
return
t
(
'app.types.chatbot'
)
if
(
response
?.
mode
===
'agent-chat'
)
return
t
(
'app.types.agent'
)
if
(
response
?.
mode
===
'completion'
)
return
t
(
'app.types.completion'
)
return
t
(
'app.types.workflow'
)
})()
const
navigation
=
useMemo
(()
=>
{
const
navs
=
[
...(
isCurrentWorkspaceManager
...
...
@@ -97,7 +84,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
return
(
<
div
className=
{
cn
(
s
.
app
,
'flex'
,
'overflow-hidden'
)
}
>
<
AppSideBar
title=
{
response
.
name
}
icon=
{
response
.
icon
}
icon_background=
{
response
.
icon_background
}
desc=
{
appModeNam
e
}
navigation=
{
navigation
}
/>
<
AppSideBar
title=
{
response
.
name
}
icon=
{
response
.
icon
}
icon_background=
{
response
.
icon_background
}
desc=
{
response
.
mod
e
}
navigation=
{
navigation
}
/>
<
div
className=
"bg-white grow overflow-hidden"
>
{
children
}
</
div
>
...
...
web/app/(commonLayout)/apps/AppCard.tsx
View file @
4edaa95c
...
...
@@ -122,6 +122,8 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
message
:
t
(
'app.newApp.appCreated'
),
})
localStorage
.
setItem
(
NEED_REFRESH_APP_LIST_KEY
,
'1'
)
mutateApps
()
onPlanInfoChanged
()
getRedirection
(
isCurrentWorkspaceManager
,
newApp
,
push
)
}
catch
(
e
)
{
...
...
@@ -175,13 +177,17 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
<
span
className=
{
s
.
actionName
}
>
{
t
(
'common.operation.settings'
)
}
</
span
>
</
button
>
<
Divider
className=
"!my-1"
/>
<
button
className=
{
s
.
actionItem
}
onClick=
{
onClickDuplicate
}
disabled=
{
detailState
.
loading
}
>
<
span
className=
{
s
.
actionName
}
>
{
t
(
'app.duplicate'
)
}
</
span
>
</
button
>
<
button
className=
{
s
.
actionItem
}
onClick=
{
onClickExport
}
disabled=
{
detailState
.
loading
}
>
<
span
className=
{
s
.
actionName
}
>
{
t
(
'app.export'
)
}
</
span
>
</
button
>
<
Divider
className=
"!my-1"
/>
{
app
.
mode
!==
'completion'
&&
(
<>
<
button
className=
{
s
.
actionItem
}
onClick=
{
onClickDuplicate
}
disabled=
{
detailState
.
loading
}
>
<
span
className=
{
s
.
actionName
}
>
{
t
(
'app.duplicate'
)
}
</
span
>
</
button
>
<
button
className=
{
s
.
actionItem
}
onClick=
{
onClickExport
}
disabled=
{
detailState
.
loading
}
>
<
span
className=
{
s
.
actionName
}
>
{
t
(
'app.export'
)
}
</
span
>
</
button
>
<
Divider
className=
"!my-1"
/>
</>
)
}
<
div
className=
{
cn
(
s
.
actionItem
,
s
.
deleteActionItem
,
'group'
)
}
onClick=
{
onClickDelete
}
...
...
web/app/(commonLayout)/apps/Apps.tsx
View file @
4edaa95c
...
...
@@ -49,11 +49,10 @@ const Apps = () => {
)
const
anchorRef
=
useRef
<
HTMLDivElement
>
(
null
)
// #TODO# query key ???
const
options
=
[
{
value
:
'all'
,
text
:
t
(
'app.types.all'
)
},
{
value
:
'chat'
,
text
:
t
(
'app.types.chatbot'
)
},
{
value
:
'agent
-chat
'
,
text
:
t
(
'app.types.agent'
)
},
{
value
:
'agent'
,
text
:
t
(
'app.types.agent'
)
},
{
value
:
'workflow'
,
text
:
t
(
'app.types.workflow'
)
},
]
...
...
web/app/components/app-sidebar/app-info.tsx
0 → 100644
View file @
4edaa95c
This diff is collapsed.
Click to expand it.
web/app/components/app-sidebar/index.tsx
View file @
4edaa95c
...
...
@@ -2,6 +2,7 @@ import React, { useCallback, useState } from 'react'
import
NavLink
from
'./navLink'
import
type
{
NavIcon
}
from
'./navLink'
import
AppBasic
from
'./basic'
import
AppInfo
from
'./app-info'
import
useBreakpoints
,
{
MediaType
}
from
'@/hooks/use-breakpoints'
import
{
AlignLeft01
,
...
...
@@ -62,14 +63,19 @@ const AppDetailNav = ({ title, desc, icon, icon_background, navigation, extraInf
${expand ? 'p-4' : 'p-2'}
`
}
>
<
AppBasic
mode=
{
modeState
}
iconType=
{
iconType
}
icon=
{
icon
}
icon_background=
{
icon_background
}
name=
{
title
}
type=
{
desc
}
/>
{
iconType
===
'app'
&&
(
<
AppInfo
expand=
{
expand
}
/>
)
}
{
iconType
!==
'app'
&&
(
<
AppBasic
mode=
{
modeState
}
iconType=
{
iconType
}
icon=
{
icon
}
icon_background=
{
icon_background
}
name=
{
title
}
type=
{
desc
}
/>
)
}
</
div
>
<
nav
className=
{
`
...
...
web/app/components/explore/app-list/index.tsx
View file @
4edaa95c
...
...
@@ -149,7 +149,10 @@ const Apps = ({
</
div
>
{
isShowCreateModal
&&
(
<
CreateAppModal
appIcon=
{
currApp
?.
app
.
icon
||
''
}
appIconBackground=
{
currApp
?.
app
.
icon_background
||
''
}
appName=
{
currApp
?.
app
.
name
||
''
}
appDescription=
{
currApp
?.
app
.
description
||
''
}
show=
{
isShowCreateModal
}
onConfirm=
{
onCreate
}
onHide=
{
()
=>
setIsShowCreateModal
(
false
)
}
...
...
web/app/components/explore/create-app-modal/index.tsx
View file @
4edaa95c
...
...
@@ -11,9 +11,12 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import
{
XClose
}
from
'@/app/components/base/icons/src/vender/line/general'
export
type
CreateAppModalProps
=
{
appName
:
string
appDescription
?:
string
show
:
boolean
isEditModal
?:
boolean
appName
:
string
appDescription
:
string
appIcon
:
string
appIconBackground
:
string
onConfirm
:
(
info
:
{
name
:
string
icon
:
string
...
...
@@ -24,9 +27,12 @@ export type CreateAppModalProps = {
}
const
CreateAppModal
=
({
show
=
false
,
isEditModal
=
false
,
appIcon
,
appIconBackground
,
appName
,
appDescription
,
show
=
false
,
onConfirm
,
onHide
,
}:
CreateAppModalProps
)
=>
{
...
...
@@ -34,7 +40,7 @@ const CreateAppModal = ({
const
[
name
,
setName
]
=
React
.
useState
(
appName
)
const
[
showEmojiPicker
,
setShowEmojiPicker
]
=
useState
(
false
)
const
[
emoji
,
setEmoji
]
=
useState
({
icon
:
'🤖'
,
icon_background
:
'#FFEAD5'
})
const
[
emoji
,
setEmoji
]
=
useState
({
icon
:
appIcon
,
icon_background
:
appIconBackground
})
const
[
description
,
setDescription
]
=
useState
(
appDescription
||
''
)
const
{
plan
,
enableBilling
}
=
useProviderContext
()
...
...
@@ -64,7 +70,12 @@ const CreateAppModal = ({
<
div
className=
'absolute right-4 top-4 p-2 cursor-pointer'
onClick=
{
onHide
}
>
<
XClose
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
<
div
className=
'mb-9 font-semibold text-xl leading-[30px] text-gray-900'
>
{
t
(
'explore.appCustomize.title'
,
{
name
:
appName
})
}
</
div
>
{
isEditModal
&&
(
<
div
className=
'mb-9 font-semibold text-xl leading-[30px] text-gray-900'
>
{
t
(
'app.editAppTitle'
)
}
</
div
>
)
}
{
!
isEditModal
&&
(
<
div
className=
'mb-9 font-semibold text-xl leading-[30px] text-gray-900'
>
{
t
(
'explore.appCustomize.title'
,
{
name
:
appName
})
}
</
div
>
)
}
<
div
className=
'mb-9'
>
{
/* icon & name */
}
<
div
className=
'pt-2'
>
...
...
@@ -78,16 +89,6 @@ const CreateAppModal = ({
className=
'grow h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg border border-transparent outline-none appearance-none caret-primary-600 placeholder:text-gray-400 hover:bg-gray-50 hover:border hover:border-gray-300 focus:bg-gray-50 focus:border focus:border-gray-300 focus:shadow-xs'
/>
</
div
>
{
showEmojiPicker
&&
<
EmojiPicker
onSelect=
{
(
icon
,
icon_background
)
=>
{
setEmoji
({
icon
,
icon_background
})
setShowEmojiPicker
(
false
)
}
}
onClose=
{
()
=>
{
setEmoji
({
icon
:
'🤖'
,
icon_background
:
'#FFEAD5'
})
setShowEmojiPicker
(
false
)
}
}
/>
}
</
div
>
{
/* description */
}
<
div
className=
'pt-2'
>
...
...
@@ -99,10 +100,10 @@ const CreateAppModal = ({
onChange=
{
e
=>
setDescription
(
e
.
target
.
value
)
}
/>
</
div
>
{
isAppsFull
&&
<
AppsFull
loc=
'app-explore-create'
/>
}
{
!
isEditModal
&&
isAppsFull
&&
<
AppsFull
loc=
'app-explore-create'
/>
}
</
div
>
<
div
className=
'flex flex-row-reverse'
>
<
Button
disabled=
{
isAppsFull
}
className=
'w-24 ml-2'
type=
'primary'
onClick=
{
submit
}
>
{
t
(
'common.operation.creat
e'
)
}
</
Button
>
<
Button
disabled=
{
!
isEditModal
&&
isAppsFull
}
className=
'w-24 ml-2'
type=
'primary'
onClick=
{
submit
}
>
{
!
isEditModal
?
t
(
'common.operation.create'
)
:
t
(
'common.operation.sav
e'
)
}
</
Button
>
<
Button
className=
'w-24'
onClick=
{
onHide
}
>
{
t
(
'common.operation.cancel'
)
}
</
Button
>
</
div
>
</
Modal
>
...
...
@@ -112,7 +113,7 @@ const CreateAppModal = ({
setShowEmojiPicker
(
false
)
}
}
onClose=
{
()
=>
{
setEmoji
({
icon
:
'🤖'
,
icon_background
:
'#FFEAD5'
})
setEmoji
({
icon
:
appIcon
,
icon_background
:
appIconBackground
})
setShowEmojiPicker
(
false
)
}
}
/>
}
...
...
web/i18n/en-US/app.ts
View file @
4edaa95c
...
...
@@ -58,9 +58,10 @@ const translation = {
appCreated
:
'App created'
,
appCreateFailed
:
'Failed to create app'
,
},
editApp
:
{
startToEdit
:
'Edit App'
,
},
editApp
:
'Edit Info'
,
editAppTitle
:
'Edit App Info'
,
editDone
:
'App info updated'
,
editFailed
:
'Failed to update app info'
,
emoji
:
{
ok
:
'OK'
,
cancel
:
'Cancel'
,
...
...
web/i18n/zh-Hans/app.ts
View file @
4edaa95c
...
...
@@ -57,9 +57,10 @@ const translation = {
appCreated
:
'应用已创建'
,
appCreateFailed
:
'应用创建失败'
,
},
editApp
:
{
startToEdit
:
'编辑应用'
,
},
editApp
:
'编辑信息'
,
editAppTitle
:
'编辑应用信息'
,
editDone
:
'应用信息已更新'
,
editFailed
:
'更新应用信息失败'
,
emoji
:
{
ok
:
'确认'
,
cancel
:
'取消'
,
...
...
web/models/explore.ts
View file @
4edaa95c
import
type
{
AppMode
}
from
'@/types/app'
export
type
AppBasicInfo
=
{
id
:
string
name
:
string
mode
:
AppMode
icon
:
string
icon_background
:
string
is_agent
:
boolean
name
:
string
description
:
string
}
export
type
AppCategory
=
'Writing'
|
'Translate'
|
'HR'
|
'Programming'
|
'Assistant'
...
...
web/service/apps.ts
View file @
4edaa95c
import
type
{
Fetcher
}
from
'swr'
import
{
del
,
get
,
post
}
from
'./base'
import
{
del
,
get
,
post
,
put
}
from
'./base'
import
type
{
ApikeysListResponse
,
AppDailyConversationsResponse
,
AppDailyEndUsersResponse
,
AppDetailResponse
,
AppListResponse
,
AppStatisticsResponse
,
AppTemplatesResponse
,
AppTokenCostsResponse
,
AppVoicesListResponse
,
CreateApiKeyResponse
,
GenerationIntroductionResponse
,
UpdateAppModelConfigResponse
,
UpdateAppSiteCodeResponse
,
UpdateOpenAIKeyResponse
,
ValidateOpenAIKeyResponse
}
from
'@/models/app'
import
type
{
CommonResponse
}
from
'@/models/common'
import
type
{
AppMode
,
ModelConfig
}
from
'@/types/app'
...
...
@@ -20,6 +20,10 @@ export const createApp: Fetcher<AppDetailResponse, { name: string; icon: string;
return
post
<
AppDetailResponse
>
(
'apps'
,
{
body
:
{
name
,
icon
,
icon_background
,
mode
,
description
,
model_config
:
config
}
})
}
export
const
updateAppInfo
:
Fetcher
<
AppDetailResponse
,
{
appID
:
string
;
name
:
string
;
icon
:
string
;
icon_background
:
string
;
description
:
string
}
>
=
({
appID
,
name
,
icon
,
icon_background
,
description
})
=>
{
return
put
<
AppDetailResponse
>
(
`apps/
${
appID
}
`
,
{
body
:
{
name
,
icon
,
icon_background
,
description
}
})
}
export
const
copyApp
:
Fetcher
<
AppDetailResponse
,
{
appID
:
string
;
name
:
string
;
icon
:
string
;
icon_background
:
string
;
mode
:
AppMode
;
description
?:
string
}
>
=
({
appID
,
name
,
icon
,
icon_background
,
mode
,
description
})
=>
{
return
post
<
AppDetailResponse
>
(
`apps/
${
appID
}
/copy`
,
{
body
:
{
name
,
icon
,
icon_background
,
mode
,
description
}
})
}
...
...
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