-
Notifications
You must be signed in to change notification settings - Fork 367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tech-story: [M3-8939] - Get rid of DrawerContent
#11338
Changes from 3 commits
f064d2a
05efcc0
368c7ec
06b5690
550bfd2
e9eb6a2
dbef87e
a9ebc5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
* | ||
|
@@ -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 ? ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addition of error handling is the change here |
||
<Box display="flex" justifyContent="center" mt={12}> | ||
<CircleProgress size="md" /> | ||
</Box> | ||
) : ( | ||
children | ||
)} | ||
</_Drawer> | ||
); | ||
} | ||
); | ||
|
||
const useStyles = makeStyles()((theme: Theme) => ({ | ||
button: { | ||
|
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,7 @@ import * as React from 'react'; | |
import Download from 'src/assets/icons/download.svg'; | ||
import { CodeBlock } from 'src/components/CodeBlock/CodeBlock'; | ||
import { Drawer } from 'src/components/Drawer'; | ||
import { DrawerContent } from 'src/components/DrawerContent'; | ||
import { useKubenetesKubeConfigQuery } from 'src/queries/kubernetes'; | ||
import { useKubernetesKubeConfigQuery } from 'src/queries/kubernetes'; | ||
import { downloadFile } from 'src/utilities/downloadFile'; | ||
|
||
interface Props { | ||
|
@@ -19,50 +18,39 @@ interface Props { | |
export const KubeConfigDrawer = (props: Props) => { | ||
const { closeDrawer, clusterId, clusterLabel, open } = props; | ||
|
||
const { | ||
data, | ||
error, | ||
isFetching, | ||
isLoading, | ||
refetch, | ||
} = useKubenetesKubeConfigQuery(clusterId, open); | ||
|
||
// refetchOnMount isnt good enough for this query because | ||
// it is already mounted in the rendered Drawer | ||
React.useEffect(() => { | ||
if (open && !isLoading && !isFetching) { | ||
refetch(); | ||
} | ||
}, [open]); | ||
Comment on lines
-30
to
-36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this removal intentional? Wondering if we should adopt this pattern here so we can actually use React Query's If I'm remembering correctly, we wanted the refetching of the bube config to intentionally be aggressive so that there would be less of a chance of the user seeing an old kube config in the case they re-generate it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seemed like a bad pattern to me - i'll look around and test this some more.
is there a reason why this does not get invalidated properly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is cleaner? 06b5690 Also makes sure this issue wouldn't be happening in other places it is used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do invalidate the kube config but, if I remember correctly, the kube config takes some time (a few minutes) on the backend to actually be regenerated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That works too! |
||
const { data, failureReason, isFetching } = useKubernetesKubeConfigQuery( | ||
clusterId, | ||
open | ||
); | ||
|
||
return ( | ||
<Drawer onClose={closeDrawer} open={open} title="View Kubeconfig" wide> | ||
<DrawerContent | ||
error={!!error} | ||
errorMessage={error?.[0].reason} | ||
loading={isLoading} | ||
title={clusterLabel} | ||
> | ||
<Box display="flex"> | ||
<Typography mr={2} variant="h3"> | ||
{clusterLabel} | ||
</Typography> | ||
<StyledDownloadButton | ||
onClick={() => | ||
downloadFile(`${clusterLabel}-kubeconfig.yaml`, data ?? '') | ||
} | ||
title="Download" | ||
> | ||
<Download /> | ||
</StyledDownloadButton> | ||
</Box> | ||
<CodeBlock | ||
command={data ?? ''} | ||
commandType="Kube Config Yaml" | ||
handleCopyIconClick={() => null} | ||
language="yaml" | ||
/> | ||
</DrawerContent> | ||
<Drawer | ||
error={failureReason} | ||
isFetching={isFetching} | ||
onClose={closeDrawer} | ||
open={open} | ||
title="View Kubeconfig" | ||
wide | ||
> | ||
<Box display="flex"> | ||
<Typography mr={2} variant="h3"> | ||
{clusterLabel} | ||
</Typography> | ||
<StyledDownloadButton | ||
onClick={() => | ||
downloadFile(`${clusterLabel}-kubeconfig.yaml`, data ?? '') | ||
} | ||
title="Download" | ||
> | ||
<Download /> | ||
</StyledDownloadButton> | ||
</Box> | ||
<CodeBlock | ||
command={data ?? ''} | ||
commandType="Kube Config Yaml" | ||
handleCopyIconClick={() => null} | ||
language="yaml" | ||
/> | ||
</Drawer> | ||
); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this change indentation but is a minor change
this should remove A LOT of warnings through the APP with mounted drawers