From 77da8c6994219e262c72a0313ebe9bef6d47749b Mon Sep 17 00:00:00 2001 From: mabashian Date: Tue, 20 Oct 2020 14:47:44 -0400 Subject: [PATCH] Adds copy button to notification templates list rows --- .../NotificationTemplateList.jsx | 1 + .../NotificationTemplateListItem.jsx | 33 +++++++++++- .../NotificationTemplateListItem.test.jsx | 53 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.jsx b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.jsx index 258cd7cbb6..67588fc267 100644 --- a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.jsx +++ b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.jsx @@ -166,6 +166,7 @@ function NotificationTemplatesList({ i18n }) { renderItem={template => ( row.id === template.id)} diff --git a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.jsx b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.jsx index 59d9fb748d..5f3d0a2a10 100644 --- a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.jsx +++ b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.jsx @@ -14,9 +14,11 @@ import { Tooltip, } from '@patternfly/react-core'; import { PencilAltIcon, BellIcon } from '@patternfly/react-icons'; +import { timeOfDay } from '../../../util/dates'; import { NotificationTemplatesAPI, NotificationsAPI } from '../../../api'; import DataListCell from '../../../components/DataListCell'; import StatusLabel from '../../../components/StatusLabel'; +import CopyButton from '../../../components/CopyButton'; import useRequest from '../../../util/useRequest'; import { NOTIFICATION_TYPES } from '../constants'; @@ -24,7 +26,7 @@ const DataListAction = styled(_DataListAction)` align-items: center; display: grid; grid-gap: 16px; - grid-template-columns: 40px 40px; + grid-template-columns: repeat(3, 40px); `; const NUM_RETRIES = 25; @@ -33,6 +35,7 @@ const RETRY_TIMEOUT = 5000; function NotificationTemplateListItem({ template, detailUrl, + fetchTemplates, isSelected, onSelect, i18n, @@ -42,6 +45,22 @@ function NotificationTemplateListItem({ ? recentNotifications[0]?.status : null; const [status, setStatus] = useState(latestStatus); + const [isCopyDisabled, setIsCopyDisabled] = useState(false); + + const copyTemplate = useCallback(async () => { + await NotificationTemplatesAPI.copy(template.id, { + name: `${template.name} @ ${timeOfDay()}`, + }); + await fetchTemplates(); + }, [template.id, template.name, fetchTemplates]); + + const handleCopyStart = useCallback(() => { + setIsCopyDisabled(true); + }, []); + + const handleCopyFinish = useCallback(() => { + setIsCopyDisabled(false); + }, []); useEffect(() => { setStatus(latestStatus); @@ -136,6 +155,18 @@ function NotificationTemplateListItem({ ) : (
)} + {template.summary_fields.user_capabilities.copy && ( + + )} diff --git a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.jsx b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.jsx index 58878d3b96..65f959522c 100644 --- a/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.jsx +++ b/awx/ui_next/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.jsx @@ -13,6 +13,7 @@ const template = { summary_fields: { user_capabilities: { edit: true, + copy: true, }, recent_notifications: [ { @@ -63,4 +64,56 @@ describe('', () => { .text() ).toEqual('Running'); }); + + test('should call api to copy inventory', async () => { + NotificationTemplatesAPI.copy.mockResolvedValue(); + + const wrapper = mountWithContexts( + + ); + + await act(async () => + wrapper.find('Button[aria-label="Copy"]').prop('onClick')() + ); + expect(NotificationTemplatesAPI.copy).toHaveBeenCalled(); + jest.clearAllMocks(); + }); + + test('should render proper alert modal on copy error', async () => { + NotificationTemplatesAPI.copy.mockRejectedValue(new Error()); + + const wrapper = mountWithContexts( + + ); + await act(async () => + wrapper.find('Button[aria-label="Copy"]').prop('onClick')() + ); + wrapper.update(); + expect(wrapper.find('Modal').prop('isOpen')).toBe(true); + jest.clearAllMocks(); + }); + + test('should not render copy button', async () => { + const wrapper = mountWithContexts( + + ); + expect(wrapper.find('CopyButton').length).toBe(0); + }); });