Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 44 additions & 40 deletions awx/ui/src/components/Schedule/Schedule.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useEffect, useCallback } from 'react';
import { useLingui } from '@lingui/react/macro';

import { Link } from 'react-router-dom';
import {
Switch,
Routes,
Route,
Link,
Redirect,
Navigate,
useLocation,
useParams,
} from 'react-router-dom';
} from 'react-router-dom-v5-compat';
import { CaretLeftIcon } from '@patternfly/react-icons';
import { SchedulesAPI } from 'api';
import useRequest from 'hooks/useRequest';
Expand All @@ -31,7 +31,7 @@ function Schedule({

const { pathname } = useLocation();

const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
const pathRoot = pathname.substring(0, pathname.indexOf('schedules'));

const {
isLoading,
Expand Down Expand Up @@ -120,42 +120,46 @@ function Schedule({
return (
<>
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
<Switch>
<Redirect
from={`${pathRoot}schedules/:scheduleId`}
to={`${pathRoot}schedules/:scheduleId/details`}
exact
/>
{schedule && [
<Route key="edit" path={`${pathRoot}schedules/:id/edit`}>
<ScheduleEdit
hasDaysToKeepField={hasDaysToKeepField}
schedule={schedule}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
</Route>,
<Routes>
<Route index element={<Navigate to="details" replace />} />
{schedule && (
<Route
key="details"
path={`${pathRoot}schedules/:scheduleId/details`}
>
<ScheduleDetail
hasDaysToKeepField={hasDaysToKeepField}
schedule={schedule}
surveyConfig={surveyConfig}
/>
</Route>,
]}
<Route key="not-found" path="*">
<ContentError>
{resource && (
<Link to={`${pathRoot}details`}>{t`View Details`}</Link>
)}
</ContentError>
</Route>
</Switch>
path="edit"
element={
<ScheduleEdit
hasDaysToKeepField={hasDaysToKeepField}
schedule={schedule}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
}
/>
)}
{schedule && (
<Route
path="details"
element={
<ScheduleDetail
hasDaysToKeepField={hasDaysToKeepField}
schedule={schedule}
surveyConfig={surveyConfig}
/>
}
/>
)}
<Route
path="*"
element={
<ContentError>
{resource && (
<Link to={`${pathRoot}details`}>{t`View Details`}</Link>
)}
</ContentError>
}
/>
</Routes>
</>
);
}
Expand Down
78 changes: 45 additions & 33 deletions awx/ui/src/components/Schedule/Schedules.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Switch, Route, useRouteMatch } from 'react-router-dom';
import { Routes, Route } from 'react-router-dom-v5-compat';

import Schedule from './Schedule';
import ScheduleAdd from './ScheduleAdd';
Expand All @@ -15,7 +15,9 @@ function Schedules({
resource,
resourceDefaultCredentials,
}) {
const match = useRouteMatch();
// This component is mounted under a ".../schedules/*" route on several
// screens (templates, projects, inventory sources, management jobs), so its
// routes are relative to that parent and resolve under any of them.

// For some management jobs that delete data, we want to provide an additional
// field on the scheduler for configuring the number of days to retain.
Expand All @@ -26,37 +28,47 @@ function Schedules({
].includes(resource?.job_type);

return (
<Switch>
<Route path={`${match.path}/add`}>
<ScheduleAdd
hasDaysToKeepField={hasDaysToKeepField}
apiModel={apiModel}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
</Route>
<Route key="details" path={`${match.path}/:scheduleId`}>
<Schedule
hasDaysToKeepField={hasDaysToKeepField}
setBreadcrumb={setBreadcrumb}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
</Route>
<Route key="list" path={`${match.path}`}>
<ScheduleList
resource={resource}
loadSchedules={loadSchedules}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
loadScheduleOptions={loadScheduleOptions}
/>
</Route>
</Switch>
<Routes>
<Route
path="add"
element={
<ScheduleAdd
hasDaysToKeepField={hasDaysToKeepField}
apiModel={apiModel}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
}
/>
{/* so the nested <Schedule> route tree can match */}
<Route
path=":scheduleId/*"
element={
<Schedule
hasDaysToKeepField={hasDaysToKeepField}
setBreadcrumb={setBreadcrumb}
resource={resource}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
resourceDefaultCredentials={resourceDefaultCredentials}
/>
}
/>
<Route
index
element={
<ScheduleList
resource={resource}
loadSchedules={loadSchedules}
launchConfig={launchConfig}
surveyConfig={surveyConfig}
loadScheduleOptions={loadScheduleOptions}
/>
}
/>
</Routes>
);
}

Expand Down
31 changes: 18 additions & 13 deletions awx/ui/src/components/Schedule/Schedules.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history';
import { Routes, Route } from 'react-router-dom-v5-compat';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Schedules from './Schedules';

Expand All @@ -12,21 +13,25 @@ describe('<Schedules />', () => {
});
const jobTemplate = { id: 1, name: 'Mock JT' };

// Schedules uses relative routes, so mount it under its ".../schedules/*"
// parent route.
await act(async () => {
wrapper = mountWithContexts(
<Schedules
setBreadcrumb={() => {}}
jobTemplate={jobTemplate}
loadSchedules={() => {}}
loadScheduleOptions={() => {}}
apiModel={{ createSchedule: () => {} }}
/>,

{
context: {
router: { history, route: { location: history.location } },
},
}
<Routes>
<Route
path="/templates/job_template/:id/schedules/*"
element={
<Schedules
setBreadcrumb={() => {}}
jobTemplate={jobTemplate}
loadSchedules={() => {}}
loadScheduleOptions={() => {}}
apiModel={{ createSchedule: () => {} }}
/>
}
/>
</Routes>,
{ context: { router: { history } } }
);
});
expect(wrapper.length).toBe(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React, { useEffect, useCallback } from 'react';

import { useLingui } from '@lingui/react/macro';
import { Link, Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
import { Link } from 'react-router-dom';
import {
Routes,
Route,
Navigate,
useParams,
} from 'react-router-dom-v5-compat';
import { CaretLeftIcon } from '@patternfly/react-icons';
import ContentError from 'components/ContentError';
import ContentLoading from 'components/ContentLoading';
Expand All @@ -12,9 +18,8 @@ import AdvancedInventoryHostDetail from '../AdvancedInventoryHostDetail';

function AdvancedInventoryHost({ inventory, setBreadcrumb }) {
const { t } = useLingui();
const { params, path, url } = useRouteMatch(
'/inventories/:inventoryType/:id/hosts/:hostId'
);
const { inventoryType, hostId } = useParams();
const hostBaseUrl = `/inventories/${inventoryType}/${inventory.id}/hosts/${hostId}`;

const {
result: host,
Expand All @@ -25,10 +30,10 @@ function AdvancedInventoryHost({ inventory, setBreadcrumb }) {
useCallback(async () => {
const response = await InventoriesAPI.readHostDetail(
inventory.id,
params.hostId
hostId
);
return response;
}, [inventory.id, params.hostId]),
}, [inventory.id, hostId]),
{ isLoading: true }
);

Expand All @@ -53,12 +58,12 @@ function AdvancedInventoryHost({ inventory, setBreadcrumb }) {
{t`Back to Hosts`}
</>
),
link: `/inventories/${params.inventoryType}/${inventory.id}/hosts`,
link: `/inventories/${inventoryType}/${inventory.id}/hosts`,
id: 0,
},
{
name: t`Details`,
link: `${url}/details`,
link: `${hostBaseUrl}/details`,
id: 1,
},
];
Expand All @@ -70,25 +75,28 @@ function AdvancedInventoryHost({ inventory, setBreadcrumb }) {
{isLoading && <ContentLoading />}

{!isLoading && host && (
<Switch>
<Redirect
from="/inventories/:inventoryType/:id/hosts/:hostId"
to={`${path}/details`}
exact
<Routes>
<Route
index
element={<Navigate to={`${hostBaseUrl}/details`} replace />}
/>
<Route
path="details"
element={<AdvancedInventoryHostDetail host={host} />}
/>
<Route
path="*"
element={
<ContentError isNotFound>
<Link to={`${hostBaseUrl}/details`}>
{inventoryType === 'smart_inventory'
? t`View smart inventory host details`
: t`View constructed inventory host details`}
</Link>
</ContentError>
}
/>
<Route key="details" path={`${path}/details`}>
<AdvancedInventoryHostDetail host={host} />
</Route>
<Route key="not-found" path="*">
<ContentError isNotFound>
<Link to={`${url}/details`}>
{params.inventoryType === 'smart_inventory'
? t`View smart inventory host details`
: t`View constructed inventory host details`}
</Link>
</ContentError>
</Route>
</Switch>
</Routes>
)}
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Link, useParams } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { useParams } from 'react-router-dom-v5-compat';
import { useLingui } from '@lingui/react/macro';
import { Host } from 'types';
import { CardBody } from 'components/Card';
Expand Down
Loading