diff --git a/web/context/get-query-client.ts b/web/context/get-query-client.ts new file mode 100644 index 0000000000..85e2cc68b3 --- /dev/null +++ b/web/context/get-query-client.ts @@ -0,0 +1,15 @@ +import type { QueryClient } from '@tanstack/react-query' +import { isServer } from '@/utils/client' +import { makeQueryClient } from './query-client-server' + +let browserQueryClient: QueryClient | undefined + +export function getQueryClient() { + if (isServer) + return makeQueryClient() + + if (!browserQueryClient) + browserQueryClient = makeQueryClient() + + return browserQueryClient +} diff --git a/web/context/query-client.tsx b/web/context/query-client.tsx index 38292bfc8c..7511da311f 100644 --- a/web/context/query-client.tsx +++ b/web/context/query-client.tsx @@ -1,21 +1,8 @@ 'use client' -import type { QueryClient } from '@tanstack/react-query' import { QueryClientProvider } from '@tanstack/react-query' import { TanStackDevtoolsLoader } from '@/app/components/devtools/tanstack/loader' -import { isServer } from '@/utils/client' -import { makeQueryClient } from './query-client-server' - -let browserQueryClient: QueryClient | undefined - -function getQueryClient() { - if (isServer) { - return makeQueryClient() - } - if (!browserQueryClient) - browserQueryClient = makeQueryClient() - return browserQueryClient -} +import { getQueryClient } from './get-query-client' export const TanstackQueryInitializer = ({ children }: { children: React.ReactNode }) => { const queryClient = getQueryClient() diff --git a/web/features/deployments/components/deploy-drawer.tsx b/web/features/deployments/components/deploy-drawer.tsx index ccffc61850..dacc255d44 100644 --- a/web/features/deployments/components/deploy-drawer.tsx +++ b/web/features/deployments/components/deploy-drawer.tsx @@ -7,10 +7,11 @@ import { Dialog, DialogCloseButton, DialogContent, DialogDescription, DialogTitl import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select' import { skipToken, useQuery } from '@tanstack/react-query' import * as React from 'react' -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' import { consoleQuery } from '@/service/client' +import { deploymentAppDataQueryOptions } from '@/service/deployments' import { useDeploymentsStore } from '../store' import { environmentHealth, environmentMode, environmentName, releaseCommit, releaseLabel } from '../utils' import { HealthBadge, ModeBadge } from './status-badge' @@ -432,11 +433,23 @@ const DeployForm: FC = ({ const DeployDrawer: FC = () => { const { t } = useTranslation('deployments') const drawer = useDeploymentsStore(state => state.deployDrawer) - const appData = useDeploymentsStore(state => drawer.appId ? state.appData[drawer.appId] : undefined) + const drawerAppId = drawer.appId + const storedAppData = useDeploymentsStore(state => drawerAppId ? state.appData[drawerAppId] : undefined) + const applyAppData = useDeploymentsStore(state => state.applyAppData) const closeDeployDrawer = useDeploymentsStore(state => state.closeDeployDrawer) const startDeploy = useDeploymentsStore(state => state.startDeploy) const open = drawer.open + const appDataQuery = useQuery({ + ...deploymentAppDataQueryOptions(drawerAppId ?? ''), + enabled: open && Boolean(drawerAppId) && !storedAppData, + }) + useEffect(() => { + if (appDataQuery.data) + applyAppData(appDataQuery.data) + }, [appDataQuery.data, applyAppData]) + + const appData = storedAppData ?? (appDataQuery.data?.appId === drawerAppId ? appDataQuery.data : undefined) const environments = appData?.candidates.environmentOptions ?? [] const releases = appData?.candidates.releases ?? [] const defaultReleaseId = appData?.candidates.defaultReleaseId @@ -449,28 +462,35 @@ const DeployDrawer: FC = () => { > - {!drawer.appId + {!drawerAppId ?
{t('deployDrawer.notFound')}
- : ( - - startDeploy({ - appId: drawer.appId!, - environmentId, - releaseId, - releaseNote, - bindings, - })} - /> - )} + : !appData + ? ( +
+ + {t('createModal.loadingApps')} +
+ ) + : ( + + startDeploy({ + appId: drawerAppId, + environmentId, + releaseId, + releaseNote, + bindings, + })} + /> + )}
) diff --git a/web/features/deployments/store.ts b/web/features/deployments/store.ts index 2dbc5bf228..69414d3b4f 100644 --- a/web/features/deployments/store.ts +++ b/web/features/deployments/store.ts @@ -7,8 +7,8 @@ import { createApiKey, createDeployment, deleteApiKey, - fetchDeploymentAppData, patchAccessChannel, + refreshDeploymentAppData, rollbackEnvironment, undeployEnvironment, updateEnvironmentAccessPolicy, @@ -146,7 +146,7 @@ export const useDeploymentsStore = create((set, get) => ({ })), refreshAppData: async (appId) => { - const data = await fetchDeploymentAppData(appId) + const data = await refreshDeploymentAppData(appId) get().applyAppData(data) }, diff --git a/web/service/deployments.ts b/web/service/deployments.ts index be419963d6..4ce05de553 100644 --- a/web/service/deployments.ts +++ b/web/service/deployments.ts @@ -8,6 +8,7 @@ import type { ListReleaseHistoryReply, } from '@/contract/console/deployments' import { queryOptions } from '@tanstack/react-query' +import { getQueryClient } from '@/context/get-query-client' import { consoleClient } from './client' const DEPLOYMENT_PAGE_SIZE = 100 @@ -32,6 +33,8 @@ export type CreateDeploymentParams = { const idempotencyKey = (prefix: string) => `${prefix}-${globalThis.crypto?.randomUUID?.() ?? Date.now()}` +export const deploymentAppDataQueryKey = (appId: string) => ['console', 'deployments', 'app-data', appId] as const + export const fetchDeploymentAppData = async (appId: string): Promise => { const input = { params: { appId } } const [ @@ -72,11 +75,18 @@ export const fetchDeploymentAppData = async (appId: string): Promise queryOptions({ - queryKey: ['console', 'deployments', 'app-data', appId], + queryKey: deploymentAppDataQueryKey(appId), queryFn: () => fetchDeploymentAppData(appId), staleTime: DEPLOYMENT_APP_DATA_STALE_TIME, }) +export const refreshDeploymentAppData = async (appId: string): Promise => { + return getQueryClient().fetchQuery({ + ...deploymentAppDataQueryOptions(appId), + staleTime: 0, + }) +} + export const createDeployment = async ({ appId, environmentId,