diff --git a/src/pages/Jobs.jsx b/src/pages/Jobs.jsx
deleted file mode 100644
index e78e62cfbd..0000000000
--- a/src/pages/Jobs.jsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React, { Component, Fragment } from 'react';
-import { withI18n } from '@lingui/react';
-import { t } from '@lingui/macro';
-import {
- PageSection,
- PageSectionVariants,
- Title,
-} from '@patternfly/react-core';
-
-class Jobs extends Component {
- render () {
- const { i18n } = this.props;
- const { light, medium } = PageSectionVariants;
-
- return (
-
-
-
- {i18n._(t`Jobs`)}
-
-
-
-
- );
- }
-}
-
-export default withI18n()(Jobs);
diff --git a/src/pages/Jobs/Job.jsx b/src/pages/Jobs/Job.jsx
new file mode 100644
index 0000000000..bdf5746a51
--- /dev/null
+++ b/src/pages/Jobs/Job.jsx
@@ -0,0 +1,139 @@
+import React, { Component } from 'react'
+import { Route, withRouter, Switch, Redirect } from 'react-router-dom';
+import { withI18n } from '@lingui/react';
+import { t } from '@lingui/macro';
+import styled from 'styled-components';
+
+import { withNetwork } from '../../contexts/Network';
+import { JobsAPI } from '../../api';
+import { Card, CardHeader as PFCardHeader, PageSection } from '@patternfly/react-core';
+import CardCloseButton from '../../components/CardCloseButton';
+import RoutedTabs from '../../components/Tabs/RoutedTabs';
+import JobDetail from './JobDetail';
+import JobOutput from './JobOutput';
+
+export class Job extends Component {
+ constructor (props) {
+ super(props);
+
+ this.state = {
+ job: null,
+ error: false,
+ loading: true
+ }
+
+ this.fetchJob = this.fetchJob.bind(this);
+ }
+
+ componentDidMount () {
+ this.fetchJob();
+ }
+
+ async componentDidUpdate (prevProps) {
+ const { location } = this.props;
+ if (location !== prevProps.location) {
+ await this.fetchJob();
+ }
+ }
+ async fetchJob () {
+ const {
+ match,
+ setBreadcrumb,
+ handleHttpError
+ } = this.props;
+
+ try {
+ const { data } = await JobsAPI.readDetail(match.params.id);
+ setBreadcrumb(data);
+ this.setState({
+ job: data,
+ loading: false
+ })
+ } catch (error) {
+ handleHttpError(error) || this.setState({ error: true, loading: false });
+ }
+ }
+
+ render() {
+ const {
+ location,
+ history,
+ match,
+ i18n
+ } = this.props;
+
+ const {
+ job,
+ error,
+ loading
+ } = this.state;
+
+ const tabsArray = [
+ { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
+ { name: i18n._(t`Output`), link: `${match.url}/output`, id: 1 }
+ ]
+
+ const CardHeader = styled(PFCardHeader)`
+ --pf-c-card--first-child--PaddingTop: 0;
+ --pf-c-card--child--PaddingLeft: 0;
+ --pf-c-card--child--PaddingRight: 0;
+ position: relative;
+ `;
+
+ const cardHeader = (
+ loading ? '' : (
+
+
+
+
+ )
+ );
+
+ return (
+
+
+ { cardHeader }
+
+
+ {job && (
+ (
+
+ )}
+ />
+ )}
+ {job && (
+ (
+
+ )}
+ />
+ )}
+
+
+
+ )
+ }
+}
+
+export default withI18n()(withNetwork(withRouter(Job)));
diff --git a/src/pages/Jobs/JobDetail/JobDetail.jsx b/src/pages/Jobs/JobDetail/JobDetail.jsx
new file mode 100644
index 0000000000..ff1fa26a95
--- /dev/null
+++ b/src/pages/Jobs/JobDetail/JobDetail.jsx
@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+import { CardBody } from '@patternfly/react-core';
+
+
+class JobDetail extends Component {
+ constructor (props) {
+ super(props);
+ }
+
+ render () {
+ const {
+ job
+ } = this.props;
+
+ return (
+
+ {job.name}
+
+ );
+ }
+}
+
+export default JobDetail;
diff --git a/src/pages/Jobs/JobDetail/index.js b/src/pages/Jobs/JobDetail/index.js
new file mode 100644
index 0000000000..a13fb1cebc
--- /dev/null
+++ b/src/pages/Jobs/JobDetail/index.js
@@ -0,0 +1,4 @@
+import JobDetail from './JobDetail';
+
+export default JobDetail;
+
diff --git a/src/pages/Jobs/JobOutput/JobOutput.jsx b/src/pages/Jobs/JobOutput/JobOutput.jsx
new file mode 100644
index 0000000000..b5087d0d51
--- /dev/null
+++ b/src/pages/Jobs/JobOutput/JobOutput.jsx
@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+import { CardBody } from '@patternfly/react-core';
+
+
+class JobOutput extends Component {
+ constructor (props) {
+ super(props);
+ }
+
+ render () {
+ const {
+ job
+ } = this.props;
+
+ return (
+
+ {job.name}
+
+ );
+ }
+}
+
+export default JobOutput;
diff --git a/src/pages/Jobs/JobOutput/index.js b/src/pages/Jobs/JobOutput/index.js
new file mode 100644
index 0000000000..8d482ce336
--- /dev/null
+++ b/src/pages/Jobs/JobOutput/index.js
@@ -0,0 +1,4 @@
+import JobOutput from './JobOutput';
+
+export default JobOutput;
+
diff --git a/src/pages/Jobs/Jobs.jsx b/src/pages/Jobs/Jobs.jsx
new file mode 100644
index 0000000000..aabb48d8c0
--- /dev/null
+++ b/src/pages/Jobs/Jobs.jsx
@@ -0,0 +1,85 @@
+import React, { Component, Fragment } from 'react';
+import { Route, withRouter, Switch } from 'react-router-dom';
+import { withI18n } from '@lingui/react';
+import { t } from '@lingui/macro';
+
+import { NetworkProvider } from '../../contexts/Network';
+import { withRootDialog } from '../../contexts/RootDialog';
+
+import Breadcrumbs from '../../components/Breadcrumbs/Breadcrumbs';
+import Job from './Job';
+
+class Jobs extends Component {
+ constructor (props) {
+ super(props);
+
+ const { i18n } = props;
+
+ this.state = {
+ breadcrumbConfig: {
+ '/jobs': i18n._(`Jobs`)
+ }
+ }
+ }
+
+ setBreadcrumbConfig = (job) => {
+ const { i18n } = this.props;
+
+ if (!job) {
+ return;
+ }
+
+ const breadcrumbConfig = {
+ '/jobs': i18n._(`Jobs`),
+ [`/jobs/${job.id}`]: `${job.name}`,
+ [`/jobs/${job.id}/details`]: i18n._(`Details`),
+ [`/jobs/${job.id}/output`]: i18n._(`Output`)
+ };
+
+ this.setState({ breadcrumbConfig });
+ }
+
+ render () {
+ const { match, history, location, setRootDialogMessage, i18n } = this.props;
+ const { breadcrumbConfig } = this.state;
+
+ return (
+
+
+
+ (
+ {
+ history.replace('/jobs');
+ setRootDialogMessage({
+ title: '404',
+ bodyText: (
+
+ {i18n._(t`Cannot find job with ID`)}
+ {` ${newRouteMatch.params.id}`}
+ .
+
+ ),
+ variant: 'warning'
+ });
+ }}
+ >
+
+
+ )}
+ />
+
+
+ );
+ }
+}
+
+export default withI18n()(withRootDialog(withRouter(Jobs)));
diff --git a/src/pages/Jobs/index.js b/src/pages/Jobs/index.js
new file mode 100644
index 0000000000..d640a4f4d9
--- /dev/null
+++ b/src/pages/Jobs/index.js
@@ -0,0 +1,3 @@
+import Jobs from "./Jobs";
+
+export default Jobs;
\ No newline at end of file