From d3f2dedbd5de538227200f72ae9509c9709ae72e Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Tue, 8 Sep 2020 13:19:20 -0400 Subject: [PATCH] Add routing system for mgmt jobs --- awx/ui_next/src/api/index.js | 3 + .../src/api/models/SystemJobTemplates.js | 14 ++ .../screens/ManagementJob/ManagementJob.jsx | 147 ++++++++++++++++++ .../ManagementJobDetails.jsx | 10 ++ .../ManagementJobDetails/index.js | 1 + .../ManagementJobEdit/ManagementJobEdit.jsx | 9 ++ .../ManagementJob/ManagementJobEdit/index.js | 1 + .../ManagementJobList/ManagementJobList.jsx | 13 ++ .../ManagementJob/ManagementJobList/index.js | 1 + .../ManagementJobNotifications.jsx | 9 ++ .../ManagementJobNotifications/index.js | 1 + .../ManagementJobSchedules.jsx | 10 ++ .../ManagementJobSchedules/index.js | 1 + .../screens/ManagementJob/ManagementJobs.jsx | 48 +++++- .../ManagementJob/ManagementJobs.test.jsx | 5 +- 15 files changed, 265 insertions(+), 8 deletions(-) create mode 100644 awx/ui_next/src/api/models/SystemJobTemplates.js create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/ManagementJobDetails.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/index.js create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/ManagementJobEdit.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/index.js create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobList/ManagementJobList.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobList/index.js create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/ManagementJobNotifications.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/index.js create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/ManagementJobSchedules.jsx create mode 100644 awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/index.js diff --git a/awx/ui_next/src/api/index.js b/awx/ui_next/src/api/index.js index cddf01e259..3160ebd907 100644 --- a/awx/ui_next/src/api/index.js +++ b/awx/ui_next/src/api/index.js @@ -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, diff --git a/awx/ui_next/src/api/models/SystemJobTemplates.js b/awx/ui_next/src/api/models/SystemJobTemplates.js new file mode 100644 index 0000000000..54712b9abe --- /dev/null +++ b/awx/ui_next/src/api/models/SystemJobTemplates.js @@ -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; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx new file mode 100644 index 0000000000..a875f95141 --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJob.jsx @@ -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: ( + <> + + {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 = ( + + + {pathname.endsWith('edit') ? null : ( + + )} + + + + ); + + const ErrorScreen = ( + + + + {error?.response?.status === 404 && ( + + {i18n._(t`Management job not found.`)} + {''} + {i18n._(t`View all management jobs`)} + + )} + + + + ); + + if (error) { + return ErrorScreen; + } + + if (isLoading) { + return LoadingScreen; + } + + return ( + + + {pathname.endsWith('edit') ? null : ( + + )} + + + + + + + + + + + + + + + + + + ); +} + +export default withI18n()(ManagementJob); diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/ManagementJobDetails.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/ManagementJobDetails.jsx new file mode 100644 index 0000000000..2ed939563a --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/ManagementJobDetails.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { withI18n } from '@lingui/react'; + +import { CardBody } from '../../../components/Card'; + +function ManagementJobDetails() { + return Management Job Details; +} + +export default withI18n()(ManagementJobDetails); diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/index.js b/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/index.js new file mode 100644 index 0000000000..bcd1ccefec --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobDetails/index.js @@ -0,0 +1 @@ +export { default } from './ManagementJobDetails'; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/ManagementJobEdit.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/ManagementJobEdit.jsx new file mode 100644 index 0000000000..9ddff5539a --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/ManagementJobEdit.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +import { CardBody } from '../../../components/Card'; + +function ManagementJobEdit() { + return Management Job Edit; +} + +export default ManagementJobEdit; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/index.js b/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/index.js new file mode 100644 index 0000000000..2924ff2c14 --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobEdit/index.js @@ -0,0 +1 @@ +export { default } from './ManagementJobEdit'; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobList/ManagementJobList.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobList/ManagementJobList.jsx new file mode 100644 index 0000000000..d1fdde1c37 --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobList/ManagementJobList.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { withI18n } from '@lingui/react'; +import { Card, PageSection } from '@patternfly/react-core'; + +function ManagementJobDetails() { + return ( + + Management Job List + + ); +} + +export default withI18n()(ManagementJobDetails); diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobList/index.js b/awx/ui_next/src/screens/ManagementJob/ManagementJobList/index.js new file mode 100644 index 0000000000..e55f0f261f --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobList/index.js @@ -0,0 +1 @@ +export { default } from './ManagementJobList'; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/ManagementJobNotifications.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/ManagementJobNotifications.jsx new file mode 100644 index 0000000000..43d8ba78c0 --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/ManagementJobNotifications.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +import { CardBody } from '../../../components/Card'; + +function ManagementJobNotifications({ managementJob }) { + return Management Job Notifications; +} + +export default ManagementJobNotifications; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/index.js b/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/index.js new file mode 100644 index 0000000000..799d7c45fb --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobNotifications/index.js @@ -0,0 +1 @@ +export { default } from './ManagementJobNotifications'; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/ManagementJobSchedules.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/ManagementJobSchedules.jsx new file mode 100644 index 0000000000..e3f48f9c57 --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/ManagementJobSchedules.jsx @@ -0,0 +1,10 @@ +import React from 'react'; + +import { CardBody } from '../../../components/Card'; +import { Schedules } from '../../../components/Schedule'; + +function ManagementJobSchedules({ managementJob }) { + return Management Job Schedules; +} + +export default ManagementJobSchedules; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/index.js b/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/index.js new file mode 100644 index 0000000000..983527b91a --- /dev/null +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobSchedules/index.js @@ -0,0 +1 @@ +export { default } from './ManagementJobSchedules'; diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobs.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobs.jsx index 94f5a077c5..8f9ff47304 100644 --- a/awx/ui_next/src/screens/ManagementJob/ManagementJobs.jsx +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobs.jsx @@ -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 ( - - - + <> + + + + + + + + + + ); } diff --git a/awx/ui_next/src/screens/ManagementJob/ManagementJobs.test.jsx b/awx/ui_next/src/screens/ManagementJob/ManagementJobs.test.jsx index df422fe8ec..04e9ed4894 100644 --- a/awx/ui_next/src/screens/ManagementJob/ManagementJobs.test.jsx +++ b/awx/ui_next/src/screens/ManagementJob/ManagementJobs.test.jsx @@ -10,17 +10,20 @@ jest.mock('react-router-dom', () => ({ describe('', () => { let pageWrapper; + let pageSections; beforeEach(() => { pageWrapper = mountWithContexts(); + 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); }); });