From c8a7399257de05b1d7e155f4741eeebbd666f710 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Mon, 4 Mar 2024 10:12:13 -0500 Subject: [PATCH 1/5] Allow disabling type to confirm input --- .../TypeToConfirmDialog/TypeToConfirmDialog.tsx | 8 ++++++-- .../PlacementGroups/PlacementGroupsDeleteModal.tsx | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx index 883a2d5cc48..084d5f6c203 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx @@ -33,6 +33,7 @@ interface EntityInfo { interface TypeToConfirmDialogProps { children?: React.ReactNode; + disableTypeToConfirmInput?: boolean; entity: EntityInfo; errors?: APIError[] | null | undefined; label: string; @@ -48,6 +49,7 @@ type CombinedProps = TypeToConfirmDialogProps & export const TypeToConfirmDialog = (props: CombinedProps) => { const { children, + disableTypeToConfirmInput, entity, errors, inputProps, @@ -64,8 +66,9 @@ export const TypeToConfirmDialog = (props: CombinedProps) => { const [confirmText, setConfirmText] = React.useState(''); const { data: preferences } = usePreferences(); - const disabled = + const isPrimaryButtonDisabled = preferences?.type_to_confirm !== false && confirmText !== entity.name; + const isTypeToConfirmInputDisabled = disableTypeToConfirmInput; React.useEffect(() => { if (open) { @@ -82,7 +85,7 @@ export const TypeToConfirmDialog = (props: CombinedProps) => { { setConfirmText(input); }} data-testid={'dialog-confirm-text-input'} + disabled={isTypeToConfirmInputDisabled} expand hideInstructions={entity.subType === 'CloseAccount'} inputProps={inputProps} diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx index af7c99be0f4..4bc0486c5e0 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx @@ -96,6 +96,7 @@ export const PlacementGroupsDeleteModal = (props: Props) => { inputProps={{ disabled: isDisabled, }} + disableTypeToConfirmInput disabled={isDisabled} label="Placement Group" loading={placementGroupDataLoading || deletePlacementLoading} From 492fab4f5b7af7a5e3894c69d49d9784e23a3fb4 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Mon, 4 Mar 2024 10:27:26 -0500 Subject: [PATCH 2/5] PlacementGroupDelete update --- .../features/PlacementGroups/PlacementGroupsDeleteModal.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx index 4bc0486c5e0..390d2104066 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx @@ -93,10 +93,7 @@ export const PlacementGroupsDeleteModal = (props: Props) => { ? [{ reason: 'Placement Group not found.' }] : undefined } - inputProps={{ - disabled: isDisabled, - }} - disableTypeToConfirmInput + disableTypeToConfirmInput={isDisabled} disabled={isDisabled} label="Placement Group" loading={placementGroupDataLoading || deletePlacementLoading} From 9de33b867404bf038c56da9f2f5cda35c26c19d5 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Mon, 4 Mar 2024 10:54:33 -0500 Subject: [PATCH 3/5] Improve coverage --- .../TypeToConfirmDialog.test.tsx | 58 +++++++++++++++++++ .../TypeToConfirmDialog.tsx | 24 ++++++++ 2 files changed, 82 insertions(+) diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx index d45202f27b4..33e7e88aa60 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx @@ -1,3 +1,4 @@ +import { fireEvent } from '@testing-library/react'; import * as React from 'react'; import { Typography } from 'src/components/Typography'; @@ -33,4 +34,61 @@ describe('TypeToConfirmDialog Component', () => { ); getByText(warningText); }); + + it('should have its button disabled by default', () => { + const { getByTestId } = renderWithTheme( + + + Warning: {warningText} + + + ); + + const submitButton = getByTestId('confirm'); + expect(submitButton).toBeDisabled(); + + const input = getByTestId('textfield-input'); + fireEvent.change(input, { target: { value: 'test' } }); + + expect(submitButton).toBeEnabled(); + }); + + it('should disabled the Type To Confirm input field given the prop', () => { + const { getByTestId } = renderWithTheme( + + + Warning: {warningText} + + + ); + + const input = getByTestId('textfield-input'); + expect(input).toBeDisabled(); + }); }); diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx index 084d5f6c203..4bcc305b82e 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx @@ -32,13 +32,37 @@ interface EntityInfo { } interface TypeToConfirmDialogProps { + /** + * Chidlren are rendered above the TypeToConfirm input + */ children?: React.ReactNode; + /** + * Props to be allow disabling the input + */ disableTypeToConfirmInput?: boolean; + /** + * The entity being confirmed + */ entity: EntityInfo; + /** + * Error to be displayed in the dialog + */ errors?: APIError[] | null | undefined; + /* + * The label for the dialog + */ label: string; + /** + * The loading state of dialog + */ loading: boolean; + /** + * The click handler for the primary button + */ onClick: () => void; + /** + * The open/closed state of the dialog + */ open: boolean; } From 53ffd9f9651160b0afe8433dc72409661f8ecb87 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Tue, 5 Mar 2024 13:26:36 -0500 Subject: [PATCH 4/5] feedback and update interface --- .../TypeToConfirmDialog.test.tsx | 1 - .../TypeToConfirmDialog/TypeToConfirmDialog.tsx | 10 ++++++++-- .../src/features/Account/CloseAccountDialog.tsx | 17 ----------------- .../DeleteKubernetesClusterDialog.test.tsx | 4 ++-- .../PlacementGroupsDeleteModal.tsx | 1 - 5 files changed, 10 insertions(+), 23 deletions(-) diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx index 33e7e88aa60..86cb3b12ade 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx @@ -80,7 +80,6 @@ describe('TypeToConfirmDialog Component', () => { open={true} title="Delete Linode test?" {...props} - disabled > Warning: {warningText} diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx index 4bcc305b82e..6bf1f6eb4f5 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.tsx @@ -40,6 +40,10 @@ interface TypeToConfirmDialogProps { * Props to be allow disabling the input */ disableTypeToConfirmInput?: boolean; + /** + * Props to be allow disabling the submit button + */ + disableTypeToConfirmSubmit?: boolean; /** * The entity being confirmed */ @@ -68,12 +72,13 @@ interface TypeToConfirmDialogProps { type CombinedProps = TypeToConfirmDialogProps & ConfirmationDialogProps & - Partial; + Partial>; export const TypeToConfirmDialog = (props: CombinedProps) => { const { children, disableTypeToConfirmInput, + disableTypeToConfirmSubmit, entity, errors, inputProps, @@ -91,7 +96,8 @@ export const TypeToConfirmDialog = (props: CombinedProps) => { const { data: preferences } = usePreferences(); const isPrimaryButtonDisabled = - preferences?.type_to_confirm !== false && confirmText !== entity.name; + (preferences?.type_to_confirm !== false && confirmText !== entity.name) || + disableTypeToConfirmSubmit; const isTypeToConfirmInputDisabled = disableTypeToConfirmInput; React.useEffect(() => { diff --git a/packages/manager/src/features/Account/CloseAccountDialog.tsx b/packages/manager/src/features/Account/CloseAccountDialog.tsx index 5ebca3b4297..a01aaa8464e 100644 --- a/packages/manager/src/features/Account/CloseAccountDialog.tsx +++ b/packages/manager/src/features/Account/CloseAccountDialog.tsx @@ -29,8 +29,6 @@ const CloseAccountDialog = ({ closeDialog, open }: Props) => { ); const [errors, setErrors] = React.useState(undefined); const [comments, setComments] = React.useState(''); - const [inputtedUsername, setUsername] = React.useState(''); - const [canSubmit, setCanSubmit] = React.useState(false); const { classes } = useStyles(); const history = useHistory(); const { data: profile } = useProfile(); @@ -42,23 +40,9 @@ const CloseAccountDialog = ({ closeDialog, open }: Props) => { * intentionally not resetting comments */ setErrors(undefined); - setUsername(''); - setCanSubmit(false); } }, [open]); - /** - * enable the submit button if the user entered their - * username correctly - */ - React.useEffect(() => { - if (inputtedUsername === profile?.username) { - setCanSubmit(true); - } else { - setCanSubmit(false); - } - }, [inputtedUsername, profile]); - const inputRef = React.useCallback( (node: any) => { /** @@ -103,7 +87,6 @@ const CloseAccountDialog = ({ closeDialog, open }: Props) => { subType: 'CloseAccount', type: 'AccountSetting', }} - disabled={!canSubmit} inputRef={inputRef} label={`Please enter your Username (${profile.username}) to confirm.`} loading={isClosingAccount} diff --git a/packages/manager/src/features/Kubernetes/KubernetesClusterDetail/DeleteKubernetesClusterDialog.test.tsx b/packages/manager/src/features/Kubernetes/KubernetesClusterDetail/DeleteKubernetesClusterDialog.test.tsx index 44482f79662..0440b167e3c 100644 --- a/packages/manager/src/features/Kubernetes/KubernetesClusterDetail/DeleteKubernetesClusterDialog.test.tsx +++ b/packages/manager/src/features/Kubernetes/KubernetesClusterDetail/DeleteKubernetesClusterDialog.test.tsx @@ -42,13 +42,13 @@ describe('Kubernetes deletion dialog', () => { ); const button = getByTestId('confirm'); - expect(button).toHaveAttribute('aria-disabled', 'true'); + expect(button).toBeDisabled; await findByTestId('textfield-input'); const input = getByTestId('textfield-input'); fireEvent.change(input, { target: { value: 'this-cluster' } }); - expect(button).toHaveAttribute('aria-disabled', 'false'); + expect(button).toBeEnabled(); }); }); diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx index 390d2104066..5454d348365 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx @@ -94,7 +94,6 @@ export const PlacementGroupsDeleteModal = (props: Props) => { : undefined } disableTypeToConfirmInput={isDisabled} - disabled={isDisabled} label="Placement Group" loading={placementGroupDataLoading || deletePlacementLoading} onClick={onDelete} From d02007f0252e9f5c56a05b5d77247877b51b8fb0 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Tue, 5 Mar 2024 14:05:16 -0500 Subject: [PATCH 5/5] Improve coverage --- .../TypeToConfirmDialog.test.tsx | 33 ++++++++++++++++++- .../PlacementGroupsDeleteModal.tsx | 1 + 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx index 86cb3b12ade..e3b308e52f7 100644 --- a/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx +++ b/packages/manager/src/components/TypeToConfirmDialog/TypeToConfirmDialog.test.tsx @@ -65,7 +65,7 @@ describe('TypeToConfirmDialog Component', () => { expect(submitButton).toBeEnabled(); }); - it('should disabled the Type To Confirm input field given the prop', () => { + it('should disabled the Type To Confirm input field given the `disableTypeToConfirmInput` prop', () => { const { getByTestId } = renderWithTheme( { const input = getByTestId('textfield-input'); expect(input).toBeDisabled(); }); + + it('should disabled the Type To Confirm input field given the prop', () => { + const { getByTestId } = renderWithTheme( + + + Warning: {warningText} + + + ); + + const input = getByTestId('textfield-input'); + fireEvent.change(input, { target: { value: 'test' } }); + + const submitButton = getByTestId('confirm'); + // Should still be disabled cause we overrode the disabled state with the prop + + expect(submitButton).toBeDisabled(); + }); }); diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx index 5454d348365..1a79c86d103 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsDeleteModal.tsx @@ -94,6 +94,7 @@ export const PlacementGroupsDeleteModal = (props: Props) => { : undefined } disableTypeToConfirmInput={isDisabled} + disableTypeToConfirmSubmit={isDisabled} label="Placement Group" loading={placementGroupDataLoading || deletePlacementLoading} onClick={onDelete}