From 64fc1e82818997a29cc9e3b96b9ad2171f9c9a71 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Thu, 7 May 2026 18:26:49 +0800 Subject: [PATCH] update --- .../components/create-instance-modal.tsx | 16 ++--- .../deployments/components/deploy-drawer.tsx | 7 +- .../components/deploy-drawer/form.tsx | 45 +++++------- .../deployments/components/rollback-modal.tsx | 6 +- .../deployments/detail/access-tab.tsx | 20 ++---- .../detail/access-tab/permissions.tsx | 21 ++---- .../deployments/detail/deploy-tab.tsx | 23 ++---- .../deployments/detail/deployment-sidebar.tsx | 6 +- web/features/deployments/detail/index.tsx | 6 +- .../deployments/detail/overview-tab.tsx | 6 +- .../deployments/detail/settings-tab.tsx | 7 +- .../deployments/detail/versions-tab.tsx | 12 +--- .../versions-tab/deploy-release-menu.tsx | 7 +- web/features/deployments/list/index.tsx | 70 +++++++++---------- web/features/deployments/nav/index.tsx | 51 ++++++-------- 15 files changed, 112 insertions(+), 191 deletions(-) diff --git a/web/features/deployments/components/create-instance-modal.tsx b/web/features/deployments/components/create-instance-modal.tsx index f18f9e78c6..8e003415c6 100644 --- a/web/features/deployments/components/create-instance-modal.tsx +++ b/web/features/deployments/components/create-instance-modal.tsx @@ -7,7 +7,7 @@ import { Dialog, DialogCloseButton, DialogContent, DialogDescription, DialogTitl import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover' import { toast } from '@langgenius/dify-ui/toast' import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo, useRef, useState } from 'react' +import { useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { AppTypeIcon } from '@/app/components/app/type-selector' import AppIcon from '@/app/components/base/app-icon' @@ -45,12 +45,10 @@ export function AppPicker({ apps, isLoading, value, onChange }: AppPickerProps) const triggerRef = useRef(null) const [triggerWidth, setTriggerWidth] = useState(undefined) - const filtered = useMemo(() => { - const q = keywords.trim().toLowerCase() - if (!q) - return apps - return apps.filter(a => a.name.toLowerCase().includes(q) || a.mode.toLowerCase().includes(q)) - }, [apps, keywords]) + const q = keywords.trim().toLowerCase() + const filtered = q + ? apps.filter(a => a.name.toLowerCase().includes(q) || a.mode.toLowerCase().includes(q)) + : apps const handleOpenChange = (next: boolean) => { if (next && triggerRef.current) @@ -218,9 +216,7 @@ function CreateInstanceForm({ onClose }: { }, }, })) - const apps = useMemo(() => { - return (appList?.data ?? []).map(toStudioSourceAppInfo) - }, [appList?.data]) + const apps = (appList?.data ?? []).map(toStudioSourceAppInfo) const [appId, setAppId] = useState('') const [name, setName] = useState('') diff --git a/web/features/deployments/components/deploy-drawer.tsx b/web/features/deployments/components/deploy-drawer.tsx index 185d04dc1b..8da6e730d8 100644 --- a/web/features/deployments/components/deploy-drawer.tsx +++ b/web/features/deployments/components/deploy-drawer.tsx @@ -3,7 +3,6 @@ import { Dialog, DialogCloseButton, DialogContent } from '@langgenius/dify-ui/dialog' import { toast } from '@langgenius/dify-ui/toast' import { skipToken, useMutation, useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { DEPLOYMENT_PAGE_SIZE } from '../data' @@ -34,11 +33,7 @@ export function DeployDrawer() { enabled: open, })) - const environmentOptions = useMemo( - () => environmentOptionsFromOptionsReply(environmentOptionsReply), - [environmentOptionsReply], - ) - const environments = environmentOptions + const environments = environmentOptionsFromOptionsReply(environmentOptionsReply) const releases = releaseHistory?.data?.filter(release => release.id) ?? [] const defaultReleaseId = releases[0]?.id const formKey = `${drawer.appInstanceId ?? 'none'}-${drawer.environmentId ?? 'any'}-${drawer.releaseId ?? 'new'}-${open ? '1' : '0'}` diff --git a/web/features/deployments/components/deploy-drawer/form.tsx b/web/features/deployments/components/deploy-drawer/form.tsx index c653b79f45..3198311448 100644 --- a/web/features/deployments/components/deploy-drawer/form.tsx +++ b/web/features/deployments/components/deploy-drawer/form.tsx @@ -5,7 +5,7 @@ import type { ConsoleReleaseSummary, EnvironmentOption } from '@/features/deploy import { Button } from '@langgenius/dify-ui/button' import { DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog' import { skipToken, useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { @@ -105,6 +105,20 @@ function selectedDeploymentBindings(slots: DeploymentBindingOptionSlot[], select .filter((binding): binding is DeploymentRuntimeBinding => Boolean(binding)) } +function selectedBindingSelections(slots: DeploymentBindingOptionSlot[], manualBindings: BindingSelections): BindingSelections { + const next: BindingSelections = {} + for (const slot of slots) { + const slotKey = bindingSlotKey(slot) + const candidates = bindingCandidateOptions(slot) + const existing = manualBindings[slotKey] + if (existing && candidates.some(candidate => candidate.value === existing)) + next[slotKey] = existing + else if (candidates.length === 1 && candidates[0]) + next[slotKey] = candidates[0].value + } + return next +} + function BindingOptionsPanel({ slots, selections, @@ -204,10 +218,7 @@ export function DeployForm({ onSubmit, }: DeployFormProps) { const { t } = useTranslation('deployments') - const presetRelease = useMemo( - () => presetReleaseId ? releases.find(r => r.id === presetReleaseId) : undefined, - [releases, presetReleaseId], - ) + const presetRelease = presetReleaseId ? releases.find(r => r.id === presetReleaseId) : undefined const displayedRelease = presetRelease ?? (presetReleaseId ? { id: presetReleaseId } : undefined) const isPromote = Boolean(presetReleaseId) @@ -231,28 +242,10 @@ export function DeployForm({ } : skipToken, })) - const bindingSlots = useMemo( - () => bindingOptions.data?.slots?.filter(slot => slot.slot) ?? [], - [bindingOptions.data?.slots], - ) + const bindingSlots = bindingOptions.data?.slots?.filter(slot => slot.slot) ?? [] const [manualBindings, setManualBindings] = useState({}) - const selectedBindings = useMemo(() => { - const next: BindingSelections = {} - for (const slot of bindingSlots) { - const slotKey = bindingSlotKey(slot) - const candidates = bindingCandidateOptions(slot) - const existing = manualBindings[slotKey] - if (existing && candidates.some(candidate => candidate.value === existing)) - next[slotKey] = existing - else if (candidates.length === 1 && candidates[0]) - next[slotKey] = candidates[0].value - } - return next - }, [bindingSlots, manualBindings]) - const deploymentBindings = useMemo( - () => selectedDeploymentBindings(bindingSlots, selectedBindings), - [bindingSlots, selectedBindings], - ) + const selectedBindings = selectedBindingSelections(bindingSlots, manualBindings) + const deploymentBindings = selectedDeploymentBindings(bindingSlots, selectedBindings) const bindingOptionsLoading = Boolean(targetReleaseId && (bindingOptions.isLoading || bindingOptions.isFetching)) const bindingOptionsReady = Boolean(targetReleaseId && bindingOptions.data && !bindingOptionsLoading && !bindingOptions.isError) const requiredBindingsReady = bindingSlots.every(slot => !hasMissingRequiredBinding(slot, selectedBindings[bindingSlotKey(slot)])) diff --git a/web/features/deployments/components/rollback-modal.tsx b/web/features/deployments/components/rollback-modal.tsx index 492a4e493c..d01aaa48bb 100644 --- a/web/features/deployments/components/rollback-modal.tsx +++ b/web/features/deployments/components/rollback-modal.tsx @@ -9,7 +9,6 @@ import { AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { skipToken, useMutation, useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { DEPLOYMENT_PAGE_SIZE } from '../data' @@ -68,10 +67,7 @@ export function RollbackModal() { : skipToken, enabled: modal.open && Boolean(modal.appInstanceId), })) - const environmentOptions = useMemo( - () => environmentOptionsFromOptionsReply(environmentOptionsReply), - [environmentOptionsReply], - ) + const environmentOptions = environmentOptionsFromOptionsReply(environmentOptionsReply) const currentRow = deployedRows(environmentDeployments?.data) .find(row => environmentId(row.environment) === modal.environmentId) diff --git a/web/features/deployments/detail/access-tab.tsx b/web/features/deployments/detail/access-tab.tsx index 5e581bdc04..266efd2b8e 100644 --- a/web/features/deployments/detail/access-tab.tsx +++ b/web/features/deployments/detail/access-tab.tsx @@ -6,7 +6,7 @@ import type { ConsoleEnvironmentSummary, } from '@/features/deployments/types' import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { consoleClient, consoleQuery } from '@/service/client' import { deployedRows, @@ -46,19 +46,13 @@ export function AccessTab({ instanceId: appId }: { const toggleDeveloperAPI = useMutation(consoleQuery.enterprise.appDeploy.updateDeveloperApi.mutationOptions()) const setEnvironmentAccessPolicy = useMutation(consoleQuery.enterprise.appDeploy.updateEnvironmentAccessPolicy.mutationOptions()) - const deploymentRows = useMemo( - () => deployedRows(environmentDeployments?.data), - [environmentDeployments?.data], - ) + const deploymentRows = deployedRows(environmentDeployments?.data) const policies = accessConfig?.permissions ?? EMPTY_ACCESS_PERMISSIONS - const deployedEnvs = useMemo( - () => uniqueEnvironments([ - ...deploymentRows.map(row => row.environment), - ...policies.map(policy => policy.environment), - ...(accessConfig?.accessChannels?.webappRows?.map(row => row.environment) ?? []), - ]), - [accessConfig?.accessChannels?.webappRows, deploymentRows, policies], - ) + 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) => { diff --git a/web/features/deployments/detail/access-tab/permissions.tsx b/web/features/deployments/detail/access-tab/permissions.tsx index 63ad08ec62..7cf4a80684 100644 --- a/web/features/deployments/detail/access-tab/permissions.tsx +++ b/web/features/deployments/detail/access-tab/permissions.tsx @@ -19,7 +19,7 @@ import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/pop import { toast } from '@langgenius/dify-ui/toast' import { skipToken, useQuery } from '@tanstack/react-query' import { useDebounce } from 'ahooks' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { @@ -181,10 +181,7 @@ function SubjectPicker({ const [open, setOpen] = useState(false) const [keyword, setKeyword] = useState('') const debouncedKeyword = useDebounce(keyword, { wait: 300 }) - const selectedKeys = useMemo( - () => new Set(selectedSubjects.map(subjectKey)), - [selectedSubjects], - ) + const selectedKeys = new Set(selectedSubjects.map(subjectKey)) const subjectsQuery = useQuery(consoleQuery.enterprise.appDeploy.searchAccessSubjects.queryOptions({ input: open ? { @@ -196,12 +193,9 @@ function SubjectPicker({ } : skipToken, })) - const subjects = useMemo( - () => subjectsQuery.data?.data - ?.map(normalizeSubject) - .filter((subject): subject is SelectableAccessSubject => Boolean(subject)) ?? [], - [subjectsQuery.data?.data], - ) + const subjects = subjectsQuery.data?.data + ?.map(normalizeSubject) + .filter((subject): subject is SelectableAccessSubject => Boolean(subject)) ?? [] const toggleSubject = (subject: SelectableAccessSubject) => { const key = subjectKey(subject) @@ -330,10 +324,7 @@ export function EnvironmentPermissionRow({ detailPolicy?.accessMode ?? summaryPolicy?.accessMode ?? '', policySubjectFingerprint ?? '', ].join(':') - const policySelectedSubjects = useMemo( - () => policyKind === 'specific' ? selectedSubjectsFromPolicy(detailPolicy) : [], - [detailPolicy, policyKind], - ) + const policySelectedSubjects = policyKind === 'specific' ? selectedSubjectsFromPolicy(detailPolicy) : [] const [draft, setDraft] = useState<{ fingerprint?: string kind?: AccessPermissionKind diff --git a/web/features/deployments/detail/deploy-tab.tsx b/web/features/deployments/detail/deploy-tab.tsx index db8d5096bc..565c5a9655 100644 --- a/web/features/deployments/detail/deploy-tab.tsx +++ b/web/features/deployments/detail/deploy-tab.tsx @@ -9,7 +9,7 @@ import { DropdownMenuTrigger, } from '@langgenius/dify-ui/dropdown-menu' import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { useDeploymentsStore } from '../store' @@ -45,26 +45,13 @@ export function DeployTab({ instanceId: appInstanceId }: { const openDeployDrawer = useDeploymentsStore(state => state.openDeployDrawer) const cancelDeployment = useMutation(consoleQuery.enterprise.appDeploy.cancelRuntimeDeployment.mutationOptions()) const undeployDeployment = useMutation(consoleQuery.enterprise.appDeploy.undeployRuntimeInstance.mutationOptions()) - const environmentOptions = useMemo( - () => environmentOptionsFromOptionsReply(environmentOptionsReply), - [environmentOptionsReply], - ) - - const rows = useMemo( - () => environmentDeployments?.data?.filter(row => row.environment?.id) ?? [], - [environmentDeployments?.data], - ) - const deployedRuntimeRows = useMemo( - () => deployedRows(environmentDeployments?.data), - [environmentDeployments?.data], - ) + const environmentOptions = environmentOptionsFromOptionsReply(environmentOptionsReply) + const rows = environmentDeployments?.data?.filter(row => row.environment?.id) ?? [] + const deployedRuntimeRows = deployedRows(environmentDeployments?.data) const deployedEnvIds = new Set(deployedRuntimeRows.map(row => environmentId(row.environment))) const availableEnvs = environmentOptions.filter(env => env.id && !deployedEnvIds.has(env.id)) - const expandableEnvIds = useMemo( - () => rows.filter(row => !isUndeployedDeploymentRow(row)).map(row => environmentId(row.environment)), - [rows], - ) + const expandableEnvIds = rows.filter(row => !isUndeployedDeploymentRow(row)).map(row => environmentId(row.environment)) const [expanded, setExpanded] = useState() const activeExpanded = expanded === undefined ? expandableEnvIds[0] ?? null diff --git a/web/features/deployments/detail/deployment-sidebar.tsx b/web/features/deployments/detail/deployment-sidebar.tsx index 2684a52796..5d41be66aa 100644 --- a/web/features/deployments/detail/deployment-sidebar.tsx +++ b/web/features/deployments/detail/deployment-sidebar.tsx @@ -6,7 +6,7 @@ import type { InstanceDetailTabKey } from './tabs' import type { NavIcon } from '@/app/components/app-sidebar/nav-link' import { cn } from '@langgenius/dify-ui/cn' import { useHover, useKeyPress } from 'ahooks' -import { useCallback, useEffect, useRef } from 'react' +import { useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { useShallow } from 'zustand/react/shallow' import NavLink from '@/app/components/app-sidebar/nav-link' @@ -103,9 +103,9 @@ export function DeploymentSidebar({ const sidebarMode = appSidebarExpand || 'expand' const expand = sidebarMode === 'expand' - const handleToggle = useCallback(() => { + function handleToggle() { setAppSidebarExpand(sidebarMode === 'expand' ? 'collapse' : 'expand') - }, [setAppSidebarExpand, sidebarMode]) + } useEffect(() => { const persistedMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand' diff --git a/web/features/deployments/detail/index.tsx b/web/features/deployments/detail/index.tsx index e87d6cf4b2..016416f8ad 100644 --- a/web/features/deployments/detail/index.tsx +++ b/web/features/deployments/detail/index.tsx @@ -4,7 +4,6 @@ import type { ReactNode } from 'react' import type { InstanceDetailTabKey } from './tabs' import { Button } from '@langgenius/dify-ui/button' import { useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { getAppModeLabel } from '@/app/components/app-sidebar/app-info/app-mode-labels' import useDocumentTitle from '@/hooks/use-document-title' @@ -34,10 +33,7 @@ export function InstanceDetail({ instanceId, children }: { useDocumentTitle(t('documentTitle.detail')) - const app = useMemo( - () => toAppInfoFromOverview(overviewQuery.data?.instance), - [overviewQuery.data?.instance], - ) + const app = toAppInfoFromOverview(overviewQuery.data?.instance) if (!app && overviewQuery.isLoading) { return ( diff --git a/web/features/deployments/detail/overview-tab.tsx b/web/features/deployments/detail/overview-tab.tsx index 0c318facf3..5073b93f11 100644 --- a/web/features/deployments/detail/overview-tab.tsx +++ b/web/features/deployments/detail/overview-tab.tsx @@ -3,7 +3,6 @@ import type { ReactNode } from 'react' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { getAppModeLabel } from '@/app/components/app-sidebar/app-info/app-mode-labels' import { useRouter } from '@/next/navigation' @@ -115,10 +114,7 @@ export function OverviewTab({ instanceId }: { const openDeployDrawer = useDeploymentsStore(state => state.openDeployDrawer) const app = toAppInfoFromOverview(overview?.instance) const overviewApp = overview?.instance - const deployments = useMemo( - () => overview?.deployments?.filter(row => row.environment?.id && row.status?.toLowerCase() !== 'undeployed') ?? [], - [overview?.deployments], - ) + 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 diff --git a/web/features/deployments/detail/settings-tab.tsx b/web/features/deployments/detail/settings-tab.tsx index bcf96b8d43..82154c198e 100644 --- a/web/features/deployments/detail/settings-tab.tsx +++ b/web/features/deployments/detail/settings-tab.tsx @@ -13,7 +13,7 @@ import { import { Button } from '@langgenius/dify-ui/button' import { toast } from '@langgenius/dify-ui/toast' import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { useRouter } from '@/next/navigation' import { consoleQuery } from '@/service/client' @@ -183,10 +183,7 @@ export function SettingsTab({ instanceId }: { const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({ input: appInput, })) - const app = useMemo( - () => toAppInfoFromOverview(overview?.instance), - [overview?.instance], - ) + const app = toAppInfoFromOverview(overview?.instance) const settingsQuery = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceSettings.queryOptions({ input: appInput, })) diff --git a/web/features/deployments/detail/versions-tab.tsx b/web/features/deployments/detail/versions-tab.tsx index f7154ba8cb..888dc562bd 100644 --- a/web/features/deployments/detail/versions-tab.tsx +++ b/web/features/deployments/detail/versions-tab.tsx @@ -5,7 +5,7 @@ import { Dialog, DialogCloseButton, DialogContent, DialogDescription, DialogTitl import { toast } from '@langgenius/dify-ui/toast' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' import Textarea from '@/app/components/base/textarea' @@ -47,14 +47,8 @@ export function VersionsTab({ instanceId: appId }: { const [isCreating, setIsCreating] = useState(false) const [releaseName, setReleaseName] = useState('') const [releaseDescription, setReleaseDescription] = useState('') - const releaseRows = useMemo( - () => releaseHistory?.data?.filter(row => row.id) ?? [], - [releaseHistory?.data], - ) - const deploymentRows = useMemo( - () => deployedRows(environmentDeployments?.data), - [environmentDeployments?.data], - ) + 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) diff --git a/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx b/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx index 818706c2ed..a60f949261 100644 --- a/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx +++ b/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx @@ -8,7 +8,7 @@ import { DropdownMenuTrigger, } from '@langgenius/dify-ui/dropdown-menu' import { useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { useDeploymentsStore } from '../../store' @@ -38,10 +38,7 @@ export function DeployReleaseMenu({ appInstanceId, releaseId }: { enabled: open, })) - const environmentOptions = useMemo( - () => environmentOptionsFromOptionsReply(environmentOptionsReply), - [environmentOptionsReply], - ) + const environmentOptions = environmentOptionsFromOptionsReply(environmentOptionsReply) const environments = environmentOptions.filter(env => env.id) const deploymentRows = deployedRows(environmentDeployments?.data) diff --git a/web/features/deployments/list/index.tsx b/web/features/deployments/list/index.tsx index 522b4e8b63..680aa65fe1 100644 --- a/web/features/deployments/list/index.tsx +++ b/web/features/deployments/list/index.tsx @@ -3,7 +3,6 @@ import { useQuery } from '@tanstack/react-query' import { useDebounce } from 'ahooks' import { debounce, parseAsString, useQueryState } from 'nuqs' -import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' import { consoleQuery } from '@/service/client' @@ -56,47 +55,42 @@ export function DeploymentsMain() { }, })) const { data: environmentOptionsReply } = useQuery(consoleQuery.enterprise.appDeploy.listDeploymentEnvironmentOptions.queryOptions()) - const apps = useMemo(() => sourceAppsFromList(listQuery.data), [listQuery.data]) - const summaries = useMemo(() => deploymentSummariesFromList(listQuery.data), [listQuery.data]) - const environments = useMemo(() => { - return environmentOptionsReply?.environments?.flatMap((env) => { - if (!env.id) - return [] - return [{ - id: env.id, - name: env.name || env.id, - disabled: env.deployable === false, - disabledReason: env.disabledReason, - }] - }) ?? [] - }, [environmentOptionsReply]) - - const envIdSet = useMemo(() => new Set(environments.map(e => e.id)), [environments]) + const apps = sourceAppsFromList(listQuery.data) + const summaries = deploymentSummariesFromList(listQuery.data) + const environments = environmentOptionsReply?.environments?.flatMap((env) => { + if (!env.id) + return [] + return [{ + id: env.id, + name: env.name || env.id, + disabled: env.deployable === false, + disabledReason: env.disabledReason, + }] + }) ?? [] + const envIdSet = new Set(environments.map(e => e.id)) const activeFilter = envFilter === 'all' || envFilter === 'not-deployed' || envIdSet.has(envFilter) ? envFilter : 'all' - const filterOptions = useMemo(() => { - return [ - { - value: 'all', - text: t('filter.allEnvs'), - icon: , - }, - ...environments.map(env => ({ - value: env.id, - text: env.name, - icon: , - disabled: env.disabled, - disabledReason: env.disabledReason, - })), - { - value: 'not-deployed', - text: t('filter.notDeployed'), - icon: , - }, - ] - }, [environments, t]) + const filterOptions = [ + { + value: 'all', + text: t('filter.allEnvs'), + icon: , + }, + ...environments.map(env => ({ + value: env.id, + text: env.name, + icon: , + disabled: env.disabled, + disabledReason: env.disabledReason, + })), + { + value: 'not-deployed', + text: t('filter.notDeployed'), + icon: , + }, + ] return ( <> diff --git a/web/features/deployments/nav/index.tsx b/web/features/deployments/nav/index.tsx index 7625e836cf..693c9521a4 100644 --- a/web/features/deployments/nav/index.tsx +++ b/web/features/deployments/nav/index.tsx @@ -3,7 +3,6 @@ import type { NavItem } from '@/app/components/header/nav/nav-selector' import type { AppIconType, AppModeEnum } from '@/types/app' import { skipToken, useQuery } from '@tanstack/react-query' -import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' import Nav from '@/app/components/header/nav' import { useParams, useRouter, useSelectedLayoutSegment } from '@/next/navigation' @@ -41,39 +40,35 @@ export function DeploymentsNav() { }, enabled: isActive, })) - const apps = useMemo(() => sourceAppsFromList(listQuery.data), [listQuery.data]) + const apps = sourceAppsFromList(listQuery.data) - const navigationItems = useMemo(() => { - if (!isActive) - return [] - const navApps = currentInstance && !apps.some(app => app.id === currentInstance.id) - ? [...apps, currentInstance] - : apps - return navApps.map((app) => { - return { - id: app.id, - name: app.name, - link: `/deployments/${app.id}/overview`, - icon_type: (app.iconType ?? null) as AppIconType | null, - icon: app.icon ?? '', - icon_background: app.iconBackground ?? null, - icon_url: app.iconUrl ?? null, - mode: app.mode as unknown as AppModeEnum | undefined, - } - }) - }, [apps, currentInstance, isActive]) + const navApps = currentInstance && !apps.some(app => app.id === currentInstance.id) + ? [...apps, currentInstance] + : apps + const navigationItems: NavItem[] = isActive + ? navApps.map((app) => { + return { + id: app.id, + name: app.name, + link: `/deployments/${app.id}/overview`, + icon_type: (app.iconType ?? null) as AppIconType | null, + icon: app.icon ?? '', + icon_background: app.iconBackground ?? null, + icon_url: app.iconUrl ?? null, + mode: app.mode as unknown as AppModeEnum | undefined, + } + }) + : [] - const curNav = useMemo(() => { - if (!instanceId) - return undefined - return navigationItems.find(item => item.id === instanceId) - }, [instanceId, navigationItems]) + const curNav = instanceId + ? navigationItems.find(item => item.id === instanceId) + : undefined - const handleCreate = useCallback(() => { + function handleCreate() { openCreateInstanceModal() if (selectedSegment !== 'deployments' || instanceId) router.push('/deployments') - }, [openCreateInstanceModal, router, selectedSegment, instanceId]) + } return (