mirror of
https://github.com/ansible/awx.git
synced 2026-05-24 09:07:45 -02:30
Update breadcrumb and fetch new hosts when url changes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Card, CardHeader, PageSection } from '@patternfly/react-core';
|
||||
@@ -16,54 +16,26 @@ import InventorySources from './InventorySources';
|
||||
import { InventoriesAPI } from '@api';
|
||||
import InventoryEdit from './InventoryEdit';
|
||||
|
||||
class Inventory extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
function Inventory({ history, i18n, location, match, setBreadcrumb }) {
|
||||
const [contentError, setContentError] = useState(null);
|
||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||
const [inventory, setInventory] = useState(null);
|
||||
|
||||
this.state = {
|
||||
contentError: null,
|
||||
hasContentLoading: true,
|
||||
inventory: null,
|
||||
};
|
||||
this.loadInventory = this.loadInventory.bind(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
await this.loadInventory();
|
||||
}
|
||||
|
||||
async componentDidUpdate(prevProps) {
|
||||
const { location, match } = this.props;
|
||||
const url = `/inventories/inventory/${match.params.id}/`;
|
||||
|
||||
if (
|
||||
prevProps.location.pathname.startsWith(url) &&
|
||||
prevProps.location !== location &&
|
||||
location.pathname === `${url}details`
|
||||
) {
|
||||
await this.loadInventory();
|
||||
}
|
||||
}
|
||||
|
||||
async loadInventory() {
|
||||
const { setBreadcrumb, match } = this.props;
|
||||
const { id } = match.params;
|
||||
|
||||
this.setState({ contentError: null, hasContentLoading: true });
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
try {
|
||||
const { data } = await InventoriesAPI.readDetail(id);
|
||||
const { data } = await InventoriesAPI.readDetail(match.params.id);
|
||||
setBreadcrumb(data);
|
||||
this.setState({ inventory: data });
|
||||
} catch (err) {
|
||||
this.setState({ contentError: err });
|
||||
setInventory(data);
|
||||
} catch (error) {
|
||||
setContentError(error);
|
||||
} finally {
|
||||
this.setState({ hasContentLoading: false });
|
||||
setHasContentLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { history, i18n, location, match } = this.props;
|
||||
const { contentError, hasContentLoading, inventory } = this.state;
|
||||
fetchData();
|
||||
}, [match.params.id, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||
@@ -85,10 +57,7 @@ class Inventory extends Component {
|
||||
</CardHeader>
|
||||
);
|
||||
|
||||
if (
|
||||
location.pathname.endsWith('edit') ||
|
||||
location.pathname.endsWith('add')
|
||||
) {
|
||||
if (location.pathname.endsWith('edit') || location.pathname.endsWith('add')) {
|
||||
cardHeader = null;
|
||||
}
|
||||
|
||||
@@ -100,9 +69,7 @@ class Inventory extends Component {
|
||||
{contentError.response.status === 404 && (
|
||||
<span>
|
||||
{i18n._(`Inventory not found.`)}{' '}
|
||||
<Link to="/inventories">
|
||||
{i18n._(`View all Inventories.`)}
|
||||
</Link>
|
||||
<Link to="/inventories">{i18n._(`View all Inventories.`)}</Link>
|
||||
</span>
|
||||
)}
|
||||
</ContentError>
|
||||
@@ -161,7 +128,7 @@ class Inventory extends Component {
|
||||
<Route
|
||||
key="hosts"
|
||||
path="/inventories/inventory/:id/hosts"
|
||||
render={() => <InventoryHosts inventory={inventory} />}
|
||||
render={() => <InventoryHosts />}
|
||||
/>,
|
||||
<Route
|
||||
key="sources"
|
||||
@@ -196,7 +163,6 @@ class Inventory extends Component {
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Inventory as _Inventory };
|
||||
export default withI18n()(withRouter(Inventory));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { InventoriesAPI } from '@api';
|
||||
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||
@@ -12,28 +13,24 @@ InventoriesAPI.readDetail.mockResolvedValue({
|
||||
});
|
||||
|
||||
describe('<Inventory />', () => {
|
||||
test('initially renders succesfully', async done => {
|
||||
const wrapper = mountWithContexts(
|
||||
let wrapper;
|
||||
|
||||
test('initially renders succesfully', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<Inventory setBreadcrumb={() => {}} match={{ params: { id: 1 } }} />
|
||||
);
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
'Inventory',
|
||||
el => el.state('hasContentLoading') === true
|
||||
);
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
'Inventory',
|
||||
el => el.state('hasContentLoading') === false
|
||||
);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 6);
|
||||
done();
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 6);
|
||||
});
|
||||
|
||||
test('should show content error when user attempts to navigate to erroneous route', async () => {
|
||||
const history = createMemoryHistory({
|
||||
initialEntries: ['/inventories/inventory/1/foobar'],
|
||||
});
|
||||
const wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />, {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />, {
|
||||
context: {
|
||||
router: {
|
||||
history,
|
||||
@@ -48,6 +45,7 @@ describe('<Inventory />', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ const QS_CONFIG = getQSConfig('host', {
|
||||
order_by: 'name',
|
||||
});
|
||||
|
||||
function InventoryHosts({ i18n, location, match, inventory }) {
|
||||
function InventoryHosts({ i18n, location, match }) {
|
||||
const [actions, setActions] = useState(null);
|
||||
const [contentError, setContentError] = useState(null);
|
||||
const [deletionError, setDeletionError] = useState(null);
|
||||
@@ -47,7 +47,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
|
||||
data: { actions: optionActions },
|
||||
},
|
||||
] = await Promise.all([
|
||||
fetchHosts(inventory.id, location.search),
|
||||
fetchHosts(match.params.id, location.search),
|
||||
InventoriesAPI.readOptions(),
|
||||
]);
|
||||
|
||||
@@ -62,7 +62,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
|
||||
}
|
||||
|
||||
fetchData();
|
||||
}, [inventory, location]);
|
||||
}, [match.params.id, location]);
|
||||
|
||||
const handleSelectAll = isSelected => {
|
||||
setSelected(isSelected ? [...hosts] : []);
|
||||
@@ -88,7 +88,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
|
||||
try {
|
||||
const {
|
||||
data: { count, results },
|
||||
} = await fetchHosts(inventory.id, location.search);
|
||||
} = await fetchHosts(match.params.id, location.search);
|
||||
|
||||
setHosts(results);
|
||||
setHostCount(count);
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('<InventoryHosts />', () => {
|
||||
},
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<InventoryHosts inventory={mockInventory} />);
|
||||
wrapper = mountWithContexts(<InventoryHosts />);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user