diff --git a/frontend/src/components/project/NewProjectPopup.tsx b/frontend/src/components/project/NewProjectPopup.tsx index 512f1138db9..77290a26d5e 100644 --- a/frontend/src/components/project/NewProjectPopup.tsx +++ b/frontend/src/components/project/NewProjectPopup.tsx @@ -29,7 +29,7 @@ import { useTheme, } from '@mui/material'; import { uniq } from 'lodash'; -import { ReactNode, useCallback, useMemo, useState } from 'react'; +import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { useHistory } from 'react-router'; import { useClustersConf } from '../../lib/k8s'; @@ -136,12 +136,35 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) { // Check if project name already exists (using normalized form to match existing entries) const projectNameExists = projectName.length > 0 && existingProjectNames.has(toKubernetesName(projectName)); + const namespaceToProjectMap = useMemo(() => { + const map = new Map(); + if (!namespaces) return map; + namespaces.forEach(ns => { + const projectId = ns.metadata?.labels?.[PROJECT_ID_LABEL]; + if (projectId) { + map.set(ns.metadata.name, projectId); + } + }); + return map; + }, [namespaces]); + + const effectiveNamespace = selectedNamespace || toKubernetesName(typedNamespace); + const isNamespaceAlreadyAssigned = effectiveNamespace + ? namespaceToProjectMap.has(effectiveNamespace) + : false; const isReadyToCreate = selectedClusters.length && (selectedNamespace || typedNamespace) && projectName && - !projectNameExists; + !projectNameExists && + !isNamespaceAlreadyAssigned; + + useEffect(() => { + if (selectedNamespace && namespaceToProjectMap.has(selectedNamespace)) { + setSelectedNamespace(undefined); + } + }, [selectedNamespace, namespaceToProjectMap]); /** * Creates or updates namespaces for the project @@ -285,6 +308,7 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) { onInputChange={(e, v) => { setTypedNamespace(v); }} + getOptionDisabled={option => namespaceToProjectMap.has(option)} renderInput={params => (