mirror of
https://github.com/ansible/awx.git
synced 2026-01-22 15:08:03 -03:30
Makes entire hierarchy of schedule components generic
This commit is contained in:
parent
01fe89e43c
commit
90e047821d
@ -20,19 +20,21 @@ import { TabbedCardHeader } from '@components/Card';
|
||||
import { ScheduleDetail } from '@components/Schedule';
|
||||
import { SchedulesAPI } from '@api';
|
||||
|
||||
function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
const [jobTemplateSchedule, setJobTemplateSchedule] = useState(null);
|
||||
function Schedule({ i18n, setBreadcrumb, unifiedJobTemplate }) {
|
||||
const [schedule, setSchedule] = useState(null);
|
||||
const [contentLoading, setContentLoading] = useState(true);
|
||||
const [contentError, setContentError] = useState(null);
|
||||
const { id: jobTemplateId, scheduleId } = useParams();
|
||||
const { scheduleId } = useParams();
|
||||
const location = useLocation();
|
||||
const { pathname } = location;
|
||||
const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
const { data } = await SchedulesAPI.readDetail(scheduleId);
|
||||
setJobTemplateSchedule(data);
|
||||
setBreadcrumb(jobTemplate, data);
|
||||
setSchedule(data);
|
||||
setBreadcrumb(unifiedJobTemplate, data);
|
||||
} catch (err) {
|
||||
setContentError(err);
|
||||
} finally {
|
||||
@ -41,7 +43,7 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
};
|
||||
|
||||
loadData();
|
||||
}, [location.pathname, scheduleId, jobTemplate, setBreadcrumb]);
|
||||
}, [location.pathname, scheduleId, unifiedJobTemplate, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
@ -51,14 +53,12 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
{i18n._(t`Back to Schedules`)}
|
||||
</>
|
||||
),
|
||||
link: `/templates/job_template/${jobTemplate.id}/schedules`,
|
||||
link: `${pathRoot}schedules`,
|
||||
id: 99,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Details`),
|
||||
link: `/templates/job_template/${
|
||||
jobTemplate.id
|
||||
}/schedules/${jobTemplateSchedule && jobTemplateSchedule.id}/details`,
|
||||
link: `${pathRoot}schedules/${schedule && schedule.id}/details`,
|
||||
id: 0,
|
||||
},
|
||||
];
|
||||
@ -68,15 +68,13 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
}
|
||||
|
||||
if (
|
||||
jobTemplateSchedule.summary_fields.unified_job_template.id !==
|
||||
parseInt(jobTemplateId, 10)
|
||||
schedule.summary_fields.unified_job_template.id !==
|
||||
parseInt(unifiedJobTemplate.id, 10)
|
||||
) {
|
||||
return (
|
||||
<ContentError>
|
||||
{jobTemplateSchedule && (
|
||||
<Link to={`/templates/job_template/${jobTemplate.id}/schedules`}>
|
||||
{i18n._(t`View Template Schedules`)}
|
||||
</Link>
|
||||
{schedule && (
|
||||
<Link to={`${pathRoot}schedules`}>{i18n._(t`View Schedules`)}</Link>
|
||||
)}
|
||||
</ContentError>
|
||||
);
|
||||
@ -95,9 +93,7 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton
|
||||
linkTo={`/templates/job_template/${jobTemplate.id}/schedules`}
|
||||
/>
|
||||
<CardCloseButton linkTo={`${pathRoot}schedules`} />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
@ -107,16 +103,16 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
{cardHeader}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/templates/job_template/:id/schedules/:scheduleId"
|
||||
to="/templates/job_template/:id/schedules/:scheduleId/details"
|
||||
from={`${pathRoot}schedules/:scheduleId`}
|
||||
to={`${pathRoot}schedules/:scheduleId/details`}
|
||||
exact
|
||||
/>
|
||||
{jobTemplateSchedule && [
|
||||
{schedule && [
|
||||
<Route
|
||||
key="details"
|
||||
path="/templates/job_template/:id/schedules/:scheduleId/details"
|
||||
path={`${pathRoot}schedules/:scheduleId/details`}
|
||||
render={() => {
|
||||
return <ScheduleDetail schedule={jobTemplateSchedule} />;
|
||||
return <ScheduleDetail schedule={schedule} />;
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
@ -126,11 +122,9 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
render={() => {
|
||||
return (
|
||||
<ContentError>
|
||||
{jobTemplate && (
|
||||
<Link
|
||||
to={`/templates/job_template/${jobTemplate.id}/details`}
|
||||
>
|
||||
{i18n._(t`View Template Details`)}
|
||||
{unifiedJobTemplate && (
|
||||
<Link to={`${pathRoot}details`}>
|
||||
{i18n._(t`View Details`)}
|
||||
</Link>
|
||||
)}
|
||||
</ContentError>
|
||||
@ -142,5 +136,5 @@ function JobTemplateSchedule({ i18n, setBreadcrumb, jobTemplate }) {
|
||||
);
|
||||
}
|
||||
|
||||
export { JobTemplateSchedule as _JobTemplateSchedule };
|
||||
export default withI18n()(JobTemplateSchedule);
|
||||
export { Schedule as _Schedule };
|
||||
export default withI18n()(Schedule);
|
||||
@ -4,8 +4,7 @@ import { Route } from 'react-router-dom';
|
||||
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
|
||||
import JobTemplateSchedule from './JobTemplateSchedule';
|
||||
import Schedule from './Schedule';
|
||||
|
||||
jest.mock('@api/models/Schedules');
|
||||
|
||||
@ -60,10 +59,10 @@ SchedulesAPI.readCredentials.mockResolvedValue({
|
||||
},
|
||||
});
|
||||
|
||||
describe('<JobTemplateSchedule />', () => {
|
||||
describe('<Schedule />', () => {
|
||||
let wrapper;
|
||||
let history;
|
||||
const jobTemplate = { id: 1, name: 'Mock JT' };
|
||||
const unifiedJobTemplate = { id: 1, name: 'Mock JT' };
|
||||
beforeAll(async () => {
|
||||
history = createMemoryHistory({
|
||||
initialEntries: ['/templates/job_template/1/schedules/1/details'],
|
||||
@ -73,9 +72,9 @@ describe('<JobTemplateSchedule />', () => {
|
||||
<Route
|
||||
path="/templates/job_template/:id/schedules"
|
||||
component={() => (
|
||||
<JobTemplateSchedule
|
||||
<Schedule
|
||||
setBreadcrumb={() => {}}
|
||||
jobTemplate={jobTemplate}
|
||||
unifiedJobTemplate={unifiedJobTemplate}
|
||||
/>
|
||||
)}
|
||||
/>,
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ScheduleDetail';
|
||||
@ -7,13 +7,13 @@ import { SchedulesAPI } from '@api';
|
||||
import AlertModal from '@components/AlertModal';
|
||||
import ErrorDetail from '@components/ErrorDetail';
|
||||
import DataListToolbar from '@components/DataListToolbar';
|
||||
import { ScheduleListItem } from '@components/Schedule';
|
||||
import PaginatedDataList, {
|
||||
ToolbarAddButton,
|
||||
ToolbarDeleteButton,
|
||||
} from '@components/PaginatedDataList';
|
||||
import useRequest, { useDeleteItems } from '@util/useRequest';
|
||||
import { getQSConfig, parseQueryString } from '@util/qs';
|
||||
import ScheduleListItem from './ScheduleListItem';
|
||||
|
||||
const QS_CONFIG = getQSConfig('schedule', {
|
||||
page: 1,
|
||||
@ -2,8 +2,8 @@ import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
import { SchedulesAPI } from '@api';
|
||||
import { ScheduleList } from '@components/Schedule';
|
||||
import mockSchedules from './data.schedules.json';
|
||||
import ScheduleList from './ScheduleList';
|
||||
import mockSchedules from '../data.schedules.json';
|
||||
|
||||
jest.mock('@api/models/Schedules');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
import { ScheduleListItem } from '@components/Schedule';
|
||||
import ScheduleListItem from './ScheduleListItem';
|
||||
|
||||
const mockSchedule = {
|
||||
rrule:
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ScheduleList';
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ScheduleOccurrences';
|
||||
@ -0,0 +1 @@
|
||||
export { default } from './ScheduleToggle';
|
||||
33
awx/ui_next/src/components/Schedule/Schedules.jsx
Normal file
33
awx/ui_next/src/components/Schedule/Schedules.jsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Switch, Route, useRouteMatch } from 'react-router-dom';
|
||||
import { Schedule, ScheduleList } from '@components/Schedule';
|
||||
|
||||
function Schedules({ setBreadcrumb, unifiedJobTemplate, loadSchedules }) {
|
||||
const match = useRouteMatch();
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
key="details"
|
||||
path={`${match.path}/:scheduleId`}
|
||||
render={() => (
|
||||
<Schedule
|
||||
unifiedJobTemplate={unifiedJobTemplate}
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
key="list"
|
||||
path={`${match.path}`}
|
||||
render={() => {
|
||||
return <ScheduleList loadSchedules={loadSchedules} />;
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
export { Schedules as _Schedules };
|
||||
export default withI18n()(Schedules);
|
||||
@ -2,9 +2,9 @@ import React from 'react';
|
||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import JobTemplateSchedules from './JobTemplateSchedules';
|
||||
import Schedules from './Schedules';
|
||||
|
||||
describe('<JobTemplateSchedules />', () => {
|
||||
describe('<Schedules />', () => {
|
||||
test('initially renders successfully', async () => {
|
||||
let wrapper;
|
||||
const history = createMemoryHistory({
|
||||
@ -14,10 +14,7 @@ describe('<JobTemplateSchedules />', () => {
|
||||
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<JobTemplateSchedules
|
||||
setBreadcrumb={() => {}}
|
||||
jobTemplate={jobTemplate}
|
||||
/>,
|
||||
<Schedules setBreadcrumb={() => {}} jobTemplate={jobTemplate} />,
|
||||
|
||||
{
|
||||
context: {
|
||||
@ -1,5 +1,6 @@
|
||||
export { default as Schedule } from './Schedule';
|
||||
export { default as Schedules } from './Schedules';
|
||||
export { default as ScheduleList } from './ScheduleList';
|
||||
export { default as ScheduleListItem } from './ScheduleListItem';
|
||||
export { default as ScheduleOccurrences } from './ScheduleOccurrences';
|
||||
export { default as ScheduleToggle } from './ScheduleToggle';
|
||||
export { default as ScheduleDetail } from './ScheduleDetail';
|
||||
|
||||
@ -9,7 +9,7 @@ import RoutedTabs from '@components/RoutedTabs';
|
||||
import ContentError from '@components/ContentError';
|
||||
import NotificationList from '@components/NotificationList';
|
||||
import { ResourceAccessList } from '@components/ResourceAccessList';
|
||||
import { ScheduleList } from '@components/Schedule';
|
||||
import { Schedules } from '@components/Schedule';
|
||||
import ProjectDetail from './ProjectDetail';
|
||||
import ProjectEdit from './ProjectEdit';
|
||||
import ProjectJobTemplatesList from './ProjectJobTemplatesList';
|
||||
@ -116,7 +116,7 @@ class Project extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { location, match, me, i18n } = this.props;
|
||||
const { location, match, me, i18n, setBreadcrumb } = this.props;
|
||||
|
||||
const {
|
||||
project,
|
||||
@ -175,7 +175,10 @@ class Project extends Component {
|
||||
cardHeader = null;
|
||||
}
|
||||
|
||||
if (location.pathname.endsWith('edit')) {
|
||||
if (
|
||||
location.pathname.endsWith('edit') ||
|
||||
location.pathname.includes('schedules/')
|
||||
) {
|
||||
cardHeader = null;
|
||||
}
|
||||
|
||||
@ -247,7 +250,9 @@ class Project extends Component {
|
||||
<Route
|
||||
path="/projects/:id/schedules"
|
||||
render={() => (
|
||||
<ScheduleList
|
||||
<Schedules
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
unifiedJobTemplate={project}
|
||||
loadSchedules={this.loadSchedules}
|
||||
loadScheduleOptions={this.loadScheduleOptions}
|
||||
/>
|
||||
|
||||
@ -8,7 +8,7 @@ import { ScheduleList } from '@components/Schedule';
|
||||
import { SchedulesAPI } from '@api';
|
||||
import { PageSection, Card } from '@patternfly/react-core';
|
||||
|
||||
function Schedules({ i18n }) {
|
||||
function AllSchedules({ i18n }) {
|
||||
const loadScheduleOptions = () => {
|
||||
return SchedulesAPI.readOptions();
|
||||
};
|
||||
@ -41,4 +41,4 @@ function Schedules({ i18n }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(Schedules);
|
||||
export default withI18n()(AllSchedules);
|
||||
@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import Schedules from './Schedules';
|
||||
import AllSchedules from './AllSchedules';
|
||||
|
||||
describe('<Schedules />', () => {
|
||||
describe('<AllSchedules />', () => {
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
@ -11,7 +11,7 @@ describe('<Schedules />', () => {
|
||||
});
|
||||
|
||||
test('initially renders succesfully', () => {
|
||||
wrapper = mountWithContexts(<Schedules />);
|
||||
wrapper = mountWithContexts(<AllSchedules />);
|
||||
});
|
||||
|
||||
test('should display schedule list breadcrumb heading', () => {
|
||||
@ -19,7 +19,7 @@ describe('<Schedules />', () => {
|
||||
initialEntries: ['/schedules'],
|
||||
});
|
||||
|
||||
wrapper = mountWithContexts(<Schedules />, {
|
||||
wrapper = mountWithContexts(<AllSchedules />, {
|
||||
context: {
|
||||
router: {
|
||||
history,
|
||||
@ -1 +1 @@
|
||||
export { default } from './Schedules';
|
||||
export { default } from './AllSchedules';
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export { default } from './JobTemplateSchedule';
|
||||
@ -1,26 +0,0 @@
|
||||
import React from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
|
||||
import { Switch, Route, withRouter } from 'react-router-dom';
|
||||
|
||||
import JobTemplateSchedule from '../JobTemplateSchedule/JobTemplateSchedule';
|
||||
|
||||
function JobTemplateSchedules({ setBreadcrumb, jobTemplate }) {
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
key="details"
|
||||
path="/templates/job_template/:id/schedules/:scheduleId/"
|
||||
render={() => (
|
||||
<JobTemplateSchedule
|
||||
jobTemplate={jobTemplate}
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
export { JobTemplateSchedules as _JobTemplateSchedules };
|
||||
export default withI18n()(withRouter(JobTemplateSchedules));
|
||||
@ -1 +0,0 @@
|
||||
export { default } from './JobTemplateSchedules';
|
||||
@ -10,11 +10,10 @@ import ContentError from '@components/ContentError';
|
||||
import JobList from '@components/JobList';
|
||||
import NotificationList from '@components/NotificationList';
|
||||
import RoutedTabs from '@components/RoutedTabs';
|
||||
import { ScheduleList } from '@components/Schedule';
|
||||
import { Schedules } from '@components/Schedule';
|
||||
import { ResourceAccessList } from '@components/ResourceAccessList';
|
||||
import JobTemplateDetail from './JobTemplateDetail';
|
||||
import JobTemplateEdit from './JobTemplateEdit';
|
||||
import JobTemplateSchedules from './JobTemplateSchedules';
|
||||
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
||||
import SurveyList from './shared/SurveyList';
|
||||
|
||||
@ -221,12 +220,14 @@ class Template extends Component {
|
||||
)}
|
||||
{template && (
|
||||
<Route
|
||||
key="groups"
|
||||
key="schedules"
|
||||
path="/templates/:templateType/:id/schedules"
|
||||
render={() => (
|
||||
<JobTemplateSchedules
|
||||
<Schedules
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
jobTemplate={template}
|
||||
unifiedJobTemplate={template}
|
||||
loadSchedules={this.loadSchedules}
|
||||
loadScheduleOptions={this.loadScheduleOptions}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@ -248,17 +249,6 @@ class Template extends Component {
|
||||
<JobList defaultParams={{ job__job_template: template.id }} />
|
||||
</Route>
|
||||
)}
|
||||
{template && (
|
||||
<Route
|
||||
path="/templates/:templateType/:id/schedules"
|
||||
render={() => (
|
||||
<ScheduleList
|
||||
loadSchedules={this.loadSchedules}
|
||||
loadScheduleOptions={this.loadScheduleOptions}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{template && (
|
||||
<Route
|
||||
path="/templates/:templateType/:id/survey"
|
||||
|
||||
@ -58,10 +58,11 @@ describe('<Template />', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<Template setBreadcrumb={() => {}} me={mockMe} />
|
||||
);
|
||||
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 7
|
||||
el => el.length === 6
|
||||
);
|
||||
expect(tabs.at(2).text()).toEqual('Notifications');
|
||||
done();
|
||||
|
||||
@ -10,7 +10,7 @@ import ContentError from '@components/ContentError';
|
||||
import FullPage from '@components/FullPage';
|
||||
import JobList from '@components/JobList';
|
||||
import RoutedTabs from '@components/RoutedTabs';
|
||||
import { ScheduleList } from '@components/Schedule';
|
||||
import { Schedules } from '@components/Schedule';
|
||||
import ContentLoading from '@components/ContentLoading';
|
||||
import { WorkflowJobTemplatesAPI, CredentialsAPI } from '@api';
|
||||
import WorkflowJobTemplateDetail from './WorkflowJobTemplateDetail';
|
||||
@ -88,7 +88,7 @@ class WorkflowJobTemplate extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { i18n, location, match } = this.props;
|
||||
const { i18n, location, match, setBreadcrumb } = this.props;
|
||||
const {
|
||||
contentError,
|
||||
hasContentLoading,
|
||||
@ -152,7 +152,10 @@ class WorkflowJobTemplate extends Component {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{location.pathname.endsWith('edit') ? null : cardHeader}
|
||||
{location.pathname.endsWith('edit') ||
|
||||
location.pathname.includes('schedules/')
|
||||
? null
|
||||
: cardHeader}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/templates/workflow_job_template/:id"
|
||||
@ -207,9 +210,11 @@ class WorkflowJobTemplate extends Component {
|
||||
)}
|
||||
{template?.id && (
|
||||
<Route
|
||||
path="/templates/:templateType/:id/schedules"
|
||||
path="/templates/workflow_job_template/:id/schedules"
|
||||
render={() => (
|
||||
<ScheduleList
|
||||
<Schedules
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
unifiedJobTemplate={template}
|
||||
loadSchedules={this.loadSchedules}
|
||||
loadScheduleOptions={this.loadScheduleOptions}
|
||||
/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user