From cfb1e0217f88b319aec484cac1b3cebad3fa187d Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Thu, 7 May 2026 20:08:54 +0800 Subject: [PATCH] tweaks --- web/features/deployments/detail/index.tsx | 6 +- .../deployments/detail/overview-tab.tsx | 48 +++--- .../deployments/list/instance-card.tsx | 154 +++++++++--------- 3 files changed, 102 insertions(+), 106 deletions(-) diff --git a/web/features/deployments/detail/index.tsx b/web/features/deployments/detail/index.tsx index 805d87124e..720c23b1e5 100644 --- a/web/features/deployments/detail/index.tsx +++ b/web/features/deployments/detail/index.tsx @@ -7,7 +7,8 @@ import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { getAppModeLabel } from '@/app/components/app-sidebar/app-info/app-mode-labels' import useDocumentTitle from '@/hooks/use-document-title' -import { useRouter, useSelectedLayoutSegment } from '@/next/navigation' +import Link from '@/next/link' +import { useSelectedLayoutSegment } from '@/next/navigation' import { consoleQuery } from '@/service/client' import { DeployDrawer } from '../components/deploy-drawer' import { RollbackModal } from '../components/rollback-modal' @@ -20,7 +21,6 @@ export function InstanceDetail({ instanceId, children }: { }) { const { t } = useTranslation('deployments') const { t: tCommon } = useTranslation() - const router = useRouter() const selectedSegment = useSelectedLayoutSegment() const selectedTab = selectedSegment ?? undefined const activeTab: InstanceDetailTabKey = isInstanceDetailTabKey(selectedTab) ? selectedTab : 'overview' @@ -47,7 +47,7 @@ export function InstanceDetail({ instanceId, children }: { return (
{t('detail.notFound')}
- diff --git a/web/features/deployments/detail/overview-tab.tsx b/web/features/deployments/detail/overview-tab.tsx index 8e69bdc1ae..474aafd5d6 100644 --- a/web/features/deployments/detail/overview-tab.tsx +++ b/web/features/deployments/detail/overview-tab.tsx @@ -5,7 +5,7 @@ import { cn } from '@langgenius/dify-ui/cn' import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { getAppModeLabel } from '@/app/components/app-sidebar/app-info/app-mode-labels' -import { useRouter } from '@/next/navigation' +import Link from '@/next/link' import { consoleQuery } from '@/service/client' import { StatusBadge } from '../components/status-badge' import { DEPLOYMENT_PAGE_SIZE } from '../data' @@ -17,6 +17,10 @@ import { type SwitchableTab = 'deploy' | 'versions' | 'access' | 'settings' +function tabHref(appId: string, tab: SwitchableTab): string { + return `/deployments/${appId}/${tab}` +} + function Section({ title, action, children }: { title: string action?: ReactNode @@ -79,7 +83,7 @@ function AccessOverviewRow({ label, enabled, hint, meta }: AccessOverviewRowProp ) } -function overviewDeploymentStatus(status?: string) { +function overviewDeploymentStatus(status?: string): 'deploying' | 'deploy_failed' | 'ready' { const normalized = status?.toLowerCase() ?? '' if (normalized.includes('deploying') || normalized.includes('pending')) return 'deploying' @@ -93,7 +97,6 @@ export function OverviewTab({ instanceId }: { }) { const { t } = useTranslation('deployments') const { t: tCommon } = useTranslation() - const router = useRouter() const input = { params: { appInstanceId: instanceId } } const { data: overview } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceOverview.queryOptions({ input, @@ -121,10 +124,6 @@ export function OverviewTab({ instanceId }: { const appId = overviewApp.id const appName = overviewApp.name ?? appId - const switchTab = (tab: SwitchableTab) => { - router.push(`/deployments/${appId}/${tab}`) - } - const appModeLabel = getAppModeLabel(overviewApp.mode ?? 'workflow', tCommon) const webappAccessUrl = webappUrl(overview?.access?.webappUrl) const cliUrl = overview?.access?.cliUrl @@ -145,7 +144,7 @@ export function OverviewTab({ instanceId }: {
switchTab('deploy')}> + @@ -160,20 +159,23 @@ export function OverviewTab({ instanceId }: { ? t(canCreateRelease ? 'overview.noReleaseYet' : 'overview.noReleaseSourceUnavailable') : t('overview.notDeployedYet')}
- + {releaseRows.length === 0 + ? canCreateRelease + ? ( + + ) + : ( + + ) + : ( + + )} ) : ( @@ -199,7 +201,7 @@ export function OverviewTab({ instanceId }: {
switchTab('access')}> + diff --git a/web/features/deployments/list/instance-card.tsx b/web/features/deployments/list/instance-card.tsx index b560d7182c..8a8d8e143c 100644 --- a/web/features/deployments/list/instance-card.tsx +++ b/web/features/deployments/list/instance-card.tsx @@ -1,13 +1,13 @@ 'use client' import type { AppInstanceCard } from '@dify/contracts/enterprise/types.gen' -import type { MouseEvent } from 'react' import type { AppModeEnum } from '@/types/app' import { cn } from '@langgenius/dify-ui/cn' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, + DropdownMenuLinkItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@langgenius/dify-ui/dropdown-menu' @@ -17,14 +17,13 @@ import { useTranslation } from 'react-i18next' import { AppTypeIcon } from '@/app/components/app/type-selector' import AppIcon from '@/app/components/base/app-icon' import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' -import { useRouter } from '@/next/navigation' +import Link from '@/next/link' import { useDeploymentsStore } from '../store' export function InstanceCard({ app }: { app: AppInstanceCard }) { const { t } = useTranslation('deployments') - const router = useRouter() const { formatTimeFromNow } = useFormatTimeFromNow() const [menuOpen, setMenuOpen] = useState(false) const openDeployDrawer = useDeploymentsStore(state => state.openDeployDrawer) @@ -35,14 +34,7 @@ export function InstanceCard({ app }: { const appId = app.id const appName = app.name ?? appId const appMode = app.mode ?? 'workflow' - const navigateToDetail = () => router.push(`/deployments/${appId}/overview`) - - const handleMenuAction = (e: MouseEvent, action: () => void) => { - e.stopPropagation() - e.preventDefault() - setMenuOpen(false) - action() - } + const detailHref = `/deployments/${appId}/overview` const statusCount = (status: string) => app.statuses?.find(item => item.status === status)?.count ?? 0 @@ -122,75 +114,78 @@ export function InstanceCard({ app }: { return (
{ - e.preventDefault() - navigateToDetail() - }} className="group relative col-span-1 inline-flex h-[160px] cursor-pointer flex-col rounded-xl border border-solid border-components-card-border bg-components-card-bg shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg" > -
-
- - -
-
-
-
{appName}
+ +
+
+ +
-
- {appModeLabel} +
+
+
{appName}
+
+
+ {appModeLabel} +
-
-
- - - - - {primaryText} - - {secondaryParts.length > 0 && ( - - {secondaryParts.join(' · ')} +
+ + + + + {primaryText} - )} -
- )} - /> - {statusTooltip} -
-
- - - {t('card.fromApp', { name: app.sourceAppName ?? appName })} - + {secondaryParts.length > 0 && ( + + {secondaryParts.join(' · ')} + + )} +
+ )} + /> + {statusTooltip} + +
+ + + {t('card.fromApp', { name: app.sourceAppName ?? appName })} + +
-
-
-
- - - {lastDeployedAt - ? t('card.lastDeployed', { time: formatTimeFromNow(lastDeployedAt) }) - : t('card.neverDeployed')} - +
+
+ + + {lastDeployedAt + ? t('card.lastDeployed', { time: formatTimeFromNow(lastDeployedAt) }) + : t('card.neverDeployed')} + +
+ +
{ - e.stopPropagation() - e.preventDefault() - }} > @@ -217,16 +208,19 @@ export function InstanceCard({ app }: { handleMenuAction(e, () => openDeployDrawer({ appInstanceId: appId }))} + onClick={() => { + setMenuOpen(false) + openDeployDrawer({ appInstanceId: appId }) + }} > {t('card.menu.deploy')} - handleMenuAction(e, navigateToDetail)} + render={} > {t('card.menu.viewDetail')} - +