From 1e40675405d0bf61fff68b56823c1b7a951b9ab9 Mon Sep 17 00:00:00 2001 From: Vincent T Date: Wed, 13 Nov 2024 17:30:11 -0500 Subject: [PATCH] app: home: Add delete button for clusters Signed-off-by: Vincent T --- frontend/src/components/App/Home/index.tsx | 66 +++++++++++++++------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/App/Home/index.tsx b/frontend/src/components/App/Home/index.tsx index 94c5e95159..f6dd70c697 100644 --- a/frontend/src/components/App/Home/index.tsx +++ b/frontend/src/components/App/Home/index.tsx @@ -25,6 +25,24 @@ import { ConfirmDialog } from '../../common'; import ResourceTable from '../../common/Resource/ResourceTable'; import RecentClusters from './RecentClusters'; +/** + * Gets the origin of a cluster. + * + * @param cluster + * @returns A description of where the cluster is picked up from: dynamic, in-cluster, or from a kubeconfig file. + */ +function getOrigin(cluster: Cluster): string { + if (cluster.meta_data?.source === 'kubeconfig') { + const kubeconfigPath = process.env.KUBECONFIG ?? '~/.kube/config'; + return `Kubeconfig: ${kubeconfigPath}`; + } else if (cluster.meta_data?.source === 'dynamic_cluster') { + return t('translation|Plugin'); + } else if (cluster.meta_data?.source === 'in_cluster') { + return t('translation|In-cluster'); + } + return 'Unknown'; +} + function ContextMenu({ cluster }: { cluster: Cluster }) { const { t } = useTranslation(['translation']); const history = useHistory(); @@ -32,6 +50,7 @@ function ContextMenu({ cluster }: { cluster: Cluster }) { const [anchorEl, setAnchorEl] = React.useState(null); const menuId = useId('context-menu'); const [openConfirmDialog, setOpenConfirmDialog] = React.useState(false); + const [openDeleteDynamicDialog, setOpenDeleteDynamicDialog] = React.useState(false); function removeCluster(cluster: Cluster) { deleteCluster(cluster.name || '') @@ -92,7 +111,8 @@ function ContextMenu({ cluster }: { cluster: Cluster }) { > {t('translation|Settings')} - {helpers.isElectron() && cluster.meta_data?.source === 'dynamic_cluster' && ( + + {helpers.isElectron() && ( { setOpenConfirmDialog(true); @@ -108,14 +128,36 @@ function ContextMenu({ cluster }: { cluster: Cluster }) { open={openConfirmDialog} handleClose={() => setOpenConfirmDialog(false)} onConfirm={() => { - setOpenConfirmDialog(false); + if (cluster.meta_data?.source !== 'dynamic_cluster') { + setOpenDeleteDynamicDialog(true); + } else { + setOpenConfirmDialog(false); + removeCluster(cluster); + } + }} + title={t('translation|Delete Cluster')} + description={t( + 'translation|Are you sure you want to remove the cluster "{{ clusterName }}"? from {{ source }}', + { + clusterName: cluster.name, + source: getOrigin(cluster), + } + )} + /> + + setOpenDeleteDynamicDialog(false)} + onConfirm={() => { + setOpenDeleteDynamicDialog(false); removeCluster(cluster); }} title={t('translation|Delete Cluster')} description={t( - 'translation|Are you sure you want to remove the cluster "{{ clusterName }}"?', + 'translation|The cluster "{{ clusterName }}" is not a dynamic cluster from Headlamp, this cluster will be deleted from {{ source }}.', { clusterName: cluster.name, + source: getOrigin(cluster), } )} /> @@ -239,24 +281,6 @@ function HomeComponent(props: HomeComponentProps) { .sort(); } - /** - * Gets the origin of a cluster. - * - * @param cluster - * @returns A description of where the cluster is picked up from: dynamic, in-cluster, or from a kubeconfig file. - */ - function getOrigin(cluster: Cluster): string { - if (cluster.meta_data?.source === 'kubeconfig') { - const kubeconfigPath = process.env.KUBECONFIG ?? '~/.kube/config'; - return `Kubeconfig: ${kubeconfigPath}`; - } else if (cluster.meta_data?.source === 'dynamic_cluster') { - return t('translation|Plugin'); - } else if (cluster.meta_data?.source === 'in_cluster') { - return t('translation|In-cluster'); - } - return 'Unknown'; - } - const memoizedComponent = React.useMemo( () => (