diff --git a/frontend/web/components/EnvironmentReadyChecker.tsx b/frontend/web/components/EnvironmentReadyChecker.tsx index 9e32893f2bf9..6f065fe66be1 100644 --- a/frontend/web/components/EnvironmentReadyChecker.tsx +++ b/frontend/web/components/EnvironmentReadyChecker.tsx @@ -1,8 +1,9 @@ -import { PropsWithChildren, useEffect, useState } from 'react' +import { PropsWithChildren } from 'react' import { useGetEnvironmentQuery } from 'common/services/useEnvironment' import { useRouteMatch } from 'react-router-dom' interface RouteParams { + projectId?: string environmentId?: string } @@ -10,44 +11,61 @@ type EnvironmentReadyCheckerType = { children: React.ReactNode } +const POLL_INTERVAL_MS = 1000 + +const LoadingState = () => ( +
+ +
+) + +const CreatingState = () => ( +
+
+ +

Preparing your environment

+

We are setting up your new environment...

+
+
+) + +const NotFoundState = () => ( +
+

Environment not found

+

+ This environment may have been deleted, or you may not have permission to + access it. Check the URL and try again. +

+
+) + const EnvironmentReadyChecker = ({ children, }: PropsWithChildren) => { const match = useRouteMatch() - const [environmentCreated, setEnvironmentCreated] = useState(false) + const environmentId = match?.params?.environmentId + const projectId = match?.params?.projectId + // 'create' is the new-env form route sentinel, not an env ID. + const hasEnvironmentId = !!environmentId && environmentId !== 'create' - const { data, isLoading } = useGetEnvironmentQuery( - { - id: match?.params?.environmentId || '', - }, + const { data, isError } = useGetEnvironmentQuery( + { id: environmentId || '' }, { - pollingInterval: 1000, - skip: !match?.params?.environmentId || environmentCreated, + pollingInterval: data?.is_creating ? POLL_INTERVAL_MS : 0, + skip: !hasEnvironmentId, }, ) - useEffect(() => { - if (!!data && !data?.is_creating) { - setEnvironmentCreated(true) - } - }, [data]) - if (!match?.params?.environmentId) { - return children - } - return isLoading ? ( -
- -
- ) : data?.is_creating ? ( -
-
- -

Preparing your environment

-

We are setting up your new environment...

-
-
- ) : ( - children - ) + + // Env-by-api_key endpoint isn't project-scoped — verify the match client-side. + const wrongProject = + !!data && !!projectId && data.project !== Number(projectId) + const environmentNotFound = hasEnvironmentId && (wrongProject || isError) + + if (!hasEnvironmentId) return children + if (environmentNotFound) return + if (!data) return + if (data.is_creating) return + return children } export default EnvironmentReadyChecker diff --git a/frontend/web/components/navigation/EnvironmentAside.tsx b/frontend/web/components/navigation/EnvironmentAside.tsx index 07fa75f28111..45ec3eda32a1 100644 --- a/frontend/web/components/navigation/EnvironmentAside.tsx +++ b/frontend/web/components/navigation/EnvironmentAside.tsx @@ -16,11 +16,12 @@ import AppActions from 'common/dispatcher/app-actions' import EnvironmentSelect from 'components/EnvironmentSelect' import { components } from 'react-select' import BuildVersion from 'components/BuildVersion' +import { useGetEnvironmentsQuery } from 'common/services/useEnvironment' import { useGetHealthEventsQuery } from 'common/services/useHealthEvents' import Constants from 'common/constants' import EnvironmentNavbar from './navbars/EnvironmentNavbar' import OverflowNav from './OverflowNav' -import { ProjectPermission } from 'common/types/permissions.types'; +import { ProjectPermission } from 'common/types/permissions.types' type HomeAsideType = { environmentId: string @@ -102,6 +103,8 @@ const CustomSingleValue = ({ hasWarning, ...rest }: CustomSingleValueProps) => { const EnvironmentAside: FC = ({ environmentId, projectId }) => { const history = useHistory() + const { data: environments, isSuccess: environmentsLoaded } = + useGetEnvironmentsQuery({ projectId }, { skip: !projectId }) const { data: healthEvents } = useGetHealthEventsQuery( { projectId: projectId }, { skip: !projectId }, @@ -126,9 +129,18 @@ const EnvironmentAside: FC = ({ environmentId, projectId }) => { ? null : (ProjectStore.getEnvironment(environmentId) as any) + const environmentNotFound = + environmentId !== 'create' && + environmentsLoaded && + !environments?.results?.some((env) => env.api_key === environmentId) + const onProjectSave = () => { AppActions.refreshOrganisation() } + + if (environmentNotFound) { + return null + } return ( <> diff --git a/frontend/web/components/navigation/navbars/EnvironmentNavbar.tsx b/frontend/web/components/navigation/navbars/EnvironmentNavbar.tsx index 3dccf9503c7d..15ee18c8d47d 100644 --- a/frontend/web/components/navigation/navbars/EnvironmentNavbar.tsx +++ b/frontend/web/components/navigation/navbars/EnvironmentNavbar.tsx @@ -21,30 +21,36 @@ const EnvironmentNavbar: FC = ({ }) => { const date = useRef(moment().toISOString()) - const { data: environments } = useGetEnvironmentsQuery( + const { data: environments, isSuccess: environmentsLoaded } = + useGetEnvironmentsQuery({ projectId }, { skip: !projectId }) + + const environment = environments?.results?.find( + (v) => v.api_key === environmentId, + ) + + const { data: scheduledData } = useGetChangeRequestsQuery( { - projectId: `${projectId}`, + committed: true, + environmentId, + live_from_after: date.current, + page_size: 1, }, - { skip: !projectId }, + { skip: !environment }, ) - const { data: scheduledData } = useGetChangeRequestsQuery({ - committed: true, - environmentId, - live_from_after: date.current, - page_size: 1, - }) - - const { data: changeRequestsData } = useGetChangeRequestsQuery({ - committed: false, - environmentId, - page_size: 1, - }) - - const environment = environments?.results?.find( - (v) => v.api_key === environmentId, + const { data: changeRequestsData } = useGetChangeRequestsQuery( + { + committed: false, + environmentId, + page_size: 1, + }, + { skip: !environment }, ) + if (environmentsLoaded && !environment) { + return null + } + const changeRequests = (Utils.changeRequestsEnabled( environment?.minimum_change_request_approvals,