Update breadcrumb and fetch new hosts when url changes

This commit is contained in:
Marliana Lara
2019-11-20 15:56:05 -05:00
parent fa144aa98f
commit faa0802d97
4 changed files with 165 additions and 201 deletions

View File

@@ -1,4 +1,4 @@
import React, { Component } from 'react'; import React, { useEffect, useState } from 'react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { Card, CardHeader, PageSection } from '@patternfly/react-core'; import { Card, CardHeader, PageSection } from '@patternfly/react-core';
@@ -16,54 +16,26 @@ import InventorySources from './InventorySources';
import { InventoriesAPI } from '@api'; import { InventoriesAPI } from '@api';
import InventoryEdit from './InventoryEdit'; import InventoryEdit from './InventoryEdit';
class Inventory extends Component { function Inventory({ history, i18n, location, match, setBreadcrumb }) {
constructor(props) { const [contentError, setContentError] = useState(null);
super(props); const [hasContentLoading, setHasContentLoading] = useState(true);
const [inventory, setInventory] = useState(null);
this.state = { useEffect(() => {
contentError: null, async function fetchData() {
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 });
try { try {
const { data } = await InventoriesAPI.readDetail(id); const { data } = await InventoriesAPI.readDetail(match.params.id);
setBreadcrumb(data); setBreadcrumb(data);
this.setState({ inventory: data }); setInventory(data);
} catch (err) { } catch (error) {
this.setState({ contentError: err }); setContentError(error);
} finally { } finally {
this.setState({ hasContentLoading: false }); setHasContentLoading(false);
} }
} }
render() { fetchData();
const { history, i18n, location, match } = this.props; }, [match.params.id, setBreadcrumb]);
const { contentError, hasContentLoading, inventory } = this.state;
const tabsArray = [ const tabsArray = [
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 }, { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
@@ -85,10 +57,7 @@ class Inventory extends Component {
</CardHeader> </CardHeader>
); );
if ( if (location.pathname.endsWith('edit') || location.pathname.endsWith('add')) {
location.pathname.endsWith('edit') ||
location.pathname.endsWith('add')
) {
cardHeader = null; cardHeader = null;
} }
@@ -100,9 +69,7 @@ class Inventory extends Component {
{contentError.response.status === 404 && ( {contentError.response.status === 404 && (
<span> <span>
{i18n._(`Inventory not found.`)}{' '} {i18n._(`Inventory not found.`)}{' '}
<Link to="/inventories"> <Link to="/inventories">{i18n._(`View all Inventories.`)}</Link>
{i18n._(`View all Inventories.`)}
</Link>
</span> </span>
)} )}
</ContentError> </ContentError>
@@ -161,7 +128,7 @@ class Inventory extends Component {
<Route <Route
key="hosts" key="hosts"
path="/inventories/inventory/:id/hosts" path="/inventories/inventory/:id/hosts"
render={() => <InventoryHosts inventory={inventory} />} render={() => <InventoryHosts />}
/>, />,
<Route <Route
key="sources" key="sources"
@@ -196,7 +163,6 @@ class Inventory extends Component {
</PageSection> </PageSection>
); );
} }
}
export { Inventory as _Inventory }; export { Inventory as _Inventory };
export default withI18n()(withRouter(Inventory)); export default withI18n()(withRouter(Inventory));

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history'; import { createMemoryHistory } from 'history';
import { InventoriesAPI } from '@api'; import { InventoriesAPI } from '@api';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
@@ -12,28 +13,24 @@ InventoriesAPI.readDetail.mockResolvedValue({
}); });
describe('<Inventory />', () => { describe('<Inventory />', () => {
test('initially renders succesfully', async done => { let wrapper;
const wrapper = mountWithContexts(
test('initially renders succesfully', async () => {
await act(async () => {
wrapper = mountWithContexts(
<Inventory setBreadcrumb={() => {}} match={{ params: { id: 1 } }} /> <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 () => { test('should show content error when user attempts to navigate to erroneous route', async () => {
const history = createMemoryHistory({ const history = createMemoryHistory({
initialEntries: ['/inventories/inventory/1/foobar'], initialEntries: ['/inventories/inventory/1/foobar'],
}); });
const wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />, { await act(async () => {
wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />, {
context: { context: {
router: { router: {
history, history,
@@ -48,6 +45,7 @@ describe('<Inventory />', () => {
}, },
}, },
}); });
});
await waitForElement(wrapper, 'ContentError', el => el.length === 1); await waitForElement(wrapper, 'ContentError', el => el.length === 1);
}); });
}); });

View File

@@ -20,7 +20,7 @@ const QS_CONFIG = getQSConfig('host', {
order_by: 'name', order_by: 'name',
}); });
function InventoryHosts({ i18n, location, match, inventory }) { function InventoryHosts({ i18n, location, match }) {
const [actions, setActions] = useState(null); const [actions, setActions] = useState(null);
const [contentError, setContentError] = useState(null); const [contentError, setContentError] = useState(null);
const [deletionError, setDeletionError] = useState(null); const [deletionError, setDeletionError] = useState(null);
@@ -47,7 +47,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
data: { actions: optionActions }, data: { actions: optionActions },
}, },
] = await Promise.all([ ] = await Promise.all([
fetchHosts(inventory.id, location.search), fetchHosts(match.params.id, location.search),
InventoriesAPI.readOptions(), InventoriesAPI.readOptions(),
]); ]);
@@ -62,7 +62,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
} }
fetchData(); fetchData();
}, [inventory, location]); }, [match.params.id, location]);
const handleSelectAll = isSelected => { const handleSelectAll = isSelected => {
setSelected(isSelected ? [...hosts] : []); setSelected(isSelected ? [...hosts] : []);
@@ -88,7 +88,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
try { try {
const { const {
data: { count, results }, data: { count, results },
} = await fetchHosts(inventory.id, location.search); } = await fetchHosts(match.params.id, location.search);
setHosts(results); setHosts(results);
setHostCount(count); setHostCount(count);

View File

@@ -81,7 +81,7 @@ describe('<InventoryHosts />', () => {
}, },
}); });
await act(async () => { await act(async () => {
wrapper = mountWithContexts(<InventoryHosts inventory={mockInventory} />); wrapper = mountWithContexts(<InventoryHosts />);
}); });
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
}); });