From 3f36471ec01b403730cd6217e4dd32f959a42abb Mon Sep 17 00:00:00 2001
From: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
Date: Thu, 7 May 2026 19:23:49 +0800
Subject: [PATCH] tweaks
---
.../components/create-instance-modal.tsx | 20 +++++++++++----
.../deployments/components/rollback-modal.tsx | 9 ++++---
.../deployments/detail/deployment-sidebar.tsx | 7 +++---
web/features/deployments/detail/index.tsx | 15 +++++------
.../deployments/detail/overview-tab.tsx | 18 ++++++-------
.../deployments/detail/settings-tab.tsx | 25 +++++++++----------
web/features/deployments/types.ts | 20 ---------------
web/features/deployments/utils.ts | 22 ----------------
8 files changed, 52 insertions(+), 84 deletions(-)
diff --git a/web/features/deployments/components/create-instance-modal.tsx b/web/features/deployments/components/create-instance-modal.tsx
index 8e003415c6..592753cc29 100644
--- a/web/features/deployments/components/create-instance-modal.tsx
+++ b/web/features/deployments/components/create-instance-modal.tsx
@@ -1,5 +1,4 @@
'use client'
-import type { AppInfo, AppMode } from '../types'
import type { App, AppModeEnum } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
@@ -18,11 +17,22 @@ import { useDeploymentsStore } from '../store'
const MAX_STUDIO_SOURCE_APPS = 100
-function toStudioSourceAppInfo(app: App): AppInfo {
+type StudioSourceApp = {
+ id: string
+ name: string
+ mode: string
+ iconType?: App['icon_type']
+ icon?: string
+ iconBackground?: string
+ iconUrl?: string | null
+ description?: string
+}
+
+function toStudioSourceAppInfo(app: App): StudioSourceApp {
return {
id: app.id,
name: app.name,
- mode: (app.mode || 'workflow') as AppMode,
+ mode: app.mode || 'workflow',
iconType: app.icon_type,
icon: app.icon,
iconBackground: app.icon_background ?? undefined,
@@ -32,13 +42,13 @@ function toStudioSourceAppInfo(app: App): AppInfo {
}
type AppPickerProps = {
- apps: AppInfo[]
+ apps: StudioSourceApp[]
isLoading: boolean
value: string
onChange: (appId: string) => void
}
-export function AppPicker({ apps, isLoading, value, onChange }: AppPickerProps) {
+function AppPicker({ apps, isLoading, value, onChange }: AppPickerProps) {
const { t } = useTranslation('deployments')
const [open, setOpen] = useState(false)
const [keywords, setKeywords] = useState('')
diff --git a/web/features/deployments/components/rollback-modal.tsx b/web/features/deployments/components/rollback-modal.tsx
index d01aaa48bb..9e6b9d83c2 100644
--- a/web/features/deployments/components/rollback-modal.tsx
+++ b/web/features/deployments/components/rollback-modal.tsx
@@ -21,7 +21,6 @@ import {
environmentOptionsFromOptionsReply,
releaseCommit,
releaseLabel,
- toAppInfoFromOverview,
} from '../utils'
function InfoRow({ label, value }: {
@@ -77,7 +76,9 @@ export function RollbackModal() {
const currentRelease = activeRelease(currentRow)
const environment = currentRow?.environment
?? environmentOptions.find(env => env.id === modal.environmentId)
- const app = toAppInfoFromOverview(overview?.instance)
+ const app = overview?.instance
+ const appName = app?.name ?? '-'
+ const sourceAppName = app?.sourceAppName ?? appName
const confirm = () => {
if (!modal.appInstanceId || !modal.environmentId || !modal.targetReleaseId)
@@ -110,8 +111,8 @@ export function RollbackModal() {
-
-
+
+
)
: (
diff --git a/web/features/deployments/detail/index.tsx b/web/features/deployments/detail/index.tsx
index 016416f8ad..805d87124e 100644
--- a/web/features/deployments/detail/index.tsx
+++ b/web/features/deployments/detail/index.tsx
@@ -11,7 +11,6 @@ import { useRouter, useSelectedLayoutSegment } from '@/next/navigation'
import { consoleQuery } from '@/service/client'
import { DeployDrawer } from '../components/deploy-drawer'
import { RollbackModal } from '../components/rollback-modal'
-import { toAppInfoFromOverview } from '../utils'
import { DeploymentSidebar } from './deployment-sidebar'
import { isInstanceDetailTabKey } from './tabs'
@@ -33,9 +32,10 @@ export function InstanceDetail({ instanceId, children }: {
useDocumentTitle(t('documentTitle.detail'))
- const app = toAppInfoFromOverview(overviewQuery.data?.instance)
+ const app = overviewQuery.data?.instance
+ const appId = app?.id
- if (!app && overviewQuery.isLoading) {
+ if (!appId && overviewQuery.isLoading) {
return (
@@ -43,7 +43,7 @@ export function InstanceDetail({ instanceId, children }: {
)
}
- if (!app) {
+ if (!appId || !app) {
return (
{t('detail.notFound')}
@@ -54,14 +54,15 @@ export function InstanceDetail({ instanceId, children }: {
)
}
- const appModeLabel = app ? getAppModeLabel(app.mode, tCommon) : t('detail.sourceAppDeleted')
+ const appName = app.name ?? appId
+ const appModeLabel = getAppModeLabel(app.mode ?? 'workflow', tCommon)
return (
<>
state.openDeployDrawer)
- const app = toAppInfoFromOverview(overview?.instance)
const overviewApp = overview?.instance
const deployments = overview?.deployments?.filter(row => row.environment?.id && row.status?.toLowerCase() !== 'undeployed') ?? []
const releaseRows = releaseHistory?.data?.filter(row => row.id) ?? []
const canCreateRelease = overviewApp?.canCreateRelease ?? true
- if (!app)
+ if (!overviewApp?.id)
return null
+ const appId = overviewApp.id
+ const appName = overviewApp.name ?? appId
const switchTab = (tab: SwitchableTab) => {
- router.push(`/deployments/${instanceId}/${tab}`)
+ router.push(`/deployments/${appId}/${tab}`)
}
- const appModeLabel = getAppModeLabel(overviewApp?.mode ?? app.mode, tCommon)
+ const appModeLabel = getAppModeLabel(overviewApp.mode ?? 'workflow', tCommon)
const webappAccessUrl = webappUrl(overview?.access?.webappUrl)
const cliUrl = overview?.access?.cliUrl
const apiUrl = overview?.access?.apiUrl ?? accessConfig?.developerApi?.apiUrl
@@ -135,9 +135,9 @@ export function OverviewTab({ instanceId }: {
@@ -169,7 +169,7 @@ export function OverviewTab({ instanceId }: {
switchTab('versions')
return
}
- openDeployDrawer({ appInstanceId: app.id })
+ openDeployDrawer({ appInstanceId: appId })
}}
>
{releaseRows.length === 0 ? t('overview.createRelease') : t('overview.deploy')}
diff --git a/web/features/deployments/detail/settings-tab.tsx b/web/features/deployments/detail/settings-tab.tsx
index 82154c198e..1e8050a479 100644
--- a/web/features/deployments/detail/settings-tab.tsx
+++ b/web/features/deployments/detail/settings-tab.tsx
@@ -1,5 +1,5 @@
'use client'
-import type { AppInfo } from '../types'
+import type { AppInstanceBasicInfo } from '@dify/contracts/enterprise/types.gen'
import type { GetAppInstanceSettingsReply } from '@/features/deployments/types'
import {
AlertDialog,
@@ -17,27 +17,25 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from '@/next/navigation'
import { consoleQuery } from '@/service/client'
-import {
- deployedRows,
- toAppInfoFromOverview,
-} from '../utils'
+import { deployedRows } from '../utils'
type SettingsFormProps = {
- app: AppInfo
+ app: AppInstanceBasicInfo
settings?: GetAppInstanceSettingsReply
hasDeployments: boolean
- onSave: (patch: Pick
) => Promise
+ onSave: (patch: Pick) => Promise
onDelete: () => Promise
}
function SettingsForm({ app, settings, hasDeployments, onSave, onDelete }: SettingsFormProps) {
const { t } = useTranslation('deployments')
- const [name, setName] = useState(settings?.name ?? app.name)
+ const appName = app.name ?? app.id ?? ''
+ const [name, setName] = useState(settings?.name ?? appName)
const [description, setDescription] = useState(settings?.description ?? app.description ?? '')
const [isSaving, setIsSaving] = useState(false)
const [isDeleting, setIsDeleting] = useState(false)
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
- const initialName = settings?.name ?? app.name
+ const initialName = settings?.name ?? appName
const initialDescription = settings?.description ?? app.description ?? ''
const canSave = Boolean(name.trim() && (name !== initialName || description !== initialDescription) && !isSaving)
const canDelete = !hasDeployments && Boolean(settings) && settings?.deleteGuard?.canDelete !== false
@@ -153,7 +151,7 @@ function SettingsForm({ app, settings, hasDeployments, onSave, onDelete }: Setti
{t('settings.deleteConfirmTitle')}
- {t('settings.deleteConfirmDesc', { name: app.name })}
+ {t('settings.deleteConfirmDesc', { name: appName })}
@@ -183,16 +181,17 @@ export function SettingsTab({ instanceId }: {
const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({
input: appInput,
}))
- const app = toAppInfoFromOverview(overview?.instance)
+ const app = overview?.instance
const settingsQuery = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceSettings.queryOptions({
input: appInput,
}))
- if (!app)
+ if (!app?.id)
return null
const hasDeployments = deployedRows(environmentDeployments?.data).length > 0
- const formKey = `${app.id}-${settingsQuery.data?.name ?? app.name}-${settingsQuery.data?.description ?? app.description ?? ''}`
+ const appName = app.name ?? app.id
+ const formKey = `${app.id}-${settingsQuery.data?.name ?? appName}-${settingsQuery.data?.description ?? app.description ?? ''}`
return (
environment.id)