mirror of
https://github.com/ansible/awx.git
synced 2026-05-11 11:27:36 -02:30
use unified jobs api to redirect to canonical url from /jobs/:id
This commit is contained in:
@@ -15,6 +15,7 @@ import RoutedTabs from '@components/RoutedTabs';
|
|||||||
|
|
||||||
import JobDetail from './JobDetail';
|
import JobDetail from './JobDetail';
|
||||||
import JobOutput from './JobOutput';
|
import JobOutput from './JobOutput';
|
||||||
|
import { JOB_TYPE_URL_SEGMENTS } from './constants';
|
||||||
|
|
||||||
class Job extends Component {
|
class Job extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -59,9 +60,13 @@ class Job extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { history, match, i18n } = this.props;
|
const { history, match, i18n, lookup } = this.props;
|
||||||
|
|
||||||
const { job, contentError, hasContentLoading, isInitialized } = this.state;
|
const { job, contentError, hasContentLoading, isInitialized } = this.state;
|
||||||
|
let jobType;
|
||||||
|
if (job) {
|
||||||
|
jobType = JOB_TYPE_URL_SEGMENTS[job.type];
|
||||||
|
}
|
||||||
|
|
||||||
const tabsArray = [
|
const tabsArray = [
|
||||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||||
@@ -100,6 +105,19 @@ class Job extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lookup && job) {
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<Redirect from="jobs/:id" to={`/jobs/${jobType}/:id/details`} />
|
||||||
|
<Redirect
|
||||||
|
from="jobs/:id/details"
|
||||||
|
to={`/jobs/${jobType}/:id/details`}
|
||||||
|
/>
|
||||||
|
<Redirect from="jobs/:id/output" to={`/jobs/${jobType}/:id/output`} />
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Card>
|
<Card>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
import DataListCell from '@components/DataListCell';
|
import DataListCell from '@components/DataListCell';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
import VerticalSeparator from '@components/VerticalSeparator';
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
import { JOB_TYPE_URLS } from '../constants';
|
import { JOB_TYPE_URL_SEGMENTS } from '../constants';
|
||||||
|
|
||||||
class JobListItem extends Component {
|
class JobListItem extends Component {
|
||||||
render() {
|
render() {
|
||||||
@@ -32,7 +32,9 @@ class JobListItem extends Component {
|
|||||||
<DataListCell key="divider">
|
<DataListCell key="divider">
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
<span>
|
<span>
|
||||||
<Link to={`/jobs/${JOB_TYPE_URLS[job.type]}/${job.id}`}>
|
<Link
|
||||||
|
to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}
|
||||||
|
>
|
||||||
<b>{job.name}</b>
|
<b>{job.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
52
awx/ui_next/src/screens/Job/JobTypeRedirect.jsx
Normal file
52
awx/ui_next/src/screens/Job/JobTypeRedirect.jsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Redirect } from 'react-router-dom';
|
||||||
|
import { UnifiedJobsAPI } from '@api';
|
||||||
|
import { JOB_TYPE_URL_SEGMENTS } from './constants';
|
||||||
|
|
||||||
|
class JobTypeRedirect extends Component {
|
||||||
|
static defaultProps = {
|
||||||
|
view: 'details',
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
hasError: false,
|
||||||
|
job: null,
|
||||||
|
};
|
||||||
|
this.loadJob = this.loadJob.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.loadJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadJob() {
|
||||||
|
const { id } = this.props;
|
||||||
|
try {
|
||||||
|
const { data } = await UnifiedJobsAPI.read({ id });
|
||||||
|
this.setState({
|
||||||
|
job: data.results[0],
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.setState({ hasError: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { path, view } = this.props;
|
||||||
|
const { hasError, job } = this.state;
|
||||||
|
|
||||||
|
if (hasError) {
|
||||||
|
return <div>Error</div>;
|
||||||
|
}
|
||||||
|
if (!job) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
const type = JOB_TYPE_URL_SEGMENTS[job.type];
|
||||||
|
return <Redirect from={path} to={`/jobs/${type}/${job.id}/${view}`} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default JobTypeRedirect;
|
||||||
@@ -4,8 +4,9 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import Breadcrumbs from '@components/Breadcrumbs/Breadcrumbs';
|
import Breadcrumbs from '@components/Breadcrumbs/Breadcrumbs';
|
||||||
import Job from './Job';
|
import Job from './Job';
|
||||||
|
import JobTypeRedirect from './JobTypeRedirect';
|
||||||
import JobList from './JobList/JobList';
|
import JobList from './JobList/JobList';
|
||||||
import { JOB_TYPE_URLS } from './constants';
|
import { JOB_TYPE_URL_SEGMENTS } from './constants';
|
||||||
|
|
||||||
class Jobs extends Component {
|
class Jobs extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -27,7 +28,7 @@ class Jobs extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = JOB_TYPE_URLS[job.type];
|
const type = JOB_TYPE_URL_SEGMENTS[job.type];
|
||||||
const breadcrumbConfig = {
|
const breadcrumbConfig = {
|
||||||
'/jobs': i18n._(t`Jobs`),
|
'/jobs': i18n._(t`Jobs`),
|
||||||
[`/jobs/${type}/${job.id}`]: `${job.name}`,
|
[`/jobs/${type}/${job.id}`]: `${job.name}`,
|
||||||
@@ -57,6 +58,18 @@ class Jobs extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={`${match.path}/:id/details`}
|
||||||
|
render={({ match: m }) => (
|
||||||
|
<JobTypeRedirect id={m.params.id} path={m.path} view="details" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={`${match.path}/:id/output`}
|
||||||
|
render={({ match: m }) => (
|
||||||
|
<JobTypeRedirect id={m.params.id} path={m.path} view="output" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={`${match.path}/:type/:id`}
|
path={`${match.path}/:type/:id`}
|
||||||
render={() => (
|
render={() => (
|
||||||
@@ -67,6 +80,12 @@ class Jobs extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={`${match.path}/:id`}
|
||||||
|
render={({ match: m }) => (
|
||||||
|
<JobTypeRedirect id={m.params.id} path={m.path} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable-next-line import/prefer-default-export */
|
/* eslint-disable-next-line import/prefer-default-export */
|
||||||
export const JOB_TYPE_URLS = {
|
export const JOB_TYPE_URL_SEGMENTS = {
|
||||||
job: 'playbook',
|
job: 'playbook',
|
||||||
project_update: 'project',
|
project_update: 'project',
|
||||||
system_job: 'system',
|
system_job: 'system',
|
||||||
|
|||||||
@@ -377,9 +377,9 @@ exports[`<OrganizationAccessItem /> initially renders succesfully 1`] = `
|
|||||||
"componentStyle": ComponentStyle {
|
"componentStyle": ComponentStyle {
|
||||||
"componentId": "DetailList-sc-12g7m4-0",
|
"componentId": "DetailList-sc-12g7m4-0",
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"lastClassName": "hndBXy",
|
"lastClassName": "gmERnX",
|
||||||
"rules": Array [
|
"rules": Array [
|
||||||
"display:grid;grid-gap:20px;",
|
"display:grid;grid-gap:20px;align-items:baseline;",
|
||||||
[Function],
|
[Function],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -397,15 +397,15 @@ exports[`<OrganizationAccessItem /> initially renders succesfully 1`] = `
|
|||||||
stacked={true}
|
stacked={true}
|
||||||
>
|
>
|
||||||
<DetailList
|
<DetailList
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
stacked={true}
|
stacked={true}
|
||||||
>
|
>
|
||||||
<TextList
|
<TextList
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
component="dl"
|
component="dl"
|
||||||
>
|
>
|
||||||
<dl
|
<dl
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
data-pf-content={true}
|
data-pf-content={true}
|
||||||
>
|
>
|
||||||
<Detail
|
<Detail
|
||||||
@@ -545,9 +545,9 @@ exports[`<OrganizationAccessItem /> initially renders succesfully 1`] = `
|
|||||||
"componentStyle": ComponentStyle {
|
"componentStyle": ComponentStyle {
|
||||||
"componentId": "DetailList-sc-12g7m4-0",
|
"componentId": "DetailList-sc-12g7m4-0",
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"lastClassName": "hndBXy",
|
"lastClassName": "gmERnX",
|
||||||
"rules": Array [
|
"rules": Array [
|
||||||
"display:grid;grid-gap:20px;",
|
"display:grid;grid-gap:20px;align-items:baseline;",
|
||||||
[Function],
|
[Function],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -565,15 +565,15 @@ exports[`<OrganizationAccessItem /> initially renders succesfully 1`] = `
|
|||||||
stacked={true}
|
stacked={true}
|
||||||
>
|
>
|
||||||
<DetailList
|
<DetailList
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
stacked={true}
|
stacked={true}
|
||||||
>
|
>
|
||||||
<TextList
|
<TextList
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
component="dl"
|
component="dl"
|
||||||
>
|
>
|
||||||
<dl
|
<dl
|
||||||
className="DetailList-sc-12g7m4-0 hndBXy"
|
className="DetailList-sc-12g7m4-0 gmERnX"
|
||||||
data-pf-content={true}
|
data-pf-content={true}
|
||||||
>
|
>
|
||||||
<Detail
|
<Detail
|
||||||
|
|||||||
Reference in New Issue
Block a user