mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 23:12:08 -03:30
Merge pull request #9287 from mabashian/7679-copy-inv-w-source
Disable inventory copy button when inventory has sources Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
4e48118704
@ -3,7 +3,7 @@ import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
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 useRequest, { useDismissableError } from '../../util/useRequest';
|
||||
import AlertModal from '../AlertModal';
|
||||
@ -15,7 +15,7 @@ function CopyButton({
|
||||
isDisabled,
|
||||
onCopyStart,
|
||||
onCopyFinish,
|
||||
helperText,
|
||||
errorMessage,
|
||||
i18n,
|
||||
}) {
|
||||
const { isLoading, error: copyError, request: copyItemToAPI } = useRequest(
|
||||
@ -33,17 +33,15 @@ function CopyButton({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip content={helperText.tooltip} position="top">
|
||||
<Button
|
||||
id={id}
|
||||
isDisabled={isLoading || isDisabled}
|
||||
aria-label={i18n._(t`Copy`)}
|
||||
variant="plain"
|
||||
onClick={copyItemToAPI}
|
||||
>
|
||||
<CopyIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
id={id}
|
||||
isDisabled={isLoading || isDisabled}
|
||||
aria-label={i18n._(t`Copy`)}
|
||||
variant="plain"
|
||||
onClick={copyItemToAPI}
|
||||
>
|
||||
<CopyIcon />
|
||||
</Button>
|
||||
<AlertModal
|
||||
aria-label={i18n._(t`Copy Error`)}
|
||||
isOpen={error}
|
||||
@ -51,7 +49,7 @@ function CopyButton({
|
||||
title={i18n._(t`Error!`)}
|
||||
onClose={dismissError}
|
||||
>
|
||||
{helperText.errorMessage}
|
||||
{errorMessage}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
</>
|
||||
@ -62,10 +60,7 @@ CopyButton.propTypes = {
|
||||
copyItem: PropTypes.func.isRequired,
|
||||
onCopyStart: PropTypes.func.isRequired,
|
||||
onCopyFinish: PropTypes.func.isRequired,
|
||||
helperText: PropTypes.shape({
|
||||
tooltip: PropTypes.string.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
isDisabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
||||
@ -1,36 +1,44 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
import CopyButton from './CopyButton';
|
||||
|
||||
jest.mock('../../api');
|
||||
|
||||
let wrapper;
|
||||
|
||||
describe('<CopyButton/>', () => {
|
||||
test('shold mount properly', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<CopyButton
|
||||
onCopyStart={() => {}}
|
||||
onCopyFinish={() => {}}
|
||||
copyItem={() => {}}
|
||||
helperText={{
|
||||
tooltip: `Copy Template`,
|
||||
errorMessage: `Failed to copy template.`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
test('should mount properly', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<CopyButton
|
||||
onCopyStart={() => {}}
|
||||
onCopyFinish={() => {}}
|
||||
copyItem={() => {}}
|
||||
errorMessage="Failed to copy template."
|
||||
/>
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('CopyButton').length).toBe(1);
|
||||
});
|
||||
test('should render proper tooltip', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<CopyButton
|
||||
onCopyStart={() => {}}
|
||||
onCopyFinish={() => {}}
|
||||
copyItem={() => {}}
|
||||
helperText={{
|
||||
tooltip: `Copy Template`,
|
||||
errorMessage: `Failed to copy template.`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.find('Tooltip').prop('content')).toBe('Copy Template');
|
||||
test('should call the correct function on button click', async () => {
|
||||
const copyItem = jest.fn();
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<CopyButton
|
||||
onCopyStart={() => {}}
|
||||
onCopyFinish={() => {}}
|
||||
copyItem={copyItem}
|
||||
errorMessage="Failed to copy template."
|
||||
/>
|
||||
);
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper.find('button').simulate('click');
|
||||
});
|
||||
expect(copyItem).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -14,7 +14,7 @@ export default function ActionItem({ column, tooltip, visible, children }) {
|
||||
`}
|
||||
>
|
||||
<Tooltip content={tooltip} position="top">
|
||||
{children}
|
||||
<div>{children}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -12,7 +12,7 @@ describe('<ActionItem />', () => {
|
||||
|
||||
const tooltip = wrapper.find('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 () => {
|
||||
|
||||
@ -177,13 +177,13 @@ function TemplateListItem({
|
||||
<PencilAltIcon />
|
||||
</Button>
|
||||
</ActionItem>
|
||||
<ActionItem visible={template.summary_fields.user_capabilities.copy}>
|
||||
<ActionItem
|
||||
tooltip={i18n._(t`Copy Template`)}
|
||||
visible={template.summary_fields.user_capabilities.copy}
|
||||
>
|
||||
<CopyButton
|
||||
id={`template-action-copy-${template.id}`}
|
||||
helperText={{
|
||||
errorMessage: i18n._(t`Failed to copy template.`),
|
||||
tooltip: i18n._(t`Copy Template`),
|
||||
}}
|
||||
errorMessage={i18n._(t`Failed to copy template.`)}
|
||||
isDisabled={isDisabled}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
|
||||
@ -72,16 +72,16 @@ function CredentialListItem({
|
||||
<PencilAltIcon />
|
||||
</Button>
|
||||
</ActionItem>
|
||||
<ActionItem visible={credential.summary_fields.user_capabilities.copy}>
|
||||
<ActionItem
|
||||
tooltip={i18n._(t`Copy Credential`)}
|
||||
visible={credential.summary_fields.user_capabilities.copy}
|
||||
>
|
||||
<CopyButton
|
||||
isDisabled={isDisabled}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
copyItem={copyCredential}
|
||||
helperText={{
|
||||
tooltip: i18n._(t`Copy Credential`),
|
||||
errorMessage: i18n._(t`Failed to copy credential.`),
|
||||
}}
|
||||
errorMessage={i18n._(t`Failed to copy credential.`)}
|
||||
/>
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
|
||||
@ -28,7 +28,7 @@ function InventoryListItem({
|
||||
isSelected: bool.isRequired,
|
||||
onSelect: func.isRequired,
|
||||
};
|
||||
const [isDisabled, setIsDisabled] = useState(false);
|
||||
const [isCopying, setIsCopying] = useState(false);
|
||||
|
||||
const copyInventory = useCallback(async () => {
|
||||
await InventoriesAPI.copy(inventory.id, {
|
||||
@ -38,11 +38,11 @@ function InventoryListItem({
|
||||
}, [inventory.id, inventory.name, fetchInventories]);
|
||||
|
||||
const handleCopyStart = useCallback(() => {
|
||||
setIsDisabled(true);
|
||||
setIsCopying(true);
|
||||
}, []);
|
||||
|
||||
const handleCopyFinish = useCallback(() => {
|
||||
setIsDisabled(false);
|
||||
setIsCopying(false);
|
||||
}, []);
|
||||
|
||||
const labelId = `check-action-${inventory.id}`;
|
||||
@ -115,7 +115,7 @@ function InventoryListItem({
|
||||
tooltip={i18n._(t`Edit Inventory`)}
|
||||
>
|
||||
<Button
|
||||
isDisabled={isDisabled}
|
||||
isDisabled={isCopying}
|
||||
aria-label={i18n._(t`Edit Inventory`)}
|
||||
variant="plain"
|
||||
component={Link}
|
||||
@ -128,17 +128,18 @@ function InventoryListItem({
|
||||
</ActionItem>
|
||||
<ActionItem
|
||||
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
|
||||
copyItem={copyInventory}
|
||||
isDisabled={isDisabled}
|
||||
isDisabled={isCopying || inventory.has_inventory_sources}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
helperText={{
|
||||
tooltip: i18n._(t`Copy Inventory`),
|
||||
errorMessage: i18n._(t`Failed to copy inventory.`),
|
||||
}}
|
||||
errorMessage={i18n._(t`Failed to copy inventory.`)}
|
||||
/>
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
|
||||
@ -159,16 +159,15 @@ function NotificationTemplateListItem({
|
||||
<div />
|
||||
)}
|
||||
{template.summary_fields.user_capabilities.copy && (
|
||||
<CopyButton
|
||||
copyItem={copyTemplate}
|
||||
isCopyDisabled={isCopyDisabled}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
helperText={{
|
||||
tooltip: i18n._(t`Copy Notification Template`),
|
||||
errorMessage: i18n._(t`Failed to copy template.`),
|
||||
}}
|
||||
/>
|
||||
<Tooltip content={i18n._(t`Copy Notification Template`)}>
|
||||
<CopyButton
|
||||
copyItem={copyTemplate}
|
||||
isCopyDisabled={isCopyDisabled}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
errorMessage={i18n._(t`Failed to copy template.`)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</DataListAction>
|
||||
</DataListItemRow>
|
||||
|
||||
@ -143,16 +143,16 @@ function ProjectListItem({
|
||||
<PencilAltIcon />
|
||||
</Button>
|
||||
</ActionItem>
|
||||
<ActionItem visible={project.summary_fields.user_capabilities.copy}>
|
||||
<ActionItem
|
||||
tooltip={i18n._(t`Copy Project`)}
|
||||
visible={project.summary_fields.user_capabilities.copy}
|
||||
>
|
||||
<CopyButton
|
||||
copyItem={copyProject}
|
||||
isDisabled={isDisabled}
|
||||
onCopyStart={handleCopyStart}
|
||||
onCopyFinish={handleCopyFinish}
|
||||
helperText={{
|
||||
tooltip: i18n._(t`Copy Project`),
|
||||
errorMessage: i18n._(t`Failed to copy project.`),
|
||||
}}
|
||||
errorMessage={i18n._(t`Failed to copy project.`)}
|
||||
/>
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user