mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 19:10:07 -03:30
Add routing system for mgmt jobs
This commit is contained in:
parent
fe605596b5
commit
d3f2dedbd5
@ -29,6 +29,7 @@ import Root from './models/Root';
|
||||
import Schedules from './models/Schedules';
|
||||
import Settings from './models/Settings';
|
||||
import SystemJobs from './models/SystemJobs';
|
||||
import SystemJobTemplates from './models/SystemJobTemplates';
|
||||
import Teams from './models/Teams';
|
||||
import Tokens from './models/Tokens';
|
||||
import UnifiedJobTemplates from './models/UnifiedJobTemplates';
|
||||
@ -71,6 +72,7 @@ const RootAPI = new Root();
|
||||
const SchedulesAPI = new Schedules();
|
||||
const SettingsAPI = new Settings();
|
||||
const SystemJobsAPI = new SystemJobs();
|
||||
const SystemJobTemplatesAPI = new SystemJobTemplates();
|
||||
const TeamsAPI = new Teams();
|
||||
const TokensAPI = new Tokens();
|
||||
const UnifiedJobTemplatesAPI = new UnifiedJobTemplates();
|
||||
@ -114,6 +116,7 @@ export {
|
||||
SchedulesAPI,
|
||||
SettingsAPI,
|
||||
SystemJobsAPI,
|
||||
SystemJobTemplatesAPI,
|
||||
TeamsAPI,
|
||||
TokensAPI,
|
||||
UnifiedJobTemplatesAPI,
|
||||
|
||||
14
awx/ui_next/src/api/models/SystemJobTemplates.js
Normal file
14
awx/ui_next/src/api/models/SystemJobTemplates.js
Normal file
@ -0,0 +1,14 @@
|
||||
import Base from '../Base';
|
||||
|
||||
class SystemJobTemplates extends Base {
|
||||
constructor(http) {
|
||||
super(http);
|
||||
this.baseUrl = '/api/v2/system_job_templates/';
|
||||
}
|
||||
|
||||
readDetail(id) {
|
||||
return this.http.get(`${this.baseUrl}${id}/`).then(({ data }) => data);
|
||||
}
|
||||
}
|
||||
|
||||
export default SystemJobTemplates;
|
||||
147
awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx
Normal file
147
awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx
Normal file
@ -0,0 +1,147 @@
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Link,
|
||||
Redirect,
|
||||
Route,
|
||||
Switch,
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { SystemJobTemplatesAPI } from '../../api';
|
||||
|
||||
import ContentError from '../../components/ContentError';
|
||||
import ContentLoading from '../../components/ContentLoading';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import { useConfig } from '../../contexts/Config';
|
||||
import useRequest from '../../util/useRequest';
|
||||
|
||||
import ManagementJobDetails from './ManagementJobDetails';
|
||||
import ManagementJobEdit from './ManagementJobEdit';
|
||||
import ManagementJobNotifications from './ManagementJobNotifications';
|
||||
import ManagementJobSchedules from './ManagementJobSchedules';
|
||||
|
||||
function ManagementJob({ i18n, setBreadcrumb }) {
|
||||
const segment = '/management_jobs';
|
||||
|
||||
const match = useRouteMatch();
|
||||
const { id } = useParams();
|
||||
const { pathname } = useLocation();
|
||||
const { me, isNotificationAdmin } = useConfig();
|
||||
|
||||
const { isLoading, error, request, result } = useRequest(
|
||||
useCallback(async () => SystemJobTemplatesAPI.readDetail(id), [id])
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
request();
|
||||
}, [request, pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!result) return;
|
||||
|
||||
setBreadcrumb(result);
|
||||
}, [result, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
id: 99,
|
||||
link: segment,
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to management jobs`)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
link: `${segment}/${id}/details`,
|
||||
name: i18n._(t`Details`),
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: i18n._(t`Schedules`),
|
||||
link: `${match.url}/schedules`,
|
||||
},
|
||||
];
|
||||
|
||||
if (me?.is_system_auditor || isNotificationAdmin) {
|
||||
tabsArray.push({
|
||||
id: 2,
|
||||
name: i18n._(t`Notifications`),
|
||||
link: `${match.url}/notifications`,
|
||||
});
|
||||
}
|
||||
|
||||
const LoadingScreen = (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{pathname.endsWith('edit') ? null : (
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
)}
|
||||
<ContentLoading />
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
|
||||
const ErrorScreen = (
|
||||
<PageSection>
|
||||
<Card>
|
||||
<ContentError error={error}>
|
||||
{error?.response?.status === 404 && (
|
||||
<span>
|
||||
{i18n._(t`Management job not found.`)}
|
||||
{''}
|
||||
<Link to={segment}>{i18n._(t`View all management jobs`)}</Link>
|
||||
</span>
|
||||
)}
|
||||
</ContentError>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return ErrorScreen;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return LoadingScreen;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{pathname.endsWith('edit') ? null : (
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
)}
|
||||
<Switch>
|
||||
<Redirect
|
||||
exact
|
||||
from={`${segment}/:id`}
|
||||
to={`${segment}/:id/details`}
|
||||
/>
|
||||
<Route path={`${segment}/:id/details`}>
|
||||
<ManagementJobDetails managementJob={result} />
|
||||
</Route>
|
||||
<Route path={`${segment}/:id/edit`}>
|
||||
<ManagementJobEdit managementJob={result} />
|
||||
</Route>
|
||||
<Route path={`${segment}/:id/notifications`}>
|
||||
<ManagementJobNotifications managementJob={result} />
|
||||
</Route>
|
||||
<Route path={`${segment}/:id/schedules`}>
|
||||
<ManagementJobSchedules managementJob={result} />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(ManagementJob);
|
||||
@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
|
||||
import { CardBody } from '../../../components/Card';
|
||||
|
||||
function ManagementJobDetails() {
|
||||
return <CardBody>Management Job Details</CardBody>;
|
||||
}
|
||||
|
||||
export default withI18n()(ManagementJobDetails);
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ManagementJobDetails';
|
||||
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import { CardBody } from '../../../components/Card';
|
||||
|
||||
function ManagementJobEdit() {
|
||||
return <CardBody>Management Job Edit</CardBody>;
|
||||
}
|
||||
|
||||
export default ManagementJobEdit;
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ManagementJobEdit';
|
||||
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
|
||||
function ManagementJobDetails() {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>Management Job List </Card>
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(ManagementJobDetails);
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ManagementJobList';
|
||||
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import { CardBody } from '../../../components/Card';
|
||||
|
||||
function ManagementJobNotifications({ managementJob }) {
|
||||
return <CardBody>Management Job Notifications</CardBody>;
|
||||
}
|
||||
|
||||
export default ManagementJobNotifications;
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ManagementJobNotifications';
|
||||
@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
import { CardBody } from '../../../components/Card';
|
||||
import { Schedules } from '../../../components/Schedule';
|
||||
|
||||
function ManagementJobSchedules({ managementJob }) {
|
||||
return <CardBody>Management Job Schedules</CardBody>;
|
||||
}
|
||||
|
||||
export default ManagementJobSchedules;
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ManagementJobSchedules';
|
||||
@ -1,17 +1,51 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
|
||||
import ScreenHeader from '../../components/ScreenHeader';
|
||||
import ManagementJob from './ManagementJob';
|
||||
import ManagementJobList from './ManagementJobList';
|
||||
|
||||
function ManagementJobs({ i18n }) {
|
||||
const basePath = '/management_jobs';
|
||||
|
||||
const [breadcrumbConfig, setBreadcrumbConfig] = useState({
|
||||
[basePath]: i18n._(t`Management jobs`),
|
||||
});
|
||||
|
||||
const buildBreadcrumbConfig = useCallback(
|
||||
({ id, name }, nested) => {
|
||||
if (!id) return;
|
||||
|
||||
setBreadcrumbConfig({
|
||||
[basePath]: i18n._(t`Management job`),
|
||||
[`${basePath}/${id}`]: name,
|
||||
[`${basePath}/${id}/details`]: i18n._(t`Details`),
|
||||
[`${basePath}/${id}/edit`]: i18n._(t`Edit details`),
|
||||
[`${basePath}/${id}/notifications`]: i18n._(t`Notifications`),
|
||||
[`${basePath}/schedules`]: i18n._(t`Schedules`),
|
||||
[`${basePath}/schedules/add`]: i18n._(t`Create New Schedule`),
|
||||
[`${basePath}/schedules/${nested?.id}`]: `${nested?.name}`,
|
||||
[`${basePath}/schedules/${nested?.id}/details`]: i18n._(t`Details`),
|
||||
[`${basePath}/schedules/${nested?.id}/edit`]: i18n._(t`Edit Details`),
|
||||
});
|
||||
},
|
||||
[i18n]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<ScreenHeader
|
||||
streamType="none"
|
||||
breadcrumbConfig={{ '/management_jobs': i18n._(t`Management Jobs`) }}
|
||||
/>
|
||||
</Fragment>
|
||||
<>
|
||||
<ScreenHeader streamType="none" breadcrumbConfig={breadcrumbConfig} />
|
||||
<Switch>
|
||||
<Route path={`${basePath}/:id`}>
|
||||
<ManagementJob setBreadcrumb={buildBreadcrumbConfig} />
|
||||
</Route>
|
||||
<Route path={basePath}>
|
||||
<ManagementJobList setBreadcrumb={buildBreadcrumbConfig} />
|
||||
</Route>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -10,17 +10,20 @@ jest.mock('react-router-dom', () => ({
|
||||
|
||||
describe('<ManagementJobs />', () => {
|
||||
let pageWrapper;
|
||||
let pageSections;
|
||||
|
||||
beforeEach(() => {
|
||||
pageWrapper = mountWithContexts(<ManagementJobs />);
|
||||
pageSections = pageWrapper.find('PageSection');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
pageWrapper.unmount();
|
||||
});
|
||||
|
||||
test('initially renders without crashing', () => {
|
||||
test('renders ok', () => {
|
||||
expect(pageWrapper.length).toBe(1);
|
||||
expect(pageWrapper.find('ScreenHeader').length).toBe(1);
|
||||
expect(pageSections.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user