Disable inventory copy button when inventory has sources. Refactor copy button props since tooltip is now handled by the ActionItem component.

This commit is contained in:
mabashian
2021-02-09 11:22:25 -05:00
parent 67f1f9ac69
commit a691caf346
9 changed files with 83 additions and 80 deletions

View File

@@ -3,7 +3,7 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Tooltip } from '@patternfly/react-core'; import { Button } from '@patternfly/react-core';
import { CopyIcon } from '@patternfly/react-icons'; import { CopyIcon } from '@patternfly/react-icons';
import useRequest, { useDismissableError } from '../../util/useRequest'; import useRequest, { useDismissableError } from '../../util/useRequest';
import AlertModal from '../AlertModal'; import AlertModal from '../AlertModal';
@@ -15,7 +15,7 @@ function CopyButton({
isDisabled, isDisabled,
onCopyStart, onCopyStart,
onCopyFinish, onCopyFinish,
helperText, errorMessage,
i18n, i18n,
}) { }) {
const { isLoading, error: copyError, request: copyItemToAPI } = useRequest( const { isLoading, error: copyError, request: copyItemToAPI } = useRequest(
@@ -33,17 +33,15 @@ function CopyButton({
return ( return (
<> <>
<Tooltip content={helperText.tooltip} position="top"> <Button
<Button id={id}
id={id} isDisabled={isLoading || isDisabled}
isDisabled={isLoading || isDisabled} aria-label={i18n._(t`Copy`)}
aria-label={i18n._(t`Copy`)} variant="plain"
variant="plain" onClick={copyItemToAPI}
onClick={copyItemToAPI} >
> <CopyIcon />
<CopyIcon /> </Button>
</Button>
</Tooltip>
<AlertModal <AlertModal
aria-label={i18n._(t`Copy Error`)} aria-label={i18n._(t`Copy Error`)}
isOpen={error} isOpen={error}
@@ -51,7 +49,7 @@ function CopyButton({
title={i18n._(t`Error!`)} title={i18n._(t`Error!`)}
onClose={dismissError} onClose={dismissError}
> >
{helperText.errorMessage} {errorMessage}
<ErrorDetail error={error} /> <ErrorDetail error={error} />
</AlertModal> </AlertModal>
</> </>
@@ -62,10 +60,7 @@ CopyButton.propTypes = {
copyItem: PropTypes.func.isRequired, copyItem: PropTypes.func.isRequired,
onCopyStart: PropTypes.func.isRequired, onCopyStart: PropTypes.func.isRequired,
onCopyFinish: PropTypes.func.isRequired, onCopyFinish: PropTypes.func.isRequired,
helperText: PropTypes.shape({ errorMessage: PropTypes.string.isRequired,
tooltip: PropTypes.string.isRequired,
errorMessage: PropTypes.string.isRequired,
}).isRequired,
isDisabled: PropTypes.bool, isDisabled: PropTypes.bool,
}; };

View File

@@ -1,36 +1,44 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import CopyButton from './CopyButton'; import CopyButton from './CopyButton';
jest.mock('../../api'); jest.mock('../../api');
let wrapper;
describe('<CopyButton/>', () => { describe('<CopyButton/>', () => {
test('shold mount properly', () => { afterEach(() => {
const wrapper = mountWithContexts( wrapper.unmount();
<CopyButton });
onCopyStart={() => {}} test('should mount properly', async () => {
onCopyFinish={() => {}} await act(async () => {
copyItem={() => {}} wrapper = mountWithContexts(
helperText={{ <CopyButton
tooltip: `Copy Template`, onCopyStart={() => {}}
errorMessage: `Failed to copy template.`, onCopyFinish={() => {}}
}} copyItem={() => {}}
/> errorMessage={`Failed to copy template.`}
); />
);
});
expect(wrapper.find('CopyButton').length).toBe(1); expect(wrapper.find('CopyButton').length).toBe(1);
}); });
test('should render proper tooltip', () => { test('should call the correct function on button click', async () => {
const wrapper = mountWithContexts( const copyItem = jest.fn();
<CopyButton await act(async () => {
onCopyStart={() => {}} wrapper = mountWithContexts(
onCopyFinish={() => {}} <CopyButton
copyItem={() => {}} onCopyStart={() => {}}
helperText={{ onCopyFinish={() => {}}
tooltip: `Copy Template`, copyItem={copyItem}
errorMessage: `Failed to copy template.`, errorMessage={`Failed to copy template.`}
}} />
/> );
); });
expect(wrapper.find('Tooltip').prop('content')).toBe('Copy Template'); await act(async () => {
wrapper.find('button').simulate('click');
});
expect(copyItem).toHaveBeenCalledTimes(1);
}); });
}); });

View File

@@ -14,7 +14,7 @@ export default function ActionItem({ column, tooltip, visible, children }) {
`} `}
> >
<Tooltip content={tooltip} position="top"> <Tooltip content={tooltip} position="top">
{children} <div>{children}</div>
</Tooltip> </Tooltip>
</div> </div>
); );

View File

@@ -12,7 +12,7 @@ describe('<ActionItem />', () => {
const tooltip = wrapper.find('Tooltip'); const tooltip = wrapper.find('Tooltip');
expect(tooltip.prop('content')).toEqual('a tooltip'); expect(tooltip.prop('content')).toEqual('a tooltip');
expect(tooltip.prop('children')).toEqual('foo'); expect(tooltip.prop('children')).toEqual(<div>foo</div>);
}); });
test('should render null if not visible', async () => { test('should render null if not visible', async () => {

View File

@@ -177,13 +177,13 @@ function TemplateListItem({
<PencilAltIcon /> <PencilAltIcon />
</Button> </Button>
</ActionItem> </ActionItem>
<ActionItem visible={template.summary_fields.user_capabilities.copy}> <ActionItem
tooltip={i18n._(t`Copy Template`)}
visible={template.summary_fields.user_capabilities.copy}
>
<CopyButton <CopyButton
id={`template-action-copy-${template.id}`} id={`template-action-copy-${template.id}`}
helperText={{ errorMessage={i18n._(t`Failed to copy template.`)}
errorMessage: i18n._(t`Failed to copy template.`),
tooltip: i18n._(t`Copy Template`),
}}
isDisabled={isDisabled} isDisabled={isDisabled}
onCopyStart={handleCopyStart} onCopyStart={handleCopyStart}
onCopyFinish={handleCopyFinish} onCopyFinish={handleCopyFinish}

View File

@@ -72,16 +72,16 @@ function CredentialListItem({
<PencilAltIcon /> <PencilAltIcon />
</Button> </Button>
</ActionItem> </ActionItem>
<ActionItem visible={credential.summary_fields.user_capabilities.copy}> <ActionItem
tooltip={i18n._(t`Copy Credential`)}
visible={credential.summary_fields.user_capabilities.copy}
>
<CopyButton <CopyButton
isDisabled={isDisabled} isDisabled={isDisabled}
onCopyStart={handleCopyStart} onCopyStart={handleCopyStart}
onCopyFinish={handleCopyFinish} onCopyFinish={handleCopyFinish}
copyItem={copyCredential} copyItem={copyCredential}
helperText={{ errorMessage={i18n._(t`Failed to copy credential.`)}
tooltip: i18n._(t`Copy Credential`),
errorMessage: i18n._(t`Failed to copy credential.`),
}}
/> />
</ActionItem> </ActionItem>
</ActionsTd> </ActionsTd>

View File

@@ -28,7 +28,7 @@ function InventoryListItem({
isSelected: bool.isRequired, isSelected: bool.isRequired,
onSelect: func.isRequired, onSelect: func.isRequired,
}; };
const [isDisabled, setIsDisabled] = useState(false); const [isCopying, setIsCopying] = useState(false);
const copyInventory = useCallback(async () => { const copyInventory = useCallback(async () => {
await InventoriesAPI.copy(inventory.id, { await InventoriesAPI.copy(inventory.id, {
@@ -38,11 +38,11 @@ function InventoryListItem({
}, [inventory.id, inventory.name, fetchInventories]); }, [inventory.id, inventory.name, fetchInventories]);
const handleCopyStart = useCallback(() => { const handleCopyStart = useCallback(() => {
setIsDisabled(true); setIsCopying(true);
}, []); }, []);
const handleCopyFinish = useCallback(() => { const handleCopyFinish = useCallback(() => {
setIsDisabled(false); setIsCopying(false);
}, []); }, []);
const labelId = `check-action-${inventory.id}`; const labelId = `check-action-${inventory.id}`;
@@ -115,7 +115,7 @@ function InventoryListItem({
tooltip={i18n._(t`Edit Inventory`)} tooltip={i18n._(t`Edit Inventory`)}
> >
<Button <Button
isDisabled={isDisabled} isDisabled={isCopying}
aria-label={i18n._(t`Edit Inventory`)} aria-label={i18n._(t`Edit Inventory`)}
variant="plain" variant="plain"
component={Link} component={Link}
@@ -128,17 +128,18 @@ function InventoryListItem({
</ActionItem> </ActionItem>
<ActionItem <ActionItem
visible={inventory.summary_fields.user_capabilities.copy} visible={inventory.summary_fields.user_capabilities.copy}
tooltip={i18n._(t`Copy Inventory`)} tooltip={
inventory.has_inventory_sources
? i18n._(t`Inventories with sources cannot be copied`)
: i18n._(t`Copy Inventory`)
}
> >
<CopyButton <CopyButton
copyItem={copyInventory} copyItem={copyInventory}
isDisabled={isDisabled} isDisabled={isCopying || inventory.has_inventory_sources}
onCopyStart={handleCopyStart} onCopyStart={handleCopyStart}
onCopyFinish={handleCopyFinish} onCopyFinish={handleCopyFinish}
helperText={{ errorMessage={i18n._(t`Failed to copy inventory.`)}
tooltip: i18n._(t`Copy Inventory`),
errorMessage: i18n._(t`Failed to copy inventory.`),
}}
/> />
</ActionItem> </ActionItem>
</ActionsTd> </ActionsTd>

View File

@@ -159,16 +159,15 @@ function NotificationTemplateListItem({
<div /> <div />
)} )}
{template.summary_fields.user_capabilities.copy && ( {template.summary_fields.user_capabilities.copy && (
<CopyButton <Tooltip content={i18n._(t`Copy Notification Template`)}>
copyItem={copyTemplate} <CopyButton
isCopyDisabled={isCopyDisabled} copyItem={copyTemplate}
onCopyStart={handleCopyStart} isCopyDisabled={isCopyDisabled}
onCopyFinish={handleCopyFinish} onCopyStart={handleCopyStart}
helperText={{ onCopyFinish={handleCopyFinish}
tooltip: i18n._(t`Copy Notification Template`), errorMessage={i18n._(t`Failed to copy template.`)}
errorMessage: i18n._(t`Failed to copy template.`), />
}} </Tooltip>
/>
)} )}
</DataListAction> </DataListAction>
</DataListItemRow> </DataListItemRow>

View File

@@ -143,16 +143,16 @@ function ProjectListItem({
<PencilAltIcon /> <PencilAltIcon />
</Button> </Button>
</ActionItem> </ActionItem>
<ActionItem visible={project.summary_fields.user_capabilities.copy}> <ActionItem
tooltip={i18n._(t`Copy Project`)}
visible={project.summary_fields.user_capabilities.copy}
>
<CopyButton <CopyButton
copyItem={copyProject} copyItem={copyProject}
isDisabled={isDisabled} isDisabled={isDisabled}
onCopyStart={handleCopyStart} onCopyStart={handleCopyStart}
onCopyFinish={handleCopyFinish} onCopyFinish={handleCopyFinish}
helperText={{ errorMessage={i18n._(t`Failed to copy project.`)}
tooltip: i18n._(t`Copy Project`),
errorMessage: i18n._(t`Failed to copy project.`),
}}
/> />
</ActionItem> </ActionItem>
</ActionsTd> </ActionsTd>