diff --git a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx index 76a3777d50..768dea9e6c 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx @@ -14,6 +14,7 @@ import Ansi from 'ansi-to-html'; import hasAnsi from 'has-ansi'; import { AllHtmlEntities } from 'html-entities'; import { + Button, Toolbar as _Toolbar, ToolbarContent as _ToolbarContent, ToolbarItem, @@ -293,13 +294,15 @@ function JobOutput({ const interval = useRef(null); const history = useHistory(); const [contentError, setContentError] = useState(null); - const [hasContentLoading, setHasContentLoading] = useState(true); - const [results, setResults] = useState({}); - const [currentlyLoading, setCurrentlyLoading] = useState([]); - const [isHostModalOpen, setIsHostModalOpen] = useState(false); - const [hostEvent, setHostEvent] = useState({}); const [cssMap, setCssMap] = useState({}); + const [currentlyLoading, setCurrentlyLoading] = useState([]); + const [hasContentLoading, setHasContentLoading] = useState(true); + const [hostEvent, setHostEvent] = useState({}); + const [isHostModalOpen, setIsHostModalOpen] = useState(false); + const [jobStatus, setJobStatus] = useState(job.status ?? 'waiting'); + const [showCancelModal, setShowCancelModal] = useState(false); const [remoteRowCount, setRemoteRowCount] = useState(0); + const [results, setResults] = useState({}); useEffect(() => { isMounted.current = true; @@ -307,10 +310,18 @@ function JobOutput({ if (isJobRunning(job.status)) { connectJobSocket(job, data => { - if (data.counter && data.counter > jobSocketCounter.current) { - jobSocketCounter.current = data.counter; - } else if (data.final_counter && data.unified_job_id === job.id) { - jobSocketCounter.current = data.final_counter; + if (data.group_name === 'job_events') { + if (data.counter && data.counter > jobSocketCounter.current) { + jobSocketCounter.current = data.counter; + } + } + if (data.group_name === 'jobs' && data.unified_job_id === job.id) { + if (data.final_counter) { + jobSocketCounter.current = data.final_counter; + } + if (job.status) { + setJobStatus(job.status); + } } }); interval.current = setInterval(() => monitorJobSocketCounter(), 5000); @@ -331,9 +342,25 @@ function JobOutput({ } }, [currentlyLoading, cssMap, remoteRowCount]); + const { + error: cancelError, + isLoading: isCancelling, + request: cancelJob, + } = useRequest( + useCallback(async () => { + await JobsAPI.cancel(job.id, type); + }, [job.id, type]), + {} + ); + + const { + error: dismissableCancelError, + dismissError: dismissCancelError, + } = useDismissableError(cancelError); + const { request: deleteJob, - isLoading: isDeleteLoading, + isLoading: isDeleting, error: deleteError, } = useRequest( useCallback(async () => { @@ -360,7 +387,10 @@ function JobOutput({ }, [job, history]) ); - const { error, dismissError } = useDismissableError(deleteError); + const { + error: dismissableDeleteError, + dismissError: dismissDeleteError, + } = useDismissableError(deleteError); const monitorJobSocketCounter = () => { if (jobSocketCounter.current === remoteRowCount) { @@ -702,8 +732,10 @@ function JobOutput({ setShowCancelModal(true)} onDelete={deleteJob} - isDeleteDisabled={isDeleteLoading} + isDeleteDisabled={isDeleting} /> @@ -770,15 +802,60 @@ function JobOutput({ - {error && ( + {showCancelModal && isJobRunning(job.status) && ( setShowCancelModal(false)} + title={i18n._(t`Cancel Job`)} + label={i18n._(t`Cancel Job`)} + actions={[ + , + , + ]} + > + {i18n._( + t`Are you sure you want to submit the request to cancel this job?` + )} + + )} + {dismissableDeleteError && ( + - + + + )} + {dismissableCancelError && ( + + )} diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/OutputToolbar.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/OutputToolbar.jsx index 5fa9f822f1..1e2c19129d 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/shared/OutputToolbar.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/OutputToolbar.jsx @@ -65,10 +65,10 @@ const OUTPUT_NO_COUNT_JOB_TYPES = [ const OutputToolbar = ({ i18n, job, - jobStatus, onDelete, onCancel, isDeleteDisabled, + jobStatus, }) => { const hideCounts = OUTPUT_NO_COUNT_JOB_TYPES.includes(job.type);