Add routing system for mgmt jobs

This commit is contained in:
Jake McDermott 2020-09-08 13:19:20 -04:00
parent fe605596b5
commit d3f2dedbd5
No known key found for this signature in database
GPG Key ID: 0E56ED990CDFCB4F
15 changed files with 265 additions and 8 deletions

View File

@ -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,

View 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;

View 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);

View File

@ -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);

View File

@ -0,0 +1 @@
export { default } from './ManagementJobDetails';

View File

@ -0,0 +1,9 @@
import React from 'react';
import { CardBody } from '../../../components/Card';
function ManagementJobEdit() {
return <CardBody>Management Job Edit</CardBody>;
}
export default ManagementJobEdit;

View File

@ -0,0 +1 @@
export { default } from './ManagementJobEdit';

View File

@ -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);

View File

@ -0,0 +1 @@
export { default } from './ManagementJobList';

View File

@ -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;

View File

@ -0,0 +1 @@
export { default } from './ManagementJobNotifications';

View File

@ -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;

View File

@ -0,0 +1 @@
export { default } from './ManagementJobSchedules';

View File

@ -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>
</>
);
}

View File

@ -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);
});
});