diff --git a/awx/ui_next/src/screens/Job/Job.jsx b/awx/ui_next/src/screens/Job/Job.jsx
index 9530c4eeb3..48e4f1d4fa 100644
--- a/awx/ui_next/src/screens/Job/Job.jsx
+++ b/awx/ui_next/src/screens/Job/Job.jsx
@@ -1,5 +1,13 @@
-import React, { Component } from 'react';
-import { Route, withRouter, Switch, Redirect, Link } from 'react-router-dom';
+import React, { useEffect, useCallback } from 'react';
+import {
+ Route,
+ withRouter,
+ Switch,
+ Redirect,
+ Link,
+ useParams,
+ useRouteMatch,
+} from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { CaretLeftIcon } from '@patternfly/react-icons';
@@ -7,157 +15,114 @@ import { Card, PageSection } from '@patternfly/react-core';
import { JobsAPI } from '../../api';
import ContentError from '../../components/ContentError';
import RoutedTabs from '../../components/RoutedTabs';
+import useRequest from '../../util/useRequest';
import JobDetail from './JobDetail';
import JobOutput from './JobOutput';
+import WorkflowDetail from './WorkflowDetail';
import { WorkflowOutput } from './WorkflowOutput';
import { JOB_TYPE_URL_SEGMENTS } from '../../constants';
-class Job extends Component {
- constructor(props) {
- super(props);
+function Job({ i18n, lookup, setBreadcrumb }) {
+ const { id, type } = useParams();
+ const match = useRouteMatch();
- this.state = {
- job: null,
- contentError: null,
- hasContentLoading: true,
- isInitialized: false,
- };
-
- this.loadJob = this.loadJob.bind(this);
- }
-
- async componentDidMount() {
- await this.loadJob();
- this.setState({ isInitialized: true });
- }
-
- async componentDidUpdate(prevProps) {
- const { location } = this.props;
- if (location !== prevProps.location) {
- await this.loadJob();
- }
- }
-
- async loadJob() {
- const { match, setBreadcrumb } = this.props;
- const id = parseInt(match.params.id, 10);
-
- this.setState({ contentError: null, hasContentLoading: true });
- try {
- const { data } = await JobsAPI.readDetail(id, match.params.type);
+ const { isLoading, error, request: fetchJob, result: job } = useRequest(
+ useCallback(async () => {
+ const { data } = await JobsAPI.readDetail(id, type);
setBreadcrumb(data);
- this.setState({ job: data });
- } catch (err) {
- this.setState({ contentError: err });
- } finally {
- this.setState({ hasContentLoading: false });
- }
+ return data;
+ }, [id, type, setBreadcrumb]),
+ null
+ );
+
+ useEffect(() => {
+ fetchJob();
+ }, [fetchJob]);
+
+ let jobType;
+ if (job) {
+ jobType = JOB_TYPE_URL_SEGMENTS[job.type];
}
- render() {
- const { match, i18n, lookup } = this.props;
-
- const { job, contentError, hasContentLoading, isInitialized } = this.state;
- let jobType;
- if (job) {
- jobType = JOB_TYPE_URL_SEGMENTS[job.type];
- }
-
- const tabsArray = [
- {
- name: (
- <>
-
- {i18n._(t`Back to Jobs`)}
- >
- ),
- link: `/jobs`,
- id: 99,
- },
- { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
- { name: i18n._(t`Output`), link: `${match.url}/output`, id: 1 },
- ];
-
- let showCardHeader = true;
-
- if (!isInitialized) {
- showCardHeader = false;
- }
-
- if (!hasContentLoading && contentError) {
- return (
-
-
-
- {contentError.response.status === 404 && (
-
- {i18n._(t`The page you requested could not be found.`)}{' '}
- {i18n._(t`View all Jobs.`)}
-
- )}
-
-
-
- );
- }
-
- if (lookup && job) {
- return (
-
-
-
-
-
- );
- }
+const tabsArray = [
+ {
+ name: (
+ <>
+
+ {i18n._(t`Back to Jobs`)}
+ >
+ ),
+ link: `/jobs`,
+ id: 99,
+ },
+ { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
+ { name: i18n._(t`Output`), link: `${match.url}/output`, id: 1 },
+ ];
+ if (!isLoading && error) {
return (
- {showCardHeader && }
-
-
- {job &&
- job.type === 'workflow_job' && [
-
-
- ,
-
-
- ,
- ]}
- {job &&
- job.type !== 'workflow_job' && [
-
-
- ,
-
-
- ,
-
- {!hasContentLoading && (
-
-
- {i18n._(t`View Job Details`)}
-
-
- )}
- ,
- ]}
-
+
+ {error.response.status === 404 && (
+
+ {i18n._(t`The page you requested could not be found.`)}{' '}
+ {i18n._(t`View all Jobs.`)}
+
+ )}
+
);
}
+
+ if (lookup && job) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+ {!isLoading && }
+
+
+ {job &&
+ job.type === 'workflow_job' && [
+
+
+ ,
+
+
+ ,
+ ]}
+ {job &&
+ job.type !== 'workflow_job' && [
+
+
+ ,
+
+
+ ,
+
+ {!isLoading && (
+
+
+ {i18n._(t`View Job Details`)}
+
+
+ )}
+ ,
+ ]}
+
+
+
+ );
}
export default withI18n()(withRouter(Job));