-
{t('plugin.task.installedError')}
+
+ {t('plugin.task.installedError', { errorLength: errorPlugins.length })}
+
{
errorPlugins.map(errorPlugin => (
= ({
const handleSend = () => {
setIsCallBatchAPI(false)
setControlSend(Date.now())
+
// eslint-disable-next-line ts/no-use-before-define
setAllTaskList([]) // clear batch task running status
+
// eslint-disable-next-line ts/no-use-before-define
showResSidebar()
}
diff --git a/web/app/components/workflow/block-selector/all-tools.tsx b/web/app/components/workflow/block-selector/all-tools.tsx
index d60ceb1f71..d27fb6385b 100644
--- a/web/app/components/workflow/block-selector/all-tools.tsx
+++ b/web/app/components/workflow/block-selector/all-tools.tsx
@@ -43,16 +43,14 @@ const AllTools = ({
supportAddCustomTool,
onShowAddCustomCollectionModal,
}: AllToolsProps) => {
- const tabs = useToolTabs()
const language = useGetLanguage()
+ const tabs = useToolTabs()
const [activeTab, setActiveTab] = useState(ToolTypeEnum.All)
const [activeView, setActiveView] = useState
(ViewType.flat)
-
+ const hasFilter = searchText || tags.length > 0
const isMatchingKeywords = (text: string, keywords: string) => {
return text.toLowerCase().includes(keywords.toLowerCase())
}
-
- const hasFilter = searchText || tags.length > 0
const tools = useMemo(() => {
let mergedTools: ToolWithProvider[] = []
if (activeTab === ToolTypeEnum.All)
diff --git a/web/app/components/workflow/plugin-dependency/index.tsx b/web/app/components/workflow/plugin-dependency/index.tsx
index c7f5b71c75..13f138114b 100644
--- a/web/app/components/workflow/plugin-dependency/index.tsx
+++ b/web/app/components/workflow/plugin-dependency/index.tsx
@@ -1,13 +1,25 @@
+import { useCallback } from 'react'
import { useStore } from './store'
+import InstallBundle from '@/app/components/plugins/install-plugin/install-bundle'
const PluginDependency = () => {
const dependencies = useStore(s => s.dependencies)
+ const handleCancelInstallBundle = useCallback(() => {
+ const { setDependencies } = useStore.getState()
+ setDependencies([])
+ }, [])
+
if (!dependencies.length)
return null
return (
- a
+
+
+
)
}
diff --git a/web/app/components/workflow/run/iteration-result-panel.tsx b/web/app/components/workflow/run/iteration-result-panel.tsx
index b13eadec99..f71adbbece 100644
--- a/web/app/components/workflow/run/iteration-result-panel.tsx
+++ b/web/app/components/workflow/run/iteration-result-panel.tsx
@@ -104,17 +104,17 @@ const IterationResultPanel: FC = ({
onClick={() => toggleIteration(index)}
>
-
+
-
+
{t(`${i18nPrefix}.iteration`)} {index + 1}
{iterationStatusShow(index, iteration, iterDurationMap)}
{expandedIterations[index] && }
= ({
className='flex items-center w-full self-stretch gap-2 px-3 py-2 bg-components-button-tertiary-bg-hover hover:bg-components-button-tertiary-bg-hover rounded-lg cursor-pointer border-none'
onClick={handleOnShowIterationDetail}
>
-
+
{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && (
<>
{t('workflow.nodes.iteration.comma')}
@@ -153,12 +153,12 @@ const NodePanel: FC
= ({
)}
{justShowIterationNavArrow
? (
-
+
)
: (
{t('workflow.common.viewDetailInTracingPanel')}
-
+
)}
diff --git a/web/app/components/workflow/run/tracing-panel.tsx b/web/app/components/workflow/run/tracing-panel.tsx
index 57b3a5cf5f..3f1c2465cf 100644
--- a/web/app/components/workflow/run/tracing-panel.tsx
+++ b/web/app/components/workflow/run/tracing-panel.tsx
@@ -57,7 +57,7 @@ function buildLogTree(nodes: NodeTracing[], t: (key: string) => string): Tracing
levelCounts[levelKey]++
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
- const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1
+ const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
return `${t('workflow.common.parallel')}-${levelNumber}${letter}`
}
@@ -65,7 +65,7 @@ function buildLogTree(nodes: NodeTracing[], t: (key: string) => string): Tracing
const getBranchTitle = (parentId: string | null, branchNum: number): string => {
const levelKey = parentId || 'root'
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
- const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1
+ const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
const branchLetter = String.fromCharCode(64 + branchNum)
return `${t('workflow.common.branch')}-${levelNumber}${letter}-${branchLetter}`
@@ -227,7 +227,7 @@ const TracingPanel: FC
= ({
{node.parallelTitle}
diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx
index 86a3648c4e..cc19b2790c 100644
--- a/web/app/components/workflow/update-dsl-modal.tsx
+++ b/web/app/components/workflow/update-dsl-modal.tsx
@@ -77,17 +77,13 @@ const UpdateDSLModal = ({
return
try {
if (appDetail && fileContent) {
- const leakedData = await mutateAsync({ dslString: fileContent })
- if (leakedData?.leaked.length) {
- isCreatingRef.current = false
- return
- }
setLoading(true)
const {
graph,
features,
hash,
} = await updateWorkflowDraftFromDSL(appDetail.id, fileContent)
+ await mutateAsync({ dslString: fileContent })
const { nodes, edges, viewport } = graph
const newFeatures = {
file: {
diff --git a/web/i18n/en-US/app.ts b/web/i18n/en-US/app.ts
index 3377a9b2f3..639ca289eb 100644
--- a/web/i18n/en-US/app.ts
+++ b/web/i18n/en-US/app.ts
@@ -133,6 +133,12 @@ const translation = {
removeConfirmContent: 'The current configuration is in use, removing it will turn off the Tracing feature.',
},
},
+ appSelector: {
+ label: 'APP',
+ placeholder: 'Select an app...',
+ params: 'APP PARAMETERS',
+ noParams: 'No parameters needed',
+ },
}
export default translation
diff --git a/web/i18n/sl-SI/plugin-tags.ts b/web/i18n/sl-SI/plugin-tags.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/web/i18n/sl-SI/plugin.ts b/web/i18n/sl-SI/plugin.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/web/i18n/zh-Hans/app.ts b/web/i18n/zh-Hans/app.ts
index ee316200fa..b7249b4af8 100644
--- a/web/i18n/zh-Hans/app.ts
+++ b/web/i18n/zh-Hans/app.ts
@@ -132,6 +132,12 @@ const translation = {
removeConfirmContent: '当前配置正在使用中,删除它将关闭追踪功能。',
},
},
+ appSelector: {
+ label: '应用',
+ placeholder: '选择一个应用',
+ params: '应用参数',
+ noParams: '无需参数',
+ },
}
export default translation
diff --git a/web/i18n/zh-Hans/common.ts b/web/i18n/zh-Hans/common.ts
index 28be0bf3e9..ab87085652 100644
--- a/web/i18n/zh-Hans/common.ts
+++ b/web/i18n/zh-Hans/common.ts
@@ -127,7 +127,7 @@ const translation = {
explore: '探索',
apps: '工作室',
plugins: '插件',
- exploreMarketplace: '探索市场',
+ exploreMarketplace: '探索 Marketplace',
pluginsTips: '集成第三方插件或创建与 ChatGPT 兼容的 AI 插件。',
datasets: '知识库',
datasetsTips: '即将到来: 上传自己的长文本数据,或通过 Webhook 集成自己的数据源',
diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts
index 2e9f234af6..f4b1aeb53b 100644
--- a/web/i18n/zh-Hans/plugin.ts
+++ b/web/i18n/zh-Hans/plugin.ts
@@ -22,15 +22,15 @@ const translation = {
noInstalled: '无已安装的插件',
notFound: '未找到插件',
source: {
- marketplace: '从市场安装',
- github: '从GitHub安装',
- local: '从本地文件安装',
+ marketplace: '从 Marketplace 安装',
+ github: '从 GitHub 安装',
+ local: '本地插件',
},
},
source: {
- marketplace: '市场',
+ marketplace: 'Marketplace',
github: 'GitHub',
- local: '本地文件',
+ local: '本地插件',
},
detailPanel: {
categoryTip: {
diff --git a/web/service/use-apps.ts b/web/service/use-apps.ts
new file mode 100644
index 0000000000..1a3e9cedbb
--- /dev/null
+++ b/web/service/use-apps.ts
@@ -0,0 +1,27 @@
+import { get } from './base'
+import type { App } from '@/types/app'
+import type { AppListResponse } from '@/models/app'
+import { useInvalid } from './use-base'
+import { useQuery } from '@tanstack/react-query'
+
+const NAME_SPACE = 'apps'
+
+// TODO paging for list
+const useAppFullListKey = [NAME_SPACE, 'full-list']
+export const useAppFullList = () => {
+ return useQuery
({
+ queryKey: useAppFullListKey,
+ queryFn: () => get('/apps', { params: { page: 1, limit: 100 } }),
+ })
+}
+
+export const useInvalidateAppFullList = () => {
+ return useInvalid(useAppFullListKey)
+}
+
+export const useAppDetail = (appID: string) => {
+ return useQuery({
+ queryKey: [NAME_SPACE, 'detail', appID],
+ queryFn: () => get(`/apps/${appID}`),
+ })
+}
diff --git a/web/service/use-common.ts b/web/service/use-common.ts
new file mode 100644
index 0000000000..98ab535948
--- /dev/null
+++ b/web/service/use-common.ts
@@ -0,0 +1,14 @@
+import { get } from './base'
+import type {
+ FileUploadConfigResponse,
+} from '@/models/common'
+import { useQuery } from '@tanstack/react-query'
+
+const NAME_SPACE = 'common'
+
+export const useFileUploadConfig = () => {
+ return useQuery({
+ queryKey: [NAME_SPACE, 'file-upload-config'],
+ queryFn: () => get('/files/upload'),
+ })
+}
diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts
index 6697948877..8ab970db13 100644
--- a/web/service/use-plugins.ts
+++ b/web/service/use-plugins.ts
@@ -9,6 +9,7 @@ import type {
PluginsFromMarketplaceResponse,
uploadGitHubResponse,
} from '@/app/components/plugins/types'
+import { TaskStatus } from '@/app/components/plugins/types'
import type {
PluginsSearchParams,
} from '@/app/components/plugins/marketplace/types'
@@ -97,7 +98,7 @@ export const useUploadGitHub = (payload: {
export const useInstallFromMarketplaceAndGitHub = ({
onSuccess,
}: {
- onSuccess?: () => void
+ onSuccess?: (res: { success: boolean }[]) => void
}) => {
return useMutation({
mutationFn: (payload: Dependency[]) => {
@@ -121,6 +122,7 @@ export const useInstallFromMarketplaceAndGitHub = ({
})
return ({ success: true })
}
+ // eslint-disable-next-line unused-imports/no-unused-vars
catch (e) {
return Promise.resolve({ success: false })
}
@@ -216,14 +218,14 @@ export const usePluginTaskList = () => {
queryKey: usePluginTaskListKey,
queryFn: async () => {
const currentData = await get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100')
- const taskDone = currentData.tasks.every(task => task.total_plugins === task.completed_plugins)
+ const taskDone = currentData.tasks.every(task => task.status === TaskStatus.success)
if (taskDone)
setEnabled(false)
return currentData
},
- // refetchInterval: 5000,
+ refetchInterval: 5000,
enabled,
})
const handleRefetch = useCallback(() => {
diff --git a/web/service/use-workflow.ts b/web/service/use-workflow.ts
new file mode 100644
index 0000000000..9413854726
--- /dev/null
+++ b/web/service/use-workflow.ts
@@ -0,0 +1,18 @@
+import { get } from './base'
+import type {
+ FetchWorkflowDraftResponse,
+} from '@/types/workflow'
+import { useQuery } from '@tanstack/react-query'
+
+const NAME_SPACE = 'workflow'
+
+export const useAppWorkflow = (appID: string) => {
+ return useQuery({
+ queryKey: [NAME_SPACE, 'publish', appID],
+ queryFn: () => {
+ if (appID === 'empty')
+ return Promise.resolve({} as unknown as FetchWorkflowDraftResponse)
+ return get(`/apps/${appID}/workflows/publish`)
+ },
+ })
+}
diff --git a/web/types/app.ts b/web/types/app.ts
index a95a2cf0cd..2f5f6254ff 100644
--- a/web/types/app.ts
+++ b/web/types/app.ts
@@ -351,6 +351,13 @@ export type App = {
/** api site url */
api_base_url: string
tags: Tag[]
+ workflow?: {
+ id: string
+ created_at: number
+ created_by?: string
+ updated_at: number
+ updated_by?: string
+ }
}
export type AppSSO = {