Skip to content

Commit

Permalink
tech-story: [M3-8939] - Get rid of DrawerContent (#11338)
Browse files Browse the repository at this point in the history
* KubeConfigDrawer

* KubeControlPlaneACLDrawer

* HistoryDrawer

* feedback @bnussman-akamai

* feedback @bnussman-akamai

* Fix passing data

* Update e2e lke update suite for better label

* fix maybe flaky DB test
  • Loading branch information
abailly-akamai authored Dec 2, 2024
1 parent 5aeb650 commit 2581eb5
Show file tree
Hide file tree
Showing 15 changed files with 310 additions and 397 deletions.
14 changes: 7 additions & 7 deletions packages/manager/cypress/e2e/core/kubernetes/lke-update.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ describe('LKE ACL updates', () => {
.click();

ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// Confirm submit button is disabled if form has not been changed
Expand Down Expand Up @@ -1508,7 +1508,7 @@ describe('LKE ACL updates', () => {

// confirm data within drawer is updated and edit IPs again
ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// Confirm submit button is disabled if form has not been changed
Expand Down Expand Up @@ -1565,7 +1565,7 @@ describe('LKE ACL updates', () => {

// confirm data within drawer is updated again
ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// confirm updated IPv6 addresses display
Expand Down Expand Up @@ -1625,7 +1625,7 @@ describe('LKE ACL updates', () => {
.click();

ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// Confirm submit button is disabled if form has not been changed
Expand Down Expand Up @@ -1694,7 +1694,7 @@ describe('LKE ACL updates', () => {

// confirm data within drawer is updated
ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// confirm enable toggle was updated
Expand Down Expand Up @@ -1758,7 +1758,7 @@ describe('LKE ACL updates', () => {
);

ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// Confirm installation notice is displayed
Expand Down Expand Up @@ -1840,7 +1840,7 @@ describe('LKE ACL updates', () => {
.click();

ui.drawer
.findByTitle('Control Plane ACL')
.findByTitle(`Control Plane ACL for ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// Confirm ACL IP validation works as expected for IPv4
Expand Down
187 changes: 106 additions & 81 deletions packages/manager/src/components/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import { makeStyles } from 'tss-react/mui';

import { convertForAria } from 'src/utilities/stringUtils';

import { ErrorState } from './ErrorState/ErrorState';
import { NotFound } from './NotFound';

import type { APIError } from '@linode/api-v4';
import type { DrawerProps as _DrawerProps } from '@mui/material/Drawer';
import type { Theme } from '@mui/material/styles';

export interface DrawerProps extends _DrawerProps {
error?: APIError[] | null | string;
/**
* Whether the drawer is fetching the entity's data.
*
Expand Down Expand Up @@ -39,93 +44,113 @@ export interface DrawerProps extends _DrawerProps {
* - Clicking a button on the screen opens the drawer.
* - Drawers can be closed by pressing the `esc` key, clicking the “X” icon, or clicking the “Cancel” button.
*/
export const Drawer = (props: DrawerProps) => {
const { classes, cx } = useStyles();
const { children, isFetching, onClose, open, title, wide, ...rest } = props;
const titleID = convertForAria(title);
export const Drawer = React.forwardRef<HTMLDivElement, DrawerProps>(
(props: DrawerProps, ref) => {
const { classes, cx } = useStyles();
const {
children,
error,
isFetching,
onClose,
open,
title,
wide,
...rest
} = props;
const titleID = convertForAria(title);

// Store the last valid children and title in refs
// This is to prevent flashes of content during the drawer's closing transition,
// and its content becomes potentially undefined
const lastChildrenRef = React.useRef(children);
const lastTitleRef = React.useRef(title);
// Update refs when the drawer is open and content is matched
if (open && children) {
lastChildrenRef.current = children;
lastTitleRef.current = title;
}
// Store the last valid children and title in refs
// This is to prevent flashes of content during the drawer's closing transition,
// and its content becomes potentially undefined
const lastChildrenRef = React.useRef(children);
const lastTitleRef = React.useRef(title);
// Update refs when the drawer is open and content is matched
if (open && children) {
lastChildrenRef.current = children;
lastTitleRef.current = title;
}

return (
<_Drawer
classes={{
paper: cx(classes.common, {
[classes.default]: !wide,
[classes.wide]: wide,
}),
}}
onClose={(_, reason) => {
if (onClose && reason !== 'backdropClick') {
onClose({}, 'escapeKeyDown');
}
}}
anchor="right"
open={open}
{...rest}
aria-labelledby={titleID}
data-qa-drawer
data-testid="drawer"
role="dialog"
>
<Grid
sx={{
position: 'relative',
return (
<_Drawer
classes={{
paper: cx(classes.common, {
[classes.default]: !wide,
[classes.wide]: wide,
}),
}}
onClose={(_, reason) => {
if (onClose && reason !== 'backdropClick') {
onClose({}, 'escapeKeyDown');
}
}}
alignItems="flex-start"
className={classes.drawerHeader}
container
justifyContent="space-between"
wrap="nowrap"
anchor="right"
open={open}
ref={ref}
{...rest}
aria-labelledby={titleID}
data-qa-drawer
data-testid="drawer"
role="dialog"
>
<Grid>
{isFetching ? null : (
<Typography
className={classes.title}
data-qa-drawer-title={title}
data-testid="drawer-title"
id={titleID}
variant="h2"
<Grid
sx={{
position: 'relative',
}}
alignItems="flex-start"
className={classes.drawerHeader}
container
justifyContent="space-between"
wrap="nowrap"
>
<Grid>
{isFetching ? null : (
<Typography
className={classes.title}
data-qa-drawer-title={title}
data-testid="drawer-title"
id={titleID}
variant="h2"
>
{title}
</Typography>
)}
</Grid>
<Grid>
<IconButton
sx={{
position: 'absolute',
right: '-12px',
top: '-12px',
}}
aria-label="Close drawer"
color="primary"
data-qa-close-drawer
onClick={() => onClose?.({}, 'escapeKeyDown')}
size="large"
>
{title}
</Typography>
)}
<Close />
</IconButton>
</Grid>
</Grid>
<Grid>
<IconButton
sx={{
position: 'absolute',
right: '-12px',
top: '-12px',
}}
aria-label="Close drawer"
color="primary"
data-qa-close-drawer
onClick={() => onClose?.({}, 'escapeKeyDown')}
size="large"
>
<Close />
</IconButton>
</Grid>
</Grid>
{isFetching ? (
<Box display="flex" justifyContent="center" mt={8}>
<CircleProgress size="md" />
</Box>
) : (
children
)}
</_Drawer>
);
};
{error ? (
error === 'Not Found' ? (
<NotFound />
) : (
<ErrorState
errorText={Array.isArray(error) ? error[0].reason : error}
/>
)
) : isFetching ? (
<Box display="flex" justifyContent="center" mt={12}>
<CircleProgress size="md" />
</Box>
) : (
children
)}
</_Drawer>
);
}
);

const useStyles = makeStyles()((theme: Theme) => ({
button: {
Expand Down

This file was deleted.

27 changes: 0 additions & 27 deletions packages/manager/src/components/DrawerContent/DrawerContent.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions packages/manager/src/components/DrawerContent/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ describe('Database Backups', () => {

const { findByText, getAllByRole } = renderWithTheme(<DatabaseBackups />);

for (const backup of backups) {
const backupPromises = backups.map((backup) => {
const expectedDate = formatDate(backup.created, { timezone: 'utc' });
return findByText(expectedDate);
});

// eslint-disable-next-line no-await-in-loop
const backupItem = await findByText(expectedDate);

const backupElements = await Promise.all(backupPromises);
backupElements.forEach((backupItem) => {
expect(backupItem).toBeVisible();
}
});

// Verify there is a table row for each backup (and a row for the table header)
expect(getAllByRole('row')).toHaveLength(backups.length + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ResetIcon from 'src/assets/icons/reset.svg';
import { MaskableText } from 'src/components/MaskableText/MaskableText';
import {
useAllKubernetesClusterAPIEndpointsQuery,
useKubenetesKubeConfigQuery,
useKubernetesKubeConfigQuery,
} from 'src/queries/kubernetes';
import { downloadFile } from 'src/utilities/downloadFile';
import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';
Expand Down Expand Up @@ -103,7 +103,7 @@ export const KubeConfigDisplay = (props: Props) => {
const { enqueueSnackbar } = useSnackbar();
const { classes, cx } = useStyles();

const { isFetching, refetch: getKubeConfig } = useKubenetesKubeConfigQuery(
const { isFetching, refetch: getKubeConfig } = useKubernetesKubeConfigQuery(
clusterId,
false
);
Expand Down
Loading

0 comments on commit 2581eb5

Please sign in to comment.