mirror of
https://github.com/langgenius/dify.git
synced 2025-12-21 06:54:41 +00:00
Compare commits
454 Commits
fix/fail-b
...
chore/infr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76a5f66334 | ||
|
|
30dd37a52d | ||
|
|
52cfe80dcd | ||
|
|
13d3430948 | ||
|
|
4dbc4b66f6 | ||
|
|
6bcb8bcda1 | ||
|
|
79a2a4f0aa | ||
|
|
e5d43eb51d | ||
|
|
db055b49ff | ||
|
|
ea7a6e2129 | ||
|
|
cd3d1a8d33 | ||
|
|
52f3236740 | ||
|
|
6653b6e072 | ||
|
|
dcfadbd315 | ||
|
|
fe78f42176 | ||
|
|
acb8e8077d | ||
|
|
1e4f3bc459 | ||
|
|
d062519f60 | ||
|
|
688a461a5b | ||
|
|
5e579322ae | ||
|
|
95e2e038e1 | ||
|
|
3e9c3d0bb7 | ||
|
|
fec3bb4469 | ||
|
|
dbd5e8d7a0 | ||
|
|
d4a09805a3 | ||
|
|
7e1d9894fb | ||
|
|
eeb1ed486a | ||
|
|
802dc15d87 | ||
|
|
a8a8a5513c | ||
|
|
470e72c820 | ||
|
|
7ddb568804 | ||
|
|
fef2326d6e | ||
|
|
a7575e6a41 | ||
|
|
087a106fbe | ||
|
|
2649f9f56f | ||
|
|
beebba0340 | ||
|
|
4e27d82d68 | ||
|
|
cdeaf3f70b | ||
|
|
24839bb3e1 | ||
|
|
1650dbfbb1 | ||
|
|
fd11817044 | ||
|
|
6642fc6012 | ||
|
|
2710242982 | ||
|
|
1de84fdda0 | ||
|
|
3befbc1d68 | ||
|
|
fd5028da5b | ||
|
|
c044cc5160 | ||
|
|
62c413aca5 | ||
|
|
6887b501b8 | ||
|
|
f93bf131ab | ||
|
|
ef1f429437 | ||
|
|
c966bf1474 | ||
|
|
899df30bf6 | ||
|
|
8d8d3e3f2f | ||
|
|
5f0fa38ec6 | ||
|
|
cc1fe70d34 | ||
|
|
15ee1e11be | ||
|
|
c8b4a76530 | ||
|
|
6ee4eba86b | ||
|
|
357d2e8be8 | ||
|
|
b5accda3fe | ||
|
|
de4752a16b | ||
|
|
60427f1adf | ||
|
|
1a313c868d | ||
|
|
0b32b1988f | ||
|
|
e56c051d97 | ||
|
|
0a6b4d01d7 | ||
|
|
98b139c680 | ||
|
|
f0a3c14adb | ||
|
|
51947575c2 | ||
|
|
cb8debee3e | ||
|
|
d56079a549 | ||
|
|
c08b451874 | ||
|
|
ac336ff359 | ||
|
|
4cbd511cd7 | ||
|
|
c03adcb154 | ||
|
|
04dade2f9b | ||
|
|
f69220ca96 | ||
|
|
a5e24ff6d3 | ||
|
|
71976f9192 | ||
|
|
39ec6c8025 | ||
|
|
e370045ac4 | ||
|
|
28edbbac0b | ||
|
|
782abcecd8 | ||
|
|
4deb02fc2c | ||
|
|
f967180dc2 | ||
|
|
cead13cbc3 | ||
|
|
078c151065 | ||
|
|
17babca362 | ||
|
|
8efed8858c | ||
|
|
0d411a0b5a | ||
|
|
13f0c01f93 | ||
|
|
3c014f3ae5 | ||
|
|
e4c4490175 | ||
|
|
94a62f6b4e | ||
|
|
d76af08784 | ||
|
|
f748d6c7c4 | ||
|
|
76e24d91c0 | ||
|
|
5ce4ddc0ed | ||
|
|
491d641485 | ||
|
|
172c5f19cc | ||
|
|
b7d168ac59 | ||
|
|
fb309462ad | ||
|
|
b56d2b739b | ||
|
|
fb7b2c8ff3 | ||
|
|
c3440a27fb | ||
|
|
ff3d3f71fb | ||
|
|
9685b9a302 | ||
|
|
07c7b7b886 | ||
|
|
8d75abc976 | ||
|
|
aa6452b3bf | ||
|
|
3799d40937 | ||
|
|
d2ff8a2381 | ||
|
|
5f51a19de2 | ||
|
|
71e0bfcbd8 | ||
|
|
d815c74fc5 | ||
|
|
107e44c8fb | ||
|
|
adf7eea7fe | ||
|
|
6e73ad2fc6 | ||
|
|
06412b37d3 | ||
|
|
63665a5ff1 | ||
|
|
05a43e3e80 | ||
|
|
83fdb42520 | ||
|
|
cbf405beea | ||
|
|
af2aede783 | ||
|
|
e359ace633 | ||
|
|
a5555f90c6 | ||
|
|
78664c8903 | ||
|
|
45070535bd | ||
|
|
048e8cf0d1 | ||
|
|
598d208e54 | ||
|
|
8102cee8df | ||
|
|
c9eb9c14d7 | ||
|
|
e77cd87842 | ||
|
|
ac5e3caebc | ||
|
|
23066a9ba8 | ||
|
|
0249f15609 | ||
|
|
2f523dd29f | ||
|
|
b34d815883 | ||
|
|
51cc63d9ce | ||
|
|
430af95b53 | ||
|
|
0164d1410a | ||
|
|
cbc5045b7a | ||
|
|
b980c07af8 | ||
|
|
e231cf2c48 | ||
|
|
80d8e47e42 | ||
|
|
fee4dd7d7a | ||
|
|
00cf5f3841 | ||
|
|
9ee0c7a694 | ||
|
|
6ee7ca1890 | ||
|
|
f589397f25 | ||
|
|
ee080dddf9 | ||
|
|
ee6841648c | ||
|
|
5a57dad93c | ||
|
|
4199998c7e | ||
|
|
39656f7f84 | ||
|
|
bf39e314d8 | ||
|
|
8cc4c109d0 | ||
|
|
a1cdca02e3 | ||
|
|
1b21d7513d | ||
|
|
d5c708c62b | ||
|
|
342d4060ff | ||
|
|
05232d36f0 | ||
|
|
636dde94c7 | ||
|
|
75fe785d88 | ||
|
|
a61da6cf95 | ||
|
|
93c3699128 | ||
|
|
6357450a7a | ||
|
|
6339706c68 | ||
|
|
65a4cb769b | ||
|
|
63206a7967 | ||
|
|
9a6f120e5c | ||
|
|
dedc1b0c3a | ||
|
|
46bb246ecc | ||
|
|
3c628d0c26 | ||
|
|
c2983ecbb7 | ||
|
|
527c1cf608 | ||
|
|
93786f516c | ||
|
|
a175d6b2d7 | ||
|
|
296fd82bbf | ||
|
|
4ccd571364 | ||
|
|
ae72514cb4 | ||
|
|
16b49ac436 | ||
|
|
c377eb8c28 | ||
|
|
337eff2b79 | ||
|
|
b7ac287fec | ||
|
|
c1a85b0208 | ||
|
|
01efdee1dd | ||
|
|
0af9c4fd9d | ||
|
|
ee38bd8817 | ||
|
|
86291c13e4 | ||
|
|
7679a57f18 | ||
|
|
dcf19549cb | ||
|
|
574a6c1ded | ||
|
|
c34877aecf | ||
|
|
632b2bac2a | ||
|
|
77a62f33b3 | ||
|
|
ad899844a1 | ||
|
|
b10d6051ba | ||
|
|
fb44cd87e7 | ||
|
|
89af726985 | ||
|
|
6f2d5ff099 | ||
|
|
687455ca31 | ||
|
|
8c5928da2f | ||
|
|
772009115d | ||
|
|
0452dfd029 | ||
|
|
eead6abe85 | ||
|
|
5c6d919a4a | ||
|
|
e39eddab03 | ||
|
|
db726e02a0 | ||
|
|
e4b8220bc2 | ||
|
|
08cfcb453c | ||
|
|
992e1eedde | ||
|
|
c2ce8e638e | ||
|
|
ba3659a792 | ||
|
|
965fabd578 | ||
|
|
accbbae755 | ||
|
|
49bd1a7a49 | ||
|
|
5ff9cee326 | ||
|
|
200f9af5d8 | ||
|
|
1443fd6739 | ||
|
|
e63ae36665 | ||
|
|
cfa7c89dfe | ||
|
|
a6835ac64d | ||
|
|
a700b49461 | ||
|
|
22df86fe8a | ||
|
|
24734009b9 | ||
|
|
959d060a44 | ||
|
|
4492295683 | ||
|
|
88fac0d898 | ||
|
|
8b30099672 | ||
|
|
97a3727962 | ||
|
|
2cb640de15 | ||
|
|
fb4ee813c7 | ||
|
|
6300e506fb | ||
|
|
a0543ab8fb | ||
|
|
634cb6233e | ||
|
|
db68ae4a73 | ||
|
|
d25e79e794 | ||
|
|
183b943803 | ||
|
|
5828abcd62 | ||
|
|
56bd0dedfe | ||
|
|
f6136427a4 | ||
|
|
21fd58caf9 | ||
|
|
9a69d03fbe | ||
|
|
1d2118fc5d | ||
|
|
bc0724b499 | ||
|
|
5cdbfe2f41 | ||
|
|
5fd82084f9 | ||
|
|
f0637ba332 | ||
|
|
115c9486c3 | ||
|
|
8b5231b7ee | ||
|
|
38cae29757 | ||
|
|
7a2b2a04c9 | ||
|
|
fe677cc5f9 | ||
|
|
28c9ec3f4f | ||
|
|
6baa98f166 | ||
|
|
e9d69f020a | ||
|
|
3c89d45a2d | ||
|
|
baab81714e | ||
|
|
507bb3549a | ||
|
|
2d1e5fb4e0 | ||
|
|
b9198639e2 | ||
|
|
43c7739b88 | ||
|
|
f65d577f54 | ||
|
|
b88145096f | ||
|
|
33219e850a | ||
|
|
3040d538f7 | ||
|
|
4e1af81e11 | ||
|
|
56e19fd8f5 | ||
|
|
d330d31ee5 | ||
|
|
0858108423 | ||
|
|
2cd976846a | ||
|
|
5d2c88ef59 | ||
|
|
fe3cde973e | ||
|
|
794f495ef2 | ||
|
|
0dda682033 | ||
|
|
01d8d10f1c | ||
|
|
c711c5e36e | ||
|
|
1e27557865 | ||
|
|
2d9632d8b9 | ||
|
|
7e42de1e7b | ||
|
|
bd674d27be | ||
|
|
5735761920 | ||
|
|
405b704f02 | ||
|
|
f38abaaa6a | ||
|
|
c8a5fee622 | ||
|
|
fe1c0ac602 | ||
|
|
e79c3e4531 | ||
|
|
3ea3df7189 | ||
|
|
b01e7d778e | ||
|
|
7c45859594 | ||
|
|
aa9fd76072 | ||
|
|
e7d947379f | ||
|
|
8cd386f2c1 | ||
|
|
987e1b9ced | ||
|
|
81a77d0623 | ||
|
|
ac1f93e3d5 | ||
|
|
0d5c0b4fe4 | ||
|
|
d1c480a7d8 | ||
|
|
007b561e32 | ||
|
|
c100f24f7d | ||
|
|
d92cb994a9 | ||
|
|
413326905e | ||
|
|
5605ff9803 | ||
|
|
84b7a4607a | ||
|
|
10cc4e758c | ||
|
|
8070be9b76 | ||
|
|
f1f1baae9c | ||
|
|
f20c9ef763 | ||
|
|
f798add31c | ||
|
|
8c2dbe876f | ||
|
|
6fd0a55b00 | ||
|
|
bb58f5c6e5 | ||
|
|
18edeb8e0a | ||
|
|
459cb9dd72 | ||
|
|
f9e2c738b0 | ||
|
|
739e15f88b | ||
|
|
5bf86ff66d | ||
|
|
c657378d06 | ||
|
|
685e8cdc7d | ||
|
|
d36dece0af | ||
|
|
5f61aa85db | ||
|
|
e5837b88e0 | ||
|
|
ffdc6f5c60 | ||
|
|
99c8f364ae | ||
|
|
a0a1243c90 | ||
|
|
b916b4064a | ||
|
|
dea2962a79 | ||
|
|
1450e5d5cb | ||
|
|
43a2d4335b | ||
|
|
11270a7ef2 | ||
|
|
53e1b45d40 | ||
|
|
bedbd658fe | ||
|
|
7b62b5578e | ||
|
|
ccbe42eb5f | ||
|
|
45f8651a3d | ||
|
|
7754431a34 | ||
|
|
fa7215cfea | ||
|
|
678c89891a | ||
|
|
beebcbd962 | ||
|
|
8495ed3348 | ||
|
|
31cca4a849 | ||
|
|
43ffccc8fd | ||
|
|
a81293cf5a | ||
|
|
276701e1b7 | ||
|
|
8e1cf3233c | ||
|
|
dd551e6ca8 | ||
|
|
ae1eeb9b2a | ||
|
|
b58f8dd7b4 | ||
|
|
118fa66567 | ||
|
|
699d41deec | ||
|
|
dd0462c1dc | ||
|
|
a470e0e60e | ||
|
|
2622159763 | ||
|
|
dfaf639790 | ||
|
|
ae96f66a08 | ||
|
|
570b7d18ac | ||
|
|
a9c21ef929 | ||
|
|
e27a03ae15 | ||
|
|
56b7853afe | ||
|
|
e12f4009d3 | ||
|
|
6dfc31a542 | ||
|
|
c9f80b46a1 | ||
|
|
0025b27200 | ||
|
|
0dd05d7b6d | ||
|
|
7c83d5ce76 | ||
|
|
a57f60a6e0 | ||
|
|
2f36692bf9 | ||
|
|
bcdb407be8 | ||
|
|
d4e007f9db | ||
|
|
8563155d1b | ||
|
|
8236373498 | ||
|
|
196bfeaaf4 | ||
|
|
957ab093c9 | ||
|
|
e9e5c8806a | ||
|
|
c8bc3892b3 | ||
|
|
735e57b73a | ||
|
|
635a53ea38 | ||
|
|
7b76b1ff82 | ||
|
|
47c8824be6 | ||
|
|
1c3213184e | ||
|
|
d9cced8419 | ||
|
|
c3359a9291 | ||
|
|
2da32e49d0 | ||
|
|
1837692a66 | ||
|
|
5dcd25a613 | ||
|
|
507fff0259 | ||
|
|
0ad9dbea63 | ||
|
|
4c28034224 | ||
|
|
1d575524c3 | ||
|
|
dc255cc154 | ||
|
|
ea497f828f | ||
|
|
153dc5b3f3 | ||
|
|
a91951b374 | ||
|
|
68c10a1672 | ||
|
|
592f85f7a9 | ||
|
|
cda9f6ec6b | ||
|
|
64706c709c | ||
|
|
9722e6bcb1 | ||
|
|
1907d791e1 | ||
|
|
fb3a701c86 | ||
|
|
947bfdc807 | ||
|
|
7a3e756020 | ||
|
|
435e71eb60 | ||
|
|
91cb80f795 | ||
|
|
3c1d32e3ac | ||
|
|
eef79a5196 | ||
|
|
2223dfb266 | ||
|
|
9693b5ad0c | ||
|
|
d4bf575d0a | ||
|
|
73ce692e24 | ||
|
|
661392eaef | ||
|
|
c472ea6c67 | ||
|
|
4eaba3049a | ||
|
|
00d1c45518 | ||
|
|
87c746f6bb | ||
|
|
70c001436e | ||
|
|
cf73374c1b | ||
|
|
b0d53c0ac4 | ||
|
|
9c7bcd5abc | ||
|
|
b7c5abc5dd | ||
|
|
de01ca8d55 | ||
|
|
60e75dc748 | ||
|
|
279dee485d | ||
|
|
db8bf2a85e | ||
|
|
46ba16fe90 | ||
|
|
886a160115 | ||
|
|
cf4e9f317e | ||
|
|
1fa3b9cfd8 | ||
|
|
50a5cfe56a | ||
|
|
ece82b87bf | ||
|
|
12ea085e22 | ||
|
|
41ed2e0cc2 | ||
|
|
113ff27d07 | ||
|
|
ec711d094d | ||
|
|
a073de44e9 | ||
|
|
6ce02b07d3 | ||
|
|
f47712beae | ||
|
|
4a8d3c54ca | ||
|
|
c8b0160ea9 | ||
|
|
531ffaec4f | ||
|
|
c28998a6f0 | ||
|
|
4b4741f7ed | ||
|
|
25b8a512bf | ||
|
|
02d26818ad | ||
|
|
31e8b134d1 | ||
|
|
d52476c1c9 | ||
|
|
f29b44acd8 | ||
|
|
ed7fcc5f7d | ||
|
|
c6f34f5c17 | ||
|
|
e1db77eec2 | ||
|
|
563d81277b | ||
|
|
364df36ac4 |
@@ -3,7 +3,7 @@ import Main from '@/app/components/app/log-annotation'
|
||||
import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type'
|
||||
|
||||
export type IProps = {
|
||||
params: { appId: string }
|
||||
params: Promise<{ appId: string }>
|
||||
}
|
||||
|
||||
const Logs = async () => {
|
||||
|
||||
@@ -3,12 +3,13 @@ import type { Locale } from '@/i18n'
|
||||
import DevelopMain from '@/app/components/develop'
|
||||
|
||||
export type IDevelopProps = {
|
||||
params: { locale: Locale; appId: string }
|
||||
params: Promise<{ locale: Locale; appId: string }>
|
||||
}
|
||||
|
||||
const Develop = async ({
|
||||
params: { appId },
|
||||
params,
|
||||
}: IDevelopProps) => {
|
||||
const appId = (await params).appId
|
||||
return <DevelopMain appId={appId} />
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { useUnmount } from 'ahooks'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import {
|
||||
RiDashboard2Fill,
|
||||
RiDashboard2Line,
|
||||
RiFileList3Fill,
|
||||
RiFileList3Line,
|
||||
RiTerminalBoxFill,
|
||||
RiTerminalBoxLine,
|
||||
RiTerminalWindowFill,
|
||||
RiTerminalWindowLine,
|
||||
} from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useContextSelector } from 'use-context-selector'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useStore } from '@/app/components/app/store'
|
||||
import AppSideBar from '@/app/components/app-sidebar'
|
||||
import type { NavIcon } from '@/app/components/app-sidebar/navLink'
|
||||
import { fetchAppDetail, fetchAppSSO } from '@/service/apps'
|
||||
import AppContext, { useAppContext } from '@/context/app-context'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import type { App } from '@/types/app'
|
||||
|
||||
export type IAppDetailLayoutProps = {
|
||||
children: React.ReactNode
|
||||
appId: string
|
||||
}
|
||||
|
||||
const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
appId, // get appId in path
|
||||
} = props
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
const { isCurrentWorkspaceEditor, isLoadingCurrentWorkspace } = useAppContext()
|
||||
const { appDetail, setAppDetail, setAppSiderbarExpand } = useStore(useShallow(state => ({
|
||||
appDetail: state.appDetail,
|
||||
setAppDetail: state.setAppDetail,
|
||||
setAppSiderbarExpand: state.setAppSiderbarExpand,
|
||||
})))
|
||||
const [isLoadingAppDetail, setIsLoadingAppDetail] = useState(false)
|
||||
const [appDetailRes, setAppDetailRes] = useState<App | null>(null)
|
||||
const [navigation, setNavigation] = useState<Array<{
|
||||
name: string
|
||||
href: string
|
||||
icon: NavIcon
|
||||
selectedIcon: NavIcon
|
||||
}>>([])
|
||||
const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures)
|
||||
|
||||
const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => {
|
||||
const navs = [
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: t('common.appMenus.promptEng'),
|
||||
href: `/app/${appId}/${(mode === 'workflow' || mode === 'advanced-chat') ? 'workflow' : 'configuration'}`,
|
||||
icon: RiTerminalWindowLine,
|
||||
selectedIcon: RiTerminalWindowFill,
|
||||
}]
|
||||
: []
|
||||
),
|
||||
{
|
||||
name: t('common.appMenus.apiAccess'),
|
||||
href: `/app/${appId}/develop`,
|
||||
icon: RiTerminalBoxLine,
|
||||
selectedIcon: RiTerminalBoxFill,
|
||||
},
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: mode !== 'workflow'
|
||||
? t('common.appMenus.logAndAnn')
|
||||
: t('common.appMenus.logs'),
|
||||
href: `/app/${appId}/logs`,
|
||||
icon: RiFileList3Line,
|
||||
selectedIcon: RiFileList3Fill,
|
||||
}]
|
||||
: []
|
||||
),
|
||||
{
|
||||
name: t('common.appMenus.overview'),
|
||||
href: `/app/${appId}/overview`,
|
||||
icon: RiDashboard2Line,
|
||||
selectedIcon: RiDashboard2Fill,
|
||||
},
|
||||
]
|
||||
return navs
|
||||
}, [t])
|
||||
|
||||
useEffect(() => {
|
||||
if (appDetail) {
|
||||
document.title = `${(appDetail.name || 'App')} - Dify`
|
||||
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
|
||||
const mode = isMobile ? 'collapse' : 'expand'
|
||||
setAppSiderbarExpand(isMobile ? mode : localeMode)
|
||||
// TODO: consider screen size and mode
|
||||
// if ((appDetail.mode === 'advanced-chat' || appDetail.mode === 'workflow') && (pathname).endsWith('workflow'))
|
||||
// setAppSiderbarExpand('collapse')
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appDetail, isMobile])
|
||||
|
||||
useEffect(() => {
|
||||
setAppDetail()
|
||||
setIsLoadingAppDetail(true)
|
||||
fetchAppDetail({ url: '/apps', id: appId }).then((res) => {
|
||||
setAppDetailRes(res)
|
||||
}).catch((e: any) => {
|
||||
if (e.status === 404)
|
||||
router.replace('/apps')
|
||||
}).finally(() => {
|
||||
setIsLoadingAppDetail(false)
|
||||
})
|
||||
}, [appId, router, setAppDetail])
|
||||
|
||||
useEffect(() => {
|
||||
if (!appDetailRes || isLoadingCurrentWorkspace || isLoadingAppDetail)
|
||||
return
|
||||
const res = appDetailRes
|
||||
// redirection
|
||||
const canIEditApp = isCurrentWorkspaceEditor
|
||||
if (!canIEditApp && (pathname.endsWith('configuration') || pathname.endsWith('workflow') || pathname.endsWith('logs'))) {
|
||||
router.replace(`/app/${appId}/overview`)
|
||||
return
|
||||
}
|
||||
if ((res.mode === 'workflow' || res.mode === 'advanced-chat') && (pathname).endsWith('configuration')) {
|
||||
router.replace(`/app/${appId}/workflow`)
|
||||
}
|
||||
else if ((res.mode !== 'workflow' && res.mode !== 'advanced-chat') && (pathname).endsWith('workflow')) {
|
||||
router.replace(`/app/${appId}/configuration`)
|
||||
}
|
||||
else {
|
||||
setAppDetail({ ...res, enable_sso: false })
|
||||
setNavigation(getNavigations(appId, isCurrentWorkspaceEditor, res.mode))
|
||||
if (systemFeatures.enable_web_sso_switch_component && canIEditApp) {
|
||||
fetchAppSSO({ appId }).then((ssoRes) => {
|
||||
setAppDetail({ ...res, enable_sso: ssoRes.enabled })
|
||||
})
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appDetailRes, appId, getNavigations, isCurrentWorkspaceEditor, isLoadingAppDetail, isLoadingCurrentWorkspace, router, setAppDetail, systemFeatures.enable_web_sso_switch_component])
|
||||
|
||||
useUnmount(() => {
|
||||
setAppDetail()
|
||||
})
|
||||
|
||||
if (!appDetail) {
|
||||
return (
|
||||
<div className='bg-background-body flex h-full items-center justify-center'>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn(s.app, 'relative flex', 'overflow-hidden')}>
|
||||
{appDetail && (
|
||||
<AppSideBar title={appDetail.name} icon={appDetail.icon} icon_background={appDetail.icon_background as string} desc={appDetail.mode} navigation={navigation} />
|
||||
)}
|
||||
<div className="bg-components-panel-bg grow overflow-hidden">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(AppDetailLayout)
|
||||
@@ -1,176 +1,14 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { useUnmount } from 'ahooks'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import {
|
||||
RiDashboard2Fill,
|
||||
RiDashboard2Line,
|
||||
RiFileList3Fill,
|
||||
RiFileList3Line,
|
||||
RiTerminalBoxFill,
|
||||
RiTerminalBoxLine,
|
||||
RiTerminalWindowFill,
|
||||
RiTerminalWindowLine,
|
||||
} from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useContextSelector } from 'use-context-selector'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useStore } from '@/app/components/app/store'
|
||||
import AppSideBar from '@/app/components/app-sidebar'
|
||||
import type { NavIcon } from '@/app/components/app-sidebar/navLink'
|
||||
import { fetchAppDetail, fetchAppSSO } from '@/service/apps'
|
||||
import AppContext, { useAppContext } from '@/context/app-context'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import type { App } from '@/types/app'
|
||||
import Main from './layout-main'
|
||||
|
||||
export type IAppDetailLayoutProps = {
|
||||
const AppDetailLayout = async (props: {
|
||||
children: React.ReactNode
|
||||
params: { appId: string }
|
||||
}
|
||||
|
||||
const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
params: Promise<{ appId: string }>
|
||||
}) => {
|
||||
const {
|
||||
children,
|
||||
params: { appId }, // get appId in path
|
||||
params,
|
||||
} = props
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
const { isCurrentWorkspaceEditor, isLoadingCurrentWorkspace } = useAppContext()
|
||||
const { appDetail, setAppDetail, setAppSiderbarExpand } = useStore(useShallow(state => ({
|
||||
appDetail: state.appDetail,
|
||||
setAppDetail: state.setAppDetail,
|
||||
setAppSiderbarExpand: state.setAppSiderbarExpand,
|
||||
})))
|
||||
const [isLoadingAppDetail, setIsLoadingAppDetail] = useState(false)
|
||||
const [appDetailRes, setAppDetailRes] = useState<App | null>(null)
|
||||
const [navigation, setNavigation] = useState<Array<{
|
||||
name: string
|
||||
href: string
|
||||
icon: NavIcon
|
||||
selectedIcon: NavIcon
|
||||
}>>([])
|
||||
const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures)
|
||||
|
||||
const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => {
|
||||
const navs = [
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: t('common.appMenus.promptEng'),
|
||||
href: `/app/${appId}/${(mode === 'workflow' || mode === 'advanced-chat') ? 'workflow' : 'configuration'}`,
|
||||
icon: RiTerminalWindowLine,
|
||||
selectedIcon: RiTerminalWindowFill,
|
||||
}]
|
||||
: []
|
||||
),
|
||||
{
|
||||
name: t('common.appMenus.apiAccess'),
|
||||
href: `/app/${appId}/develop`,
|
||||
icon: RiTerminalBoxLine,
|
||||
selectedIcon: RiTerminalBoxFill,
|
||||
},
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: mode !== 'workflow'
|
||||
? t('common.appMenus.logAndAnn')
|
||||
: t('common.appMenus.logs'),
|
||||
href: `/app/${appId}/logs`,
|
||||
icon: RiFileList3Line,
|
||||
selectedIcon: RiFileList3Fill,
|
||||
}]
|
||||
: []
|
||||
),
|
||||
{
|
||||
name: t('common.appMenus.overview'),
|
||||
href: `/app/${appId}/overview`,
|
||||
icon: RiDashboard2Line,
|
||||
selectedIcon: RiDashboard2Fill,
|
||||
},
|
||||
]
|
||||
return navs
|
||||
}, [t])
|
||||
|
||||
useEffect(() => {
|
||||
if (appDetail) {
|
||||
document.title = `${(appDetail.name || 'App')} - Dify`
|
||||
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
|
||||
const mode = isMobile ? 'collapse' : 'expand'
|
||||
setAppSiderbarExpand(isMobile ? mode : localeMode)
|
||||
// TODO: consider screen size and mode
|
||||
// if ((appDetail.mode === 'advanced-chat' || appDetail.mode === 'workflow') && (pathname).endsWith('workflow'))
|
||||
// setAppSiderbarExpand('collapse')
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appDetail, isMobile])
|
||||
|
||||
useEffect(() => {
|
||||
setAppDetail()
|
||||
setIsLoadingAppDetail(true)
|
||||
fetchAppDetail({ url: '/apps', id: appId }).then((res) => {
|
||||
setAppDetailRes(res)
|
||||
}).catch((e: any) => {
|
||||
if (e.status === 404)
|
||||
router.replace('/apps')
|
||||
}).finally(() => {
|
||||
setIsLoadingAppDetail(false)
|
||||
})
|
||||
}, [appId, router, setAppDetail])
|
||||
|
||||
useEffect(() => {
|
||||
if (!appDetailRes || isLoadingCurrentWorkspace || isLoadingAppDetail)
|
||||
return
|
||||
const res = appDetailRes
|
||||
// redirection
|
||||
const canIEditApp = isCurrentWorkspaceEditor
|
||||
if (!canIEditApp && (pathname.endsWith('configuration') || pathname.endsWith('workflow') || pathname.endsWith('logs'))) {
|
||||
router.replace(`/app/${appId}/overview`)
|
||||
return
|
||||
}
|
||||
if ((res.mode === 'workflow' || res.mode === 'advanced-chat') && (pathname).endsWith('configuration')) {
|
||||
router.replace(`/app/${appId}/workflow`)
|
||||
}
|
||||
else if ((res.mode !== 'workflow' && res.mode !== 'advanced-chat') && (pathname).endsWith('workflow')) {
|
||||
router.replace(`/app/${appId}/configuration`)
|
||||
}
|
||||
else {
|
||||
setAppDetail({ ...res, enable_sso: false })
|
||||
setNavigation(getNavigations(appId, isCurrentWorkspaceEditor, res.mode))
|
||||
if (systemFeatures.enable_web_sso_switch_component && canIEditApp) {
|
||||
fetchAppSSO({ appId }).then((ssoRes) => {
|
||||
setAppDetail({ ...res, enable_sso: ssoRes.enabled })
|
||||
})
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appDetailRes, appId, getNavigations, isCurrentWorkspaceEditor, isLoadingAppDetail, isLoadingCurrentWorkspace, router, setAppDetail, systemFeatures.enable_web_sso_switch_component])
|
||||
|
||||
useUnmount(() => {
|
||||
setAppDetail()
|
||||
})
|
||||
|
||||
if (!appDetail) {
|
||||
return (
|
||||
<div className='flex h-full items-center justify-center bg-background-body'>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn(s.app, 'flex relative', 'overflow-hidden')}>
|
||||
{appDetail && (
|
||||
<AppSideBar title={appDetail.name} icon={appDetail.icon} icon_background={appDetail.icon_background as string} desc={appDetail.mode} navigation={navigation} />
|
||||
)}
|
||||
<div className="bg-components-panel-bg grow overflow-hidden">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
return <Main appId={(await params).appId}>{children}</Main>
|
||||
}
|
||||
export default React.memo(AppDetailLayout)
|
||||
export default AppDetailLayout
|
||||
|
||||
@@ -122,7 +122,7 @@ const CardView: FC<ICardViewProps> = ({ appId, isInPanel, className }) => {
|
||||
return <Loading />
|
||||
|
||||
return (
|
||||
<div className={className || 'grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'}>
|
||||
<div className={className || 'mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'}>
|
||||
<AppCard
|
||||
appInfo={appDetail}
|
||||
cardType="webapp"
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function ChartView({ appId }: IChartViewProps) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='flex flex-row items-center mt-8 mb-4 system-xl-semibold text-text-primary'>
|
||||
<div className='system-xl-semibold text-text-primary mb-4 mt-8 flex flex-row items-center'>
|
||||
<span className='mr-3'>{t('appOverview.analysis.title')}</span>
|
||||
<SimpleSelect
|
||||
items={Object.entries(TIME_PERIOD_MAPPING).map(([k, v]) => ({ value: k, name: t(`appLog.filter.period.${v.name}`) }))}
|
||||
@@ -61,13 +61,13 @@ export default function ChartView({ appId }: IChartViewProps) {
|
||||
/>
|
||||
</div>
|
||||
{!isWorkflow && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
<ConversationsChart period={period} id={appId} />
|
||||
<EndUsersChart period={period} id={appId} />
|
||||
</div>
|
||||
)}
|
||||
{!isWorkflow && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
{isChatApp
|
||||
? (
|
||||
<AvgSessionInteractions period={period} id={appId} />
|
||||
@@ -79,24 +79,24 @@ export default function ChartView({ appId }: IChartViewProps) {
|
||||
</div>
|
||||
)}
|
||||
{!isWorkflow && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
<UserSatisfactionRate period={period} id={appId} />
|
||||
<CostChart period={period} id={appId} />
|
||||
</div>
|
||||
)}
|
||||
{!isWorkflow && isChatApp && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
<MessagesChart period={period} id={appId} />
|
||||
</div>
|
||||
)}
|
||||
{isWorkflow && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
<WorkflowMessagesChart period={period} id={appId} />
|
||||
<WorkflowDailyTerminalsChart period={period} id={appId} />
|
||||
</div>
|
||||
)}
|
||||
{isWorkflow && (
|
||||
<div className='grid gap-6 grid-cols-1 xl:grid-cols-2 w-full mb-6'>
|
||||
<div className='mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'>
|
||||
<WorkflowCostChart period={period} id={appId} />
|
||||
<AvgUserInteractions period={period} id={appId} />
|
||||
</div>
|
||||
|
||||
@@ -5,14 +5,15 @@ import TracingPanel from './tracing/panel'
|
||||
import ApikeyInfoPanel from '@/app/components/app/overview/apikey-info-panel'
|
||||
|
||||
export type IDevelopProps = {
|
||||
params: { appId: string }
|
||||
params: Promise<{ appId: string }>
|
||||
}
|
||||
|
||||
const Overview = async ({
|
||||
params: { appId },
|
||||
params,
|
||||
}: IDevelopProps) => {
|
||||
const { appId } = await params
|
||||
return (
|
||||
<div className="h-full px-4 sm:px-12 py-6 overflow-scroll bg-chatbot-bg">
|
||||
<div className="bg-chatbot-bg h-full overflow-scroll px-4 py-6 sm:px-12">
|
||||
<ApikeyInfoPanel />
|
||||
<TracingPanel />
|
||||
<CardView appId={appId} />
|
||||
|
||||
@@ -58,8 +58,8 @@ const ConfigBtn: FC<Props> = ({
|
||||
}}
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={handleTrigger}>
|
||||
<div className={cn(className, 'p-1 rounded-md')}>
|
||||
<RiEqualizer2Line className='w-4 h-4 text-text-tertiary' />
|
||||
<div className={cn(className, 'rounded-md p-1')}>
|
||||
<RiEqualizer2Line className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[11]'>
|
||||
|
||||
@@ -162,15 +162,15 @@ const ConfigPopup: FC<PopupProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='w-[420px] p-4 rounded-2xl bg-components-panel-bg border-[0.5px] border-components-panel-border shadow-xl'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<div className='bg-components-panel-bg border-components-panel-border w-[420px] rounded-2xl border-[0.5px] p-4 shadow-xl'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center'>
|
||||
<TracingIcon size='md' className='mr-2' />
|
||||
<div className='text-text-primary title-2xl-semibold'>{t(`${I18N_PREFIX}.tracing`)}</div>
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
<Indicator color={enabled ? 'green' : 'gray'} />
|
||||
<div className={cn('ml-1 system-xs-semibold-uppercase text-text-tertiary', enabled && 'text-util-colors-green-green-600')}>
|
||||
<div className={cn('system-xs-semibold-uppercase text-text-tertiary ml-1', enabled && 'text-util-colors-green-green-600')}>
|
||||
{t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)}
|
||||
</div>
|
||||
{!readOnly && (
|
||||
@@ -189,7 +189,7 @@ const ConfigPopup: FC<PopupProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-2 system-xs-regular text-text-tertiary'>
|
||||
<div className='system-xs-regular text-text-tertiary mt-2'>
|
||||
{t(`${I18N_PREFIX}.tracingDescription`)}
|
||||
</div>
|
||||
<Divider className='my-3' />
|
||||
@@ -211,7 +211,7 @@ const ConfigPopup: FC<PopupProps> = ({
|
||||
<div className='mt-2 space-y-2'>
|
||||
{configuredProviderPanel()}
|
||||
</div>
|
||||
<div className='mt-3 system-xs-medium-uppercase text-text-tertiary'>{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`)}</div>
|
||||
<div className='system-xs-medium-uppercase text-text-tertiary mt-3'>{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`)}</div>
|
||||
<div className='mt-2 space-y-2'>
|
||||
{moreProviderPanel()}
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,7 @@ const Field: FC<Props> = ({
|
||||
return (
|
||||
<div className={cn(className)}>
|
||||
<div className='flex py-[7px]'>
|
||||
<div className={cn(labelClassName, 'flex items-center h-[18px] text-[13px] font-medium text-text-primary')}>{label} </div>
|
||||
<div className={cn(labelClassName, 'text-text-primary flex h-[18px] items-center text-[13px] font-medium')}>{label} </div>
|
||||
{isRequired && <span className='ml-0.5 text-xs font-semibold text-[#D92D20]'>*</span>}
|
||||
</div>
|
||||
<Input
|
||||
|
||||
@@ -31,7 +31,7 @@ const Title = ({
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={cn('flex items-center system-xl-semibold text-text-primary', className)}>
|
||||
<div className={cn('system-xl-semibold text-text-primary flex items-center', className)}>
|
||||
{t('common.appMenus.overview')}
|
||||
</div>
|
||||
)
|
||||
@@ -80,9 +80,7 @@ const Panel: FC = () => {
|
||||
? LangsmithIcon
|
||||
: inUseTracingProvider === TracingProvider.langfuse
|
||||
? LangfuseIcon
|
||||
: inUseTracingProvider === TracingProvider.opik
|
||||
? OpikIcon
|
||||
: null
|
||||
: OpikIcon
|
||||
|
||||
const [langSmithConfig, setLangSmithConfig] = useState<LangSmithConfig | null>(null)
|
||||
const [langFuseConfig, setLangFuseConfig] = useState<LangFuseConfig | null>(null)
|
||||
@@ -143,7 +141,7 @@ const Panel: FC = () => {
|
||||
}, [setControlShowPopup])
|
||||
if (!isLoaded) {
|
||||
return (
|
||||
<div className='flex items-center justify-between mb-3'>
|
||||
<div className='mb-3 flex items-center justify-between'>
|
||||
<Title className='h-[41px]' />
|
||||
<div className='w-[200px]'>
|
||||
<Loading />
|
||||
@@ -153,11 +151,11 @@ const Panel: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('mb-3 flex justify-between items-center')}>
|
||||
<div className={cn('mb-3 flex items-center justify-between')}>
|
||||
<Title className='h-[41px]' />
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center p-2 rounded-xl bg-background-default-dodge border-t border-l-[0.5px] border-effects-highlight shadow-xs cursor-pointer hover:bg-background-default-lighter hover:border-effects-highlight-lightmode-off',
|
||||
'bg-background-default-dodge border-effects-highlight shadow-xs hover:bg-background-default-lighter hover:border-effects-highlight-lightmode-off flex cursor-pointer items-center rounded-xl border-l-[0.5px] border-t p-2',
|
||||
controlShowPopup && 'bg-background-default-lighter border-effects-highlight-lightmode-off',
|
||||
)}
|
||||
onClick={showPopup}
|
||||
@@ -165,7 +163,7 @@ const Panel: FC = () => {
|
||||
{!inUseTracingProvider && (
|
||||
<>
|
||||
<TracingIcon size='md' />
|
||||
<div className='mx-2 system-sm-semibold text-text-secondary'>{t(`${I18N_PREFIX}.title`)}</div>
|
||||
<div className='system-sm-semibold text-text-secondary mx-2'>{t(`${I18N_PREFIX}.title`)}</div>
|
||||
<div className='flex items-center' onClick={e => e.stopPropagation()}>
|
||||
<ConfigButton
|
||||
appId={appId}
|
||||
@@ -184,8 +182,8 @@ const Panel: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
<Divider type='vertical' className='h-3.5' />
|
||||
<div className='p-1 rounded-md'>
|
||||
<RiArrowDownDoubleLine className='w-4 h-4 text-text-tertiary' />
|
||||
<div className='rounded-md p-1'>
|
||||
<RiArrowDownDoubleLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -193,7 +191,7 @@ const Panel: FC = () => {
|
||||
<>
|
||||
<div className='ml-4 mr-1 flex items-center'>
|
||||
<Indicator color={enabled ? 'green' : 'gray'} />
|
||||
<div className='ml-1.5 system-xs-semibold-uppercase text-text-tertiary'>
|
||||
<div className='system-xs-semibold-uppercase text-text-tertiary ml-1.5'>
|
||||
{t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -219,8 +217,8 @@ const Panel: FC = () => {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div >
|
||||
</div >
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(Panel)
|
||||
|
||||
@@ -167,11 +167,11 @@ const ProviderConfigModal: FC<Props> = ({
|
||||
{!isShowRemoveConfirm
|
||||
? (
|
||||
<PortalToFollowElem open>
|
||||
<PortalToFollowElemContent className='w-full h-full z-[60]'>
|
||||
<div className='fixed inset-0 flex items-center justify-center bg-background-overlay'>
|
||||
<div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-components-panel-bg shadow-xl rounded-2xl overflow-y-auto'>
|
||||
<PortalToFollowElemContent className='z-[60] h-full w-full'>
|
||||
<div className='bg-background-overlay fixed inset-0 flex items-center justify-center'>
|
||||
<div className='bg-components-panel-bg mx-2 max-h-[calc(100vh-120px)] w-[640px] overflow-y-auto rounded-2xl shadow-xl'>
|
||||
<div className='px-8 pt-8'>
|
||||
<div className='flex justify-between items-center mb-4'>
|
||||
<div className='mb-4 flex items-center justify-between'>
|
||||
<div className='title-2xl-semibold text-text-primary'>{t(`${I18N_PREFIX}.title`)}{t(`app.tracing.${type}.title`)}</div>
|
||||
</div>
|
||||
|
||||
@@ -265,20 +265,20 @@ const ProviderConfigModal: FC<Props> = ({
|
||||
)}
|
||||
|
||||
</div>
|
||||
<div className='my-8 flex justify-between items-center h-8'>
|
||||
<div className='my-8 flex h-8 items-center justify-between'>
|
||||
<a
|
||||
className='flex items-center space-x-1 leading-[18px] text-xs font-normal text-[#155EEF]'
|
||||
className='flex items-center space-x-1 text-xs font-normal leading-[18px] text-[#155EEF]'
|
||||
target='_blank'
|
||||
href={docURL[type]}
|
||||
>
|
||||
<span>{t(`${I18N_PREFIX}.viewDocsLink`, { key: t(`app.tracing.${type}.title`) })}</span>
|
||||
<LinkExternal02 className='w-3 h-3' />
|
||||
<LinkExternal02 className='h-3 w-3' />
|
||||
</a>
|
||||
<div className='flex items-center'>
|
||||
{isEdit && (
|
||||
<>
|
||||
<Button
|
||||
className='h-9 text-sm font-medium text-text-secondary'
|
||||
className='text-text-secondary h-9 text-sm font-medium'
|
||||
onClick={showRemoveConfirm}
|
||||
>
|
||||
<span className='text-[#D92D20]'>{t('common.operation.remove')}</span>
|
||||
@@ -287,7 +287,7 @@ const ProviderConfigModal: FC<Props> = ({
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
className='mr-2 h-9 text-sm font-medium text-text-secondary'
|
||||
className='text-text-secondary mr-2 h-9 text-sm font-medium'
|
||||
onClick={onCancel}
|
||||
>
|
||||
{t('common.operation.cancel')}
|
||||
@@ -304,9 +304,9 @@ const ProviderConfigModal: FC<Props> = ({
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='border-t-[0.5px] border-divider-regular'>
|
||||
<div className='flex justify-center items-center py-3 bg-background-section-burn text-xs text-text-tertiary'>
|
||||
<Lock01 className='mr-1 w-3 h-3 text-text-tertiary' />
|
||||
<div className='border-divider-regular border-t-[0.5px]'>
|
||||
<div className='bg-background-section-burn text-text-tertiary flex items-center justify-center py-3 text-xs'>
|
||||
<Lock01 className='text-text-tertiary mr-1 h-3 w-3' />
|
||||
{t('common.modelProvider.encrypted.front')}
|
||||
<a
|
||||
className='text-primary-600 mx-1'
|
||||
|
||||
@@ -65,36 +65,36 @@ const ProviderPanel: FC<Props> = ({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'px-4 py-3 rounded-xl border-[1.5px] bg-background-section-burn',
|
||||
'bg-background-section-burn rounded-xl border-[1.5px] px-4 py-3',
|
||||
isChosen ? 'bg-background-section border-components-option-card-option-selected-border' : 'border-transparent',
|
||||
!isChosen && hasConfigured && !readOnly && 'cursor-pointer',
|
||||
)}
|
||||
onClick={handleChosen}
|
||||
>
|
||||
<div className={'flex justify-between items-center space-x-1'}>
|
||||
<div className={'flex items-center justify-between space-x-1'}>
|
||||
<div className='flex items-center'>
|
||||
<Icon className='h-6' />
|
||||
{isChosen && <div className='ml-1 flex items-center h-4 px-1 rounded-[4px] border border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary'>{t(`${I18N_PREFIX}.inUse`)}</div>}
|
||||
{isChosen && <div className='border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary ml-1 flex h-4 items-center rounded-[4px] border px-1'>{t(`${I18N_PREFIX}.inUse`)}</div>}
|
||||
</div>
|
||||
{!readOnly && (
|
||||
<div className={'flex justify-between items-center space-x-1'}>
|
||||
<div className={'flex items-center justify-between space-x-1'}>
|
||||
{hasConfigured && (
|
||||
<div className='flex px-2 items-center h-6 bg-components-button-secondary-bg rounded-md border-[0.5px] border-components-button-secondary-border shadow-xs cursor-pointer text-text-secondary space-x-1' onClick={viewBtnClick} >
|
||||
<View className='w-3 h-3' />
|
||||
<div className='bg-components-button-secondary-bg border-components-button-secondary-border shadow-xs text-text-secondary flex h-6 cursor-pointer items-center space-x-1 rounded-md border-[0.5px] px-2' onClick={viewBtnClick} >
|
||||
<View className='h-3 w-3' />
|
||||
<div className='text-xs font-medium'>{t(`${I18N_PREFIX}.view`)}</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className='flex px-2 items-center h-6 bg-components-button-secondary-bg rounded-md border-[0.5px] border-components-button-secondary-border shadow-xs cursor-pointer text-text-secondary space-x-1'
|
||||
className='bg-components-button-secondary-bg border-components-button-secondary-border shadow-xs text-text-secondary flex h-6 cursor-pointer items-center space-x-1 rounded-md border-[0.5px] px-2'
|
||||
onClick={handleConfigBtnClick}
|
||||
>
|
||||
<RiEqualizer2Line className='w-3 h-3' />
|
||||
<RiEqualizer2Line className='h-3 w-3' />
|
||||
<div className='text-xs font-medium'>{t(`${I18N_PREFIX}.config`)}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='mt-2 system-xs-regular text-text-tertiary'>
|
||||
<div className='system-xs-regular text-text-tertiary mt-2'>
|
||||
{t(`${I18N_PREFIX}.${type}.description`)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ const TracingIcon: FC<Props> = ({
|
||||
const sizeClass = sizeClassMap[size]
|
||||
return (
|
||||
<div className={cn(className, sizeClass, 'bg-primary-500 shadow-md')}>
|
||||
<Icon className='w-full h-full' />
|
||||
<Icon className='h-full w-full' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Workflow from '@/app/components/workflow'
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<div className='w-full h-full overflow-x-auto'>
|
||||
<div className='h-full w-full overflow-x-auto'>
|
||||
<Workflow />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -241,10 +241,10 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
<>
|
||||
<Divider className="!my-1" />
|
||||
<div
|
||||
className='h-9 py-2 px-3 mx-1 flex items-center hover:bg-gray-50 rounded-lg cursor-pointer'
|
||||
className='mx-1 flex h-9 cursor-pointer items-center rounded-lg px-3 py-2 hover:bg-gray-50'
|
||||
onClick={onClickSwitch}
|
||||
>
|
||||
<span className='text-gray-700 text-sm leading-5'>{t('app.switch')}</span>
|
||||
<span className='text-sm leading-5 text-gray-700'>{t('app.switch')}</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -277,9 +277,9 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
e.preventDefault()
|
||||
getRedirection(isCurrentWorkspaceEditor, app, push)
|
||||
}}
|
||||
className='relative h-[160px] group col-span-1 bg-components-card-bg border-[1px] border-solid border-components-card-border rounded-xl shadow-sm inline-flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg'
|
||||
className='bg-components-card-bg border-components-card-border group relative col-span-1 inline-flex h-[160px] cursor-pointer flex-col rounded-xl border-[1px] border-solid shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg'
|
||||
>
|
||||
<div className='flex pt-[14px] px-[14px] pb-3 h-[66px] items-center gap-3 grow-0 shrink-0'>
|
||||
<div className='flex h-[66px] shrink-0 grow-0 items-center gap-3 px-[14px] pb-3 pt-[14px]'>
|
||||
<div className='relative shrink-0'>
|
||||
<AppIcon
|
||||
size="large"
|
||||
@@ -288,13 +288,13 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
background={app.icon_background}
|
||||
imageUrl={app.icon_url}
|
||||
/>
|
||||
<AppTypeIcon type={app.mode} wrapperClassName='absolute -bottom-0.5 -right-0.5 w-4 h-4 shadow-sm' className='w-3 h-3' />
|
||||
<AppTypeIcon type={app.mode} wrapperClassName='absolute -bottom-0.5 -right-0.5 w-4 h-4 shadow-sm' className='h-3 w-3' />
|
||||
</div>
|
||||
<div className='grow w-0 py-[1px]'>
|
||||
<div className='flex items-center text-sm leading-5 font-semibold text-text-secondary'>
|
||||
<div className='w-0 grow py-[1px]'>
|
||||
<div className='text-text-secondary flex items-center text-sm font-semibold leading-5'>
|
||||
<div className='truncate' title={app.name}>{app.name}</div>
|
||||
</div>
|
||||
<div className='flex items-center text-[10px] leading-[18px] text-text-tertiary font-medium'>
|
||||
<div className='text-text-tertiary flex items-center text-[10px] font-medium leading-[18px]'>
|
||||
{app.mode === 'advanced-chat' && <div className='truncate'>{t('app.types.advanced').toUpperCase()}</div>}
|
||||
{app.mode === 'chat' && <div className='truncate'>{t('app.types.chatbot').toUpperCase()}</div>}
|
||||
{app.mode === 'agent-chat' && <div className='truncate'>{t('app.types.agent').toUpperCase()}</div>}
|
||||
@@ -303,7 +303,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='title-wrapper h-[90px] px-[14px] text-xs leading-normal text-text-tertiary'>
|
||||
<div className='title-wrapper text-text-tertiary h-[90px] px-[14px] text-xs leading-normal'>
|
||||
<div
|
||||
className={cn(tags.length ? 'line-clamp-2' : 'line-clamp-4', 'group-hover:line-clamp-2')}
|
||||
title={app.description}
|
||||
@@ -312,17 +312,17 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(
|
||||
'absolute bottom-1 left-0 right-0 items-center shrink-0 pt-1 pl-[14px] pr-[6px] pb-[6px] h-[42px]',
|
||||
'absolute bottom-1 left-0 right-0 h-[42px] shrink-0 items-center pb-[6px] pl-[14px] pr-[6px] pt-1',
|
||||
tags.length ? 'flex' : '!hidden group-hover:!flex',
|
||||
)}>
|
||||
{isCurrentWorkspaceEditor && (
|
||||
<>
|
||||
<div className={cn('grow flex items-center gap-1 w-0')} onClick={(e) => {
|
||||
<div className={cn('flex w-0 grow items-center gap-1')} onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}}>
|
||||
<div className={cn(
|
||||
'group-hover:!block group-hover:!mr-0 mr-[41px] grow w-full',
|
||||
'mr-[41px] w-full grow group-hover:!mr-0 group-hover:!block',
|
||||
tags.length ? '!block' : '!hidden',
|
||||
)}>
|
||||
<TagSelector
|
||||
@@ -336,23 +336,23 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='!hidden group-hover:!flex shrink-0 mx-1 w-[1px] h-[14px]' />
|
||||
<div className='!hidden group-hover:!flex shrink-0'>
|
||||
<div className='mx-1 !hidden h-[14px] w-[1px] shrink-0 group-hover:!flex' />
|
||||
<div className='!hidden shrink-0 group-hover:!flex'>
|
||||
<CustomPopover
|
||||
htmlContent={<Operations />}
|
||||
position="br"
|
||||
trigger="click"
|
||||
btnElement={
|
||||
<div
|
||||
className='flex items-center justify-center w-8 h-8 cursor-pointer rounded-md'
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-md'
|
||||
>
|
||||
<RiMoreFill className='w-4 h-4 text-text-tertiary' />
|
||||
<RiMoreFill className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
}
|
||||
btnClassName={open =>
|
||||
cn(
|
||||
open ? '!bg-black/5 !shadow-none' : '!bg-transparent',
|
||||
'h-8 w-8 !p-2 rounded-md border-none hover:!bg-black/5',
|
||||
'h-8 w-8 rounded-md border-none !p-2 hover:!bg-black/5',
|
||||
)
|
||||
}
|
||||
popupClassName={
|
||||
@@ -360,7 +360,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
? '!w-[256px] translate-x-[-224px]'
|
||||
: '!w-[160px] translate-x-[-128px]'
|
||||
}
|
||||
className={'h-fit !z-20'}
|
||||
className={'!z-20 h-fit'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -78,10 +78,10 @@ const Apps = () => {
|
||||
|
||||
const anchorRef = useRef<HTMLDivElement>(null)
|
||||
const options = [
|
||||
{ value: 'all', text: t('app.types.all'), icon: <RiApps2Line className='w-[14px] h-[14px] mr-1' /> },
|
||||
{ value: 'chat', text: t('app.types.chatbot'), icon: <RiMessage3Line className='w-[14px] h-[14px] mr-1' /> },
|
||||
{ value: 'agent-chat', text: t('app.types.agent'), icon: <RiRobot3Line className='w-[14px] h-[14px] mr-1' /> },
|
||||
{ value: 'workflow', text: t('app.types.workflow'), icon: <RiExchange2Line className='w-[14px] h-[14px] mr-1' /> },
|
||||
{ value: 'all', text: t('app.types.all'), icon: <RiApps2Line className='mr-1 h-[14px] w-[14px]' /> },
|
||||
{ value: 'chat', text: t('app.types.chatbot'), icon: <RiMessage3Line className='mr-1 h-[14px] w-[14px]' /> },
|
||||
{ value: 'agent-chat', text: t('app.types.agent'), icon: <RiRobot3Line className='mr-1 h-[14px] w-[14px]' /> },
|
||||
{ value: 'workflow', text: t('app.types.workflow'), icon: <RiExchange2Line className='mr-1 h-[14px] w-[14px]' /> },
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
@@ -128,7 +128,7 @@ const Apps = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-background-body z-10 flex-wrap gap-y-2'>
|
||||
<div className='bg-background-body sticky top-0 z-10 flex flex-wrap items-center justify-between gap-y-2 px-12 pb-2 pt-4 leading-[56px]'>
|
||||
<TabSliderNew
|
||||
value={activeTab}
|
||||
onChange={setActiveTab}
|
||||
@@ -153,14 +153,14 @@ const Apps = () => {
|
||||
</div>
|
||||
</div>
|
||||
{(data && data[0].total > 0)
|
||||
? <div className='grid content-start grid-cols-1 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6 gap-4 px-12 pt-2 grow relative'>
|
||||
? <div className='2k:grid-cols-6 relative grid grow grid-cols-1 content-start gap-4 px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5'>
|
||||
{isCurrentWorkspaceEditor
|
||||
&& <NewAppCard onSuccess={mutate} />}
|
||||
{data.map(({ data: apps }) => apps.map(app => (
|
||||
<AppCard key={app.id} app={app} onRefresh={mutate} />
|
||||
)))}
|
||||
</div>
|
||||
: <div className='grid content-start grid-cols-1 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6 gap-4 px-12 pt-2 grow relative overflow-hidden'>
|
||||
: <div className='2k:grid-cols-6 relative grid grow grid-cols-1 content-start gap-4 overflow-hidden px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5'>
|
||||
{isCurrentWorkspaceEditor
|
||||
&& <NewAppCard className='z-10' onSuccess={mutate} />}
|
||||
<NoAppsFound />
|
||||
@@ -180,14 +180,14 @@ function NoAppsFound() {
|
||||
const { t } = useTranslation()
|
||||
function renderDefaultCard() {
|
||||
const defaultCards = Array.from({ length: 36 }, (_, index) => (
|
||||
<div key={index} className='h-[160px] inline-flex rounded-xl bg-background-default-lighter'></div>
|
||||
<div key={index} className='bg-background-default-lighter inline-flex h-[160px] rounded-xl'></div>
|
||||
))
|
||||
return defaultCards
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{renderDefaultCard()}
|
||||
<div className='absolute top-0 left-0 right-0 bottom-0 flex items-center justify-center bg-gradient-to-t from-background-body to-transparent'>
|
||||
<div className='from-background-body absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-gradient-to-t to-transparent'>
|
||||
<span className='system-md-medium text-text-tertiary'>{t('app.newApp.noAppsFound')}</span>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { forwardRef, useMemo, useState } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import {
|
||||
useRouter,
|
||||
useSearchParams,
|
||||
@@ -18,7 +18,15 @@ export type CreateAppCardProps = {
|
||||
onSuccess?: () => void
|
||||
}
|
||||
|
||||
const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ className, onSuccess }, ref) => {
|
||||
const CreateAppCard = (
|
||||
{
|
||||
ref,
|
||||
className,
|
||||
onSuccess,
|
||||
}: CreateAppCardProps & {
|
||||
ref?: React.RefObject<HTMLDivElement>;
|
||||
},
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const { onPlanInfoChanged } = useProviderContext()
|
||||
const searchParams = useSearchParams()
|
||||
@@ -39,22 +47,22 @@ const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ classNam
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('relative col-span-1 inline-flex flex-col justify-between h-[160px] bg-components-card-bg rounded-xl border-[0.5px] border-components-card-border', className)}
|
||||
className={cn('bg-components-card-bg border-components-card-border relative col-span-1 inline-flex h-[160px] flex-col justify-between rounded-xl border-[0.5px]', className)}
|
||||
>
|
||||
<div className='grow p-2 rounded-t-xl'>
|
||||
<div className='px-6 pt-2 pb-1 text-xs font-medium leading-[18px] text-text-tertiary'>{t('app.createApp')}</div>
|
||||
<button className='w-full flex items-center mb-1 px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover' onClick={() => setShowNewAppModal(true)}>
|
||||
<FilePlus01 className='shrink-0 mr-2 w-4 h-4' />
|
||||
<div className='grow rounded-t-xl p-2'>
|
||||
<div className='text-text-tertiary px-6 pb-1 pt-2 text-xs font-medium leading-[18px]'>{t('app.createApp')}</div>
|
||||
<button className='text-text-tertiary hover:text-text-secondary hover:bg-state-base-hover mb-1 flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px]' onClick={() => setShowNewAppModal(true)}>
|
||||
<FilePlus01 className='mr-2 h-4 w-4 shrink-0' />
|
||||
{t('app.newApp.startFromBlank')}
|
||||
</button>
|
||||
<button className='w-full flex items-center px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover' onClick={() => setShowNewAppTemplateDialog(true)}>
|
||||
<FilePlus02 className='shrink-0 mr-2 w-4 h-4' />
|
||||
<button className='text-text-tertiary hover:text-text-secondary hover:bg-state-base-hover flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px]' onClick={() => setShowNewAppTemplateDialog(true)}>
|
||||
<FilePlus02 className='mr-2 h-4 w-4 shrink-0' />
|
||||
{t('app.newApp.startFromTemplate')}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowCreateFromDSLModal(true)}
|
||||
className='w-full flex items-center px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover'>
|
||||
<FileArrow01 className='shrink-0 mr-2 w-4 h-4' />
|
||||
className='text-text-tertiary hover:text-text-secondary hover:bg-state-base-hover flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px]'>
|
||||
<FileArrow01 className='mr-2 h-4 w-4 shrink-0' />
|
||||
{t('app.importDSL')}
|
||||
</button>
|
||||
</div>
|
||||
@@ -103,7 +111,7 @@ const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ classNam
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
CreateAppCard.displayName = 'CreateAppCard'
|
||||
export default CreateAppCard
|
||||
|
||||
@@ -13,17 +13,17 @@ const AppList = () => {
|
||||
const systemFeatures = useContextSelector(AppContext, v => v.systemFeatures)
|
||||
|
||||
return (
|
||||
<div className='relative flex flex-col overflow-y-auto bg-background-body shrink-0 h-0 grow'>
|
||||
<div className='bg-background-body relative flex h-0 shrink-0 grow flex-col overflow-y-auto'>
|
||||
<Apps />
|
||||
{systemFeatures.license.status === LicenseStatus.NONE && <footer className='px-12 py-6 grow-0 shrink-0'>
|
||||
<h3 className='text-xl font-semibold leading-tight text-gradient'>{t('app.join')}</h3>
|
||||
<p className='mt-1 system-sm-regular text-text-tertiary'>{t('app.communityIntro')}</p>
|
||||
<div className='flex items-center gap-2 mt-3'>
|
||||
{systemFeatures.license.status === LicenseStatus.NONE && <footer className='shrink-0 grow-0 px-12 py-6'>
|
||||
<h3 className='text-gradient text-xl font-semibold leading-tight'>{t('app.join')}</h3>
|
||||
<p className='system-sm-regular text-text-tertiary mt-1'>{t('app.communityIntro')}</p>
|
||||
<div className='mt-3 flex items-center gap-2'>
|
||||
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://github.com/langgenius/dify'>
|
||||
<RiGithubFill className='w-5 h-5 text-text-tertiary' />
|
||||
<RiGithubFill className='text-text-tertiary h-5 w-5' />
|
||||
</Link>
|
||||
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://discord.gg/FngNHpbcY7'>
|
||||
<RiDiscordFill className='w-5 h-5 text-text-tertiary' />
|
||||
<RiDiscordFill className='text-text-tertiary h-5 w-5' />
|
||||
</Link>
|
||||
</div>
|
||||
</footer>}
|
||||
|
||||
@@ -2,12 +2,13 @@ import React from 'react'
|
||||
import MainDetail from '@/app/components/datasets/documents/detail'
|
||||
|
||||
export type IDocumentDetailProps = {
|
||||
params: { datasetId: string; documentId: string }
|
||||
params: Promise<{ datasetId: string; documentId: string }>
|
||||
}
|
||||
|
||||
const DocumentDetail = async ({
|
||||
params: { datasetId, documentId },
|
||||
params,
|
||||
}: IDocumentDetailProps) => {
|
||||
const { datasetId, documentId } = (await params)
|
||||
return (
|
||||
<MainDetail datasetId={datasetId} documentId={documentId} />
|
||||
)
|
||||
|
||||
@@ -2,12 +2,13 @@ import React from 'react'
|
||||
import Settings from '@/app/components/datasets/documents/detail/settings'
|
||||
|
||||
export type IProps = {
|
||||
params: { datasetId: string; documentId: string }
|
||||
params: Promise<{ datasetId: string; documentId: string }>
|
||||
}
|
||||
|
||||
const DocumentSettings = async ({
|
||||
params: { datasetId, documentId },
|
||||
params,
|
||||
}: IProps) => {
|
||||
const { datasetId, documentId } = (await params)
|
||||
return (
|
||||
<Settings datasetId={datasetId} documentId={documentId} />
|
||||
)
|
||||
|
||||
@@ -2,12 +2,13 @@ import React from 'react'
|
||||
import DatasetUpdateForm from '@/app/components/datasets/create'
|
||||
|
||||
export type IProps = {
|
||||
params: { datasetId: string }
|
||||
params: Promise<{ datasetId: string }>
|
||||
}
|
||||
|
||||
const Create = async ({
|
||||
params: { datasetId },
|
||||
params,
|
||||
}: IProps) => {
|
||||
const datasetId = (await params).datasetId
|
||||
return (
|
||||
<DatasetUpdateForm datasetId={datasetId} />
|
||||
)
|
||||
|
||||
@@ -2,14 +2,14 @@ import React from 'react'
|
||||
import Main from '@/app/components/datasets/documents'
|
||||
|
||||
export type IProps = {
|
||||
params: { datasetId: string }
|
||||
params: Promise<{ datasetId: string }>
|
||||
}
|
||||
|
||||
const Documents = async ({
|
||||
params: { datasetId },
|
||||
params,
|
||||
}: IProps) => {
|
||||
return (
|
||||
<Main datasetId={datasetId} />
|
||||
<Main datasetId={(await params).datasetId} />
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ import React from 'react'
|
||||
import Main from '@/app/components/datasets/hit-testing'
|
||||
|
||||
type Props = {
|
||||
params: { datasetId: string }
|
||||
params: Promise<{ datasetId: string }>
|
||||
}
|
||||
|
||||
const HitTesting = ({
|
||||
params: { datasetId },
|
||||
const HitTesting = async ({
|
||||
params,
|
||||
}: Props) => {
|
||||
const datasetId = (await params).datasetId
|
||||
return (
|
||||
<Main datasetId={datasetId} />
|
||||
)
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
'use client'
|
||||
import type { FC, SVGProps } from 'react'
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import useSWR from 'swr'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import {
|
||||
Cog8ToothIcon,
|
||||
DocumentTextIcon,
|
||||
PaperClipIcon,
|
||||
} from '@heroicons/react/24/outline'
|
||||
import {
|
||||
Cog8ToothIcon as Cog8ToothSolidIcon,
|
||||
// CommandLineIcon as CommandLineSolidIcon,
|
||||
DocumentTextIcon as DocumentTextSolidIcon,
|
||||
} from '@heroicons/react/24/solid'
|
||||
import { RiApps2AddLine, RiInformation2Line } from '@remixicon/react'
|
||||
import s from './style.module.css'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
|
||||
import type { RelatedAppResponse } from '@/models/datasets'
|
||||
import AppSideBar from '@/app/components/app-sidebar'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import { DataSourceType } from '@/models/datasets'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { LanguagesSupported } from '@/i18n/language'
|
||||
import { useStore } from '@/app/components/app/store'
|
||||
import { getLocaleOnClient } from '@/i18n'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import LinkedAppsPanel from '@/app/components/base/linked-apps-panel'
|
||||
|
||||
export type IAppDetailLayoutProps = {
|
||||
children: React.ReactNode
|
||||
params: { datasetId: string }
|
||||
}
|
||||
|
||||
const TargetIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<g clipPath="url(#clip0_4610_6951)">
|
||||
<path d="M10.6666 5.33325V3.33325L12.6666 1.33325L13.3332 2.66659L14.6666 3.33325L12.6666 5.33325H10.6666ZM10.6666 5.33325L7.9999 7.99988M14.6666 7.99992C14.6666 11.6818 11.6818 14.6666 7.99992 14.6666C4.31802 14.6666 1.33325 11.6818 1.33325 7.99992C1.33325 4.31802 4.31802 1.33325 7.99992 1.33325M11.3333 7.99992C11.3333 9.84087 9.84087 11.3333 7.99992 11.3333C6.15897 11.3333 4.66659 9.84087 4.66659 7.99992C4.66659 6.15897 6.15897 4.66659 7.99992 4.66659" stroke="#344054" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4610_6951">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
}
|
||||
|
||||
const TargetSolidIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12.7733 0.67512C12.9848 0.709447 13.1669 0.843364 13.2627 1.03504L13.83 2.16961L14.9646 2.73689C15.1563 2.83273 15.2902 3.01486 15.3245 3.22639C15.3588 3.43792 15.2894 3.65305 15.1379 3.80458L13.1379 5.80458C13.0128 5.92961 12.8433 5.99985 12.6665 5.99985H10.9426L8.47124 8.47124C8.21089 8.73159 7.78878 8.73159 7.52843 8.47124C7.26808 8.21089 7.26808 7.78878 7.52843 7.52843L9.9998 5.05707V3.33318C9.9998 3.15637 10.07 2.9868 10.1951 2.86177L12.1951 0.861774C12.3466 0.710244 12.5617 0.640794 12.7733 0.67512Z" fill="#155EEF" />
|
||||
<path d="M1.99984 7.99984C1.99984 4.68613 4.68613 1.99984 7.99984 1.99984C8.36803 1.99984 8.6665 1.70136 8.6665 1.33317C8.6665 0.964981 8.36803 0.666504 7.99984 0.666504C3.94975 0.666504 0.666504 3.94975 0.666504 7.99984C0.666504 12.0499 3.94975 15.3332 7.99984 15.3332C12.0499 15.3332 15.3332 12.0499 15.3332 7.99984C15.3332 7.63165 15.0347 7.33317 14.6665 7.33317C14.2983 7.33317 13.9998 7.63165 13.9998 7.99984C13.9998 11.3135 11.3135 13.9998 7.99984 13.9998C4.68613 13.9998 1.99984 11.3135 1.99984 7.99984Z" fill="#155EEF" />
|
||||
<path d="M5.33317 7.99984C5.33317 6.52708 6.52708 5.33317 7.99984 5.33317C8.36803 5.33317 8.6665 5.03469 8.6665 4.6665C8.6665 4.29831 8.36803 3.99984 7.99984 3.99984C5.7907 3.99984 3.99984 5.7907 3.99984 7.99984C3.99984 10.209 5.7907 11.9998 7.99984 11.9998C10.209 11.9998 11.9998 10.209 11.9998 7.99984C11.9998 7.63165 11.7014 7.33317 11.3332 7.33317C10.965 7.33317 10.6665 7.63165 10.6665 7.99984C10.6665 9.4726 9.4726 10.6665 7.99984 10.6665C6.52708 10.6665 5.33317 9.4726 5.33317 7.99984Z" fill="#155EEF" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
const BookOpenIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path opacity="0.12" d="M1 3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7V10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1Z" fill="#155EEF" />
|
||||
<path d="M6 10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7M6 10.5V4.7M6 10.5L6.05003 10.425C6.39735 9.90398 6.57101 9.64349 6.80045 9.45491C7.00357 9.28796 7.23762 9.1627 7.4892 9.0863C7.77337 9 8.08645 9 8.71259 9H9.4C9.96005 9 10.2401 9 10.454 8.89101C10.6422 8.79513 10.7951 8.64215 10.891 8.45399C11 8.24008 11 7.96005 11 7.4V3.1C11 2.53995 11 2.25992 10.891 2.04601C10.7951 1.85785 10.6422 1.70487 10.454 1.60899C10.2401 1.5 9.96005 1.5 9.4 1.5H9.2C8.07989 1.5 7.51984 1.5 7.09202 1.71799C6.71569 1.90973 6.40973 2.21569 6.21799 2.59202C6 3.01984 6 3.5799 6 4.7" stroke="#155EEF" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
type IExtraInfoProps = {
|
||||
isMobile: boolean
|
||||
relatedApps?: RelatedAppResponse
|
||||
expand: boolean
|
||||
}
|
||||
|
||||
const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
|
||||
const locale = getLocaleOnClient()
|
||||
const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
|
||||
const { t } = useTranslation()
|
||||
|
||||
const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
|
||||
const relatedAppsTotal = relatedApps?.data?.length || 0
|
||||
|
||||
useEffect(() => {
|
||||
setShowTips(!isMobile)
|
||||
}, [isMobile, setShowTips])
|
||||
|
||||
return <div>
|
||||
{hasRelatedApps && (
|
||||
<>
|
||||
{!isMobile && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<LinkedAppsPanel
|
||||
relatedApps={relatedApps.data}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className='system-xs-medium-uppercase text-text-secondary inline-flex cursor-pointer items-center space-x-1'>
|
||||
<span>{relatedAppsTotal || '--'} {t('common.datasetMenus.relatedApp')}</span>
|
||||
<RiInformation2Line className='h-4 w-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isMobile && <div className={classNames(s.subTitle, 'flex items-center justify-center !px-0 gap-1')}>
|
||||
{relatedAppsTotal || '--'}
|
||||
<PaperClipIcon className='h-4 w-4 text-gray-700' />
|
||||
</div>}
|
||||
</>
|
||||
)}
|
||||
{!hasRelatedApps && !expand && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<div className='border-components-panel-border bg-components-panel-bg-blur w-[240px] rounded-xl border-[0.5px] p-4'>
|
||||
<div className='border-components-panel-border-subtle bg-background-default-subtle inline-flex rounded-lg border-[0.5px] p-2'>
|
||||
<RiApps2AddLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
<div className='text-text-tertiary my-2 text-xs'>{t('common.datasetMenus.emptyTip')}</div>
|
||||
<a
|
||||
className='text-text-accent mt-2 inline-flex cursor-pointer items-center text-xs'
|
||||
href={
|
||||
locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
: 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
>
|
||||
<BookOpenIcon className='mr-1' />
|
||||
{t('common.datasetMenus.viewDoc')}
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className='system-xs-medium-uppercase text-text-secondary inline-flex cursor-pointer items-center space-x-1'>
|
||||
<span>{t('common.datasetMenus.noRelatedApp')}</span>
|
||||
<RiInformation2Line className='h-4 w-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
|
||||
const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
params: { datasetId },
|
||||
} = props
|
||||
const pathname = usePathname()
|
||||
const hideSideBar = /documents\/create$/.test(pathname)
|
||||
const { t } = useTranslation()
|
||||
const { isCurrentWorkspaceDatasetOperator } = useAppContext()
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const { data: datasetRes, error, mutate: mutateDatasetRes } = useSWR({
|
||||
url: 'fetchDatasetDetail',
|
||||
datasetId,
|
||||
}, apiParams => fetchDatasetDetail(apiParams.datasetId))
|
||||
|
||||
const { data: relatedApps } = useSWR({
|
||||
action: 'fetchDatasetRelatedApps',
|
||||
datasetId,
|
||||
}, apiParams => fetchDatasetRelatedApps(apiParams.datasetId))
|
||||
|
||||
const navigation = useMemo(() => {
|
||||
const baseNavigation = [
|
||||
{ name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: TargetIcon, selectedIcon: TargetSolidIcon },
|
||||
// { name: 'api & webhook', href: `/datasets/${datasetId}/api`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon },
|
||||
{ name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon },
|
||||
]
|
||||
|
||||
if (datasetRes?.provider !== 'external') {
|
||||
baseNavigation.unshift({
|
||||
name: t('common.datasetMenus.documents'),
|
||||
href: `/datasets/${datasetId}/documents`,
|
||||
icon: DocumentTextIcon,
|
||||
selectedIcon: DocumentTextSolidIcon,
|
||||
})
|
||||
}
|
||||
return baseNavigation
|
||||
}, [datasetRes?.provider, datasetId, t])
|
||||
|
||||
useEffect(() => {
|
||||
if (datasetRes)
|
||||
document.title = `${datasetRes.name || 'Dataset'} - Dify`
|
||||
}, [datasetRes])
|
||||
|
||||
const setAppSiderbarExpand = useStore(state => state.setAppSiderbarExpand)
|
||||
|
||||
useEffect(() => {
|
||||
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
|
||||
const mode = isMobile ? 'collapse' : 'expand'
|
||||
setAppSiderbarExpand(isMobile ? mode : localeMode)
|
||||
}, [isMobile, setAppSiderbarExpand])
|
||||
|
||||
if (!datasetRes && !error)
|
||||
return <Loading type='app' />
|
||||
|
||||
return (
|
||||
<div className='flex grow overflow-hidden'>
|
||||
{!hideSideBar && <AppSideBar
|
||||
title={datasetRes?.name || '--'}
|
||||
icon={datasetRes?.icon || 'https://static.dify.ai/images/dataset-default-icon.png'}
|
||||
icon_background={datasetRes?.icon_background || '#F5F5F5'}
|
||||
desc={datasetRes?.description || '--'}
|
||||
isExternal={datasetRes?.provider === 'external'}
|
||||
navigation={navigation}
|
||||
extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} expand={mode === 'collapse'} /> : undefined}
|
||||
iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'}
|
||||
/>}
|
||||
<DatasetDetailContext.Provider value={{
|
||||
indexingTechnique: datasetRes?.indexing_technique,
|
||||
dataset: datasetRes,
|
||||
mutateDatasetRes: () => mutateDatasetRes(),
|
||||
}}>
|
||||
<div className="bg-background-default-subtle grow overflow-hidden">{children}</div>
|
||||
</DatasetDetailContext.Provider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(DatasetDetailLayout)
|
||||
@@ -1,228 +1,17 @@
|
||||
'use client'
|
||||
import type { FC, SVGProps } from 'react'
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import useSWR from 'swr'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import {
|
||||
Cog8ToothIcon,
|
||||
DocumentTextIcon,
|
||||
PaperClipIcon,
|
||||
} from '@heroicons/react/24/outline'
|
||||
import {
|
||||
Cog8ToothIcon as Cog8ToothSolidIcon,
|
||||
// CommandLineIcon as CommandLineSolidIcon,
|
||||
DocumentTextIcon as DocumentTextSolidIcon,
|
||||
} from '@heroicons/react/24/solid'
|
||||
import { RiApps2AddLine, RiInformation2Line } from '@remixicon/react'
|
||||
import s from './style.module.css'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
|
||||
import type { RelatedAppResponse } from '@/models/datasets'
|
||||
import AppSideBar from '@/app/components/app-sidebar'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import { DataSourceType } from '@/models/datasets'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { LanguagesSupported } from '@/i18n/language'
|
||||
import { useStore } from '@/app/components/app/store'
|
||||
import { getLocaleOnClient } from '@/i18n'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import LinkedAppsPanel from '@/app/components/base/linked-apps-panel'
|
||||
import Main from './layout-main'
|
||||
|
||||
export type IAppDetailLayoutProps = {
|
||||
children: React.ReactNode
|
||||
params: { datasetId: string }
|
||||
}
|
||||
const DatasetDetailLayout = async (
|
||||
props: {
|
||||
children: React.ReactNode
|
||||
params: Promise<{ datasetId: string }>
|
||||
}
|
||||
) => {
|
||||
const params = await props.params;
|
||||
|
||||
const TargetIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<g clipPath="url(#clip0_4610_6951)">
|
||||
<path d="M10.6666 5.33325V3.33325L12.6666 1.33325L13.3332 2.66659L14.6666 3.33325L12.6666 5.33325H10.6666ZM10.6666 5.33325L7.9999 7.99988M14.6666 7.99992C14.6666 11.6818 11.6818 14.6666 7.99992 14.6666C4.31802 14.6666 1.33325 11.6818 1.33325 7.99992C1.33325 4.31802 4.31802 1.33325 7.99992 1.33325M11.3333 7.99992C11.3333 9.84087 9.84087 11.3333 7.99992 11.3333C6.15897 11.3333 4.66659 9.84087 4.66659 7.99992C4.66659 6.15897 6.15897 4.66659 7.99992 4.66659" stroke="#344054" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4610_6951">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
}
|
||||
|
||||
const TargetSolidIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12.7733 0.67512C12.9848 0.709447 13.1669 0.843364 13.2627 1.03504L13.83 2.16961L14.9646 2.73689C15.1563 2.83273 15.2902 3.01486 15.3245 3.22639C15.3588 3.43792 15.2894 3.65305 15.1379 3.80458L13.1379 5.80458C13.0128 5.92961 12.8433 5.99985 12.6665 5.99985H10.9426L8.47124 8.47124C8.21089 8.73159 7.78878 8.73159 7.52843 8.47124C7.26808 8.21089 7.26808 7.78878 7.52843 7.52843L9.9998 5.05707V3.33318C9.9998 3.15637 10.07 2.9868 10.1951 2.86177L12.1951 0.861774C12.3466 0.710244 12.5617 0.640794 12.7733 0.67512Z" fill="#155EEF" />
|
||||
<path d="M1.99984 7.99984C1.99984 4.68613 4.68613 1.99984 7.99984 1.99984C8.36803 1.99984 8.6665 1.70136 8.6665 1.33317C8.6665 0.964981 8.36803 0.666504 7.99984 0.666504C3.94975 0.666504 0.666504 3.94975 0.666504 7.99984C0.666504 12.0499 3.94975 15.3332 7.99984 15.3332C12.0499 15.3332 15.3332 12.0499 15.3332 7.99984C15.3332 7.63165 15.0347 7.33317 14.6665 7.33317C14.2983 7.33317 13.9998 7.63165 13.9998 7.99984C13.9998 11.3135 11.3135 13.9998 7.99984 13.9998C4.68613 13.9998 1.99984 11.3135 1.99984 7.99984Z" fill="#155EEF" />
|
||||
<path d="M5.33317 7.99984C5.33317 6.52708 6.52708 5.33317 7.99984 5.33317C8.36803 5.33317 8.6665 5.03469 8.6665 4.6665C8.6665 4.29831 8.36803 3.99984 7.99984 3.99984C5.7907 3.99984 3.99984 5.7907 3.99984 7.99984C3.99984 10.209 5.7907 11.9998 7.99984 11.9998C10.209 11.9998 11.9998 10.209 11.9998 7.99984C11.9998 7.63165 11.7014 7.33317 11.3332 7.33317C10.965 7.33317 10.6665 7.63165 10.6665 7.99984C10.6665 9.4726 9.4726 10.6665 7.99984 10.6665C6.52708 10.6665 5.33317 9.4726 5.33317 7.99984Z" fill="#155EEF" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
const BookOpenIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path opacity="0.12" d="M1 3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7V10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1Z" fill="#155EEF" />
|
||||
<path d="M6 10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7M6 10.5V4.7M6 10.5L6.05003 10.425C6.39735 9.90398 6.57101 9.64349 6.80045 9.45491C7.00357 9.28796 7.23762 9.1627 7.4892 9.0863C7.77337 9 8.08645 9 8.71259 9H9.4C9.96005 9 10.2401 9 10.454 8.89101C10.6422 8.79513 10.7951 8.64215 10.891 8.45399C11 8.24008 11 7.96005 11 7.4V3.1C11 2.53995 11 2.25992 10.891 2.04601C10.7951 1.85785 10.6422 1.70487 10.454 1.60899C10.2401 1.5 9.96005 1.5 9.4 1.5H9.2C8.07989 1.5 7.51984 1.5 7.09202 1.71799C6.71569 1.90973 6.40973 2.21569 6.21799 2.59202C6 3.01984 6 3.5799 6 4.7" stroke="#155EEF" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
type IExtraInfoProps = {
|
||||
isMobile: boolean
|
||||
relatedApps?: RelatedAppResponse
|
||||
expand: boolean
|
||||
}
|
||||
|
||||
const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
|
||||
const locale = getLocaleOnClient()
|
||||
const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
|
||||
const { t } = useTranslation()
|
||||
|
||||
const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
|
||||
const relatedAppsTotal = relatedApps?.data?.length || 0
|
||||
|
||||
useEffect(() => {
|
||||
setShowTips(!isMobile)
|
||||
}, [isMobile, setShowTips])
|
||||
|
||||
return <div>
|
||||
{hasRelatedApps && (
|
||||
<>
|
||||
{!isMobile && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<LinkedAppsPanel
|
||||
relatedApps={relatedApps.data}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
|
||||
<span>{relatedAppsTotal || '--'} {t('common.datasetMenus.relatedApp')}</span>
|
||||
<RiInformation2Line className='w-4 h-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isMobile && <div className={classNames(s.subTitle, 'flex items-center justify-center !px-0 gap-1')}>
|
||||
{relatedAppsTotal || '--'}
|
||||
<PaperClipIcon className='h-4 w-4 text-gray-700' />
|
||||
</div>}
|
||||
</>
|
||||
)}
|
||||
{!hasRelatedApps && !expand && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<div className='p-4 w-[240px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl'>
|
||||
<div className='inline-flex p-2 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle'>
|
||||
<RiApps2AddLine className='h-4 w-4 text-text-tertiary' />
|
||||
</div>
|
||||
<div className='text-xs text-text-tertiary my-2'>{t('common.datasetMenus.emptyTip')}</div>
|
||||
<a
|
||||
className='inline-flex items-center text-xs text-text-accent mt-2 cursor-pointer'
|
||||
href={
|
||||
locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
: 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
>
|
||||
<BookOpenIcon className='mr-1' />
|
||||
{t('common.datasetMenus.viewDoc')}
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
|
||||
<span>{t('common.datasetMenus.noRelatedApp')}</span>
|
||||
<RiInformation2Line className='w-4 h-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
|
||||
const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
params: { datasetId },
|
||||
} = props
|
||||
const pathname = usePathname()
|
||||
const hideSideBar = /documents\/create$/.test(pathname)
|
||||
const { t } = useTranslation()
|
||||
const { isCurrentWorkspaceDatasetOperator } = useAppContext()
|
||||
children
|
||||
} = props;
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const { data: datasetRes, error, mutate: mutateDatasetRes } = useSWR({
|
||||
url: 'fetchDatasetDetail',
|
||||
datasetId,
|
||||
}, apiParams => fetchDatasetDetail(apiParams.datasetId))
|
||||
|
||||
const { data: relatedApps } = useSWR({
|
||||
action: 'fetchDatasetRelatedApps',
|
||||
datasetId,
|
||||
}, apiParams => fetchDatasetRelatedApps(apiParams.datasetId))
|
||||
|
||||
const navigation = useMemo(() => {
|
||||
const baseNavigation = [
|
||||
{ name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: TargetIcon, selectedIcon: TargetSolidIcon },
|
||||
// { name: 'api & webhook', href: `/datasets/${datasetId}/api`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon },
|
||||
{ name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon },
|
||||
]
|
||||
|
||||
if (datasetRes?.provider !== 'external') {
|
||||
baseNavigation.unshift({
|
||||
name: t('common.datasetMenus.documents'),
|
||||
href: `/datasets/${datasetId}/documents`,
|
||||
icon: DocumentTextIcon,
|
||||
selectedIcon: DocumentTextSolidIcon,
|
||||
})
|
||||
}
|
||||
return baseNavigation
|
||||
}, [datasetRes?.provider, datasetId, t])
|
||||
|
||||
useEffect(() => {
|
||||
if (datasetRes)
|
||||
document.title = `${datasetRes.name || 'Dataset'} - Dify`
|
||||
}, [datasetRes])
|
||||
|
||||
const setAppSiderbarExpand = useStore(state => state.setAppSiderbarExpand)
|
||||
|
||||
useEffect(() => {
|
||||
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
|
||||
const mode = isMobile ? 'collapse' : 'expand'
|
||||
setAppSiderbarExpand(isMobile ? mode : localeMode)
|
||||
}, [isMobile, setAppSiderbarExpand])
|
||||
|
||||
if (!datasetRes && !error)
|
||||
return <Loading type='app' />
|
||||
|
||||
return (
|
||||
<div className='grow flex overflow-hidden'>
|
||||
{!hideSideBar && <AppSideBar
|
||||
title={datasetRes?.name || '--'}
|
||||
icon={datasetRes?.icon || 'https://static.dify.ai/images/dataset-default-icon.png'}
|
||||
icon_background={datasetRes?.icon_background || '#F5F5F5'}
|
||||
desc={datasetRes?.description || '--'}
|
||||
isExternal={datasetRes?.provider === 'external'}
|
||||
navigation={navigation}
|
||||
extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} expand={mode === 'collapse'} /> : undefined}
|
||||
iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'}
|
||||
/>}
|
||||
<DatasetDetailContext.Provider value={{
|
||||
indexingTechnique: datasetRes?.indexing_technique,
|
||||
dataset: datasetRes,
|
||||
mutateDatasetRes: () => mutateDatasetRes(),
|
||||
}}>
|
||||
<div className="bg-background-default-subtle grow overflow-hidden">{children}</div>
|
||||
</DatasetDetailContext.Provider>
|
||||
</div>
|
||||
)
|
||||
return <Main params={(await params)}>{children}</Main>
|
||||
}
|
||||
export default React.memo(DatasetDetailLayout)
|
||||
export default DatasetDetailLayout
|
||||
|
||||
@@ -3,13 +3,13 @@ import { getLocaleOnServer, useTranslation as translate } from '@/i18n/server'
|
||||
import Form from '@/app/components/datasets/settings/form'
|
||||
|
||||
const Settings = async () => {
|
||||
const locale = getLocaleOnServer()
|
||||
const locale = await getLocaleOnServer()
|
||||
const { t } = await translate(locale, 'dataset-settings')
|
||||
|
||||
return (
|
||||
<div className='h-full overflow-y-auto'>
|
||||
<div className='px-6 py-3'>
|
||||
<div className='mb-1 system-xl-semibold text-text-primary'>{t('title')}</div>
|
||||
<div className='system-xl-semibold text-text-primary mb-1'>{t('title')}</div>
|
||||
<div className='system-sm-regular text-text-tertiary'>{t('desc')}</div>
|
||||
</div>
|
||||
<Form />
|
||||
|
||||
@@ -15,22 +15,22 @@ const ApiServer: FC<ApiServerProps> = ({
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex items-center flex-wrap gap-y-2'>
|
||||
<div className='flex items-center mr-2 pl-1.5 pr-1 h-8 bg-white/80 border-[0.5px] border-white rounded-lg leading-5'>
|
||||
<div className='mr-0.5 px-1.5 h-5 border border-gray-200 text-[11px] text-gray-500 rounded-md shrink-0'>{t('appApi.apiServer')}</div>
|
||||
<div className='px-1 truncate w-fit sm:w-[248px] text-[13px] font-medium text-gray-800'>{apiBaseUrl}</div>
|
||||
<div className='mx-1 w-[1px] h-[14px] bg-gray-200'></div>
|
||||
<div className='flex flex-wrap items-center gap-y-2'>
|
||||
<div className='mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-white bg-white/80 pl-1.5 pr-1 leading-5'>
|
||||
<div className='mr-0.5 h-5 shrink-0 rounded-md border border-gray-200 px-1.5 text-[11px] text-gray-500'>{t('appApi.apiServer')}</div>
|
||||
<div className='w-fit truncate px-1 text-[13px] font-medium text-gray-800 sm:w-[248px]'>{apiBaseUrl}</div>
|
||||
<div className='mx-1 h-[14px] w-[1px] bg-gray-200'></div>
|
||||
<CopyFeedback
|
||||
content={apiBaseUrl}
|
||||
selectorId={randomString(8)}
|
||||
className={'!w-6 !h-6 hover:bg-gray-200'}
|
||||
className={'!h-6 !w-6 hover:bg-gray-200'}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex items-center mr-2 px-3 h-8 bg-[#ECFDF3] text-xs font-semibold text-[#039855] rounded-lg border-[0.5px] border-[#D1FADF]'>
|
||||
<div className='mr-2 flex h-8 items-center rounded-lg border-[0.5px] border-[#D1FADF] bg-[#ECFDF3] px-3 text-xs font-semibold text-[#039855]'>
|
||||
{t('appApi.ok')}
|
||||
</div>
|
||||
<SecretKeyButton
|
||||
className='shrink-0 !h-8 bg-white'
|
||||
className='!h-8 shrink-0 bg-white'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -82,8 +82,8 @@ const Container = () => {
|
||||
}, [currentWorkspace, router])
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className='grow relative flex flex-col bg-background-body overflow-y-auto scroll-container'>
|
||||
<div className='sticky top-0 flex justify-between pt-4 px-12 pb-2 leading-[56px] bg-background-body z-10 flex-wrap gap-y-2'>
|
||||
<div ref={containerRef} className='bg-background-body scroll-container relative flex grow flex-col overflow-y-auto'>
|
||||
<div className='bg-background-body sticky top-0 z-10 flex flex-wrap justify-between gap-y-2 px-12 pb-2 pt-4 leading-[56px]'>
|
||||
<TabSliderNew
|
||||
value={activeTab}
|
||||
onChange={newActiveTab => setActiveTab(newActiveTab)}
|
||||
@@ -108,13 +108,13 @@ const Container = () => {
|
||||
onChange={e => handleKeywordsChange(e.target.value)}
|
||||
onClear={() => handleKeywordsChange('')}
|
||||
/>
|
||||
<div className="w-[1px] h-4 bg-divider-regular" />
|
||||
<div className="bg-divider-regular h-4 w-[1px]" />
|
||||
<Button
|
||||
className='gap-0.5 shadows-shadow-xs'
|
||||
className='shadows-shadow-xs gap-0.5'
|
||||
onClick={() => setShowExternalApiPanel(true)}
|
||||
>
|
||||
<ApiConnectionMod className='w-4 h-4 text-components-button-secondary-text' />
|
||||
<div className='flex px-0.5 justify-center items-center gap-1 text-components-button-secondary-text system-sm-medium'>{t('dataset.externalAPIPanelTitle')}</div>
|
||||
<ApiConnectionMod className='text-components-button-secondary-text h-4 w-4' />
|
||||
<div className='text-components-button-secondary-text system-sm-medium flex items-center justify-center gap-1 px-0.5'>{t('dataset.externalAPIPanelTitle')}</div>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -84,17 +84,17 @@ const DatasetCard = ({
|
||||
}
|
||||
return (
|
||||
<div className="relative w-full py-1" onMouseLeave={onMouseLeave}>
|
||||
<div className='h-8 py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-gray-100 rounded-lg cursor-pointer' onClick={onClickRename}>
|
||||
<span className='text-gray-700 text-sm'>{t('common.operation.settings')}</span>
|
||||
<div className='mx-1 flex h-8 cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-gray-100' onClick={onClickRename}>
|
||||
<span className='text-sm text-gray-700'>{t('common.operation.settings')}</span>
|
||||
</div>
|
||||
{props.showDelete && (
|
||||
<>
|
||||
<Divider className="!my-1" />
|
||||
<div
|
||||
className='group h-8 py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-red-50 rounded-lg cursor-pointer'
|
||||
className='group mx-1 flex h-8 cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-red-50'
|
||||
onClick={onClickDelete}
|
||||
>
|
||||
<span className={cn('text-gray-700 text-sm', 'group-hover:text-red-500')}>
|
||||
<span className={cn('text-sm text-gray-700', 'group-hover:text-red-500')}>
|
||||
{t('common.operation.delete')}
|
||||
</span>
|
||||
</div>
|
||||
@@ -111,7 +111,7 @@ const DatasetCard = ({
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className='group relative col-span-1 bg-components-card-bg border-[0.5px] border-solid border-components-card-border rounded-xl shadow-sm min-h-[160px] flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg'
|
||||
className='bg-components-card-bg border-components-card-border group relative col-span-1 flex min-h-[160px] cursor-pointer flex-col rounded-xl border-[0.5px] border-solid shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg'
|
||||
data-disable-nprogress={true}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
@@ -121,25 +121,25 @@ const DatasetCard = ({
|
||||
}}
|
||||
>
|
||||
{isExternalProvider(dataset.provider) && <CornerLabel label='External' className='absolute right-0' labelClassName='rounded-tr-xl' />}
|
||||
<div className='flex pt-[14px] px-[14px] pb-3 h-[66px] items-center gap-3 grow-0 shrink-0'>
|
||||
<div className='flex h-[66px] shrink-0 grow-0 items-center gap-3 px-[14px] pb-3 pt-[14px]'>
|
||||
<div className={cn(
|
||||
'shrink-0 flex items-center justify-center p-2.5 bg-[#F5F8FF] rounded-md border-[0.5px] border-[#E0EAFF]',
|
||||
'flex shrink-0 items-center justify-center rounded-md border-[0.5px] border-[#E0EAFF] bg-[#F5F8FF] p-2.5',
|
||||
!dataset.embedding_available && 'opacity-50 hover:opacity-100',
|
||||
)}>
|
||||
<Folder className='w-5 h-5 text-[#444CE7]' />
|
||||
<Folder className='h-5 w-5 text-[#444CE7]' />
|
||||
</div>
|
||||
<div className='grow w-0 py-[1px]'>
|
||||
<div className='flex items-center text-sm leading-5 font-semibold text-text-secondary'>
|
||||
<div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100 text-text-tertiary')} title={dataset.name}>{dataset.name}</div>
|
||||
<div className='w-0 grow py-[1px]'>
|
||||
<div className='text-text-secondary flex items-center text-sm font-semibold leading-5'>
|
||||
<div className={cn('truncate', !dataset.embedding_available && 'text-text-tertiary opacity-50 hover:opacity-100')} title={dataset.name}>{dataset.name}</div>
|
||||
{!dataset.embedding_available && (
|
||||
<Tooltip
|
||||
popupContent={t('dataset.unavailableTip')}
|
||||
>
|
||||
<span className='shrink-0 inline-flex w-max ml-1 px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
|
||||
<span className='ml-1 inline-flex w-max shrink-0 rounded-md border border-gray-200 px-1 text-xs font-normal leading-[18px] text-gray-500'>{t('dataset.unavailable')}</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex items-center mt-[1px] text-xs leading-[18px] text-text-tertiary'>
|
||||
<div className='text-text-tertiary mt-[1px] flex items-center text-xs leading-[18px]'>
|
||||
<div
|
||||
className={cn('truncate', (!dataset.embedding_available || !dataset.document_count) && 'opacity-50')}
|
||||
title={dataset.provider === 'external' ? `${dataset.app_count}${t('dataset.appCount')}` : `${dataset.document_count}${t('dataset.documentCount')} · ${Math.round(dataset.word_count / 1000)}${t('dataset.wordCount')} · ${dataset.app_count}${t('dataset.appCount')}`}
|
||||
@@ -150,9 +150,9 @@ const DatasetCard = ({
|
||||
</>
|
||||
: <>
|
||||
<span>{dataset.document_count}{t('dataset.documentCount')}</span>
|
||||
<span className='shrink-0 mx-0.5 w-1 text-gray-400'>·</span>
|
||||
<span className='mx-0.5 w-1 shrink-0 text-gray-400'>·</span>
|
||||
<span>{Math.round(dataset.word_count / 1000)}{t('dataset.wordCount')}</span>
|
||||
<span className='shrink-0 mx-0.5 w-1 text-gray-400'>·</span>
|
||||
<span className='mx-0.5 w-1 shrink-0 text-gray-400'>·</span>
|
||||
<span>{dataset.app_count}{t('dataset.appCount')}</span>
|
||||
</>
|
||||
}
|
||||
@@ -162,7 +162,7 @@ const DatasetCard = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'grow mb-2 px-[14px] max-h-[72px] text-xs leading-normal text-text-tertiary group-hover:line-clamp-2 group-hover:max-h-[36px]',
|
||||
'text-text-tertiary mb-2 max-h-[72px] grow px-[14px] text-xs leading-normal group-hover:line-clamp-2 group-hover:max-h-[36px]',
|
||||
tags.length ? 'line-clamp-2' : 'line-clamp-4',
|
||||
!dataset.embedding_available && 'opacity-50 hover:opacity-100',
|
||||
)}
|
||||
@@ -170,15 +170,15 @@ const DatasetCard = ({
|
||||
{dataset.description}
|
||||
</div>
|
||||
<div className={cn(
|
||||
'items-center shrink-0 mt-1 pt-1 pl-[14px] pr-[6px] pb-[6px] h-[42px]',
|
||||
'mt-1 h-[42px] shrink-0 items-center pb-[6px] pl-[14px] pr-[6px] pt-1',
|
||||
tags.length ? 'flex' : '!hidden group-hover:!flex',
|
||||
)}>
|
||||
<div className={cn('grow flex items-center gap-1 w-0', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} onClick={(e) => {
|
||||
<div className={cn('flex w-0 grow items-center gap-1', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}}>
|
||||
<div className={cn(
|
||||
'group-hover:!block group-hover:!mr-0 mr-[41px] grow w-full',
|
||||
'mr-[41px] w-full grow group-hover:!mr-0 group-hover:!block',
|
||||
tags.length ? '!block' : '!hidden',
|
||||
)}>
|
||||
<TagSelector
|
||||
@@ -192,26 +192,26 @@ const DatasetCard = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='!hidden group-hover:!flex shrink-0 mx-1 w-[1px] h-[14px] bg-gray-200' />
|
||||
<div className='!hidden group-hover:!flex shrink-0'>
|
||||
<div className='mx-1 !hidden h-[14px] w-[1px] shrink-0 bg-gray-200 group-hover:!flex' />
|
||||
<div className='!hidden shrink-0 group-hover:!flex'>
|
||||
<CustomPopover
|
||||
htmlContent={<Operations showDelete={!isCurrentWorkspaceDatasetOperator} />}
|
||||
position="br"
|
||||
trigger="click"
|
||||
btnElement={
|
||||
<div
|
||||
className='flex items-center justify-center w-8 h-8 cursor-pointer rounded-md'
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-md'
|
||||
>
|
||||
<RiMoreFill className='w-4 h-4 text-gray-700' />
|
||||
<RiMoreFill className='h-4 w-4 text-gray-700' />
|
||||
</div>
|
||||
}
|
||||
btnClassName={open =>
|
||||
cn(
|
||||
open ? '!bg-black/5 !shadow-none' : '!bg-transparent',
|
||||
'h-8 w-8 !p-2 rounded-md border-none hover:!bg-black/5',
|
||||
'h-8 w-8 rounded-md border-none !p-2 hover:!bg-black/5',
|
||||
)
|
||||
}
|
||||
className={'!w-[128px] h-fit !z-20'}
|
||||
className={'!z-20 h-fit !w-[128px]'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,8 +6,8 @@ const DatasetFooter = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<footer className='px-12 py-6 grow-0 shrink-0'>
|
||||
<h3 className='text-xl font-semibold leading-tight text-gradient'>{t('dataset.didYouKnow')}</h3>
|
||||
<footer className='shrink-0 grow-0 px-12 py-6'>
|
||||
<h3 className='text-gradient text-xl font-semibold leading-tight'>{t('dataset.didYouKnow')}</h3>
|
||||
<p className='mt-1 text-sm font-normal leading-tight text-gray-700'>
|
||||
{t('dataset.intro1')}<span className='inline-flex items-center gap-1 text-blue-600'>{t('dataset.intro2')}</span>{t('dataset.intro3')}<br />
|
||||
{t('dataset.intro4')}<span className='inline-flex items-center gap-1 text-blue-600'>{t('dataset.intro5')}</span>{t('dataset.intro6')}
|
||||
|
||||
@@ -79,8 +79,8 @@ const Datasets = ({
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<nav className='grid content-start grid-cols-1 gap-4 px-12 pt-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 grow shrink-0'>
|
||||
{ isCurrentWorkspaceEditor && <NewDatasetCard ref={anchorRef} /> }
|
||||
<nav className='grid shrink-0 grow grid-cols-1 content-start gap-4 px-12 pt-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'>
|
||||
{isCurrentWorkspaceEditor && <NewDatasetCard ref={anchorRef} />}
|
||||
{data?.map(({ data: datasets }) => datasets.map(dataset => (
|
||||
<DatasetCard key={dataset.id} dataset={dataset} onSuccess={mutate} />),
|
||||
))}
|
||||
|
||||
@@ -71,8 +71,8 @@ const Doc = ({ apiBaseUrl }: DocProps) => {
|
||||
<div className={`fixed right-16 top-32 z-10 transition-all ${isTocExpanded ? 'w-64' : 'w-10'}`}>
|
||||
{isTocExpanded
|
||||
? (
|
||||
<nav className="toc w-full bg-gray-50 p-4 rounded-lg shadow-md max-h-[calc(100vh-150px)] overflow-y-auto">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<nav className="toc max-h-[calc(100vh-150px)] w-full overflow-y-auto rounded-lg bg-gray-50 p-4 shadow-md">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold">{t('appApi.develop.toc')}</h3>
|
||||
<button
|
||||
onClick={() => setIsTocExpanded(false)}
|
||||
@@ -86,7 +86,7 @@ const Doc = ({ apiBaseUrl }: DocProps) => {
|
||||
<li key={index}>
|
||||
<a
|
||||
href={item.href}
|
||||
className="text-gray-600 hover:text-gray-900 hover:underline transition-colors duration-200"
|
||||
className="text-gray-600 transition-colors duration-200 hover:text-gray-900 hover:underline"
|
||||
onClick={e => handleTocClick(e, item)}
|
||||
>
|
||||
{item.text}
|
||||
@@ -99,13 +99,13 @@ const Doc = ({ apiBaseUrl }: DocProps) => {
|
||||
: (
|
||||
<button
|
||||
onClick={() => setIsTocExpanded(true)}
|
||||
className="w-10 h-10 bg-gray-50 rounded-full shadow-md flex items-center justify-center hover:bg-gray-100 transition-colors duration-200"
|
||||
className="flex h-10 w-10 items-center justify-center rounded-full bg-gray-50 shadow-md transition-colors duration-200 hover:bg-gray-100"
|
||||
>
|
||||
<RiListUnordered className="w-6 h-6" />
|
||||
<RiListUnordered className="h-6 w-6" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<article className='mx-1 px-4 sm:mx-12 pt-16 bg-white rounded-t-xl prose prose-xl'>
|
||||
<article className='prose prose-xl mx-1 rounded-t-xl bg-white px-4 pt-16 sm:mx-12'>
|
||||
{locale !== LanguagesSupported[1]
|
||||
? <TemplateEn apiBaseUrl={apiBaseUrl} />
|
||||
: <TemplateZh apiBaseUrl={apiBaseUrl} />
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
'use client'
|
||||
|
||||
import { forwardRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiArrowRightLine,
|
||||
} from '@remixicon/react'
|
||||
|
||||
const CreateAppCard = forwardRef<HTMLAnchorElement>((_, ref) => {
|
||||
const CreateAppCard = (
|
||||
{
|
||||
ref,
|
||||
..._
|
||||
},
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex flex-col bg-background-default-dimm border-[0.5px] border-components-panel-border rounded-xl
|
||||
min-h-[160px] transition-all duration-200 ease-in-out'
|
||||
<div className='bg-background-default-dimm border-components-panel-border flex min-h-[160px] flex-col rounded-xl
|
||||
border-[0.5px] transition-all duration-200 ease-in-out'
|
||||
>
|
||||
<a ref={ref} className='group flex flex-grow items-start p-4 cursor-pointer' href='/datasets/create'>
|
||||
<a ref={ref} className='group flex grow cursor-pointer items-start p-4' href='/datasets/create'>
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='w-10 h-10 p-2 flex items-center justify-center border border-dashed border-divider-regular rounded-lg
|
||||
bg-background-default-lighter group-hover:border-solid group-hover:border-effects-highlight group-hover:bg-background-default-dodge'
|
||||
<div className='border-divider-regular bg-background-default-lighter group-hover:border-effects-highlight group-hover:bg-background-default-dodge flex h-10 w-10 items-center justify-center rounded-lg
|
||||
border border-dashed p-2 group-hover:border-solid'
|
||||
>
|
||||
<RiAddLine className='w-4 h-4 text-text-tertiary group-hover:text-text-accent'/>
|
||||
<RiAddLine className='text-text-tertiary group-hover:text-text-accent h-4 w-4'/>
|
||||
</div>
|
||||
<div className='system-md-semibold text-text-secondary group-hover:text-text-accent'>{t('dataset.createDataset')}</div>
|
||||
</div>
|
||||
</a>
|
||||
<div className='p-4 pt-0 text-text-tertiary system-xs-regular'>{t('dataset.createDatasetIntro')}</div>
|
||||
<a className='group flex p-4 items-center gap-1 border-t-[0.5px] border-divider-subtle rounded-b-xl cursor-pointer' href='/datasets/connect'>
|
||||
<div className='text-text-tertiary system-xs-regular p-4 pt-0'>{t('dataset.createDatasetIntro')}</div>
|
||||
<a className='border-divider-subtle group flex cursor-pointer items-center gap-1 rounded-b-xl border-t-[0.5px] p-4' href='/datasets/connect'>
|
||||
<div className='system-xs-medium text-text-tertiary group-hover:text-text-accent'>{t('dataset.connectDataset')}</div>
|
||||
<RiArrowRightLine className='w-3.5 h-3.5 text-text-tertiary group-hover:text-text-accent' />
|
||||
<RiArrowRightLine className='text-text-tertiary group-hover:text-text-accent h-3.5 w-3.5' />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
CreateAppCard.displayName = 'CreateAppCard'
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@ import React from 'react'
|
||||
import Main from '@/app/components/explore/installed-app'
|
||||
|
||||
export type IInstalledAppProps = {
|
||||
params: {
|
||||
params: Promise<{
|
||||
appId: string
|
||||
}
|
||||
}>
|
||||
}
|
||||
|
||||
const InstalledApp: FC<IInstalledAppProps> = ({ params: { appId } }) => {
|
||||
const InstalledApp: FC<IInstalledAppProps> = async ({ params }) => {
|
||||
const appId = (await params).appId
|
||||
return (
|
||||
<Main id={appId} />
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ const Layout: FC<{
|
||||
children: React.ReactNode
|
||||
}> = ({ children }) => {
|
||||
return (
|
||||
<div className="min-w-[300px] h-full pb-[env(safe-area-inset-bottom)]">
|
||||
<div className="h-full min-w-[300px] pb-[env(safe-area-inset-bottom)]">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -92,8 +92,8 @@ const WebSSOForm: FC = () => {
|
||||
}, [message, tokenFromUrl]) // Added dependencies to useEffect
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className={cn('flex flex-col items-center w-full grow justify-center', 'px-6', 'md:px-[108px]')}>
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<div className={cn('flex w-full grow flex-col items-center justify-center', 'px-6', 'md:px-[108px]')}>
|
||||
<Loading type='area' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -83,13 +83,13 @@ const AvatarWithEdit = ({ onSave, ...props }: AvatarWithEditProps) => {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div className="relative group">
|
||||
<div className="group relative">
|
||||
<Avatar {...props} />
|
||||
<div
|
||||
onClick={() => { setIsShowAvatarPicker(true) }}
|
||||
className="absolute inset-0 bg-black bg-opacity-50 rounded-full opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer flex items-center justify-center"
|
||||
className="absolute inset-0 flex cursor-pointer items-center justify-center rounded-full bg-black bg-opacity-50 opacity-0 transition-opacity group-hover:opacity-100"
|
||||
>
|
||||
<span className="text-white text-xs">
|
||||
<span className="text-xs text-white">
|
||||
<RiPencilLine />
|
||||
</span>
|
||||
</div>
|
||||
@@ -105,7 +105,7 @@ const AvatarWithEdit = ({ onSave, ...props }: AvatarWithEditProps) => {
|
||||
<ImageInput onImageInput={handleImageInput} cropShape='round' />
|
||||
<Divider className='m-0' />
|
||||
|
||||
<div className='w-full flex items-center justify-center p-3 gap-2'>
|
||||
<div className='flex w-full items-center justify-center gap-2 p-3'>
|
||||
<Button className='w-full' onClick={() => setIsShowAvatarPicker(false)}>
|
||||
{t('app.iconPicker.cancel')}
|
||||
</Button>
|
||||
|
||||
@@ -122,17 +122,17 @@ export default function AccountPage() {
|
||||
<div className='mr-3'>
|
||||
<AppIcon size='tiny' />
|
||||
</div>
|
||||
<div className='mt-[3px] system-sm-medium text-text-secondary'>{item.name}</div>
|
||||
<div className='system-sm-medium text-text-secondary mt-[3px]'>{item.name}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='pt-2 pb-3'>
|
||||
<div className='pb-3 pt-2'>
|
||||
<h4 className='title-2xl-semi-bold text-text-primary'>{t('common.account.myAccount')}</h4>
|
||||
</div>
|
||||
<div className='mb-8 p-6 rounded-xl flex items-center bg-gradient-to-r from-background-gradient-bg-fill-chat-bg-2 to-background-gradient-bg-fill-chat-bg-1'>
|
||||
<div className='from-background-gradient-bg-fill-chat-bg-2 to-background-gradient-bg-fill-chat-bg-1 mb-8 flex items-center rounded-xl bg-gradient-to-r p-6'>
|
||||
<AvatarWithEdit avatar={userProfile.avatar_url} name={userProfile.name} onSave={ mutateUserProfile } size={64} />
|
||||
<div className='ml-4'>
|
||||
<p className='system-xl-semibold text-text-primary'>{userProfile.name}</p>
|
||||
@@ -141,19 +141,19 @@ export default function AccountPage() {
|
||||
</div>
|
||||
<div className='mb-8'>
|
||||
<div className={titleClassName}>{t('common.account.name')}</div>
|
||||
<div className='flex items-center justify-between gap-2 w-full mt-2'>
|
||||
<div className='flex-1 bg-components-input-bg-normal rounded-lg p-2 system-sm-regular text-components-input-text-filled '>
|
||||
<div className='mt-2 flex w-full items-center justify-between gap-2'>
|
||||
<div className='bg-components-input-bg-normal system-sm-regular text-components-input-text-filled flex-1 rounded-lg p-2 '>
|
||||
<span className='pl-1'>{userProfile.name}</span>
|
||||
</div>
|
||||
<div className='bg-components-button-tertiary-bg rounded-lg py-2 px-3 cursor-pointer system-sm-medium text-components-button-tertiary-text' onClick={handleEditName}>
|
||||
<div className='bg-components-button-tertiary-bg system-sm-medium text-components-button-tertiary-text cursor-pointer rounded-lg px-3 py-2' onClick={handleEditName}>
|
||||
{t('common.operation.edit')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mb-8'>
|
||||
<div className={titleClassName}>{t('common.account.email')}</div>
|
||||
<div className='flex items-center justify-between gap-2 w-full mt-2'>
|
||||
<div className='flex-1 bg-components-input-bg-normal rounded-lg p-2 system-sm-regular text-components-input-text-filled '>
|
||||
<div className='mt-2 flex w-full items-center justify-between gap-2'>
|
||||
<div className='bg-components-input-bg-normal system-sm-regular text-components-input-text-filled flex-1 rounded-lg p-2 '>
|
||||
<span className='pl-1'>{userProfile.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -162,14 +162,14 @@ export default function AccountPage() {
|
||||
systemFeatures.enable_email_password_login && (
|
||||
<div className='mb-8 flex justify-between gap-2'>
|
||||
<div>
|
||||
<div className='mb-1 system-sm-semibold text-text-secondary'>{t('common.account.password')}</div>
|
||||
<div className='mb-2 body-xs-regular text-text-tertiary'>{t('common.account.passwordTip')}</div>
|
||||
<div className='system-sm-semibold text-text-secondary mb-1'>{t('common.account.password')}</div>
|
||||
<div className='body-xs-regular text-text-tertiary mb-2'>{t('common.account.passwordTip')}</div>
|
||||
</div>
|
||||
<Button onClick={() => setEditPasswordModalVisible(true)}>{userProfile.is_password_set ? t('common.account.resetPassword') : t('common.account.setPassword')}</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='mb-6 border-[1px] border-divider-subtle' />
|
||||
<div className='border-divider-subtle mb-6 border-[1px]' />
|
||||
<div className='mb-8'>
|
||||
<div className={titleClassName}>{t('common.account.langGeniusAccount')}</div>
|
||||
<div className={descriptionClassName}>{t('common.account.langGeniusAccountTip')}</div>
|
||||
@@ -181,7 +181,7 @@ export default function AccountPage() {
|
||||
wrapperClassName='mt-2'
|
||||
/>
|
||||
)}
|
||||
{!IS_CE_EDITION && <Button className='mt-2 text-components-button-destructive-secondary-text' onClick={() => setShowDeleteAccountModal(true)}>{t('common.account.delete')}</Button>}
|
||||
{!IS_CE_EDITION && <Button className='text-components-button-destructive-secondary-text mt-2' onClick={() => setShowDeleteAccountModal(true)}>{t('common.account.delete')}</Button>}
|
||||
</div>
|
||||
{
|
||||
editNameModalVisible && (
|
||||
@@ -190,13 +190,13 @@ export default function AccountPage() {
|
||||
onClose={() => setEditNameModalVisible(false)}
|
||||
className={s.modal}
|
||||
>
|
||||
<div className='mb-6 title-2xl-semi-bold text-text-primary'>{t('common.account.editName')}</div>
|
||||
<div className='title-2xl-semi-bold text-text-primary mb-6'>{t('common.account.editName')}</div>
|
||||
<div className={titleClassName}>{t('common.account.name')}</div>
|
||||
<Input className='mt-2'
|
||||
value={editName}
|
||||
onChange={e => setEditName(e.target.value)}
|
||||
/>
|
||||
<div className='flex justify-end mt-10'>
|
||||
<div className='mt-10 flex justify-end'>
|
||||
<Button className='mr-2' onClick={() => setEditNameModalVisible(false)}>{t('common.operation.cancel')}</Button>
|
||||
<Button
|
||||
disabled={editing || !editName}
|
||||
@@ -219,7 +219,7 @@ export default function AccountPage() {
|
||||
}}
|
||||
className={s.modal}
|
||||
>
|
||||
<div className='mb-6 title-2xl-semi-bold text-text-primary'>{userProfile.is_password_set ? t('common.account.resetPassword') : t('common.account.setPassword')}</div>
|
||||
<div className='title-2xl-semi-bold text-text-primary mb-6'>{userProfile.is_password_set ? t('common.account.resetPassword') : t('common.account.setPassword')}</div>
|
||||
{userProfile.is_password_set && (
|
||||
<>
|
||||
<div className={titleClassName}>{t('common.account.currentPassword')}</div>
|
||||
@@ -242,7 +242,7 @@ export default function AccountPage() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className='mt-8 system-sm-semibold text-text-secondary'>
|
||||
<div className='system-sm-semibold text-text-secondary mt-8'>
|
||||
{userProfile.is_password_set ? t('common.account.newPassword') : t('common.account.password')}
|
||||
</div>
|
||||
<div className='relative mt-2'>
|
||||
@@ -261,7 +261,7 @@ export default function AccountPage() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-8 system-sm-semibold text-text-secondary'>{t('common.account.confirmPassword')}</div>
|
||||
<div className='system-sm-semibold text-text-secondary mt-8'>{t('common.account.confirmPassword')}</div>
|
||||
<div className='relative mt-2'>
|
||||
<Input
|
||||
type={showConfirmPassword ? 'text' : 'password'}
|
||||
@@ -278,7 +278,7 @@ export default function AccountPage() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex justify-end mt-10'>
|
||||
<div className='mt-10 flex justify-end'>
|
||||
<Button className='mr-2' onClick={() => {
|
||||
setEditPasswordModalVisible(false)
|
||||
resetPasswordForm()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Fragment } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
|
||||
import Avatar from '@/app/components/base/avatar'
|
||||
import { logout } from '@/service/common'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
@@ -36,17 +36,17 @@ export default function AppSelector() {
|
||||
({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Menu.Button
|
||||
<MenuButton
|
||||
className={`
|
||||
inline-flex items-center
|
||||
rounded-[20px] p-1x text-sm
|
||||
text-text-primary
|
||||
mobile:px-1
|
||||
p-1x text-text-primary
|
||||
mobile:px-1 inline-flex items-center
|
||||
rounded-[20px]
|
||||
text-sm
|
||||
${open && 'bg-components-panel-bg-blur'}
|
||||
`}
|
||||
>
|
||||
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} size={32} />
|
||||
</Menu.Button>
|
||||
</MenuButton>
|
||||
</div>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
@@ -57,14 +57,14 @@ export default function AppSelector() {
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items
|
||||
<MenuItems
|
||||
className="
|
||||
absolute -right-2 -top-1 w-60 max-w-80
|
||||
divide-y divide-divider-subtle origin-top-right rounded-lg bg-components-panel-bg-blur
|
||||
divide-divider-subtle bg-components-panel-bg-blur absolute -right-2 -top-1
|
||||
w-60 max-w-80 origin-top-right divide-y rounded-lg
|
||||
shadow-lg
|
||||
"
|
||||
>
|
||||
<Menu.Item>
|
||||
<MenuItem>
|
||||
<div className='p-1'>
|
||||
<div className='flex flex-nowrap items-center px-3 py-2'>
|
||||
<div className='grow'>
|
||||
@@ -74,18 +74,18 @@ export default function AppSelector() {
|
||||
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} size={32} />
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<div className='p-1' onClick={() => handleLogout()}>
|
||||
<div
|
||||
className='flex items-center justify-start h-9 px-3 rounded-lg cursor-pointer group hover:bg-state-base-hover'
|
||||
className='hover:bg-state-base-hover group flex h-9 cursor-pointer items-center justify-start rounded-lg px-3'
|
||||
>
|
||||
<LogOut01 className='w-4 h-4 text-text-tertiary flex mr-1' />
|
||||
<div className='font-normal text-[14px] text-text-secondary'>{t('common.userProfile.logout')}</div>
|
||||
<LogOut01 className='text-text-tertiary mr-1 flex h-4 w-4' />
|
||||
<div className='text-text-secondary text-[14px] font-normal'>{t('common.userProfile.logout')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu.Items>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</Transition>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -29,18 +29,18 @@ export default function CheckEmail(props: DeleteAccountProps) {
|
||||
}, [getDeleteEmailVerifyCode, props])
|
||||
|
||||
return <>
|
||||
<div className='py-1 text-text-destructive body-md-medium'>
|
||||
<div className='text-text-destructive body-md-medium py-1'>
|
||||
{t('common.account.deleteTip')}
|
||||
</div>
|
||||
<div className='pt-1 pb-2 text-text-secondary body-md-regular'>
|
||||
<div className='text-text-secondary body-md-regular pb-2 pt-1'>
|
||||
{t('common.account.deletePrivacyLinkTip')}
|
||||
<Link href='https://dify.ai/privacy' className='text-text-accent'>{t('common.account.deletePrivacyLink')}</Link>
|
||||
</div>
|
||||
<label className='mt-3 mb-1 h-6 flex items-center system-sm-semibold text-text-secondary'>{t('common.account.deleteLabel')}</label>
|
||||
<label className='system-sm-semibold text-text-secondary mb-1 mt-3 flex h-6 items-center'>{t('common.account.deleteLabel')}</label>
|
||||
<Input placeholder={t('common.account.deletePlaceholder') as string} onChange={(e) => {
|
||||
setUserInputEmail(e.target.value)
|
||||
}} />
|
||||
<div className='w-full flex flex-col mt-3 gap-2'>
|
||||
<div className='mt-3 flex w-full flex-col gap-2'>
|
||||
<Button className='w-full' disabled={userInputEmail !== userProfile.email || isSendingEmail} loading={isSendingEmail} variant='primary' onClick={handleConfirm}>{t('common.account.sendVerificationButton')}</Button>
|
||||
<Button className='w-full' onClick={props.onCancel}>{t('common.operation.cancel')}</Button>
|
||||
</div>
|
||||
|
||||
@@ -56,11 +56,11 @@ export default function FeedBack(props: DeleteAccountProps) {
|
||||
className="max-w-[480px]"
|
||||
footer={false}
|
||||
>
|
||||
<label className='mt-3 mb-1 flex items-center system-sm-semibold text-text-secondary'>{t('common.account.feedbackLabel')}</label>
|
||||
<label className='system-sm-semibold text-text-secondary mb-1 mt-3 flex items-center'>{t('common.account.feedbackLabel')}</label>
|
||||
<Textarea rows={6} value={userFeedback} placeholder={t('common.account.feedbackPlaceholder') as string} onChange={(e) => {
|
||||
setUserFeedback(e.target.value)
|
||||
}} />
|
||||
<div className='w-full flex flex-col mt-3 gap-2'>
|
||||
<div className='mt-3 flex w-full flex-col gap-2'>
|
||||
<Button className='w-full' loading={isPending} variant='primary' onClick={handleSubmit}>{t('common.operation.submit')}</Button>
|
||||
<Button className='w-full' onClick={handleSkip}>{t('common.operation.skip')}</Button>
|
||||
</div>
|
||||
|
||||
@@ -35,18 +35,18 @@ export default function VerifyEmail(props: DeleteAccountProps) {
|
||||
catch (error) { console.error(error) }
|
||||
}, [emailToken, verificationCode, confirmDeleteAccount, props])
|
||||
return <>
|
||||
<div className='pt-1 text-text-destructive body-md-medium'>
|
||||
<div className='text-text-destructive body-md-medium pt-1'>
|
||||
{t('common.account.deleteTip')}
|
||||
</div>
|
||||
<div className='pt-1 pb-2 text-text-secondary body-md-regular'>
|
||||
<div className='text-text-secondary body-md-regular pb-2 pt-1'>
|
||||
{t('common.account.deletePrivacyLinkTip')}
|
||||
<Link href='https://dify.ai/privacy' className='text-text-accent'>{t('common.account.deletePrivacyLink')}</Link>
|
||||
</div>
|
||||
<label className='mt-3 mb-1 h-6 flex items-center system-sm-semibold text-text-secondary'>{t('common.account.verificationLabel')}</label>
|
||||
<label className='system-sm-semibold text-text-secondary mb-1 mt-3 flex h-6 items-center'>{t('common.account.verificationLabel')}</label>
|
||||
<Input minLength={6} maxLength={6} placeholder={t('common.account.verificationPlaceholder') as string} onChange={(e) => {
|
||||
setVerificationCode(e.target.value)
|
||||
}} />
|
||||
<div className='w-full flex flex-col mt-3 gap-2'>
|
||||
<div className='mt-3 flex w-full flex-col gap-2'>
|
||||
<Button className='w-full' disabled={shouldButtonDisabled} loading={isDeleting} variant='warning' onClick={handleConfirm}>{t('common.account.permanentlyDeleteButton')}</Button>
|
||||
<Button className='w-full' onClick={props.onCancel}>{t('common.operation.cancel')}</Button>
|
||||
<Countdown onResend={sendEmail} />
|
||||
|
||||
@@ -16,19 +16,19 @@ const Header = () => {
|
||||
return (
|
||||
<div className='flex flex-1 items-center justify-between px-4'>
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='flex items-center cursor-pointer' onClick={back}>
|
||||
<div className='flex cursor-pointer items-center' onClick={back}>
|
||||
<LogoSite className='object-contain' />
|
||||
</div>
|
||||
<div className='w-[1px] h-4 bg-divider-regular' />
|
||||
<div className='bg-divider-regular h-4 w-[1px]' />
|
||||
<p className='text-text-primary title-3xl-semi-bold'>{t('common.account.account')}</p>
|
||||
</div>
|
||||
<div className='flex items-center flex-shrink-0 gap-3'>
|
||||
<Button className='gap-2 py-2 px-3 system-sm-medium' onClick={back}>
|
||||
<RiRobot2Line className='w-4 h-4' />
|
||||
<div className='flex shrink-0 items-center gap-3'>
|
||||
<Button className='system-sm-medium gap-2 px-3 py-2' onClick={back}>
|
||||
<RiRobot2Line className='h-4 w-4' />
|
||||
<p>{t('common.account.studio')}</p>
|
||||
<RiArrowRightUpLine className='w-4 h-4' />
|
||||
<RiArrowRightUpLine className='h-4 w-4' />
|
||||
</Button>
|
||||
<div className='w-[1px] h-4 bg-divider-regular' />
|
||||
<div className='bg-divider-regular h-4 w-[1px]' />
|
||||
<Avatar />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||
<HeaderWrapper>
|
||||
<Header />
|
||||
</HeaderWrapper>
|
||||
<div className='relative flex flex-col overflow-y-auto bg-components-panel-bg shrink-0 h-0 grow'>
|
||||
<div className='bg-components-panel-bg relative flex h-0 shrink-0 grow flex-col overflow-y-auto'>
|
||||
{children}
|
||||
</div>
|
||||
</ModalContextProvider>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AccountPage from './account-page'
|
||||
|
||||
export default function Account() {
|
||||
return <div className='max-w-[640px] w-full mx-auto pt-12 px-6'>
|
||||
return <div className='mx-auto w-full max-w-[640px] px-6 pt-12'>
|
||||
<AccountPage />
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ const ActivateForm = () => {
|
||||
return (
|
||||
<div className={
|
||||
cn(
|
||||
'flex flex-col items-center w-full grow justify-center',
|
||||
'flex w-full grow flex-col items-center justify-center',
|
||||
'px-6',
|
||||
'md:px-[108px]',
|
||||
)
|
||||
@@ -49,11 +49,11 @@ const ActivateForm = () => {
|
||||
{!checkRes && <Loading />}
|
||||
{checkRes && !checkRes.is_valid && (
|
||||
<div className="flex flex-col md:w-[400px]">
|
||||
<div className="w-full mx-auto">
|
||||
<div className="mb-3 flex justify-center items-center w-20 h-20 p-5 rounded-[20px] border border-gray-100 shadow-lg text-[40px] font-bold">🤷♂️</div>
|
||||
<div className="mx-auto w-full">
|
||||
<div className="mb-3 flex h-20 w-20 items-center justify-center rounded-[20px] border border-gray-100 p-5 text-[40px] font-bold shadow-lg">🤷♂️</div>
|
||||
<h2 className="text-[32px] font-bold text-gray-900">{t('login.invalid')}</h2>
|
||||
</div>
|
||||
<div className="w-full mx-auto mt-6">
|
||||
<div className="mx-auto mt-6 w-full">
|
||||
<Button variant='primary' className='w-full !text-sm'>
|
||||
<a href="https://dify.ai">{t('login.explore')}</a>
|
||||
</Button>
|
||||
|
||||
@@ -8,14 +8,14 @@ const Activate = () => {
|
||||
return (
|
||||
<div className={cn(
|
||||
style.background,
|
||||
'flex w-full min-h-screen',
|
||||
'flex min-h-screen w-full',
|
||||
'sm:p-4 lg:p-8',
|
||||
'gap-x-20',
|
||||
'justify-center lg:justify-start',
|
||||
)}>
|
||||
<div className={
|
||||
cn(
|
||||
'flex w-full flex-col bg-white shadow rounded-2xl shrink-0',
|
||||
'flex w-full shrink-0 flex-col rounded-2xl bg-white shadow',
|
||||
'space-between',
|
||||
)
|
||||
}>
|
||||
|
||||
@@ -191,7 +191,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
}}
|
||||
className='block w-full'
|
||||
>
|
||||
<div className={cn('flex rounded-lg', expand ? 'p-2 pb-2.5 flex-col gap-2' : 'p-1 gap-1 justify-center items-start', open && 'bg-state-base-hover', isCurrentWorkspaceEditor && 'hover:bg-state-base-hover cursor-pointer')}>
|
||||
<div className={cn('flex rounded-lg', expand ? 'flex-col gap-2 p-2 pb-2.5' : 'items-start justify-center gap-1 p-1', open && 'bg-state-base-hover', isCurrentWorkspaceEditor && 'hover:bg-state-base-hover cursor-pointer')}>
|
||||
<div className={`flex items-center self-stretch ${expand ? 'justify-between' : 'flex-col gap-1'}`}>
|
||||
<AppIcon
|
||||
size={expand ? 'large' : 'small'}
|
||||
@@ -200,9 +200,9 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
background={appDetail.icon_background}
|
||||
imageUrl={appDetail.icon_url}
|
||||
/>
|
||||
<div className='flex p-0.5 justify-center items-center rounded-md'>
|
||||
<div className='flex w-5 h-5 justify-center items-center'>
|
||||
<RiEqualizer2Line className='w-4 h-4 text-text-tertiary' />
|
||||
<div className='flex items-center justify-center rounded-md p-0.5'>
|
||||
<div className='flex h-5 w-5 items-center justify-center'>
|
||||
<RiEqualizer2Line className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,9 +221,9 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
<ContentDialog
|
||||
show={open}
|
||||
onClose={() => setOpen(false)}
|
||||
className='!p-0 flex flex-col absolute left-2 top-2 bottom-2 w-[420px] rounded-2xl'
|
||||
className='absolute bottom-2 left-2 top-2 flex w-[420px] flex-col rounded-2xl !p-0'
|
||||
>
|
||||
<div className='flex p-4 flex-col justify-center items-start gap-3 self-stretch shrink-0'>
|
||||
<div className='flex shrink-0 flex-col items-start justify-center gap-3 self-stretch p-4'>
|
||||
<div className='flex items-center gap-3 self-stretch'>
|
||||
<AppIcon
|
||||
size="large"
|
||||
@@ -232,8 +232,8 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
background={appDetail.icon_background}
|
||||
imageUrl={appDetail.icon_url}
|
||||
/>
|
||||
<div className='flex flex-col justify-center items-start grow w-full'>
|
||||
<div className='text-text-secondary system-md-semibold truncate w-full'>{appDetail.name}</div>
|
||||
<div className='flex w-full grow flex-col items-start justify-center'>
|
||||
<div className='text-text-secondary system-md-semibold w-full truncate'>{appDetail.name}</div>
|
||||
<div className='text-text-tertiary system-2xs-medium-uppercase'>{appDetail.mode === 'advanced-chat' ? t('app.types.chatbot') : appDetail.mode === 'agent-chat' ? t('app.types.agent') : appDetail.mode === 'chat' ? t('app.types.chatbot') : appDetail.mode === 'completion' ? t('app.types.completion') : t('app.types.workflow')}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -252,7 +252,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
setShowEditModal(true)
|
||||
}}
|
||||
>
|
||||
<RiEditLine className='w-3.5 h-3.5 text-components-button-secondary-text' />
|
||||
<RiEditLine className='text-components-button-secondary-text h-3.5 w-3.5' />
|
||||
<span className='text-components-button-secondary-text system-xs-medium'>{t('app.editApp')}</span>
|
||||
</Button>
|
||||
<Button
|
||||
@@ -264,7 +264,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
setShowDuplicateModal(true)
|
||||
}}
|
||||
>
|
||||
<RiFileCopy2Line className='w-3.5 h-3.5 text-components-button-secondary-text' />
|
||||
<RiFileCopy2Line className='text-components-button-secondary-text h-3.5 w-3.5' />
|
||||
<span className='text-components-button-secondary-text system-xs-medium'>{t('app.duplicate')}</span>
|
||||
</Button>
|
||||
<Button
|
||||
@@ -273,7 +273,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
className='gap-[1px]'
|
||||
onClick={exportCheck}
|
||||
>
|
||||
<RiFileDownloadLine className='w-3.5 h-3.5 text-components-button-secondary-text' />
|
||||
<RiFileDownloadLine className='text-components-button-secondary-text h-3.5 w-3.5' />
|
||||
<span className='text-components-button-secondary-text system-xs-medium'>{t('app.export')}</span>
|
||||
</Button>
|
||||
{
|
||||
@@ -287,7 +287,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
setShowImportDSLModal(true)
|
||||
}}
|
||||
>
|
||||
<RiFileUploadLine className='w-3.5 h-3.5 text-components-button-secondary-text' />
|
||||
<RiFileUploadLine className='text-components-button-secondary-text h-3.5 w-3.5' />
|
||||
<span className='text-components-button-secondary-text system-xs-medium'>{t('workflow.common.importDSL')}</span>
|
||||
</Button>
|
||||
)
|
||||
@@ -298,10 +298,10 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
<CardView
|
||||
appId={appDetail.id}
|
||||
isInPanel={true}
|
||||
className='flex flex-col px-2 py-1 gap-2 grow overflow-auto'
|
||||
className='flex grow flex-col gap-2 overflow-auto px-2 py-1'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex p-2 flex-col justify-center items-start gap-3 self-stretch border-t-[0.5px] border-divider-subtle shrink-0 min-h-fit'>
|
||||
<div className='border-divider-subtle flex min-h-fit shrink-0 flex-col items-start justify-center gap-3 self-stretch border-t-[0.5px] p-2'>
|
||||
<Button
|
||||
size={'medium'}
|
||||
variant={'ghost'}
|
||||
@@ -311,7 +311,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
|
||||
setShowConfirmDelete(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4 text-text-tertiary' />
|
||||
<RiDeleteBinLine className='text-text-tertiary h-4 w-4' />
|
||||
<span className='text-text-tertiary system-sm-medium'>{t('common.operation.deleteApp')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -48,9 +48,9 @@ const NotionSvg = <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xm
|
||||
|
||||
const ICON_MAP = {
|
||||
app: <AppIcon className='border !border-[rgba(0,0,0,0.05)]' />,
|
||||
api: <AppIcon innerIcon={ApiSvg} className='border !bg-purple-50 !border-purple-200' />,
|
||||
dataset: <AppIcon innerIcon={DatasetSvg} className='!border-[0.5px] !border-indigo-100 !bg-indigo-25' />,
|
||||
webapp: <AppIcon innerIcon={WebappSvg} className='border !bg-primary-100 !border-primary-200' />,
|
||||
api: <AppIcon innerIcon={ApiSvg} className='border !border-purple-200 !bg-purple-50' />,
|
||||
dataset: <AppIcon innerIcon={DatasetSvg} className='!bg-indigo-25 !border-[0.5px] !border-indigo-100' />,
|
||||
webapp: <AppIcon innerIcon={WebappSvg} className='!bg-primary-100 !border-primary-200 border' />,
|
||||
notion: <AppIcon innerIcon={NotionSvg} className='!border-[0.5px] !border-indigo-100 !bg-white' />,
|
||||
}
|
||||
|
||||
@@ -58,20 +58,20 @@ export default function AppBasic({ icon, icon_background, name, isExternal, type
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex items-center grow">
|
||||
<div className="flex grow items-center">
|
||||
{icon && icon_background && iconType === 'app' && (
|
||||
<div className='shrink-0 mr-3'>
|
||||
<div className='mr-3 shrink-0'>
|
||||
<AppIcon icon={icon} background={icon_background} />
|
||||
</div>
|
||||
)}
|
||||
{iconType !== 'app'
|
||||
&& <div className='shrink-0 mr-3'>
|
||||
&& <div className='mr-3 shrink-0'>
|
||||
{ICON_MAP[iconType]}
|
||||
</div>
|
||||
|
||||
}
|
||||
{mode === 'expand' && <div className="group">
|
||||
<div className={`flex flex-row items-center system-md-semibold text-text-secondary group-hover:text-text-primary ${textStyle?.main ?? ''}`}>
|
||||
<div className={`system-md-semibold text-text-secondary group-hover:text-text-primary flex flex-row items-center ${textStyle?.main ?? ''}`}>
|
||||
<div className="max-w-[180px] truncate">
|
||||
{name}
|
||||
</div>
|
||||
|
||||
@@ -26,16 +26,16 @@ const DatasetInfo: FC<Props> = ({
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='pl-1 pt-1'>
|
||||
<div className='flex-shrink-0 mr-3'>
|
||||
<AppIcon innerIcon={DatasetSvg} className='!border-[0.5px] !border-indigo-100 !bg-indigo-25' />
|
||||
<div className='mr-3 shrink-0'>
|
||||
<AppIcon innerIcon={DatasetSvg} className='!bg-indigo-25 !border-[0.5px] !border-indigo-100' />
|
||||
</div>
|
||||
{expand && (
|
||||
<div className='mt-2'>
|
||||
<div className='system-md-semibold text-text-secondary'>
|
||||
{name}
|
||||
</div>
|
||||
<div className='mt-1 text-text-tertiary system-2xs-medium-uppercase'>{isExternal ? t('dataset.externalTag') : t('dataset.localDocs')}</div>
|
||||
<div className='my-3 system-xs-regular text-text-tertiary first-letter:capitalize'>{description}</div>
|
||||
<div className='text-text-tertiary system-2xs-medium-uppercase mt-1'>{isExternal ? t('dataset.externalTag') : t('dataset.localDocs')}</div>
|
||||
<div className='system-xs-regular text-text-tertiary my-3 first-letter:capitalize'>{description}</div>
|
||||
</div>
|
||||
)}
|
||||
{extraInfo}
|
||||
|
||||
@@ -50,7 +50,7 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
shrink-0 flex flex-col bg-background-default-subtle border-r border-divider-burn transition-all
|
||||
bg-background-default-subtle border-divider-burn flex shrink-0 flex-col border-r transition-all
|
||||
${expand ? 'w-[216px]' : 'w-14'}
|
||||
`}
|
||||
>
|
||||
@@ -85,7 +85,7 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
||||
)}
|
||||
</div>
|
||||
<div className='px-4'>
|
||||
<div className={cn('mt-1 mx-auto h-[1px] bg-divider-subtle', !expand && 'w-6')} />
|
||||
<div className={cn('bg-divider-subtle mx-auto mt-1 h-[1px]', !expand && 'w-6')} />
|
||||
</div>
|
||||
<nav
|
||||
className={`
|
||||
@@ -108,13 +108,13 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className='flex items-center justify-center w-6 h-6 text-gray-500 cursor-pointer'
|
||||
className='flex h-6 w-6 cursor-pointer items-center justify-center text-gray-500'
|
||||
onClick={() => handleToggle(appSidebarExpand)}
|
||||
>
|
||||
{
|
||||
expand
|
||||
? <RiLayoutRight2Line className='w-5 h-5 text-components-menu-item-text' />
|
||||
: <LayoutRight2LineMod className='w-5 h-5 text-components-menu-item-text' />
|
||||
? <RiLayoutRight2Line className='text-components-menu-item-text h-5 w-5' />
|
||||
: <LayoutRight2LineMod className='text-components-menu-item-text h-5 w-5' />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,17 +21,17 @@ const EditItem: FC<Props> = ({
|
||||
onChange,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const avatar = type === EditItemType.Query ? <User className='w-6 h-6' /> : <Robot className='w-6 h-6' />
|
||||
const avatar = type === EditItemType.Query ? <User className='h-6 w-6' /> : <Robot className='h-6 w-6' />
|
||||
const name = type === EditItemType.Query ? t('appAnnotation.addModal.queryName') : t('appAnnotation.addModal.answerName')
|
||||
const placeholder = type === EditItemType.Query ? t('appAnnotation.addModal.queryPlaceholder') : t('appAnnotation.addModal.answerPlaceholder')
|
||||
|
||||
return (
|
||||
<div className='flex' onClick={e => e.stopPropagation()}>
|
||||
<div className='shrink-0 mr-3'>
|
||||
<div className='mr-3 shrink-0'>
|
||||
{avatar}
|
||||
</div>
|
||||
<div className='grow'>
|
||||
<div className='mb-1 system-xs-semibold text-text-primary'>{name}</div>
|
||||
<div className='system-xs-semibold text-text-primary mb-1'>{name}</div>
|
||||
<Textarea
|
||||
value={content}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}
|
||||
|
||||
@@ -76,7 +76,7 @@ const AddAnnotationModal: FC<Props> = ({
|
||||
maxWidthClassName='!max-w-[480px]'
|
||||
title={t('appAnnotation.addModal.title') as string}
|
||||
body={(
|
||||
<div className='p-6 pb-4 space-y-6'>
|
||||
<div className='space-y-6 p-6 pb-4'>
|
||||
<EditItem
|
||||
type={EditItemType.Query}
|
||||
content={question}
|
||||
@@ -93,11 +93,11 @@ const AddAnnotationModal: FC<Props> = ({
|
||||
(
|
||||
<div>
|
||||
{isAnnotationFull && (
|
||||
<div className='mt-6 mb-4 px-6'>
|
||||
<div className='mb-4 mt-6 px-6'>
|
||||
<AnnotationFull />
|
||||
</div>
|
||||
)}
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div className='border-divider-subtle bg-background-section-burn system-sm-medium text-text-tertiary flex h-16 items-center justify-between rounded-bl-xl rounded-br-xl border-t px-4'>
|
||||
<div
|
||||
className='flex items-center space-x-2'
|
||||
>
|
||||
|
||||
@@ -35,17 +35,17 @@ const CSVDownload: FC = () => {
|
||||
<div className='mt-6'>
|
||||
<div className='system-sm-medium text-text-primary'>{t('share.generation.csvStructureTitle')}</div>
|
||||
<div className='mt-2 max-h-[500px] overflow-auto'>
|
||||
<table className='table-fixed w-full border-separate border-spacing-0 border border-divider-regular rounded-lg text-xs'>
|
||||
<table className='border-divider-regular w-full table-fixed border-separate border-spacing-0 rounded-lg border text-xs'>
|
||||
<thead className='text-text-tertiary'>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-regular'>{t('appAnnotation.batchModal.question')}</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-regular'>{t('appAnnotation.batchModal.answer')}</td>
|
||||
<td className='border-divider-regular h-9 border-b pl-3 pr-2'>{t('appAnnotation.batchModal.question')}</td>
|
||||
<td className='border-divider-regular h-9 border-b pl-3 pr-2'>{t('appAnnotation.batchModal.answer')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className='text-gray-700'>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-subtle text-[13px]'>{t('appAnnotation.batchModal.question')} 1</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-subtle text-[13px]'>{t('appAnnotation.batchModal.answer')} 1</td>
|
||||
<td className='border-divider-subtle h-9 border-b pl-3 pr-2 text-[13px]'>{t('appAnnotation.batchModal.question')} 1</td>
|
||||
<td className='border-divider-subtle h-9 border-b pl-3 pr-2 text-[13px]'>{t('appAnnotation.batchModal.answer')} 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 text-[13px]'>{t('appAnnotation.batchModal.question')} 2</td>
|
||||
@@ -55,14 +55,14 @@ const CSVDownload: FC = () => {
|
||||
</table>
|
||||
</div>
|
||||
<CSVDownloader
|
||||
className="block mt-2 cursor-pointer"
|
||||
className="mt-2 block cursor-pointer"
|
||||
type={Type.Link}
|
||||
filename={`template-${locale}`}
|
||||
bom={true}
|
||||
data={getTemplate()}
|
||||
>
|
||||
<div className='flex items-center h-[18px] space-x-1 text-text-accent system-xs-medium'>
|
||||
<DownloadIcon className='w-3 h-3 mr-1' />
|
||||
<div className='text-text-accent system-xs-medium flex h-[18px] items-center space-x-1'>
|
||||
<DownloadIcon className='mr-1 h-3 w-3' />
|
||||
{t('appAnnotation.batchModal.template')}
|
||||
</div>
|
||||
</CSVDownloader>
|
||||
|
||||
@@ -91,29 +91,29 @@ const CSVUploader: FC<Props> = ({
|
||||
/>
|
||||
<div ref={dropRef}>
|
||||
{!file && (
|
||||
<div className={cn('flex items-center h-20 rounded-xl bg-components-dropzone-bg border border-dashed border-components-dropzone-border system-sm-regular', dragging && 'bg-components-dropzone-bg-accent border border-components-dropzone-border-accent')}>
|
||||
<div className='w-full flex items-center justify-center space-x-2'>
|
||||
<div className={cn('bg-components-dropzone-bg border-components-dropzone-border system-sm-regular flex h-20 items-center rounded-xl border border-dashed', dragging && 'bg-components-dropzone-bg-accent border-components-dropzone-border-accent border')}>
|
||||
<div className='flex w-full items-center justify-center space-x-2'>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='text-text-tertiary'>
|
||||
{t('appAnnotation.batchModal.csvUploadTitle')}
|
||||
<span className='text-text-accent cursor-pointer' onClick={selectHandle}>{t('appAnnotation.batchModal.browse')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{dragging && <div ref={dragRef} className='absolute w-full h-full top-0 left-0' />}
|
||||
{dragging && <div ref={dragRef} className='absolute left-0 top-0 h-full w-full' />}
|
||||
</div>
|
||||
)}
|
||||
{file && (
|
||||
<div className={cn('flex items-center h-20 px-6 rounded-xl bg-components-panel-bg border border-components-panel-border text-sm font-normal group', 'hover:bg-components-panel-bg-blur hover:border-components-panel-bg-blur')}>
|
||||
<div className={cn('bg-components-panel-bg border-components-panel-border group flex h-20 items-center rounded-xl border px-6 text-sm font-normal', 'hover:bg-components-panel-bg-blur hover:border-components-panel-bg-blur')}>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='flex ml-2 w-0 grow'>
|
||||
<span className='max-w-[calc(100%_-_30px)] text-ellipsis whitespace-nowrap overflow-hidden text-text-primary'>{file.name.replace(/.csv$/, '')}</span>
|
||||
<span className='shrink-0 text-text-tertiary'>.csv</span>
|
||||
<div className='ml-2 flex w-0 grow'>
|
||||
<span className='text-text-primary max-w-[calc(100%_-_30px)] overflow-hidden text-ellipsis whitespace-nowrap'>{file.name.replace(/.csv$/, '')}</span>
|
||||
<span className='text-text-tertiary shrink-0'>.csv</span>
|
||||
</div>
|
||||
<div className='hidden group-hover:flex items-center'>
|
||||
<div className='hidden items-center group-hover:flex'>
|
||||
<Button variant='secondary' onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.change')}</Button>
|
||||
<div className='mx-2 w-px h-4 bg-divider-regular' />
|
||||
<div className='p-2 cursor-pointer' onClick={removeFile}>
|
||||
<RiDeleteBinLine className='w-4 h-4 text-text-tertiary' />
|
||||
<div className='bg-divider-regular mx-2 h-4 w-px' />
|
||||
<div className='cursor-pointer p-2' onClick={removeFile}>
|
||||
<RiDeleteBinLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,10 +87,10 @@ const BatchModal: FC<IBatchModalProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={() => { }} className='px-8 py-6 !max-w-[520px] !rounded-xl'>
|
||||
<div className='relative pb-1 system-xl-medium text-text-primary'>{t('appAnnotation.batchModal.title')}</div>
|
||||
<div className='absolute right-4 top-4 p-2 cursor-pointer' onClick={onCancel}>
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
<Modal isShow={isShow} onClose={() => { }} className='!max-w-[520px] !rounded-xl px-8 py-6'>
|
||||
<div className='system-xl-medium text-text-primary relative pb-1'>{t('appAnnotation.batchModal.title')}</div>
|
||||
<div className='absolute right-4 top-4 cursor-pointer p-2' onClick={onCancel}>
|
||||
<RiCloseLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
<CSVUploader
|
||||
file={currentCSV}
|
||||
@@ -104,8 +104,8 @@ const BatchModal: FC<IBatchModalProps> = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='mt-[28px] pt-6 flex justify-end'>
|
||||
<Button className='mr-2 text-text-tertiary system-sm-medium' onClick={onCancel}>
|
||||
<div className='mt-[28px] flex justify-end pt-6'>
|
||||
<Button className='text-text-tertiary system-sm-medium mr-2' onClick={onCancel}>
|
||||
{t('appAnnotation.batchModal.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -20,11 +20,11 @@ type Props = {
|
||||
}
|
||||
|
||||
export const EditTitle: FC<{ className?: string; title: string }> = ({ className, title }) => (
|
||||
<div className={cn(className, 'flex items-center h-[18px] system-xs-medium text-text-tertiary')}>
|
||||
<RiEditFill className='mr-1 w-3.5 h-3.5' />
|
||||
<div className={cn(className, 'system-xs-medium text-text-tertiary flex h-[18px] items-center')}>
|
||||
<RiEditFill className='mr-1 h-3.5 w-3.5' />
|
||||
<div>{title}</div>
|
||||
<div
|
||||
className='ml-2 grow h-[1px]'
|
||||
className='ml-2 h-[1px] grow'
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, rgba(0, 0, 0, 0.05) -1.65%, rgba(0, 0, 0, 0.00) 100%)',
|
||||
}}
|
||||
@@ -40,7 +40,7 @@ const EditItem: FC<Props> = ({
|
||||
const { t } = useTranslation()
|
||||
const [newContent, setNewContent] = useState('')
|
||||
const showNewContent = newContent && newContent !== content
|
||||
const avatar = type === EditItemType.Query ? <User className='w-6 h-6' /> : <Robot className='w-6 h-6' />
|
||||
const avatar = type === EditItemType.Query ? <User className='h-6 w-6' /> : <Robot className='h-6 w-6' />
|
||||
const name = type === EditItemType.Query ? t('appAnnotation.editModal.queryName') : t('appAnnotation.editModal.answerName')
|
||||
const editTitle = type === EditItemType.Query ? t('appAnnotation.editModal.yourQuery') : t('appAnnotation.editModal.yourAnswer')
|
||||
const placeholder = type === EditItemType.Query ? t('appAnnotation.editModal.queryPlaceholder') : t('appAnnotation.editModal.answerPlaceholder')
|
||||
@@ -58,11 +58,11 @@ const EditItem: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<div className='flex' onClick={e => e.stopPropagation()}>
|
||||
<div className='shrink-0 mr-3'>
|
||||
<div className='mr-3 shrink-0'>
|
||||
{avatar}
|
||||
</div>
|
||||
<div className='grow'>
|
||||
<div className='mb-1 system-xs-semibold text-text-primary'>{name}</div>
|
||||
<div className='system-xs-semibold text-text-primary mb-1'>{name}</div>
|
||||
<div className='system-sm-regular text-text-primary'>{content}</div>
|
||||
{!isEdit
|
||||
? (
|
||||
@@ -70,34 +70,34 @@ const EditItem: FC<Props> = ({
|
||||
{showNewContent && (
|
||||
<div className='mt-3'>
|
||||
<EditTitle title={editTitle} />
|
||||
<div className='mt-1 system-sm-regular text-text-primary'>{newContent}</div>
|
||||
<div className='system-sm-regular text-text-primary mt-1'>{newContent}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='mt-2 flex items-center'>
|
||||
{!readonly && (
|
||||
<div
|
||||
className='flex items-center space-x-1 system-xs-medium text-text-accent cursor-pointer'
|
||||
className='system-xs-medium text-text-accent flex cursor-pointer items-center space-x-1'
|
||||
onClick={() => {
|
||||
setIsEdit(true)
|
||||
}}
|
||||
>
|
||||
<RiEditLine className='mr-1 w-3.5 h-3.5' />
|
||||
<RiEditLine className='mr-1 h-3.5 w-3.5' />
|
||||
<div>{t('common.operation.edit')}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showNewContent && (
|
||||
<div className='ml-2 flex items-center system-xs-medium text-text-tertiary'>
|
||||
<div className='system-xs-medium text-text-tertiary ml-2 flex items-center'>
|
||||
<div className='mr-2'>·</div>
|
||||
<div
|
||||
className='flex items-center space-x-1 cursor-pointer'
|
||||
className='flex cursor-pointer items-center space-x-1'
|
||||
onClick={() => {
|
||||
setNewContent(content)
|
||||
onSave(content)
|
||||
}}
|
||||
>
|
||||
<div className='w-3.5 h-3.5'>
|
||||
<RiDeleteBinLine className='w-3.5 h-3.5' />
|
||||
<div className='h-3.5 w-3.5'>
|
||||
<RiDeleteBinLine className='h-3.5 w-3.5' />
|
||||
</div>
|
||||
<div>{t('common.operation.delete')}</div>
|
||||
</div>
|
||||
|
||||
@@ -86,7 +86,7 @@ const EditAnnotationModal: FC<Props> = ({
|
||||
title={t('appAnnotation.editModal.title') as string}
|
||||
body={(
|
||||
<div>
|
||||
<div className='p-6 pb-4 space-y-6'>
|
||||
<div className='space-y-6 p-6 pb-4'>
|
||||
<EditItem
|
||||
type={EditItemType.Query}
|
||||
content={query}
|
||||
@@ -115,7 +115,7 @@ const EditAnnotationModal: FC<Props> = ({
|
||||
foot={
|
||||
<div>
|
||||
{isAnnotationFull && (
|
||||
<div className='mt-6 mb-4 px-6'>
|
||||
<div className='mb-4 mt-6 px-6'>
|
||||
<AnnotationFull />
|
||||
</div>
|
||||
)}
|
||||
@@ -123,9 +123,9 @@ const EditAnnotationModal: FC<Props> = ({
|
||||
{
|
||||
annotationId
|
||||
? (
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div className='border-divider-subtle bg-background-section-burn system-sm-medium text-text-tertiary flex h-16 items-center justify-between rounded-bl-xl rounded-br-xl border-t px-4'>
|
||||
<div
|
||||
className='flex items-center pl-3 space-x-2 cursor-pointer'
|
||||
className='flex cursor-pointer items-center space-x-2 pl-3'
|
||||
onClick={() => setShowModal(true)}
|
||||
>
|
||||
<MessageCheckRemove />
|
||||
|
||||
@@ -13,10 +13,10 @@ const EmptyElement: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex items-center justify-center h-full'>
|
||||
<div className='bg-background-section-burn w-[560px] h-fit box-border px-5 py-4 rounded-2xl'>
|
||||
<span className='text-text-secondary system-md-semibold'>{t('appAnnotation.noData.title')}<ThreeDotsIcon className='inline relative -top-3 -left-1.5' /></span>
|
||||
<div className='mt-2 text-text-tertiary system-sm-regular'>
|
||||
<div className='flex h-full items-center justify-center'>
|
||||
<div className='bg-background-section-burn box-border h-fit w-[560px] rounded-2xl px-5 py-4'>
|
||||
<span className='text-text-secondary system-md-semibold'>{t('appAnnotation.noData.title')}<ThreeDotsIcon className='relative -left-1.5 -top-3 inline' /></span>
|
||||
<div className='text-text-tertiary system-sm-regular mt-2'>
|
||||
{t('appAnnotation.noData.description')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@ interface IFilterProps {
|
||||
appId: string
|
||||
queryParams: QueryParam
|
||||
setQueryParams: (v: QueryParam) => void
|
||||
children: JSX.Element
|
||||
children: React.JSX.Element
|
||||
}
|
||||
|
||||
const Filter: FC<IFilterProps> = ({
|
||||
@@ -29,7 +29,7 @@ const Filter: FC<IFilterProps> = ({
|
||||
if (!data)
|
||||
return null
|
||||
return (
|
||||
<div className='flex justify-between flex-row flex-wrap gap-2 items-center mb-2'>
|
||||
<div className='mb-2 flex flex-row flex-wrap items-center justify-between gap-2'>
|
||||
<Input
|
||||
wrapperClassName='w-[200px]'
|
||||
showLeftIcon
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
useCSVDownloader,
|
||||
} from 'react-papaparse'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Menu, MenuButton, MenuItems, Transition } from '@headlessui/react'
|
||||
import Button from '../../../base/button'
|
||||
import AddAnnotationModal from '../add-annotation-modal'
|
||||
import type { AnnotationItemBasic } from '../type'
|
||||
@@ -80,18 +80,18 @@ const HeaderOptions: FC<Props> = ({
|
||||
const Operations = () => {
|
||||
return (
|
||||
<div className="w-full py-1">
|
||||
<button className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]' onClick={() => {
|
||||
<button className='hover:bg-components-panel-on-panel-item-bg-hover mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 disabled:opacity-50' onClick={() => {
|
||||
setShowBulkImportModal(true)
|
||||
}}>
|
||||
<FilePlus02 className='w-4 h-4 text-text-tertiary' />
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>{t('appAnnotation.table.header.bulkImport')}</span>
|
||||
<FilePlus02 className='text-text-tertiary h-4 w-4' />
|
||||
<span className='text-text-secondary system-sm-regular grow text-left'>{t('appAnnotation.table.header.bulkImport')}</span>
|
||||
</button>
|
||||
<Menu as="div" className="relative w-full h-full">
|
||||
<Menu.Button className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]'>
|
||||
<FileDownload02 className='w-4 h-4 text-text-tertiary' />
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>{t('appAnnotation.table.header.bulkExport')}</span>
|
||||
<ChevronRight className='shrink-0 w-[14px] h-[14px] text-text-tertiary' />
|
||||
</Menu.Button>
|
||||
<Menu as="div" className="relative h-full w-full">
|
||||
<MenuButton className='hover:bg-components-panel-on-panel-item-bg-hover mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 disabled:opacity-50'>
|
||||
<FileDownload02 className='text-text-tertiary h-4 w-4' />
|
||||
<span className='text-text-secondary system-sm-regular grow text-left'>{t('appAnnotation.table.header.bulkExport')}</span>
|
||||
<ChevronRight className='text-text-tertiary h-[14px] w-[14px] shrink-0' />
|
||||
</MenuButton>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
@@ -101,9 +101,9 @@ const HeaderOptions: FC<Props> = ({
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items
|
||||
<MenuItems
|
||||
className={cn(
|
||||
'absolute top-[1px] left-1 -translate-x-full py-1 min-w-[100px] z-10 bg-components-panel-bg border-[0.5px] border-components-panel-on-panel-item-bg origin-top-right rounded-xl shadow-xs',
|
||||
'bg-components-panel-bg border-components-panel-on-panel-item-bg shadow-xs absolute left-1 top-[1px] z-10 min-w-[100px] origin-top-right -translate-x-full rounded-xl border-[0.5px] py-1',
|
||||
)}
|
||||
>
|
||||
<CSVDownloader
|
||||
@@ -115,14 +115,14 @@ const HeaderOptions: FC<Props> = ({
|
||||
...list.map(item => [item.question, item.answer]),
|
||||
]}
|
||||
>
|
||||
<button disabled={annotationUnavailable} className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]'>
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>CSV</span>
|
||||
<button disabled={annotationUnavailable} className='hover:bg-components-panel-on-panel-item-bg-hover mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 disabled:opacity-50'>
|
||||
<span className='text-text-secondary system-sm-regular grow text-left'>CSV</span>
|
||||
</button>
|
||||
</CSVDownloader>
|
||||
<button disabled={annotationUnavailable} className={cn('h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]', '!border-0')} onClick={JSONLOutput}>
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>JSONL</span>
|
||||
<button disabled={annotationUnavailable} className={cn('hover:bg-components-panel-on-panel-item-bg-hover mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 disabled:opacity-50', '!border-0')} onClick={JSONLOutput}>
|
||||
<span className='text-text-secondary system-sm-regular grow text-left'>JSONL</span>
|
||||
</button>
|
||||
</Menu.Items>
|
||||
</MenuItems>
|
||||
</Transition>
|
||||
</Menu>
|
||||
</div>
|
||||
@@ -134,7 +134,7 @@ const HeaderOptions: FC<Props> = ({
|
||||
return (
|
||||
<div className='flex space-x-2'>
|
||||
<Button variant='primary' onClick={() => setShowAddModal(true)}>
|
||||
<RiAddLine className='w-4 h-4 mr-0.5' />
|
||||
<RiAddLine className='mr-0.5 h-4 w-4' />
|
||||
<div>{t('appAnnotation.table.header.addAnnotation')}</div>
|
||||
</Button>
|
||||
<CustomPopover
|
||||
@@ -143,11 +143,11 @@ const HeaderOptions: FC<Props> = ({
|
||||
trigger="click"
|
||||
btnElement={
|
||||
<Button variant='secondary' className='w-8 p-0'>
|
||||
<RiMoreFill className='w-4 h-4' />
|
||||
<RiMoreFill className='h-4 w-4' />
|
||||
</Button>
|
||||
}
|
||||
btnClassName='p-0 border-0'
|
||||
className={'!w-[155px] h-fit !z-20'}
|
||||
className={'!z-20 h-fit !w-[155px]'}
|
||||
popupClassName='!w-full !overflow-visible'
|
||||
manualClose
|
||||
/>
|
||||
|
||||
@@ -152,15 +152,15 @@ const Annotation: FC<Props> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-col h-full'>
|
||||
<div className='flex h-full flex-col'>
|
||||
<p className='text-text-tertiary system-sm-regular'>{t('appLog.description')}</p>
|
||||
<div className='flex flex-col py-4 flex-1'>
|
||||
<div className='flex flex-1 flex-col py-4'>
|
||||
<Filter appId={appDetail.id} queryParams={queryParams} setQueryParams={setQueryParams}>
|
||||
<div className='flex items-center space-x-2'>
|
||||
{isChatApp && (
|
||||
<>
|
||||
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'flex items-center h-7 rounded-lg bg-components-panel-bg-blur border border-components-panel-border pl-2 space-x-1')}>
|
||||
<MessageFast className='w-4 h-4 text-util-colors-indigo-indigo-600' />
|
||||
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'bg-components-panel-bg-blur border-components-panel-border flex h-7 items-center space-x-1 rounded-lg border pl-2')}>
|
||||
<MessageFast className='text-util-colors-indigo-indigo-600 h-4 w-4' />
|
||||
<div className='system-sm-medium text-text-primary'>{t('appAnnotation.name')}</div>
|
||||
<Switch
|
||||
key={controlRefreshSwitch}
|
||||
@@ -188,14 +188,14 @@ const Annotation: FC<Props> = ({
|
||||
></Switch>
|
||||
{annotationConfig?.enabled && (
|
||||
<div className='flex items-center pl-1.5'>
|
||||
<div className='shrink-0 mr-1 w-[1px] h-3.5 bg-divider-subtle'></div>
|
||||
<div className='bg-divider-subtle mr-1 h-3.5 w-[1px] shrink-0'></div>
|
||||
<ActionButton onClick={() => setIsShowEdit(true)}>
|
||||
<RiEqualizer2Line className='w-4 h-4 text-text-tertiary' />
|
||||
<RiEqualizer2Line className='text-text-tertiary h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='shrink-0 mx-3 w-[1px] h-3.5 bg-divider-regular'></div>
|
||||
<div className='bg-divider-regular mx-3 h-3.5 w-[1px] shrink-0'></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -217,7 +217,7 @@ const Annotation: FC<Props> = ({
|
||||
onRemove={handleRemove}
|
||||
onView={handleView}
|
||||
/>
|
||||
: <div className='grow flex h-full items-center justify-center'><EmptyElement /></div>
|
||||
: <div className='flex h-full grow items-center justify-center'><EmptyElement /></div>
|
||||
}
|
||||
{/* Show Pagination only if the total is more than the limit */}
|
||||
{(total && total > APP_PAGE_LIMIT)
|
||||
|
||||
@@ -29,18 +29,18 @@ const List: FC<Props> = ({
|
||||
<table className={cn('mt-2 w-full min-w-[440px] border-collapse border-0')}>
|
||||
<thead className='system-xs-medium-uppercase text-text-tertiary'>
|
||||
<tr>
|
||||
<td className='pl-2 pr-1 w-5 rounded-l-lg bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.table.header.question')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.table.header.answer')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.table.header.createdAt')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.table.header.hits')}</td>
|
||||
<td className='pl-3 py-1.5 rounded-r-lg bg-background-section-burn whitespace-nowrap w-[96px]'>{t('appAnnotation.table.header.actions')}</td>
|
||||
<td className='bg-background-section-burn w-5 whitespace-nowrap rounded-l-lg pl-2 pr-1'>{t('appAnnotation.table.header.question')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.table.header.answer')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.table.header.createdAt')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.table.header.hits')}</td>
|
||||
<td className='bg-background-section-burn w-[96px] whitespace-nowrap rounded-r-lg py-1.5 pl-3'>{t('appAnnotation.table.header.actions')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-text-secondary system-sm-regular">
|
||||
{list.map(item => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className='border-b border-divider-subtle hover:bg-background-default-hover cursor-pointer'
|
||||
className='border-divider-subtle hover:bg-background-default-hover cursor-pointer border-b'
|
||||
onClick={
|
||||
() => {
|
||||
onView(item)
|
||||
@@ -48,20 +48,20 @@ const List: FC<Props> = ({
|
||||
}
|
||||
>
|
||||
<td
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2'
|
||||
title={item.question}
|
||||
>{item.question}</td>
|
||||
<td
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2'
|
||||
title={item.answer}
|
||||
>{item.answer}</td>
|
||||
<td className='p-3 pr-2'>{formatTime(item.created_at, t('appLog.dateTimeFormat') as string)}</td>
|
||||
<td className='p-3 pr-2'>{item.hit_count}</td>
|
||||
<td className='w-[96px] p-3 pr-2' onClick={e => e.stopPropagation()}>
|
||||
{/* Actions */}
|
||||
<div className='flex space-x-1 text-text-tertiary'>
|
||||
<div className='text-text-tertiary flex space-x-1'>
|
||||
<ActionButton onClick={() => onView(item)}>
|
||||
<RiEditLine className='w-4 h-4' />
|
||||
<RiEditLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
onClick={() => {
|
||||
@@ -69,7 +69,7 @@ const List: FC<Props> = ({
|
||||
setShowConfirmDelete(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -7,9 +7,9 @@ import { ClockFastForward } from '@/app/components/base/icons/src/vender/line/ti
|
||||
const HitHistoryNoData: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='mx-auto mt-20 w-[480px] p-5 rounded-2xl bg-background-section-burn space-y-2'>
|
||||
<div className='inline-block p-3 rounded-lg border border-divider-subtle'>
|
||||
<ClockFastForward className='w-5 h-5 text-text-tertiary' />
|
||||
<div className='bg-background-section-burn mx-auto mt-20 w-[480px] space-y-2 rounded-2xl p-5'>
|
||||
<div className='border-divider-subtle inline-block rounded-lg border p-3'>
|
||||
<ClockFastForward className='text-text-tertiary h-5 w-5' />
|
||||
</div>
|
||||
<div className='system-sm-regular text-text-tertiary'>{t('appAnnotation.viewModal.noHitHistory')}</div>
|
||||
</div>
|
||||
|
||||
@@ -116,30 +116,30 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
<table className={cn('w-full min-w-[440px] border-collapse border-0')} >
|
||||
<thead className="system-xs-medium-uppercase text-text-tertiary">
|
||||
<tr>
|
||||
<td className='pl-2 pr-1 w-5 rounded-l-lg bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.query')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.match')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.response')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.source')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.score')}</td>
|
||||
<td className='pl-3 py-1.5 rounded-r-lg bg-background-section-burn whitespace-nowrap w-[160px]'>{t('appAnnotation.hitHistoryTable.time')}</td>
|
||||
<td className='bg-background-section-burn w-5 whitespace-nowrap rounded-l-lg pl-2 pr-1'>{t('appAnnotation.hitHistoryTable.query')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.hitHistoryTable.match')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.hitHistoryTable.response')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.hitHistoryTable.source')}</td>
|
||||
<td className='bg-background-section-burn whitespace-nowrap py-1.5 pl-3'>{t('appAnnotation.hitHistoryTable.score')}</td>
|
||||
<td className='bg-background-section-burn w-[160px] whitespace-nowrap rounded-r-lg py-1.5 pl-3'>{t('appAnnotation.hitHistoryTable.time')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-text-secondary system-sm-regular">
|
||||
{hitHistoryList.map(item => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className={'border-b border-divider-subtle hover:bg-background-default-hover cursor-pointer'}
|
||||
className={'border-divider-subtle hover:bg-background-default-hover cursor-pointer border-b'}
|
||||
>
|
||||
<td
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2'
|
||||
title={item.question}
|
||||
>{item.question}</td>
|
||||
<td
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2'
|
||||
title={item.match}
|
||||
>{item.match}</td>
|
||||
<td
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2'
|
||||
title={item.response}
|
||||
>{item.response}</td>
|
||||
<td className='p-3 pr-2'>{item.source}</td>
|
||||
@@ -168,7 +168,7 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
maxWidthClassName='!max-w-[800px]'
|
||||
title={
|
||||
<TabSlider
|
||||
className='shrink-0 relative top-[9px]'
|
||||
className='relative top-[9px] shrink-0'
|
||||
value={activeTab}
|
||||
onChange={v => setActiveTab(v as TabType)}
|
||||
options={tabs}
|
||||
@@ -178,7 +178,7 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
}
|
||||
body={(
|
||||
<div>
|
||||
<div className='p-6 pb-4 space-y-6'>
|
||||
<div className='space-y-6 p-6 pb-4'>
|
||||
{activeTab === TabType.annotation ? annotationTab : hitHistoryTab}
|
||||
</div>
|
||||
<Confirm
|
||||
@@ -195,9 +195,9 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
)}
|
||||
foot={id
|
||||
? (
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div className='border-divider-subtle bg-background-section-burn system-sm-medium text-text-tertiary flex h-16 items-center justify-between rounded-bl-xl rounded-br-xl border-t px-4'>
|
||||
<div
|
||||
className='flex items-center pl-3 space-x-2 cursor-pointer'
|
||||
className='flex cursor-pointer items-center space-x-2 pl-3'
|
||||
onClick={() => setShowModal(true)}
|
||||
>
|
||||
<MessageCheckRemove />
|
||||
|
||||
@@ -139,19 +139,19 @@ const AppPublisher = ({
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('workflow.common.publish')}
|
||||
<RiArrowDownSLine className='w-4 h-4 ml-0.5' />
|
||||
<RiArrowDownSLine className='ml-0.5 h-4 w-4' />
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[11]'>
|
||||
<div className='w-[336px] bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl'>
|
||||
<div className='bg-components-panel-bg border-components-panel-border w-[336px] rounded-2xl border-[0.5px] shadow-xl'>
|
||||
<div className='p-4 pt-3'>
|
||||
<div className='flex items-center h-6 system-xs-medium-uppercase text-text-tertiary'>
|
||||
<div className='system-xs-medium-uppercase text-text-tertiary flex h-6 items-center'>
|
||||
{publishedAt ? t('workflow.common.latestPublished') : t('workflow.common.currentDraftUnpublished')}
|
||||
</div>
|
||||
{publishedAt
|
||||
? (
|
||||
<div className='flex justify-between items-center h-[18px]'>
|
||||
<div className='flex items-center mt-[3px] mb-[3px] leading-[18px] text-[13px] font-medium text-text-secondary'>
|
||||
<div className='flex h-[18px] items-center justify-between'>
|
||||
<div className='text-text-secondary mb-[3px] mt-[3px] flex items-center text-[13px] font-medium leading-[18px]'>
|
||||
{t('workflow.common.publishedAt')} {formatTimeFromNow(publishedAt)}
|
||||
</div>
|
||||
<Button
|
||||
@@ -165,7 +165,7 @@ const AppPublisher = ({
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className='flex items-center h-[18px] leading-[18px] text-[13px] font-medium text-text-secondary'>
|
||||
<div className='text-text-secondary flex h-[18px] items-center text-[13px] font-medium leading-[18px]'>
|
||||
{t('workflow.common.autoSaved')} · {Boolean(draftUpdatedAt) && formatTimeFromNow(draftUpdatedAt!)}
|
||||
</div>
|
||||
)}
|
||||
@@ -180,7 +180,7 @@ const AppPublisher = ({
|
||||
: (
|
||||
<Button
|
||||
variant='primary'
|
||||
className='w-full mt-3'
|
||||
className='mt-3 w-full'
|
||||
onClick={() => handlePublish()}
|
||||
disabled={publishDisabled || published}
|
||||
>
|
||||
@@ -193,14 +193,14 @@ const AppPublisher = ({
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className='p-4 pt-3 border-t-[0.5px] border-divider-regular'>
|
||||
<div className='border-divider-regular border-t-[0.5px] p-4 pt-3'>
|
||||
<SuggestedAction disabled={!publishedAt} link={appURL} icon={<PlayCircle />}>{t('workflow.common.runApp')}</SuggestedAction>
|
||||
{appDetail?.mode === 'workflow'
|
||||
? (
|
||||
<SuggestedAction
|
||||
disabled={!publishedAt}
|
||||
link={`${appURL}${appURL.includes('?') ? '&' : '?'}mode=batch`}
|
||||
icon={<LeftIndent02 className='w-4 h-4' />}
|
||||
icon={<LeftIndent02 className='h-4 w-4' />}
|
||||
>
|
||||
{t('workflow.common.batchRunApp')}
|
||||
</SuggestedAction>
|
||||
@@ -212,7 +212,7 @@ const AppPublisher = ({
|
||||
handleTrigger()
|
||||
}}
|
||||
disabled={!publishedAt}
|
||||
icon={<CodeBrowser className='w-4 h-4' />}
|
||||
icon={<CodeBrowser className='h-4 w-4' />}
|
||||
>
|
||||
{t('workflow.common.embedIntoSite')}
|
||||
</SuggestedAction>
|
||||
@@ -222,11 +222,11 @@ const AppPublisher = ({
|
||||
handleOpenInExplore()
|
||||
}}
|
||||
disabled={!publishedAt}
|
||||
icon={<RiPlanetLine className='w-4 h-4' />}
|
||||
icon={<RiPlanetLine className='h-4 w-4' />}
|
||||
>
|
||||
{t('workflow.common.openInExplore')}
|
||||
</SuggestedAction>
|
||||
<SuggestedAction disabled={!publishedAt} link='./develop' icon={<FileText className='w-4 h-4' />}>{t('workflow.common.accessAPIReference')}</SuggestedAction>
|
||||
<SuggestedAction disabled={!publishedAt} link='./develop' icon={<FileText className='h-4 w-4' />}>{t('workflow.common.accessAPIReference')}</SuggestedAction>
|
||||
{appDetail?.mode === 'workflow' && (
|
||||
<WorkflowToolConfigureButton
|
||||
disabled={!publishedAt}
|
||||
|
||||
@@ -73,25 +73,25 @@ const PublishWithMultipleModel: FC<PublishWithMultipleModelProps> = ({
|
||||
className='mt-3 w-full'
|
||||
>
|
||||
{t('appDebug.operation.applyConfig')}
|
||||
<RiArrowDownSLine className='ml-0.5 w-3 h-3' />
|
||||
<RiArrowDownSLine className='ml-0.5 h-3 w-3' />
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='mt-1 w-[288px] z-50'>
|
||||
<div className='p-1 rounded-lg border-[0.5px] border-components-panel-border shadow-lg bg-components-panel-bg'>
|
||||
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>
|
||||
<PortalToFollowElemContent className='z-50 mt-1 w-[288px]'>
|
||||
<div className='border-components-panel-border bg-components-panel-bg rounded-lg border-[0.5px] p-1 shadow-lg'>
|
||||
<div className='text-text-tertiary flex h-[22px] items-center px-3 text-xs font-medium'>
|
||||
{t('appDebug.publishAs')}
|
||||
</div>
|
||||
{
|
||||
validModelConfigs.map((item, index) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className='flex items-center h-8 px-3 text-sm text-text-tertiary rounded-lg cursor-pointer hover:bg-state-base-hover'
|
||||
className='text-text-tertiary hover:bg-state-base-hover flex h-8 cursor-pointer items-center rounded-lg px-3 text-sm'
|
||||
onClick={() => handleSelect(item)}
|
||||
>
|
||||
<span className='italic min-w-[18px]'>#{index + 1}</span>
|
||||
<span className='min-w-[18px] italic'>#{index + 1}</span>
|
||||
<ModelIcon modelName={item.model} provider={item.providerItem} className='ml-2' />
|
||||
<div
|
||||
className='ml-1 text-text-secondary truncate'
|
||||
className='text-text-secondary ml-1 truncate'
|
||||
title={item.modelItem.label[language]}
|
||||
>
|
||||
{item.modelItem.label[language]}
|
||||
|
||||
@@ -20,8 +20,8 @@ const SuggestedAction = ({ icon, link, disabled, children, className, ...props }
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div className='relative w-4 h-4'>{icon}</div>
|
||||
<div className='grow shrink basis-0 text-[13px] font-medium leading-[18px]'>{children}</div>
|
||||
<div className='relative h-4 w-4'>{icon}</div>
|
||||
<div className='shrink grow basis-0 text-[13px] font-medium leading-[18px]'>{children}</div>
|
||||
<ArrowUpRight />
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -23,15 +23,15 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] border-effects-highlight bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}>
|
||||
<div className={cn('border-effects-highlight bg-background-section-burn rounded-xl border-l-[0.5px] border-t-[0.5px] pb-3', noBodySpacing && 'pb-0', className)}>
|
||||
{/* Header */}
|
||||
<div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-b border-divider-subtle')}>
|
||||
<div className='flex justify-between items-center h-8'>
|
||||
<div className='flex items-center space-x-1 shrink-0'>
|
||||
{headerIcon && <div className='flex items-center justify-center w-6 h-6'>{headerIcon}</div>}
|
||||
<div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-divider-subtle border-b')}>
|
||||
<div className='flex h-8 items-center justify-between'>
|
||||
<div className='flex shrink-0 items-center space-x-1'>
|
||||
{headerIcon && <div className='flex h-6 w-6 items-center justify-center'>{headerIcon}</div>}
|
||||
<div className='text-text-secondary system-sm-semibold'>{title}</div>
|
||||
</div>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<div className='flex items-center gap-2'>
|
||||
{headerRight && <div>{headerRight}</div>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@ const GroupName: FC<IGroupNameProps> = ({
|
||||
name,
|
||||
}) => {
|
||||
return (
|
||||
<div className='flex items-center mb-1'>
|
||||
<div className='mr-3 leading-[18px] text-xs font-semibold text-gray-500 uppercase'>{name}</div>
|
||||
<div className='grow h-[1px]'
|
||||
<div className='mb-1 flex items-center'>
|
||||
<div className='mr-3 text-xs font-semibold uppercase leading-[18px] text-gray-500'>{name}</div>
|
||||
<div className='h-[1px] grow'
|
||||
style={{
|
||||
background: 'linear-gradient(270deg, rgba(243, 244, 246, 0) 0%, #F3F4F6 100%)',
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ const RemoveIcon = ({
|
||||
const computedIsHovered = isHoverStatus || isHovered
|
||||
return (
|
||||
<div
|
||||
className={cn(className, computedIsHovered && 'bg-[#FEE4E2]', 'flex w-6 h-6 items-center justify-center rounded-md cursor-pointer hover:bg-[#FEE4E2]')}
|
||||
className={cn(className, computedIsHovered && 'bg-[#FEE4E2]', 'flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-[#FEE4E2]')}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
onClick={onClick}
|
||||
|
||||
@@ -16,8 +16,8 @@ export type IOperationBtnProps = {
|
||||
}
|
||||
|
||||
const iconMap = {
|
||||
add: <RiAddLine className='w-3.5 h-3.5' />,
|
||||
edit: <RiEditLine className='w-3.5 h-3.5' />,
|
||||
add: <RiAddLine className='h-3.5 w-3.5' />,
|
||||
edit: <RiEditLine className='h-3.5 w-3.5' />,
|
||||
}
|
||||
|
||||
const OperationBtn: FC<IOperationBtnProps> = ({
|
||||
@@ -29,7 +29,7 @@ const OperationBtn: FC<IOperationBtnProps> = ({
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div
|
||||
className={cn('flex items-center rounded-md h-7 px-3 space-x-1 text-text-secondary cursor-pointer hover:bg-state-base-hover select-none', className)}
|
||||
className={cn('text-text-secondary hover:bg-state-base-hover flex h-7 cursor-pointer select-none items-center space-x-1 rounded-md px-3', className)}
|
||||
onClick={onClick}>
|
||||
<div>
|
||||
{iconMap[type]}
|
||||
|
||||
@@ -16,7 +16,7 @@ const VarHighlight: FC<IVarHighlightProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={name}
|
||||
className={`${s.item} ${className} flex mb-2 items-center justify-center rounded-md px-1 h-5 text-xs font-medium text-primary-600`}
|
||||
className={`${s.item} ${className} text-primary-600 mb-2 flex h-5 items-center justify-center rounded-md px-1 text-xs font-medium`}
|
||||
>
|
||||
<span className='opacity-60'>{'{{'}</span>
|
||||
<span>{name}</span>
|
||||
|
||||
@@ -20,7 +20,7 @@ const FormattingChanged: FC<IFormattingChangedProps> = ({
|
||||
description={t('appDebug.feature.dataSet.queryVariable.unableToQueryDataSetTip')}
|
||||
footer={
|
||||
<div className='flex space-x-2'>
|
||||
<Button variant='primary' className='flex justify-start !w-[96px]' onClick={onConfirm}>
|
||||
<Button variant='primary' className='flex !w-[96px] justify-start' onClick={onConfirm}>
|
||||
<span className='text-[13px] font-medium'>{t('appDebug.feature.dataSet.queryVariable.ok')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -22,11 +22,11 @@ const WarningMask: FC<IWarningMaskProps> = ({
|
||||
footer,
|
||||
}) => {
|
||||
return (
|
||||
<div className={`${s.mask} absolute z-10 inset-0 pt-16`}
|
||||
<div className={`${s.mask} absolute inset-0 z-10 pt-16`}
|
||||
>
|
||||
<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'>
|
||||
<div className={`${s.icon} flex h-11 w-11 items-center justify-center rounded-xl bg-white`}>{warningIcon}</div>
|
||||
<div className='mt-4 text-[24px] font-semibold leading-normal text-gray-800'>
|
||||
{title}
|
||||
</div>
|
||||
<div className='mt-3 text-base text-gray-500'>
|
||||
|
||||
@@ -141,17 +141,17 @@ const AdvancedPromptInput: FC<Props> = ({
|
||||
const [editorHeight, setEditorHeight] = React.useState(isChatMode ? 200 : 508)
|
||||
const contextMissing = (
|
||||
<div
|
||||
className='flex justify-between items-center h-11 pt-2 pr-3 pb-1 pl-4 rounded-tl-xl rounded-tr-xl'
|
||||
className='flex h-11 items-center justify-between rounded-tl-xl rounded-tr-xl pb-1 pl-4 pr-3 pt-2'
|
||||
style={{
|
||||
background: 'linear-gradient(180deg, #FEF0C7 0%, rgba(254, 240, 199, 0) 100%)',
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center pr-2' >
|
||||
<RiErrorWarningFill className='mr-1 w-4 h-4 text-[#F79009]' />
|
||||
<div className='leading-[18px] text-[13px] font-medium text-[#DC6803]'>{t('appDebug.promptMode.contextMissing')}</div>
|
||||
<RiErrorWarningFill className='mr-1 h-4 w-4 text-[#F79009]' />
|
||||
<div className='text-[13px] font-medium leading-[18px] text-[#DC6803]'>{t('appDebug.promptMode.contextMissing')}</div>
|
||||
</div>
|
||||
<div
|
||||
className='flex items-center h-6 px-2 rounded-md bg-[#fff] border border-gray-200 shadow-xs text-xs font-medium text-primary-600 cursor-pointer'
|
||||
className='shadow-xs text-primary-600 flex h-6 cursor-pointer items-center rounded-md border border-gray-200 bg-[#fff] px-2 text-xs font-medium'
|
||||
onClick={onHideContextMissingTip}
|
||||
>{t('common.operation.ok')}</div>
|
||||
</div>
|
||||
@@ -162,7 +162,7 @@ const AdvancedPromptInput: FC<Props> = ({
|
||||
{isContextMissing
|
||||
? contextMissing
|
||||
: (
|
||||
<div className={cn(s.boxHeader, 'flex justify-between items-center h-11 pt-2 pr-3 pb-1 pl-4 rounded-tl-xl rounded-tr-xl bg-white hover:shadow-xs')}>
|
||||
<div className={cn(s.boxHeader, 'hover:shadow-xs flex h-11 items-center justify-between rounded-tl-xl rounded-tr-xl bg-white pb-1 pl-4 pr-3 pt-2')}>
|
||||
{isChatMode
|
||||
? (
|
||||
<MessageTypeSelector value={type} onChange={onTypeChange} />
|
||||
@@ -182,11 +182,11 @@ const AdvancedPromptInput: FC<Props> = ({
|
||||
</div>)}
|
||||
<div className={cn(s.optionWrap, 'items-center space-x-1')}>
|
||||
{canDelete && (
|
||||
<RiDeleteBinLine onClick={onDelete} className='h-6 w-6 p-1 text-gray-500 cursor-pointer' />
|
||||
<RiDeleteBinLine onClick={onDelete} className='h-6 w-6 cursor-pointer p-1 text-gray-500' />
|
||||
)}
|
||||
{!isCopied
|
||||
? (
|
||||
<Clipboard className='h-6 w-6 p-1 text-gray-500 cursor-pointer' onClick={() => {
|
||||
<Clipboard className='h-6 w-6 cursor-pointer p-1 text-gray-500' onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}} />
|
||||
@@ -199,13 +199,13 @@ const AdvancedPromptInput: FC<Props> = ({
|
||||
)}
|
||||
|
||||
<PromptEditorHeightResizeWrap
|
||||
className='px-4 min-h-[102px] overflow-y-auto text-sm text-gray-700'
|
||||
className='min-h-[102px] overflow-y-auto px-4 text-sm text-gray-700'
|
||||
height={editorHeight}
|
||||
minHeight={minHeight}
|
||||
onHeightChange={setEditorHeight}
|
||||
footer={(
|
||||
<div className='pl-4 pb-2 flex'>
|
||||
<div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{value.length}</div>
|
||||
<div className='flex pb-2 pl-4'>
|
||||
<div className="h-[18px] rounded-md bg-gray-100 px-1 text-xs leading-[18px] text-gray-500">{value.length}</div>
|
||||
</div>
|
||||
)}
|
||||
hideResize={noResize}
|
||||
|
||||
@@ -46,7 +46,7 @@ const ConfirmAddVar: FC<IConfirmAddVarProps> = ({
|
||||
>
|
||||
<div className='flex items-start space-x-3'>
|
||||
<div
|
||||
className='shrink-0 flex items-center justify-center h-10 w-10 rounded-xl border border-gray-100'
|
||||
className='flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-gray-100'
|
||||
style={{
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||
boxShadow: '0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)',
|
||||
@@ -54,7 +54,7 @@ const ConfirmAddVar: FC<IConfirmAddVarProps> = ({
|
||||
>{VarIcon}</div>
|
||||
<div className='grow-1'>
|
||||
<div className='text-sm font-medium text-gray-900'>{t('appDebug.autoAddVar')}</div>
|
||||
<div className='flex flex-wrap mt-[15px] max-h-[66px] overflow-y-auto px-1 space-x-1'>
|
||||
<div className='mt-[15px] flex max-h-[66px] flex-wrap space-x-1 overflow-y-auto px-1'>
|
||||
{varNameArr.map(name => (
|
||||
<VarHighlight key={name} name={name} />
|
||||
))}
|
||||
|
||||
@@ -28,8 +28,8 @@ const EditModal: FC<Props> = ({
|
||||
isShow={isShow}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-text-primary'}>{t('appDebug.feature.conversationHistory.editModal.userPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-components-input-bg-normal'}
|
||||
<div className={'text-text-primary mt-6 text-sm font-medium leading-[21px]'}>{t('appDebug.feature.conversationHistory.editModal.userPrefix')}</div>
|
||||
<input className={'bg-components-input-bg-normal mt-2 box-border h-10 w-full rounded-lg px-3 text-sm leading-10'}
|
||||
value={tempData.user_prefix}
|
||||
onChange={e => setTempData({
|
||||
...tempData,
|
||||
@@ -37,8 +37,8 @@ const EditModal: FC<Props> = ({
|
||||
})}
|
||||
/>
|
||||
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-text-primary'}>{t('appDebug.feature.conversationHistory.editModal.assistantPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-components-input-bg-normal'}
|
||||
<div className={'text-text-primary mt-6 text-sm font-medium leading-[21px]'}>{t('appDebug.feature.conversationHistory.editModal.assistantPrefix')}</div>
|
||||
<input className={'bg-components-input-bg-normal mt-2 box-border h-10 w-full rounded-lg px-3 text-sm leading-10'}
|
||||
value={tempData.assistant_prefix}
|
||||
onChange={e => setTempData({
|
||||
...tempData,
|
||||
|
||||
@@ -30,20 +30,20 @@ const HistoryPanel: FC<Props> = ({
|
||||
</div>
|
||||
}
|
||||
headerIcon={
|
||||
<div className='p-1 rounded-md shadow-xs'>
|
||||
<MessageClockCircle className='w-4 h-4 text-[#DD2590]' />
|
||||
<div className='shadow-xs rounded-md p-1'>
|
||||
<MessageClockCircle className='h-4 w-4 text-[#DD2590]' />
|
||||
</div>}
|
||||
headerRight={
|
||||
<div className='flex items-center'>
|
||||
<div className='text-xs text-text-tertiary'>{t('appDebug.feature.conversationHistory.description')}</div>
|
||||
<div className='ml-3 w-[1px] h-[14px] bg-divider-regular'></div>
|
||||
<div className='text-text-tertiary text-xs'>{t('appDebug.feature.conversationHistory.description')}</div>
|
||||
<div className='bg-divider-regular ml-3 h-[14px] w-[1px]'></div>
|
||||
<OperationBtn type="edit" onClick={onShowEditModal} />
|
||||
</div>
|
||||
}
|
||||
noBodySpacing
|
||||
>
|
||||
{showWarning && (
|
||||
<div className='flex justify-between py-2 px-3 rounded-b-xl bg-background-section-burn text-xs text-text-secondary'>
|
||||
<div className='bg-background-section-burn text-text-secondary flex justify-between rounded-b-xl px-3 py-2 text-xs'>
|
||||
<div>{t('appDebug.feature.conversationHistory.tip')}
|
||||
<a href={`${locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/application-design/prompt-engineering'
|
||||
|
||||
@@ -157,8 +157,8 @@ const Prompt: FC<IPromptProps> = ({
|
||||
{(modelModeType === ModelModeType.chat && (currentAdvancedPrompt as PromptItem[]).length < MAX_PROMPT_MESSAGE_LENGTH) && (
|
||||
<div
|
||||
onClick={handleAddMessage}
|
||||
className='mt-3 flex items-center h-8 justify-center bg-gray-50 rounded-lg cursor-pointer text-[13px] font-medium text-gray-700 space-x-2'>
|
||||
<RiAddLine className='w-4 h-4' />
|
||||
className='mt-3 flex h-8 cursor-pointer items-center justify-center space-x-2 rounded-lg bg-gray-50 text-[13px] font-medium text-gray-700'>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
<div>{t('appDebug.promptMode.operation.addMessage')}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -24,12 +24,12 @@ const MessageTypeSelector: FC<Props> = ({
|
||||
<div className='relative left-[-8px]' ref={ref}>
|
||||
<div
|
||||
onClick={toggleShow}
|
||||
className={cn(showOption && 'bg-indigo-100', 'flex items-center h-7 pl-1.5 pr-1 space-x-0.5 rounded-lg cursor-pointer text-indigo-800')}>
|
||||
className={cn(showOption && 'bg-indigo-100', 'flex h-7 cursor-pointer items-center space-x-0.5 rounded-lg pl-1.5 pr-1 text-indigo-800')}>
|
||||
<div className='text-sm font-semibold uppercase'>{value}</div>
|
||||
<ChevronSelectorVertical className='w-3 h-3 ' />
|
||||
<ChevronSelectorVertical className='h-3 w-3 ' />
|
||||
</div>
|
||||
{showOption && (
|
||||
<div className='absolute z-10 top-[30px] p-1 border border-gray-200 shadow-lg rounded-lg bg-white'>
|
||||
<div className='absolute top-[30px] z-10 rounded-lg border border-gray-200 bg-white p-1 shadow-lg'>
|
||||
{allTypes.map(type => (
|
||||
<div
|
||||
key={type}
|
||||
@@ -37,7 +37,7 @@ const MessageTypeSelector: FC<Props> = ({
|
||||
setHide()
|
||||
onChange(type)
|
||||
}}
|
||||
className='flex items-center h-9 min-w-[44px] px-3 rounded-lg cursor-pointer text-sm font-medium text-gray-700 uppercase hover:bg-gray-50'
|
||||
className='flex h-9 min-w-[44px] cursor-pointer items-center rounded-lg px-3 text-sm font-medium uppercase text-gray-700 hover:bg-gray-50'
|
||||
>{type}</div>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ type Props = {
|
||||
height: number
|
||||
minHeight: number
|
||||
onHeightChange: (height: number) => void
|
||||
children: JSX.Element
|
||||
footer?: JSX.Element
|
||||
children: React.JSX.Element
|
||||
footer?: React.JSX.Element
|
||||
hideResize?: boolean
|
||||
}
|
||||
|
||||
@@ -85,9 +85,9 @@ const PromptEditorHeightResizeWrap: FC<Props> = ({
|
||||
{footer}
|
||||
{!hideResize && (
|
||||
<div
|
||||
className='absolute bottom-0 left-0 w-full flex justify-center h-2 cursor-row-resize'
|
||||
className='absolute bottom-0 left-0 flex h-2 w-full cursor-row-resize justify-center'
|
||||
onMouseDown={handleStartResize}>
|
||||
<div className='w-5 h-[3px] rounded-sm bg-gray-300'></div>
|
||||
<div className='h-[3px] w-5 rounded-sm bg-gray-300'></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -164,7 +164,7 @@ const Prompt: FC<ISimplePromptInput> = ({
|
||||
<div className={cn((!readonly || gradientBorder) ? `${s.gradientBorder}` : 'bg-gray-50', ' relative shadow-md')}>
|
||||
<div className='rounded-xl bg-[#EEF4FF]'>
|
||||
{!noTitle && (
|
||||
<div className="flex justify-between items-center h-11 pl-3 pr-6">
|
||||
<div className="flex h-11 items-center justify-between pl-3 pr-6">
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div>
|
||||
{!readonly && (
|
||||
@@ -186,14 +186,14 @@ const Prompt: FC<ISimplePromptInput> = ({
|
||||
)}
|
||||
|
||||
<PromptEditorHeightResizeWrap
|
||||
className='px-4 pt-2 min-h-[228px] bg-white rounded-t-xl text-sm text-gray-700'
|
||||
className='min-h-[228px] rounded-t-xl bg-white px-4 pt-2 text-sm text-gray-700'
|
||||
height={editorHeight}
|
||||
minHeight={minHeight}
|
||||
onHeightChange={setEditorHeight}
|
||||
hideResize={noResize}
|
||||
footer={(
|
||||
<div className='pl-4 pb-2 flex bg-white rounded-b-xl'>
|
||||
<div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{promptTemplate.length}</div>
|
||||
<div className='flex rounded-b-xl bg-white pb-2 pl-4'>
|
||||
<div className="h-[18px] rounded-md bg-gray-100 px-1 text-xs leading-[18px] text-gray-500">{promptTemplate.length}</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -6,7 +6,7 @@ import cn from '@/utils/classnames'
|
||||
interface Props {
|
||||
className?: string
|
||||
title: string
|
||||
children: JSX.Element
|
||||
children: React.JSX.Element
|
||||
}
|
||||
|
||||
const Field: FC<Props> = ({
|
||||
|
||||
@@ -233,7 +233,7 @@ const ConfigModal: FC<IConfigModalProps> = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className='!mt-5 flex items-center h-6 space-x-2'>
|
||||
<div className='!mt-5 flex h-6 items-center space-x-2'>
|
||||
<Checkbox checked={tempPayload.required} onCheck={() => handlePayloadChange('required')(!tempPayload.required)} />
|
||||
<span className='text-text-secondary system-sm-semibold'>{t('appDebug.variableConfig.required')}</span>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
|
||||
>
|
||||
{options.map((o, index) => (
|
||||
<div className={`${s.inputWrap} relative`} key={index}>
|
||||
<div className='handle flex items-center justify-center w-4 h-4 cursor-grab'>
|
||||
<div className='handle flex h-4 w-4 cursor-grab items-center justify-center'>
|
||||
<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M1 2C1.55228 2 2 1.55228 2 1C2 0.447715 1.55228 0 1 0C0.447715 0 0 0.447715 0 1C0 1.55228 0.447715 2 1 2ZM1 6C1.55228 6 2 5.55228 2 5C2 4.44772 1.55228 4 1 4C0.447715 4 0 4.44772 0 5C0 5.55228 0.447715 6 1 6ZM6 1C6 1.55228 5.55228 2 5 2C4.44772 2 4 1.55228 4 1C4 0.447715 4.44772 0 5 0C5.55228 0 6 0.447715 6 1ZM5 6C5.55228 6 6 5.55228 6 5C6 4.44772 5.55228 4 5 4C4.44772 4 4 4.44772 4 5C4 5.55228 4.44772 6 5 6ZM2 9C2 9.55229 1.55228 10 1 10C0.447715 10 0 9.55229 0 9C0 8.44771 0.447715 8 1 8C1.55228 8 2 8.44771 2 9ZM5 10C5.55228 10 6 9.55229 6 9C6 8.44771 5.55228 8 5 8C4.44772 8 4 8.44771 4 9C4 9.55229 4.44772 10 5 10Z" fill="#98A2B3" />
|
||||
</svg>
|
||||
@@ -59,10 +59,10 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
|
||||
return item
|
||||
}))
|
||||
}}
|
||||
className={'w-full pl-1.5 pr-8 text-sm leading-9 text-gray-900 border-0 grow h-9 bg-transparent focus:outline-none cursor-pointer'}
|
||||
className={'h-9 w-full grow cursor-pointer border-0 bg-transparent pl-1.5 pr-8 text-sm leading-9 text-gray-900 focus:outline-none'}
|
||||
/>
|
||||
<RemoveIcon
|
||||
className={`${s.deleteBtn} absolute top-1/2 translate-y-[-50%] right-1.5 items-center justify-center w-6 h-6 rounded-md cursor-pointer hover:bg-[#FEE4E2]`}
|
||||
className={`${s.deleteBtn} absolute right-1.5 top-1/2 h-6 w-6 translate-y-[-50%] cursor-pointer items-center justify-center rounded-md hover:bg-[#FEE4E2]`}
|
||||
onClick={() => {
|
||||
onChange(options.filter((_, i) => index !== i))
|
||||
}}
|
||||
@@ -75,9 +75,9 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
|
||||
|
||||
<div
|
||||
onClick={() => { onChange([...options, '']) }}
|
||||
className='flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-gray-400 bg-gray-100'>
|
||||
className='flex h-9 cursor-pointer items-center gap-2 rounded-lg bg-gray-100 px-3 text-gray-400'>
|
||||
<PlusIcon width={16} height={16}></PlusIcon>
|
||||
<div className='text-gray-500 text-[13px]'>{t('appDebug.variableConfig.addOption')}</div>
|
||||
<div className='text-[13px] text-gray-500'>{t('appDebug.variableConfig.addOption')}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -219,11 +219,11 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
>
|
||||
{!hasVar && (
|
||||
<div className='mt-1 px-3 pb-3'>
|
||||
<div className='pt-2 pb-1 text-xs text-text-tertiary'>{t('appDebug.notSetVar')}</div>
|
||||
<div className='text-text-tertiary pb-1 pt-2 text-xs'>{t('appDebug.notSetVar')}</div>
|
||||
</div>
|
||||
)}
|
||||
{hasVar && (
|
||||
<div className='flex flex-wrap mt-1 px-3 pb-3 justify-between'>
|
||||
<div className='mt-1 flex flex-wrap justify-between px-3 pb-3'>
|
||||
{promptVariables.map(({ key, name, type, required, config, icon, icon_background }, index) => (
|
||||
<VarItem
|
||||
key={index}
|
||||
|
||||
@@ -27,12 +27,12 @@ const SelectTypeItem: FC<ISelectTypeItemProps> = ({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col justify-center items-center h-[58px] rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg space-y-1 text-text-secondary',
|
||||
selected ? 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-xs system-xs-medium' : ' hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs cursor-pointer system-xs-regular')}
|
||||
'border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary flex h-[58px] flex-col items-center justify-center space-y-1 rounded-lg border',
|
||||
selected ? 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-xs system-xs-medium border-[1.5px]' : ' hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs system-xs-regular cursor-pointer')}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className='shrink-0'>
|
||||
<InputVarTypeIcon type={type} className='w-5 h-5' />
|
||||
<InputVarTypeIcon type={type} className='h-5 w-5' />
|
||||
</div>
|
||||
<span>{typeName}</span>
|
||||
</div>
|
||||
|
||||
@@ -28,11 +28,11 @@ type ItemProps = {
|
||||
const SelectItem: FC<ItemProps> = ({ text, type, value, Icon, onClick }) => {
|
||||
return (
|
||||
<div
|
||||
className='flex items-center px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
|
||||
className='flex h-8 cursor-pointer items-center rounded-lg px-3 hover:bg-gray-50'
|
||||
onClick={() => onClick(value)}
|
||||
>
|
||||
{Icon ? <Icon className='w-4 h-4 text-gray-500' /> : <InputVarTypeIcon type={type!} className='w-4 h-4 text-gray-500' />}
|
||||
<div className='ml-2 text-xs text-gray-600 truncate'>{text}</div>
|
||||
{Icon ? <Icon className='h-4 w-4 text-gray-500' /> : <InputVarTypeIcon type={type!} className='h-4 w-4 text-gray-500' />}
|
||||
<div className='ml-2 truncate text-xs text-gray-600'>{text}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -60,7 +60,7 @@ const SelectVarType: FC<Props> = ({
|
||||
<OperationBtn type='add' className={cn(open && 'bg-gray-200')} />
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent style={{ zIndex: 1000 }}>
|
||||
<div className='bg-white border border-gray-200 shadow-lg rounded-lg min-w-[192px]'>
|
||||
<div className='min-w-[192px] rounded-lg border border-gray-200 bg-white shadow-lg'>
|
||||
<div className='p-1'>
|
||||
<SelectItem type={InputVarType.textInput} value='string' text={t('appDebug.variableConfig.string')} onClick={handleChange}></SelectItem>
|
||||
<SelectItem type={InputVarType.paragraph} value='paragraph' text={t('appDebug.variableConfig.paragraph')} onClick={handleChange}></SelectItem>
|
||||
|
||||
@@ -33,37 +33,37 @@ const VarItem: FC<ItemProps> = ({
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
|
||||
return (
|
||||
<div className={cn('group relative flex items-center mb-1 last-of-type:mb-0 pl-2.5 py-2 pr-3 w-full rounded-lg bg-components-panel-on-panel-item-bg border-components-panel-border-subtle border-[0.5px] shadow-xs hover:shadow-sm hover:bg-components-panel-on-panel-item-bg-hover', isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border', readonly && 'cursor-not-allowed opacity-30')}>
|
||||
<VarIcon className='shrink-0 mr-1 w-4 h-4 text-text-accent' />
|
||||
<div className={cn('bg-components-panel-on-panel-item-bg border-components-panel-border-subtle shadow-xs hover:bg-components-panel-on-panel-item-bg-hover group relative mb-1 flex w-full items-center rounded-lg border-[0.5px] py-2 pl-2.5 pr-3 last-of-type:mb-0 hover:shadow-sm', isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border', readonly && 'cursor-not-allowed opacity-30')}>
|
||||
<VarIcon className='text-text-accent mr-1 h-4 w-4 shrink-0' />
|
||||
<div className='grow'>
|
||||
<div className='flex items-center h-[18px]'>
|
||||
<div className='flex h-[18px] items-center'>
|
||||
<div className='grow truncate' title={name}>
|
||||
<span className='system-sm-medium text-text-secondary'>{name}</span>
|
||||
<span className='px-1 system-xs-regular text-text-quaternary'>·</span>
|
||||
<span className='system-xs-regular text-text-quaternary px-1'>·</span>
|
||||
<span className='system-xs-medium text-text-tertiary'>{label}</span>
|
||||
</div>
|
||||
<div className='group-hover:hidden flex items-center'>
|
||||
<div className='flex items-center group-hover:hidden'>
|
||||
{required && <Badge text='required' />}
|
||||
<span className='pl-2 pr-1 system-xs-regular text-text-tertiary'>{type}</span>
|
||||
<span className='system-xs-regular text-text-tertiary pl-2 pr-1'>{type}</span>
|
||||
<IconTypeIcon type={type as IInputTypeIconProps['type']} className='text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!readonly && (
|
||||
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px]'>
|
||||
<div className='absolute bottom-0 right-0 top-0 hidden w-[124px] items-center justify-end rounded-lg pr-2 group-hover:flex'>
|
||||
<div
|
||||
className='flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'
|
||||
className='mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-black/5'
|
||||
onClick={onEdit}
|
||||
>
|
||||
<RiEditLine className='w-4 h-4 text-text-tertiary' />
|
||||
<RiEditLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
<div
|
||||
className='flex items-center justify-center w-6 h-6 text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
className='text-text-tertiary hover:text-text-destructive flex h-6 w-6 cursor-pointer items-center justify-center'
|
||||
onClick={onRemove}
|
||||
onMouseOver={() => setIsDeleting(true)}
|
||||
onMouseLeave={() => setIsDeleting(false)}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -57,14 +57,14 @@ const ConfigVision: FC = () => {
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className='mt-2 flex items-center gap-2 p-2 rounded-xl border-effects-highlight border-t-[0.5px] border-l-[0.5px] bg-background-section-burn'>
|
||||
<div className='border-effects-highlight bg-background-section-burn mt-2 flex items-center gap-2 rounded-xl border-l-[0.5px] border-t-[0.5px] p-2'>
|
||||
<div className='shrink-0 p-1'>
|
||||
<div className='p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-indigo-indigo-600'>
|
||||
<Vision className='w-4 h-4 text-text-primary-on-surface' />
|
||||
<div className='border-divider-subtle shadow-xs bg-util-colors-indigo-indigo-600 rounded-lg border-[0.5px] p-1'>
|
||||
<Vision className='text-text-primary-on-surface h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='grow flex items-center'>
|
||||
<div className='mr-1 text-text-secondary system-sm-semibold'>{t('appDebug.vision.name')}</div>
|
||||
<div className='flex grow items-center'>
|
||||
<div className='text-text-secondary system-sm-semibold mr-1'>{t('appDebug.vision.name')}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]' >
|
||||
@@ -73,7 +73,7 @@ const ConfigVision: FC = () => {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className='shrink-0 flex items-center'>
|
||||
<div className='flex shrink-0 items-center'>
|
||||
{/* <div className='mr-2 flex items-center gap-0.5'>
|
||||
<div className='text-text-tertiary system-xs-medium-uppercase'>{t('appDebug.vision.visionSettings.resolution')}</div>
|
||||
<Tooltip
|
||||
@@ -99,7 +99,7 @@ const ConfigVision: FC = () => {
|
||||
/>
|
||||
</div> */}
|
||||
<ParamConfig />
|
||||
<div className='ml-1 mr-3 w-[1px] h-3.5 bg-divider-regular'></div>
|
||||
<div className='bg-divider-regular ml-1 mr-3 h-3.5 w-[1px]'></div>
|
||||
<Switch
|
||||
defaultValue={isImageEnabled}
|
||||
onChange={handleChange}
|
||||
|
||||
@@ -41,11 +41,11 @@ const ParamConfigContent: FC = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='leading-6 text-base font-semibold text-text-primary'>{t('appDebug.vision.visionSettings.title')}</div>
|
||||
<div className='pt-3 space-y-6'>
|
||||
<div className='text-text-primary text-base font-semibold leading-6'>{t('appDebug.vision.visionSettings.title')}</div>
|
||||
<div className='space-y-6 pt-3'>
|
||||
<div>
|
||||
<div className='mb-2 flex items-center space-x-1'>
|
||||
<div className='leading-[18px] text-[13px] font-semibold text-text-secondary'>{t('appDebug.vision.visionSettings.resolution')}</div>
|
||||
<div className='text-text-secondary text-[13px] font-semibold leading-[18px]'>{t('appDebug.vision.visionSettings.resolution')}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]' >
|
||||
@@ -78,7 +78,7 @@ const ParamConfigContent: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className='mb-2 leading-[18px] text-[13px] font-semibold text-text-secondary'>{t('appDebug.vision.visionSettings.uploadMethod')}</div>
|
||||
<div className='text-text-secondary mb-2 text-[13px] font-semibold leading-[18px]'>{t('appDebug.vision.visionSettings.uploadMethod')}</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<OptionCard
|
||||
className='grow'
|
||||
|
||||
@@ -27,12 +27,12 @@ const ParamsConfig: FC = () => {
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
||||
<Button variant='ghost' size='small' className={cn('')}>
|
||||
<RiSettings2Line className='w-3.5 h-3.5' />
|
||||
<RiSettings2Line className='h-3.5 w-3.5' />
|
||||
<div className='ml-1'>{t('appDebug.voice.settings')}</div>
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent style={{ zIndex: 50 }}>
|
||||
<div className='w-80 sm:w-[412px] p-4 bg-components-panel-bg rounded-lg border-[0.5px] border-components-panel-border shadow-lg space-y-3'>
|
||||
<div className='bg-components-panel-bg border-components-panel-border w-80 space-y-3 rounded-lg border-[0.5px] p-4 shadow-lg sm:w-[412px]'>
|
||||
<ParamConfigContent />
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
|
||||
@@ -25,8 +25,8 @@ const AgentSettingButton: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => setIsShowAgentSetting(true)} className='shrink-0 mr-2'>
|
||||
<RiSettings2Line className='mr-1 w-4 h-4 text-text-tertiary' />
|
||||
<Button onClick={() => setIsShowAgentSetting(true)} className='mr-2 shrink-0'>
|
||||
<RiSettings2Line className='text-text-tertiary mr-1 h-4 w-4' />
|
||||
{t('appDebug.agent.setting.name')}
|
||||
</Button>
|
||||
{isShowAgentSetting && (
|
||||
|
||||
@@ -36,47 +36,47 @@ const AgentSetting: FC<Props> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='fixed z-[100] inset-0 overflow-hidden flex justify-end p-2'
|
||||
<div className='fixed inset-0 z-[100] flex justify-end overflow-hidden p-2'
|
||||
style={{
|
||||
backgroundColor: 'rgba(16, 24, 40, 0.20)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className='w-[640px] flex flex-col h-full overflow-hidden bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-xl shadow-xl'
|
||||
className='bg-components-panel-bg border-components-panel-border flex h-full w-[640px] flex-col overflow-hidden rounded-xl border-[0.5px] shadow-xl'
|
||||
>
|
||||
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-divider-regular'>
|
||||
<div className='flex flex-col text-base font-semibold text-text-primary'>
|
||||
<div className='border-divider-regular flex h-14 shrink-0 items-center justify-between border-b pl-6 pr-5'>
|
||||
<div className='text-text-primary flex flex-col text-base font-semibold'>
|
||||
<div className='leading-6'>{t('appDebug.agent.setting.name')}</div>
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
<div
|
||||
onClick={onCancel}
|
||||
className='flex justify-center items-center w-6 h-6 cursor-pointer'
|
||||
className='flex h-6 w-6 cursor-pointer items-center justify-center'
|
||||
>
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
<RiCloseLine className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<div className='grow p-6 pt-5 border-b overflow-y-auto pb-[68px]' style={{
|
||||
<div className='grow overflow-y-auto border-b p-6 pb-[68px] pt-5' style={{
|
||||
borderBottom: 'rgba(0, 0, 0, 0.05)',
|
||||
}}>
|
||||
{/* Agent Mode */}
|
||||
<ItemPanel
|
||||
className='mb-4'
|
||||
icon={
|
||||
<CuteRobot className='w-4 h-4 text-indigo-600' />
|
||||
<CuteRobot className='h-4 w-4 text-indigo-600' />
|
||||
}
|
||||
name={t('appDebug.agent.agentMode')}
|
||||
description={t('appDebug.agent.agentModeDes')}
|
||||
>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-text-primary'>{isFunctionCall ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</div>
|
||||
<div className='text-text-primary text-[13px] font-medium leading-[18px]'>{isFunctionCall ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</div>
|
||||
</ItemPanel>
|
||||
|
||||
<ItemPanel
|
||||
className='mb-4'
|
||||
icon={
|
||||
<Unblur className='w-4 h-4 text-[#FB6514]' />
|
||||
<Unblur className='h-4 w-4 text-[#FB6514]' />
|
||||
}
|
||||
name={t('appDebug.agent.setting.maximumIterations.name')}
|
||||
description={t('appDebug.agent.setting.maximumIterations.description')}
|
||||
@@ -99,7 +99,7 @@ const AgentSetting: FC<Props> = ({
|
||||
type="number"
|
||||
min={maxIterationsMin}
|
||||
max={maxIterationsMax} step={1}
|
||||
className="block w-11 h-7 leading-7 rounded-lg border-0 pl-1 px-1.5 bg-components-input-bg-normal text-text-primary placeholder:text-text-tertiary focus:ring-1 focus:ring-inset focus:ring-primary-600"
|
||||
className="bg-components-input-bg-normal text-text-primary placeholder:text-text-tertiary focus:ring-primary-600 block h-7 w-11 rounded-lg border-0 px-1.5 pl-1 leading-7 focus:ring-1 focus:ring-inset"
|
||||
value={tempPayload.max_iteration}
|
||||
onChange={(e) => {
|
||||
let value = Number.parseInt(e.target.value, 10)
|
||||
@@ -117,20 +117,20 @@ const AgentSetting: FC<Props> = ({
|
||||
</ItemPanel>
|
||||
|
||||
{!isFunctionCall && (
|
||||
<div className='py-2 bg-background-section-burn rounded-xl shadow-xs'>
|
||||
<div className='flex items-center h-8 px-4 leading-6 text-sm font-semibold text-text-secondary'>{t('tools.builtInPromptTitle')}</div>
|
||||
<div className='h-[396px] px-4 overflow-y-auto leading-5 text-sm font-normal text-text-secondary whitespace-pre-line'>
|
||||
<div className='bg-background-section-burn shadow-xs rounded-xl py-2'>
|
||||
<div className='text-text-secondary flex h-8 items-center px-4 text-sm font-semibold leading-6'>{t('tools.builtInPromptTitle')}</div>
|
||||
<div className='text-text-secondary h-[396px] overflow-y-auto whitespace-pre-line px-4 text-sm font-normal leading-5'>
|
||||
{isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion}
|
||||
</div>
|
||||
<div className='px-4'>
|
||||
<div className='inline-flex items-center h-5 px-1 bg-components-input-bg-normal rounded-md leading-[18px] text-xs font-medium text-text-tertiary'>{(isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion).length}</div>
|
||||
<div className='bg-components-input-bg-normal text-text-tertiary inline-flex h-5 items-center rounded-md px-1 text-xs font-medium leading-[18px]'>{(isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion).length}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
<div
|
||||
className='sticky z-[5] bottom-0 w-full flex justify-end py-4 px-6 border-t bg-background-section-burn border-divider-regular'
|
||||
className='bg-background-section-burn border-divider-regular sticky bottom-0 z-[5] flex w-full justify-end border-t px-6 py-4'
|
||||
>
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
|
||||
@@ -5,10 +5,10 @@ import cn from '@/utils/classnames'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
type Props = {
|
||||
className?: string
|
||||
icon: JSX.Element
|
||||
icon: React.JSX.Element
|
||||
name: string
|
||||
description: string
|
||||
children: JSX.Element
|
||||
children: React.JSX.Element
|
||||
}
|
||||
|
||||
const ItemPanel: FC<Props> = ({
|
||||
@@ -19,10 +19,10 @@ const ItemPanel: FC<Props> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn(className, 'flex justify-between items-center h-12 px-3 rounded-lg bg-background-section-burn')}>
|
||||
<div className={cn(className, 'bg-background-section-burn flex h-12 items-center justify-between rounded-lg px-3')}>
|
||||
<div className='flex items-center'>
|
||||
{icon}
|
||||
<div className='ml-3 mr-1 leading-6 text-sm font-semibold text-text-secondary'>{name}</div>
|
||||
<div className='text-text-secondary ml-3 mr-1 text-sm font-semibold leading-6'>{name}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]'>
|
||||
|
||||
@@ -121,10 +121,10 @@ const AgentTools: FC = () => {
|
||||
}
|
||||
headerRight={
|
||||
<div className='flex items-center'>
|
||||
<div className='leading-[18px] text-xs font-normal text-text-tertiary'>{tools.filter((item: any) => !!item.enabled).length}/{tools.length} {t('appDebug.agent.tools.enabled')}</div>
|
||||
<div className='text-text-tertiary text-xs font-normal leading-[18px]'>{tools.filter((item: any) => !!item.enabled).length}/{tools.length} {t('appDebug.agent.tools.enabled')}</div>
|
||||
{tools.length < MAX_TOOLS_NUM && (
|
||||
<>
|
||||
<div className='ml-3 mr-1 h-3.5 w-px bg-divider-regular'></div>
|
||||
<div className='bg-divider-regular ml-3 mr-1 h-3.5 w-px'></div>
|
||||
<ToolPicker
|
||||
trigger={<OperationBtn type="add" />}
|
||||
isShow={isShowChooseTool}
|
||||
@@ -139,25 +139,25 @@ const AgentTools: FC = () => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className='grid gap-1 grid-cols-1 2xl:grid-cols-2 items-center flex-wrap justify-between'>
|
||||
<div className='grid grid-cols-1 flex-wrap items-center justify-between gap-1 2xl:grid-cols-2'>
|
||||
{tools.map((item: AgentTool & { icon: any; collection?: Collection }, index) => (
|
||||
<div key={index}
|
||||
className={cn(
|
||||
'group relative flex justify-between items-center last-of-type:mb-0 p-1.5 pr-2 w-full bg-components-panel-on-panel-item-bg rounded-lg border-[0.5px] border-components-panel-border-subtle shadow-xs hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm cursor',
|
||||
'bg-components-panel-on-panel-item-bg border-components-panel-border-subtle shadow-xs hover:bg-components-panel-on-panel-item-bg-hover cursor group relative flex w-full items-center justify-between rounded-lg border-[0.5px] p-1.5 pr-2 last-of-type:mb-0 hover:shadow-sm',
|
||||
isDeleting === index && 'hover:bg-state-destructive-hover border-state-destructive-border',
|
||||
)}
|
||||
>
|
||||
<div className='grow w-0 flex items-center'>
|
||||
{item.isDeleted && <DefaultToolIcon className='w-5 h-5' />}
|
||||
<div className='flex w-0 grow items-center'>
|
||||
{item.isDeleted && <DefaultToolIcon className='h-5 w-5' />}
|
||||
{!item.isDeleted && (
|
||||
<div className={cn((item.notAuthor || !item.enabled) && 'opacity-50')}>
|
||||
{typeof item.icon === 'string' && <div className='w-5 h-5 bg-cover bg-center rounded-md' style={{ backgroundImage: `url(${item.icon})` }} />}
|
||||
{typeof item.icon === 'string' && <div className='h-5 w-5 rounded-md bg-cover bg-center' style={{ backgroundImage: `url(${item.icon})` }} />}
|
||||
{typeof item.icon !== 'string' && <AppIcon className='rounded-md' size='xs' icon={item.icon?.content} background={item.icon?.background} />}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={cn(
|
||||
'grow w-0 ml-1.5 flex items-center system-xs-regular truncate',
|
||||
'system-xs-regular ml-1.5 flex w-0 grow items-center truncate',
|
||||
(item.isDeleted || item.notAuthor || !item.enabled) ? 'opacity-50' : '',
|
||||
)}
|
||||
>
|
||||
@@ -168,34 +168,34 @@ const AgentTools: FC = () => {
|
||||
needsDelay
|
||||
popupContent={
|
||||
<div className='w-[180px]'>
|
||||
<div className='mb-1.5 text-text-secondary'>{item.tool_name}</div>
|
||||
<div className='mb-1.5 text-text-tertiary'>{t('tools.toolNameUsageTip')}</div>
|
||||
<div className='text-text-secondary mb-1.5'>{item.tool_name}</div>
|
||||
<div className='text-text-tertiary mb-1.5'>{t('tools.toolNameUsageTip')}</div>
|
||||
<div className='text-text-accent cursor-pointer' onClick={() => copy(item.tool_name)}>{t('tools.copyToolName')}</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className='w-4 h-4'>
|
||||
<div className='hidden group-hover:inline-block ml-0.5'>
|
||||
<RiInformation2Line className='w-4 h-4 text-text-tertiary' />
|
||||
<div className='h-4 w-4'>
|
||||
<div className='ml-0.5 hidden group-hover:inline-block'>
|
||||
<RiInformation2Line className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='shrink-0 ml-1 flex items-center'>
|
||||
<div className='ml-1 flex shrink-0 items-center'>
|
||||
{item.isDeleted && (
|
||||
<div className='flex items-center mr-2'>
|
||||
<div className='mr-2 flex items-center'>
|
||||
<Tooltip
|
||||
popupContent={t('tools.toolRemoved')}
|
||||
needsDelay
|
||||
>
|
||||
<div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer'>
|
||||
<AlertTriangle className='w-4 h-4 text-[#F79009]' />
|
||||
<div className='mr-1 cursor-pointer rounded-md p-1 hover:bg-black/5'>
|
||||
<AlertTriangle className='h-4 w-4 text-[#F79009]' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div
|
||||
className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
className='text-text-tertiary hover:text-text-destructive cursor-pointer rounded-md p-1'
|
||||
onClick={() => {
|
||||
const newModelConfig = produce(modelConfig, (draft) => {
|
||||
draft.agentConfig.tools.splice(index, 1)
|
||||
@@ -206,27 +206,27 @@ const AgentTools: FC = () => {
|
||||
onMouseOver={() => setIsDeleting(index)}
|
||||
onMouseLeave={() => setIsDeleting(-1)}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!item.isDeleted && (
|
||||
<div className='hidden group-hover:flex items-center gap-1 mr-2'>
|
||||
<div className='mr-2 hidden items-center gap-1 group-hover:flex'>
|
||||
{!item.notAuthor && (
|
||||
<Tooltip
|
||||
popupContent={t('tools.setBuiltInTools.infoAndSetting')}
|
||||
needsDelay
|
||||
>
|
||||
<div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
|
||||
<div className='cursor-pointer rounded-md p-1 hover:bg-black/5' onClick={() => {
|
||||
setCurrentTool(item)
|
||||
setIsShowSettingTool(true)
|
||||
}}>
|
||||
<RiEqualizer2Line className='w-4 h-4 text-text-tertiary' />
|
||||
<RiEqualizer2Line className='text-text-tertiary h-4 w-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
<div
|
||||
className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
className='text-text-tertiary hover:text-text-destructive cursor-pointer rounded-md p-1'
|
||||
onClick={() => {
|
||||
const newModelConfig = produce(modelConfig, (draft) => {
|
||||
draft.agentConfig.tools.splice(index, 1)
|
||||
@@ -237,7 +237,7 @@ const AgentTools: FC = () => {
|
||||
onMouseOver={() => setIsDeleting(index)}
|
||||
onMouseLeave={() => setIsDeleting(-1)}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -119,7 +119,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
const infoUI = (
|
||||
<div className=''>
|
||||
{infoSchemas.length > 0 && (
|
||||
<div className='py-2 space-y-1'>
|
||||
<div className='space-y-1 py-2'>
|
||||
{infoSchemas.map((item: any, index) => (
|
||||
<div key={index} className='py-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
@@ -132,7 +132,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
)}
|
||||
</div>
|
||||
{item.human_description && (
|
||||
<div className='mt-0.5 text-text-tertiary system-xs-regular'>
|
||||
<div className='text-text-tertiary system-xs-regular mt-0.5'>
|
||||
{item.human_description?.[language]}
|
||||
</div>
|
||||
)}
|
||||
@@ -163,47 +163,47 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
footer={null}
|
||||
mask={false}
|
||||
positionCenter={false}
|
||||
panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')}
|
||||
panelClassname={cn('!bg-components-panel-bg border-components-panel-border mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] !p-0 shadow-xl')}
|
||||
>
|
||||
<>
|
||||
{isLoading && <Loading type='app' />}
|
||||
{!isLoading && (
|
||||
<>
|
||||
{/* header */}
|
||||
<div className='relative p-4 pb-3 border-b border-divider-subtle'>
|
||||
<div className='absolute top-3 right-3'>
|
||||
<div className='border-divider-subtle relative border-b p-4 pb-3'>
|
||||
<div className='absolute right-3 top-3'>
|
||||
<ActionButton onClick={onHide}>
|
||||
<RiCloseLine className='w-4 h-4' />
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
{showBackButton && (
|
||||
<div
|
||||
className='mb-2 flex items-center gap-1 text-text-accent-secondary system-xs-semibold-uppercase cursor-pointer'
|
||||
className='text-text-accent-secondary system-xs-semibold-uppercase mb-2 flex cursor-pointer items-center gap-1'
|
||||
onClick={onHide}
|
||||
>
|
||||
<RiArrowLeftLine className='w-4 h-4' />
|
||||
<RiArrowLeftLine className='h-4 w-4' />
|
||||
BACK
|
||||
</div>
|
||||
)}
|
||||
<div className='flex items-center gap-1'>
|
||||
<Icon size='tiny' className='w-6 h-6' src={collection.icon} />
|
||||
<Icon size='tiny' className='h-6 w-6' src={collection.icon} />
|
||||
<OrgInfo
|
||||
packageNameClassName='w-auto'
|
||||
orgName={collection.author}
|
||||
packageName={collection.name.split('/').pop() || ''}
|
||||
/>
|
||||
</div>
|
||||
<div className='mt-1 text-text-primary system-md-semibold'>{currTool?.label[language]}</div>
|
||||
<div className='text-text-primary system-md-semibold mt-1'>{currTool?.label[language]}</div>
|
||||
{!!currTool?.description[language] && (
|
||||
<Description className='mt-3' text={currTool.description[language]} descriptionLineRows={2}></Description>
|
||||
)}
|
||||
</div>
|
||||
{/* form */}
|
||||
<div className='h-full'>
|
||||
<div className='flex flex-col h-full'>
|
||||
<div className='flex h-full flex-col'>
|
||||
{(hasSetting && !readonly) ? (
|
||||
<TabSlider
|
||||
className='shrink-0 mt-1 px-4'
|
||||
className='mt-1 shrink-0 px-4'
|
||||
itemClassName='py-3'
|
||||
noBorderBottom
|
||||
value={currType}
|
||||
@@ -216,15 +216,15 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>{t('tools.setBuiltInTools.parameters')}</div>
|
||||
<div className='text-text-primary system-sm-semibold-uppercase p-4 pb-1'>{t('tools.setBuiltInTools.parameters')}</div>
|
||||
)}
|
||||
<div className='grow h-0 overflow-y-auto px-4'>
|
||||
<div className='h-0 grow overflow-y-auto px-4'>
|
||||
{isInfoActive ? infoUI : settingUI}
|
||||
</div>
|
||||
{!readonly && !isInfoActive && (
|
||||
<div className='mt-2 shrink-0 flex justify-end py-4 px-6 space-x-2 rounded-b-[10px] bg-components-panel-bg border-t border-divider-regular'>
|
||||
<Button className='flex items-center h-8 !px-3 !text-[13px] font-medium ' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
<Button className='flex items-center h-8 !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button>
|
||||
<div className='bg-components-panel-bg border-divider-regular mt-2 flex shrink-0 justify-end space-x-2 rounded-b-[10px] border-t px-6 py-4'>
|
||||
<Button className='flex h-8 items-center !px-3 !text-[13px] font-medium ' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
<Button className='flex h-8 items-center !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -75,12 +75,12 @@ const Editor: FC<Props> = ({
|
||||
return (
|
||||
<div className={cn(className, s.gradientBorder, 'relative')}>
|
||||
<div className='rounded-xl bg-white'>
|
||||
<div className={cn(s.boxHeader, 'flex justify-between items-center h-11 pt-2 pr-3 pb-1 pl-4 rounded-tl-xl rounded-tr-xl bg-white hover:shadow-xs')}>
|
||||
<div className={cn(s.boxHeader, 'hover:shadow-xs flex h-11 items-center justify-between rounded-tl-xl rounded-tr-xl bg-white pb-1 pl-4 pr-3 pt-2')}>
|
||||
<div className='text-sm font-semibold uppercase text-indigo-800'>{t(`appDebug.agent.${isFirstPrompt ? 'firstPrompt' : 'nextIteration'}`)}</div>
|
||||
<div className={cn(s.optionWrap, 'items-center space-x-1')}>
|
||||
{!isCopied
|
||||
? (
|
||||
<Clipboard className='h-6 w-6 p-1 text-gray-500 cursor-pointer' onClick={() => {
|
||||
<Clipboard className='h-6 w-6 cursor-pointer p-1 text-gray-500' onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}} />
|
||||
@@ -90,7 +90,7 @@ const Editor: FC<Props> = ({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(editorHeight, ' px-4 min-h-[102px] overflow-y-auto text-sm text-gray-700')}>
|
||||
<div className={cn(editorHeight, ' min-h-[102px] overflow-y-auto px-4 text-sm text-gray-700')}>
|
||||
<PromptEditor
|
||||
className={editorHeight}
|
||||
value={value}
|
||||
@@ -138,8 +138,8 @@ const Editor: FC<Props> = ({
|
||||
onBlur={() => { }}
|
||||
/>
|
||||
</div>
|
||||
<div className='pl-4 pb-2 flex'>
|
||||
<div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{value.length}</div>
|
||||
<div className='flex pb-2 pl-4'>
|
||||
<div className="h-[18px] rounded-md bg-gray-100 px-1 text-xs leading-[18px] text-gray-500">{value.length}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user