From ff71fbec16bffcb5ffa24f4782fc9765f9154ba4 Mon Sep 17 00:00:00 2001 From: Derrick Hawkins Date: Tue, 24 Oct 2023 10:22:06 -0700 Subject: [PATCH 1/6] simplify/improve table menu click away action --- .../clusterTable/clusterTable.stories.tsx | 27 ------- components/clusterTable/clusterTable.tsx | 78 +++++++++---------- .../deleteCluster/deleteCluster.stories.tsx | 2 +- components/deleteCluster/index.tsx | 19 ++--- .../clusterManagement.styled.ts | 17 ++++ containers/clusterManagement/index.tsx | 62 ++++----------- 6 files changed, 73 insertions(+), 132 deletions(-) diff --git a/components/clusterTable/clusterTable.stories.tsx b/components/clusterTable/clusterTable.stories.tsx index f53c1fd0..9486166d 100644 --- a/components/clusterTable/clusterTable.stories.tsx +++ b/components/clusterTable/clusterTable.stories.tsx @@ -1,11 +1,8 @@ -import React, { FunctionComponent } from 'react'; import { Meta, StoryObj } from '@storybook/react'; import { noop } from '../../utils/noop'; import { mapClusterFromRaw } from '../../utils/mapClustersFromRaw'; import { mockClusterResponse } from '../../tests/mocks/mockClusterResponse'; -import { useAppDispatch, useAppSelector } from '../../redux/store'; -import { setPresentedClusterId } from '../../redux/slices/api.slice'; import { ClusterTable } from './clusterTable'; @@ -17,33 +14,9 @@ const meta: Meta = { export default meta; -const ClusterTableWithHooks: FunctionComponent = () => { - const { presentedClusterId, managementCluster, clusterMap } = useAppSelector(({ api }) => api); - - const dispatch = useAppDispatch(); - - return managementCluster ? ( - - dispatch(setPresentedClusterId(presentedClusterId)) - } - onDeleteCluster={noop} - /> - ) : ( -
No management cluster
- ); -}; - export const Default: StoryObj = { args: { onDeleteCluster: noop, managementCluster, }, }; - -export const WithSelectableRows: StoryObj = { - render: () => , -}; diff --git a/components/clusterTable/clusterTable.tsx b/components/clusterTable/clusterTable.tsx index fff62144..f7285c6c 100644 --- a/components/clusterTable/clusterTable.tsx +++ b/components/clusterTable/clusterTable.tsx @@ -1,4 +1,5 @@ import React, { useState, FunctionComponent, useMemo, ComponentPropsWithRef } from 'react'; +import { ClickAwayListener } from '@mui/material'; import TableHead from '@mui/material/TableHead'; import IconButton from '@mui/material/IconButton'; import List from '@mui/material/List'; @@ -46,6 +47,8 @@ import { StyledTable, } from './clusterTable.styled'; +import useToggle from '@/hooks/useToggle'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const CLOUD_LOGO_OPTIONS: Record = { [InstallationType.LOCAL]: k3dLogo, @@ -67,9 +70,7 @@ type ClusterRowProps = { expanded?: boolean; showExpandButton?: boolean; onExpanseClick?: () => void; - onDeleteCluster: () => void; - presentedClusterId?: string; - onMenuButtonClick?: (clusterId: Cluster['clusterId']) => void; + onDeleteCluster: (clusterId: string) => void; }; const ClusterRow: FunctionComponent = ({ @@ -78,9 +79,9 @@ const ClusterRow: FunctionComponent = ({ showExpandButton, onExpanseClick = noop, onDeleteCluster, - onMenuButtonClick = noop, - presentedClusterId, }) => { + const { isOpen, close, toggle } = useToggle(); + const { clusterId, clusterName, @@ -98,12 +99,10 @@ const ClusterRow: FunctionComponent = ({ const { iconLabel, iconType, bgColor } = CLUSTER_TAG_CONFIG[status ?? ClusterStatus.PROVISIONED]; const { nameLabel, typeLabel } = FORMATTED_CLUSTER_TYPE[type ?? ClusterType.MANAGEMENT]; - const selected = clusterId === presentedClusterId; - return ( <> - - + + {type === ClusterType.MANAGEMENT && showExpandButton && ( = ({ )} - + {clusterName} @@ -123,56 +122,58 @@ const ClusterRow: FunctionComponent = ({ {nameLabel} - + {typeLabel} - + {environment && } - + {cloudProvider - + {cloudRegion} - + {nodeCount} - + {creationDate && ( {moment(+creationDate).format('DD MMM YYYY')} )} - + {gitUser} - + - + onMenuButtonClick(clusterId)} + onClick={toggle} disabled={status === ClusterStatus.DELETED} > - {selected && ( - - - - - - Delete cluster - - - - - + {isOpen && ( + + + + + onDeleteCluster(clusterId)}> + + Delete cluster + + + + + + )} @@ -256,9 +257,7 @@ const ClusterTableHead: FunctionComponent = ({ orderBy, o interface ClusterTableProps extends Omit, 'key'> { managementCluster: ManagementCluster; clusters: ClusterCache; - onDeleteCluster: () => void; - onMenuButtonClick?: (clusterId: Cluster['clusterId']) => void; - presentedClusterId?: string; + onDeleteCluster: (clusterId: string) => void; customRef?: React.Ref; } @@ -266,9 +265,6 @@ export const ClusterTable: FunctionComponent = ({ managementCluster, clusters, onDeleteCluster, - onMenuButtonClick, - presentedClusterId, - customRef, ...rest }) => { const [expanded, setExpanded] = useState(true); @@ -298,15 +294,13 @@ export const ClusterTable: FunctionComponent = ({ - + setExpanded(!expanded)} - presentedClusterId={presentedClusterId} /> {expanded && @@ -315,8 +309,6 @@ export const ClusterTable: FunctionComponent = ({ key={cluster.clusterName} cluster={cluster} onDeleteCluster={onDeleteCluster} - onMenuButtonClick={onMenuButtonClick} - presentedClusterId={presentedClusterId} /> ))} diff --git a/components/deleteCluster/deleteCluster.stories.tsx b/components/deleteCluster/deleteCluster.stories.tsx index 35b76b16..4ab383e0 100644 --- a/components/deleteCluster/deleteCluster.stories.tsx +++ b/components/deleteCluster/deleteCluster.stories.tsx @@ -60,7 +60,7 @@ const DeleteClusterWithHooks: FunctionComponent = (props) => const [open, setOpen] = useState(true); return ( <> - setOpen(false)} onDelete={noop} /> + setOpen(false)} onDelete={noop} /> diff --git a/components/deleteCluster/index.tsx b/components/deleteCluster/index.tsx index df119708..df30833e 100644 --- a/components/deleteCluster/index.tsx +++ b/components/deleteCluster/index.tsx @@ -5,7 +5,7 @@ import LaunchOutlinedIcon from '@mui/icons-material/LaunchOutlined'; import Typography from '../typography'; import TextFieldWithRef from '../textField'; -import Modal from '../modal'; +import Modal, { IModalProps } from '../modal'; import { LAUGHING_ORANGE } from '../../constants/colors'; import Button from '../button'; import { Cluster, ClusterType, DraftCluster } from '../../types/provision'; @@ -13,25 +13,18 @@ import CopyText from '../copyText'; import { Content, CopyTextContainer, Footer, Header, NextLink } from './deleteCluster.styled'; -export interface DeleteClusterProps { +export interface DeleteClusterProps extends Omit { cluster: Cluster | DraftCluster; - isOpen: boolean; - onClose: () => void; onDelete: () => void; } -const DeleteCluster: FunctionComponent = ({ - cluster, - isOpen, - onClose, - onDelete, -}) => { +const DeleteCluster: FunctionComponent = ({ cluster, onDelete, ...rest }) => { const [matchingClusterName, setMatchingClusterName] = useState(''); const isManagementCluster = cluster.type === ClusterType.MANAGEMENT; return ( - +
@@ -70,12 +63,12 @@ const DeleteCluster: FunctionComponent = ({ )}