Skip to content
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

refactor: [M3-6063] - Refactor components to use TypeToConfirmDialog component #9175

Merged
merged 30 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1102003
WIP
carrillo-erik May 25, 2023
8d57616
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik May 31, 2023
dc5a789
refactor: [M3-6063] - Fix errors
carrillo-erik May 31, 2023
c62b219
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 2, 2023
d7ef9d0
refactor: [M3-6063] - Test changes
carrillo-erik Jun 2, 2023
b4944d4
refactor: [M3-6063] - Code cleanup
carrillo-erik Jun 2, 2023
57ebe82
Added changeset: Refactor components to use TypeToConfirmDialog
carrillo-erik Jun 2, 2023
cbb00f2
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 6, 2023
7eb8cf0
refactor: [M3-6063] - Code cleanup after feedback
carrillo-erik Jun 6, 2023
9aff1f4
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 7, 2023
f908f67
refactor: [M3-6063] - Fix failing test
carrillo-erik Jun 7, 2023
3903a66
refactor: [M3-6063] - Revert the last code change
carrillo-erik Jun 7, 2023
2a0165c
refactor: [M3-6063] - Fix create volume test spec
carrillo-erik Jun 7, 2023
8bf04f6
refactor: [M3-6063] - Revert create volume spec
carrillo-erik Jun 7, 2023
467d5d5
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 8, 2023
221eb04
refactor: [M3-6063] - PR feedback changes
carrillo-erik Jun 8, 2023
50c9558
refactor: [M3-6063] - Change if code to switch
carrillo-erik Jun 8, 2023
cb11cc4
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 14, 2023
f40d3c5
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 15, 2023
fcb0b54
refactor: [M3-6063] - Refactor conditional logic
carrillo-erik Jun 15, 2023
cd2e7e0
refactor: [M3-6063] - Fix handleRestoreDatabase()
carrillo-erik Jun 15, 2023
bf31b1f
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 20, 2023
5dd2d58
refactor: [M3-6063] - Revert primary btn text strs
carrillo-erik Jun 20, 2023
9662068
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 28, 2023
7085778
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 28, 2023
4a49592
refactor: [M3-6063] - Fix CloseAccount button
carrillo-erik Jun 28, 2023
de1a833
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jun 29, 2023
a2b2b6a
Revert "refactor: [M3-6063] - Fix CloseAccount button"
carrillo-erik Jun 29, 2023
85f0cf5
Add changes after revert of yarn.lock, cachedData
carrillo-erik Jun 29, 2023
c2ce6a6
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Jul 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Refactor components to use TypeToConfirmDialog ([#9175](https://github.com/linode/manager/pull/9175))
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const useStyles = makeStyles()((theme: Theme) => ({
marginBottom: 0,
},
},
dialogContent: {
display: 'flex',
flexDirection: 'column',
},
}));

export interface ConfirmationDialogProps extends DialogProps {
Expand Down Expand Up @@ -53,7 +57,7 @@ export const ConfirmationDialog = (props: ConfirmationDialogProps) => {
data-testid="drawer"
>
<DialogTitle title={title} onClose={onClose} />
<DialogContent data-qa-dialog-content className="dialog-content">
<DialogContent data-qa-dialog-content className={classes.dialogContent}>
{children}
{error && (
<DialogContentText className={`${classes.error} error-for-scroll`}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { TypeToConfirmDialog } from './TypeToConfirmDialog';

const meta: Meta<typeof TypeToConfirmDialog> = {
title: 'Components/TypeToConfirmDialog',
component: TypeToConfirmDialog,
argTypes: {
children: {
description: 'The items of the Dialog, passed-in as sub-components.',
},
error: { description: 'Error that will be shown in the dialog.' },
onClose: {
action: 'onClose',
description: 'Callback fired when the component requests to be closed.',
},
onClick: {
description: 'Callback fired when the action is confirmed.',
},
open: { description: 'Is the modal open?' },
title: { description: 'Title that appears in the heading of the dialog.' },
},
args: {
open: true,
title: 'Delete Linode?',
onClose: action('onClose'),
onClick: action('onDelete'),
loading: false,
label: 'Linode Label',
children: '',
error: undefined,
entity: {
type: 'Linode',
action: 'deletion',
name: 'test linode',
primaryBtnText: 'Delete',
},
},
};

export default meta;

type Story = StoryObj<typeof TypeToConfirmDialog>;

export const Default: Story = {
render: (args) => (
<TypeToConfirmDialog {...args}>{args.children}</TypeToConfirmDialog>
),
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ describe('TypeToConfirmDialog Component', () => {
const { getByText } = renderWithTheme(
<TypeToConfirmDialog
title="Delete Linode test?"
label={'Linode Label'}
open={true}
entity={{ type: 'Linode', label: 'test' }}
entity={{
type: 'Linode',
name: 'test',
action: 'deletion',
primaryBtnText: 'Delete',
}}
loading={false}
{...props}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,26 @@ import {
import { usePreferences } from 'src/queries/preferences';

interface EntityInfo {
type: 'Linode' | 'Volume' | 'NodeBalancer' | 'Bucket';
label: string | undefined;
type:
| 'Linode'
| 'Volume'
| 'NodeBalancer'
| 'Bucket'
| 'Database'
| 'Kubernetes'
| 'AccountSetting';
subType?: 'Cluster' | 'ObjectStorage' | 'CloseAccount';
action?: 'deletion' | 'detachment' | 'restoration' | 'cancellation';
name?: string | undefined;
primaryBtnText: string;
}

interface TypeToConfirmDialogProps {
entity: EntityInfo;
children: React.ReactNode;
loading: boolean;
confirmationText?: string | JSX.Element;
errors?: APIError[] | undefined | null;
label: string;
onClick: () => void;
}

Expand All @@ -38,27 +48,38 @@ export const TypeToConfirmDialog = (props: CombinedProps) => {
onClick,
loading,
entity,
label,
children,
confirmationText,
errors,
typographyStyle,
textFieldStyle,
} = props;

const [confirmText, setConfirmText] = React.useState('');

const { data: preferences } = usePreferences();
const disabled =
preferences?.type_to_confirm !== false && confirmText !== entity.label;
preferences?.type_to_confirm !== false && confirmText !== entity.name;

React.useEffect(() => {
if (open) {
setConfirmText('');
}
}, [open]);

const typeInstructions =
entity.action === 'cancellation'
? `type your Username `
: `type the name of the ${entity.type} ${entity.subType || ''} `;

const actions = (
<ActionsPanel style={{ padding: 0 }}>
<Button buttonType="secondary" onClick={onClose} data-qa-cancel>
<Button
buttonType="secondary"
onClick={onClose}
data-qa-cancel
data-testid={'dialog-cancel'}
>
Cancel
</Button>
<Button
Expand All @@ -67,10 +88,9 @@ export const TypeToConfirmDialog = (props: CombinedProps) => {
loading={loading}
disabled={disabled}
data-qa-confirm
data-testid={'dialog-confirm'}
>
{entity.type === 'Volume' && title.startsWith('Detach')
? 'Detach'
: 'Delete'}
{entity.primaryBtnText}
</Button>
</ActionsPanel>
);
Expand All @@ -85,25 +105,28 @@ export const TypeToConfirmDialog = (props: CombinedProps) => {
>
{children}
<TypeToConfirm
label={`${entity.type} ${entity.type !== 'Bucket' ? 'Label' : 'Name'}`}
hideInstructions={entity.subType === 'CloseAccount'}
label={label}
confirmationText={
confirmationText ? (
confirmationText
entity.subType === 'CloseAccount' ? (
''
) : (
<span>
To confirm deletion, type the name of the {entity.type} (
<b>{entity.label}</b>) in the field below:
To confirm {entity.action}, {typeInstructions}(
<b>{entity.name}</b>) in the field below:
</span>
)
}
value={confirmText}
typographyStyle={typographyStyle}
textFieldStyle={textFieldStyle}
data-testid={'dialog-confirm-text-input'}
expand
onChange={(input) => {
setConfirmText(input);
}}
visible={preferences?.type_to_confirm}
placeholder={entity.subType === 'CloseAccount' ? 'Username' : ''}
/>
</ConfirmationDialog>
);
Expand Down
123 changes: 49 additions & 74 deletions packages/manager/src/features/Account/CloseAccountDialog.tsx
dwiley-akamai marked this conversation as resolved.
Show resolved Hide resolved
carrillo-erik marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import { cancelAccount } from '@linode/api-v4/lib/account';
import { APIError } from '@linode/api-v4/lib/types';
import * as React from 'react';
import { useHistory } from 'react-router-dom';
import ActionsPanel from 'src/components/ActionsPanel';
import { Button } from 'src/components/Button/Button';
import { ConfirmationDialog } from 'src/components/ConfirmationDialog/ConfirmationDialog';
import { TypeToConfirmDialog } from 'src/components/TypeToConfirmDialog/TypeToConfirmDialog';
import { makeStyles } from 'tss-react/mui';
import { Theme } from '@mui/material/styles';
import { Theme, styled } from '@mui/material/styles';
import { Notice } from 'src/components/Notice/Notice';
import { Typography } from 'src/components/Typography';
import { TypeToConfirm } from 'src/components/TypeToConfirm/TypeToConfirm';
import { TextField } from 'src/components/TextField';
import { useProfile } from 'src/queries/profile';

Expand All @@ -21,6 +18,7 @@ interface Props {
const useStyles = makeStyles()((theme: Theme) => ({
dontgo: {
marginTop: theme.spacing(2),
order: 1,
},
}));

Expand All @@ -32,7 +30,6 @@ const CloseAccountDialog = ({ closeDialog, open }: Props) => {
const [comments, setComments] = React.useState<string>('');
const [inputtedUsername, setUsername] = React.useState<string>('');
const [canSubmit, setCanSubmit] = React.useState<boolean>(false);

const { classes } = useStyles();
const history = useHistory();
const { data: profile } = useProfile();
Expand Down Expand Up @@ -98,86 +95,64 @@ const CloseAccountDialog = ({ closeDialog, open }: Props) => {
}

return (
<ConfirmationDialog
open={open}
<TypeToConfirmDialog
title="Are you sure you want to close your Linode account?"
label={`Please enter your Username (${profile.username}) to confirm.`}
entity={{
type: 'AccountSetting',
subType: 'CloseAccount',
primaryBtnText: 'Close Account',
name: profile.username,
}}
open={open}
onClose={closeDialog}
error={errors ? errors[0].reason : ''}
actions={
<Actions
onClose={closeDialog}
isCanceling={isClosingAccount}
onSubmit={handleCancelAccount}
disabled={!canSubmit}
/>
}
onClick={handleCancelAccount}
loading={isClosingAccount}
inputRef={inputRef}
disabled={!canSubmit}
textFieldStyle={{ maxWidth: '415px' }}
>
<Notice warning>
<Typography style={{ fontSize: '0.875rem' }}>
<strong>Warning:</strong> Please note this is an extremely destructive
action. Closing your account means that all services including
Linodes, Volumes, DNS Records, etc will be lost and may not be able to
be restored.
</Typography>
</Notice>
<TypeToConfirm
label={`Please enter your username (${profile.username}) to confirm.`}
onChange={(input) => setUsername(input)}
inputRef={inputRef}
aria-label="username field"
value={inputtedUsername}
visible
hideInstructions
placeholder="Username"
/>
{errors ? <Notice error text={errors ? errors[0].reason : ''} /> : null}
<StyledNoticeWrapper>
<Notice warning spacingBottom={12}>
<Typography sx={{ fontSize: '0.875rem' }}>
<strong>Warning:</strong> Please note this is an extremely
destructive action. Closing your account means that all services
Linodes, Volumes, DNS Records, etc will be lost and may not be able
be restored.
</Typography>
</Notice>
</StyledNoticeWrapper>
<Typography className={classes.dontgo}>
We&rsquo;d hate to see you go. Please let us know what we could be doing
better in the comments section below. After your account is closed,
you&rsquo;ll be directed to a quick survey so we can better gauge your
feedback.
</Typography>
<TextField
label="Comments"
multiline
onChange={(e) => setComments(e.target.value)}
optional
placeholder="Provide Feedback"
rows={1}
value={comments}
aria-label="Optional comments field"
/>
</ConfirmationDialog>
<StyledCommentSectionWrapper>
<TextField
label="Comments"
multiline
onChange={(e) => setComments(e.target.value)}
optional
placeholder="Provide Feedback"
rows={1}
value={comments}
aria-label="Optional comments field"
/>
</StyledCommentSectionWrapper>
</TypeToConfirmDialog>
);
};

interface ActionsProps {
onClose: () => void;
onSubmit: () => void;
isCanceling: boolean;
disabled: boolean;
}
// The order property helps inject the TypeToConfirm input field in the TypeToConfirmDialog when the components
// below are passed in as the children prop.
const StyledNoticeWrapper = styled('div')(() => ({
order: 0,
}));

const Actions = ({
disabled,
isCanceling,
onClose,
onSubmit,
}: ActionsProps) => {
return (
<ActionsPanel>
<Button buttonType="secondary" onClick={onClose}>
Cancel
</Button>
<Button
buttonType="primary"
onClick={onSubmit}
disabled={disabled}
loading={isCanceling}
>
Close Account
</Button>
</ActionsPanel>
);
};
const StyledCommentSectionWrapper = styled('div')(() => ({
order: 2,
}));

export default React.memo(CloseAccountDialog);
Loading