diff --git a/awx/ui/src/screens/Job/JobOutput/EmptyOutput.js b/awx/ui/src/screens/Job/JobOutput/EmptyOutput.js index 69e21eba5cdc..74d0625f66f5 100644 --- a/awx/ui/src/screens/Job/JobOutput/EmptyOutput.js +++ b/awx/ui/src/screens/Job/JobOutput/EmptyOutput.js @@ -1,17 +1,29 @@ import React, { useEffect } from 'react'; +import { Link, useParams } from 'react-router-dom'; import 'styled-components/macro'; import { t } from '@lingui/macro'; -import { SearchIcon } from '@patternfly/react-icons'; +import { + SearchIcon, + ExclamationCircleIcon as PFExclamationCircleIcon, +} from '@patternfly/react-icons'; import ContentEmpty from 'components/ContentEmpty'; +import { LaunchButton, ReLaunchDropDown } from 'components/LaunchButton'; +import styled from 'styled-components'; + +const ExclamationCircleIcon = styled(PFExclamationCircleIcon)` + color: var(--pf-global--danger-color--100); +`; export default function EmptyOutput({ hasQueryParams, isJobRunning, onUnmount, + job, }) { let title; let message; let icon; + const { typeSegment, id } = useParams(); useEffect(() => onUnmount); @@ -21,6 +33,26 @@ export default function EmptyOutput({ icon = SearchIcon; } else if (isJobRunning) { title = t`Waiting for job output…`; + } else if (job.status === 'failed') { + title = t`This job failed and has not output.`; + message = ( + <> + {t`Please relaunch the job or, for more information see the`}{' '} + {t`details.`}{' '} +
+ + {({ handleRelaunch, isLaunching }) => ( + + )} + + + ); + icon = ExclamationCircleIcon; } else { title = t`No output found for this job.`; } diff --git a/awx/ui/src/screens/Job/JobOutput/JobOutput.js b/awx/ui/src/screens/Job/JobOutput/JobOutput.js index ac5383e0d699..386fb87c56df 100644 --- a/awx/ui/src/screens/Job/JobOutput/JobOutput.js +++ b/awx/ui/src/screens/Job/JobOutput/JobOutput.js @@ -687,6 +687,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) { ) { return ( 1} isJobRunning={isJobRunning(jobStatus)} onUnmount={() => { diff --git a/awx/ui/src/screens/Job/JobOutput/JobOutput.test.js b/awx/ui/src/screens/Job/JobOutput/JobOutput.test.js index 19af8a76d6d3..423595d0f96b 100644 --- a/awx/ui/src/screens/Job/JobOutput/JobOutput.test.js +++ b/awx/ui/src/screens/Job/JobOutput/JobOutput.test.js @@ -134,4 +134,20 @@ describe('', () => { }); await waitForElement(wrapper, 'ContentError', (el) => el.length === 1); }); + test('should show failed empty output screen', async () => { + JobsAPI.readEvents.mockResolvedValue({ + data: { + count: 0, + next: null, + previous: null, + results: [], + }, + }); + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + await waitForElement(wrapper, 'EmptyOutput', (el) => el.length === 1); + }); });