diff --git a/dashboard/src/components/ClusterDeletingPlaceholder.tsx b/dashboard/src/components/ClusterDeletingPlaceholder.tsx new file mode 100644 index 0000000000..14ed5d2959 --- /dev/null +++ b/dashboard/src/components/ClusterDeletingPlaceholder.tsx @@ -0,0 +1,42 @@ +import React, { useEffect, useState, useContext } from "react"; +import styled from "styled-components"; +import { RouteComponentProps, withRouter } from "react-router"; +import { pushFiltered } from "shared/routing"; + +import loading from "assets/loading.gif"; + +import { Context } from "shared/Context"; +import Heading from "components/form-components/Heading"; +import Helper from "components/form-components/Helper"; +import Text from "./porter/Text"; +import Spacer from "./porter/Spacer"; +import DashboardPlaceholder from "./porter/DashboardPlaceholder"; +import PorterLink from "components/porter/Link"; +import Button from "./porter/Button"; + +type Props = {}; + +const ClusterDeletingPlaceholder: React.FC = (props) => { + const { currentCluster } = useContext(Context); + + return ( + + + Your resources are being cleaned up + + + + You can proceed as soon as your resources are deleted. It may take a few minutes. + + + + + ); +}; + +export default withRouter(ClusterDeletingPlaceholder); + +const Img = styled.img` + height: 15px; + margin-right: 15px; +`; diff --git a/dashboard/src/main/home/add-on-dashboard/AddOnDashboard.tsx b/dashboard/src/main/home/add-on-dashboard/AddOnDashboard.tsx index 8bfc72cfd1..db37cb1391 100644 --- a/dashboard/src/main/home/add-on-dashboard/AddOnDashboard.tsx +++ b/dashboard/src/main/home/add-on-dashboard/AddOnDashboard.tsx @@ -34,6 +34,7 @@ import { Link } from "react-router-dom"; import Fieldset from "components/porter/Fieldset"; import Select from "components/porter/Select"; import ClusterProvisioningPlaceholder from "components/ClusterProvisioningPlaceholder"; +import ClusterDeletingPlaceholder from "components/ClusterDeletingPlaceholder"; import DashboardPlaceholder from "components/porter/DashboardPlaceholder"; import { useAuthState } from "main/auth/context"; @@ -155,124 +156,132 @@ const AddOnDashboard: React.FC = ({ description="Add-ons and supporting workloads for this project." disableLineBreak /> - {currentCluster?.status === "UPDATING_UNAVAILABLE" ? ( - - ) : ( - - (addOns.length === 0 || (filteredAddOns.length === 0 && searchValue === "")) ? ( - - isLoading ? - () : ( - - - No add-ons have been deployed yet - - - - Deploy from our suite of curated add-ons. - - - - - - - ) - ) : ( - <> - - - - , value: "grid" }, - { label: , value: "list" }, - ]} - active={view} - setActive={setView} - /> - - - - - - - - {filteredAddOns.length === 0 ? ( -
- - - {searchValue === "" ? "No add-ons have been deployed yet." : "No matching add-ons were found."} - -
- ) : (isLoading ? : view === "grid" ? ( - - {(filteredAddOns ?? []).map((app: any, i: number) => { - return ( - - - - {app.name} - - - - - - - {readableDate(app.info.last_deployed)} - - - - ); - })} - + { + currentCluster?.status === "DELETING" ? + : + + currentCluster?.status === "UPDATING_UNAVAILABLE" ? ( + + ) : ( + + (addOns.length === 0 || (filteredAddOns.length === 0 && searchValue === "")) ? ( + + isLoading ? + () : ( + + + No add-ons have been deployed yet + + + + Deploy from our suite of curated add-ons. + + + + + + + ) ) : ( - - {(filteredAddOns ?? []).map((app: any, i: number) => { - return ( - - - - {app.name} - - - - - - - - {readableDate(app.info.last_deployed)} - - - - ); - })} - - ) - )} - - ))} + <> + + + + , value: "grid" }, + { label: , value: "list" }, + ]} + active={view} + setActive={setView} + /> + + + + + + + + {filteredAddOns.length === 0 ? ( +
+ + + {searchValue === "" ? "No add-ons have been deployed yet." : "No matching add-ons were found."} + +
+ ) : (isLoading ? : view === "grid" ? ( + + {(filteredAddOns ?? []).map((app: any, i: number) => { + return ( + + + + {app.name} + + + + + + + {readableDate(app.info.last_deployed)} + + + + ); + })} + + ) : ( + + {(filteredAddOns ?? []).map((app: any, i: number) => { + return ( + + + + {app.name} + + + + + + + + {readableDate(app.info.last_deployed)} + + + + ); + })} + + ) + )} + + )) + } + + ); + }; export default AddOnDashboard; diff --git a/dashboard/src/main/home/app-dashboard/AppDashboard.tsx b/dashboard/src/main/home/app-dashboard/AppDashboard.tsx index 234a0f0536..9f97130744 100644 --- a/dashboard/src/main/home/app-dashboard/AppDashboard.tsx +++ b/dashboard/src/main/home/app-dashboard/AppDashboard.tsx @@ -32,6 +32,7 @@ import Fieldset from "components/porter/Fieldset"; import ClusterProvisioningPlaceholder from "components/ClusterProvisioningPlaceholder"; import Icon from "components/porter/Icon"; import DashboardPlaceholder from "components/porter/DashboardPlaceholder"; +import ClusterDeletingPlaceholder from "components/ClusterDeletingPlaceholder"; type Props = {}; @@ -213,6 +214,12 @@ const AppDashboard: React.FC = ({ }) => { description="Web services, workers, and jobs for this project." disableLineBreak /> + { + currentCluster?.status === "DELETING" + && ( + + ) + } {currentCluster?.status === "UPDATING_UNAVAILABLE" ? ( ) : ( diff --git a/dashboard/src/main/home/app-dashboard/apps/Apps.tsx b/dashboard/src/main/home/app-dashboard/apps/Apps.tsx index 66e55b1acd..3828e8c1f3 100644 --- a/dashboard/src/main/home/app-dashboard/apps/Apps.tsx +++ b/dashboard/src/main/home/app-dashboard/apps/Apps.tsx @@ -32,6 +32,7 @@ import web from "assets/web.png"; import AppGrid from "./AppGrid"; import { appRevisionWithSourceValidator } from "./types"; +import ClusterDeletingPlaceholder from "components/ClusterDeletingPlaceholder"; export type ClientAddonWithEnv = { addon: ClientAddon; @@ -78,7 +79,7 @@ const Apps: React.FC = () => { { deployment_target_id: currentProject.managed_deployment_targets_enabled && - !currentDeploymentTarget.is_preview + !currentDeploymentTarget.is_preview ? undefined : currentDeploymentTarget.id, ignore_preview_apps: !currentDeploymentTarget.is_preview, @@ -193,6 +194,9 @@ const Apps: React.FC = () => { if (currentCluster?.status === "UPDATING_UNAVAILABLE") { return ; } + if (currentCluster?.status === "DELETING") { + return ; + } if ( status === "loading" || diff --git a/dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx b/dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx index 78f6cf41cc..fcd7976d5f 100644 --- a/dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx +++ b/dashboard/src/main/home/cluster-dashboard/apps/AppDashboard.tsx @@ -20,6 +20,7 @@ import ChartList from "../chart/ChartList"; import ClusterProvisioningPlaceholder from "components/ClusterProvisioningPlaceholder"; import SortSelector from "../SortSelector"; import Spacer from "components/porter/Spacer"; +import ClusterDeletingPlaceholder from "components/ClusterDeletingPlaceholder"; type Props = RouteComponentProps & WithAuthProps & { currentView: PorterUrl; @@ -55,6 +56,12 @@ const AppDashboard: React.FC = ({ description="Continuously running web services, workers, and add-ons." disableLineBreak /> + { + currentCluster?.status === "DELETING" + && ( + + ) + } {currentCluster.status === "UPDATING_UNAVAILABLE" ? ( ) : ( diff --git a/dashboard/src/main/home/cluster-dashboard/env-groups/EnvGroupDashboard.tsx b/dashboard/src/main/home/cluster-dashboard/env-groups/EnvGroupDashboard.tsx index c1474b09ef..49c2cead6a 100644 --- a/dashboard/src/main/home/cluster-dashboard/env-groups/EnvGroupDashboard.tsx +++ b/dashboard/src/main/home/cluster-dashboard/env-groups/EnvGroupDashboard.tsx @@ -17,6 +17,7 @@ import { getQueryParam, pushQueryParams, pushFiltered } from "shared/routing"; import { withAuth, WithAuthProps } from "shared/auth/AuthorizationHoc"; import ClusterProvisioningPlaceholder from "components/ClusterProvisioningPlaceholder"; import Spacer from "components/porter/Spacer"; +import ClusterDeletingPlaceHolder from "components/ClusterDeletingPlaceholder"; type PropsType = RouteComponentProps & WithAuthProps & { @@ -79,6 +80,9 @@ const EnvGroupDashboard = (props: PropsType) => { }; const renderBody = () => { + if (props.currentCluster.status === "DELETING") { + return + } if (props.currentCluster.status === "UPDATING_UNAVAILABLE") { return } diff --git a/dashboard/src/main/home/cluster-dashboard/jobs/JobDashboard.tsx b/dashboard/src/main/home/cluster-dashboard/jobs/JobDashboard.tsx index cb4c5d94e5..e1f457affe 100644 --- a/dashboard/src/main/home/cluster-dashboard/jobs/JobDashboard.tsx +++ b/dashboard/src/main/home/cluster-dashboard/jobs/JobDashboard.tsx @@ -20,6 +20,7 @@ import LastRunStatusSelector from "../LastRunStatusSelector"; import JobRunTable from "../chart/JobRunTable"; import ChartList from "../chart/ChartList"; import ClusterProvisioningPlaceholder from "components/ClusterProvisioningPlaceholder"; +import ClusterDeletingPlaceholder from "components/ClusterDeletingPlaceholder"; type Props = RouteComponentProps & WithAuthProps & { currentView: PorterUrl; @@ -49,6 +50,12 @@ const JobDashboard: React.FC = ({ description="Scripts and tasks that run once or on a repeating interval." disableLineBreak /> + { + currentCluster?.status === "DELETING" + && ( + + ) + } {currentCluster.status === "UPDATING_UNAVAILABLE" ? ( ) : ( diff --git a/dashboard/src/main/home/database-dashboard/DatabaseDashboard.tsx b/dashboard/src/main/home/database-dashboard/DatabaseDashboard.tsx index 048b2baad3..86557e27f0 100644 --- a/dashboard/src/main/home/database-dashboard/DatabaseDashboard.tsx +++ b/dashboard/src/main/home/database-dashboard/DatabaseDashboard.tsx @@ -35,6 +35,7 @@ import { type CloudProviderWithSource, } from "./types"; import { datastoreField } from "./utils"; +import ClusterDeletingPlaceHolder from "components/ClusterDeletingPlaceholder"; type Props = { projectId: number; @@ -165,6 +166,9 @@ const DatabaseDashboard: React.FC = ({ projectId }) => { }; const renderContents = (): JSX.Element => { + if (currentCluster?.status === "DELETING") { + return ; + } if (currentCluster?.status === "UPDATING_UNAVAILABLE") { return ; } @@ -334,7 +338,7 @@ const MidIcon = styled.img<{ height?: string }>` margin-right: 11px; `; -const Row = styled(Link)<{ isAtBottom?: boolean }>` +const Row = styled(Link) <{ isAtBottom?: boolean }>` cursor: pointer; display: block; padding: 15px;