From 04124edd70efa29dbd2909509bcdb5a4f4592ca2 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Thu, 7 May 2026 18:39:28 +0800 Subject: [PATCH] tweaks --- .../deployments/detail/access-tab.tsx | 111 ++++++++++++------ .../deployments/detail/deploy-tab.tsx | 111 ++++++++++-------- .../deployments/detail/versions-tab.tsx | 111 ++++++++++-------- 3 files changed, 196 insertions(+), 137 deletions(-) diff --git a/web/features/deployments/detail/access-tab.tsx b/web/features/deployments/detail/access-tab.tsx index 266efd2b8e..a8395143eb 100644 --- a/web/features/deployments/detail/access-tab.tsx +++ b/web/features/deployments/detail/access-tab.tsx @@ -4,6 +4,7 @@ import type { AccessPermission, AccessSubject, ConsoleEnvironmentSummary, + DeveloperAPIKeySummary, } from '@/features/deployments/types' import { useMutation, useQuery } from '@tanstack/react-query' import { useState } from 'react' @@ -26,44 +27,39 @@ function uniqueEnvironments(environments: (ConsoleEnvironmentSummary | undefined }) } -export function AccessTab({ instanceId: appId }: { - instanceId: string -}) { - const appInput = { params: { appInstanceId: appId } } - const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({ - input: appInput, - })) - const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({ - input: appInput, - })) +type DeveloperApiAccessSectionProps = { + appId: string + apiEnabled: boolean + apiUrl?: string + environments: ConsoleEnvironmentSummary[] + apiKeys: DeveloperAPIKeySummary[] +} + +function DeveloperApiAccessSection({ + appId, + apiEnabled, + apiUrl, + environments, + apiKeys, +}: DeveloperApiAccessSectionProps) { const [createdApiToken, setCreatedApiToken] = useState<{ appId: string token: string }>() const generateApiKey = useMutation(consoleQuery.enterprise.appDeploy.createDeveloperApiKey.mutationOptions()) const revokeApiKey = useMutation(consoleQuery.enterprise.appDeploy.deleteDeveloperApiKey.mutationOptions()) - const toggleAccessChannel = useMutation(consoleQuery.enterprise.appDeploy.updateAccessChannels.mutationOptions()) const toggleDeveloperAPI = useMutation(consoleQuery.enterprise.appDeploy.updateDeveloperApi.mutationOptions()) - const setEnvironmentAccessPolicy = useMutation(consoleQuery.enterprise.appDeploy.updateEnvironmentAccessPolicy.mutationOptions()) - const deploymentRows = deployedRows(environmentDeployments?.data) - const policies = accessConfig?.permissions ?? EMPTY_ACCESS_PERMISSIONS - const deployedEnvs = uniqueEnvironments([ - ...deploymentRows.map(row => row.environment), - ...policies.map(policy => policy.environment), - ...(accessConfig?.accessChannels?.webappRows?.map(row => row.environment) ?? []), - ]) - const apiEnabled = accessConfig?.developerApi?.enabled ?? false - const apiKeys = accessConfig?.developerApi?.apiKeys ?? [] - const createApiKeyLabel = (environmentId: string) => { + function createApiKeyLabel(environmentId: string) { const existingCount = apiKeys.filter(key => key.environment?.id === environmentId, ).length - const name = deployedEnvs.find(env => env.id === environmentId)?.name ?? 'env' + const name = environments.find(env => env.id === environmentId)?.name ?? 'env' return `${name}-key-${String(existingCount + 1).padStart(3, '0')}` } - const handleGenerateApiKey = (environmentId: string) => { + + function handleGenerateApiKey(environmentId: string) { generateApiKey.mutate( { params: { @@ -82,7 +78,8 @@ export function AccessTab({ instanceId: appId }: { }, ) } - const handleRevokeApiKey = (_environmentId: string, apiKeyId: string) => { + + function handleRevokeApiKey(_environmentId: string, apiKeyId: string) { revokeApiKey.mutate({ params: { appInstanceId: appId, @@ -90,7 +87,8 @@ export function AccessTab({ instanceId: appId }: { }, }) } - const handleCopyApiKey = async (apiKeyId: string) => { + + async function handleCopyApiKey(apiKeyId: string) { const response = await consoleClient.enterprise.appDeploy.revealDeveloperApiKey({ params: { appInstanceId: appId, @@ -101,6 +99,52 @@ export function AccessTab({ instanceId: appId }: { throw new Error('Reveal developer API key did not return a token.') return response.token } + + const visibleCreatedApiToken = createdApiToken?.appId === appId + ? createdApiToken.token + : undefined + + return ( + toggleDeveloperAPI.mutate({ + params: { appInstanceId: appId }, + body: { enabled }, + })} + onGenerate={handleGenerateApiKey} + onCopyApiKey={handleCopyApiKey} + onRevoke={handleRevokeApiKey} + onClearCreatedToken={() => setCreatedApiToken(undefined)} + /> + ) +} + +export function AccessTab({ instanceId: appId }: { + instanceId: string +}) { + const appInput = { params: { appInstanceId: appId } } + const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({ + input: appInput, + })) + const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({ + input: appInput, + })) + const toggleAccessChannel = useMutation(consoleQuery.enterprise.appDeploy.updateAccessChannels.mutationOptions()) + const setEnvironmentAccessPolicy = useMutation(consoleQuery.enterprise.appDeploy.updateEnvironmentAccessPolicy.mutationOptions()) + + const deploymentRows = deployedRows(environmentDeployments?.data) + const policies = accessConfig?.permissions ?? EMPTY_ACCESS_PERMISSIONS + const deployedEnvs = uniqueEnvironments([ + ...deploymentRows.map(row => row.environment), + ...policies.map(policy => policy.environment), + ...(accessConfig?.accessChannels?.webappRows?.map(row => row.environment) ?? []), + ]) + const apiEnabled = accessConfig?.developerApi?.enabled ?? false + const apiKeys = accessConfig?.developerApi?.apiKeys ?? [] const handleSetEnvironmentAccessPolicy = async ( appId: string, environmentId: string, @@ -120,9 +164,6 @@ export function AccessTab({ instanceId: appId }: { } const webappRows = accessConfig?.accessChannels?.webappRows?.filter(row => row.url) ?? [] const runEnabled = accessConfig?.accessChannels?.enabled ?? false - const visibleCreatedApiToken = createdApiToken?.appId === appId - ? createdApiToken.token - : undefined const cliDomain = getUrlOrigin(accessConfig?.accessChannels?.cli?.url) const cliDocsUrl = cliDomain ? `${cliDomain}/cli` : undefined @@ -144,20 +185,12 @@ export function AccessTab({ instanceId: appId }: { body: { enabled }, })} /> - toggleDeveloperAPI.mutate({ - params: { appInstanceId: appId }, - body: { enabled }, - })} - onGenerate={handleGenerateApiKey} - onCopyApiKey={handleCopyApiKey} - onRevoke={handleRevokeApiKey} - onClearCreatedToken={() => setCreatedApiToken(undefined)} /> ) diff --git a/web/features/deployments/detail/deploy-tab.tsx b/web/features/deployments/detail/deploy-tab.tsx index 565c5a9655..8012f27028 100644 --- a/web/features/deployments/detail/deploy-tab.tsx +++ b/web/features/deployments/detail/deploy-tab.tsx @@ -1,5 +1,6 @@ 'use client' import type { KeyboardEvent } from 'react' +import type { EnvironmentOption } from '../types' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { @@ -32,6 +33,66 @@ import { DeploymentStatusSummary } from './deploy-tab/deployment-status-summary' const GRID_TEMPLATE = 'lg:grid-cols-[minmax(180px,1fr)_minmax(140px,0.75fr)_minmax(180px,0.85fr)_240px]' +function NewDeploymentMenu({ appInstanceId, availableEnvs }: { + appInstanceId: string + availableEnvs: EnvironmentOption[] +}) { + const { t } = useTranslation('deployments') + const openDeployDrawer = useDeploymentsStore(state => state.openDeployDrawer) + const [open, setOpen] = useState(false) + + return ( + + + + {t('deployTab.newDeployment')} + + + {open && ( + + { + setOpen(false) + openDeployDrawer({ appInstanceId }) + }} + > + {t('deployTab.deployToNewEnv')} + + {availableEnvs.length > 0 && ( + <> +
{t('deployTab.shortcut')}
+ {availableEnvs.map(env => ( + { + if (env.disabled) + return + setOpen(false) + openDeployDrawer({ appInstanceId, environmentId: env.id }) + }} + > + + {t('deployTab.deployToEnv', { name: environmentName(env) })} + + + ))} + + )} +
+ )} +
+ ) +} + export function DeployTab({ instanceId: appInstanceId }: { instanceId: string }) { @@ -64,7 +125,6 @@ export function DeployTab({ instanceId: appInstanceId }: { return current === id ? null : id }) } - const [deployMenuOpen, setDeployMenuOpen] = useState(false) return (
@@ -78,54 +138,7 @@ export function DeployTab({ instanceId: appInstanceId }: { )
- - - - {t('deployTab.newDeployment')} - - - {deployMenuOpen && ( - - { - setDeployMenuOpen(false) - openDeployDrawer({ appInstanceId }) - }} - > - {t('deployTab.deployToNewEnv')} - - {availableEnvs.length > 0 && ( - <> -
{t('deployTab.shortcut')}
- {availableEnvs.map(env => ( - { - if (env.disabled) - return - setDeployMenuOpen(false) - openDeployDrawer({ appInstanceId, environmentId: env.id }) - }} - > - - {t('deployTab.deployToEnv', { name: environmentName(env) })} - - - ))} - - )} -
- )} -
+ {rows.length === 0 diff --git a/web/features/deployments/detail/versions-tab.tsx b/web/features/deployments/detail/versions-tab.tsx index 888dc562bd..656f480690 100644 --- a/web/features/deployments/detail/versions-tab.tsx +++ b/web/features/deployments/detail/versions-tab.tsx @@ -23,37 +23,19 @@ import { getReleaseDeployments } from './versions-tab/release-deployments' const GRID_TEMPLATE = 'grid-cols-[minmax(0,0.9fr)_minmax(0,1fr)_minmax(0,0.8fr)_minmax(0,1.5fr)_96px]' -export function VersionsTab({ instanceId: appId }: { - instanceId: string +function CreateReleaseControl({ appId, canCreateRelease }: { + appId: string + canCreateRelease: boolean }) { const { t } = useTranslation('deployments') - const input = { params: { appInstanceId: appId } } - const { data: overview } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceOverview.queryOptions({ - input, - })) - const { data: releaseHistory } = useQuery(consoleQuery.enterprise.appDeploy.listReleases.queryOptions({ - input: { - ...input, - query: { - pageNumber: 1, - resultsPerPage: DEPLOYMENT_PAGE_SIZE, - }, - }, - })) - const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({ - input, - })) const createRelease = useMutation(consoleQuery.enterprise.appDeploy.createRelease.mutationOptions()) const [isCreating, setIsCreating] = useState(false) const [releaseName, setReleaseName] = useState('') const [releaseDescription, setReleaseDescription] = useState('') - const releaseRows = releaseHistory?.data?.filter(row => row.id) ?? [] - const deploymentRows = deployedRows(environmentDeployments?.data) - const canCreateRelease = overview?.instance?.canCreateRelease ?? true const trimmedReleaseName = releaseName.trim() const canSubmitRelease = Boolean(canCreateRelease && trimmedReleaseName && !createRelease.isPending) - const handleCreateRelease = async () => { + async function handleCreateRelease() { if (!canSubmitRelease) return @@ -79,33 +61,16 @@ export function VersionsTab({ instanceId: appId }: { } return ( -
-
-
- {t('versions.releaseHistory')} - {' '} - - ( - {releaseRows.length} - ) - -
- -
- - {!canCreateRelease && ( -
- {t('versions.sourceAppUnavailable')} -
- )} + <> + @@ -192,6 +157,54 @@ export function VersionsTab({ instanceId: appId }: { + + ) +} + +export function VersionsTab({ instanceId: appId }: { + instanceId: string +}) { + const { t } = useTranslation('deployments') + const input = { params: { appInstanceId: appId } } + const { data: overview } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceOverview.queryOptions({ + input, + })) + const { data: releaseHistory } = useQuery(consoleQuery.enterprise.appDeploy.listReleases.queryOptions({ + input: { + ...input, + query: { + pageNumber: 1, + resultsPerPage: DEPLOYMENT_PAGE_SIZE, + }, + }, + })) + const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({ + input, + })) + const releaseRows = releaseHistory?.data?.filter(row => row.id) ?? [] + const deploymentRows = deployedRows(environmentDeployments?.data) + const canCreateRelease = overview?.instance?.canCreateRelease ?? true + + return ( +
+
+
+ {t('versions.releaseHistory')} + {' '} + + ( + {releaseRows.length} + ) + +
+ +
+ + {!canCreateRelease && ( +
+ {t('versions.sourceAppUnavailable')} +
+ )} {releaseRows.length === 0 ? (