mirror of
https://github.com/ansible/awx.git
synced 2026-02-28 08:18:43 -03:30
RoutedTabs is now a functional component
This commit is contained in:
@@ -5,27 +5,24 @@ import { Router } from 'react-router-dom';
|
|||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { I18nProvider } from '@lingui/react';
|
import { I18nProvider } from '@lingui/react';
|
||||||
import RoutedTabs from '../../src/components/Tabs/RoutedTabs';
|
import RoutedTabs from '../../src/components/Tabs/RoutedTabs';
|
||||||
import { DonateIcon } from '@patternfly/react-icons';
|
|
||||||
|
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
|
||||||
afterEach(() => {
|
let history;
|
||||||
jest.clearAllMocks();
|
|
||||||
|
beforeEach(() => {
|
||||||
|
history = createMemoryHistory({
|
||||||
|
initialEntries: ['/organizations/19/details'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ name: 'Details', link: 'organizations/19/details', id: 0 },
|
{ name: 'Details', link: 'organizations/19/details', id: 0 },
|
||||||
{ name: 'Access', link: 'organizations/19/access', id: 1 },
|
{ name: 'Access', link: 'organizations/19/access', id: 1 },
|
||||||
{ name: 'Teams', link: 'organizations/19/teams', id: 2 }
|
{ name: 'Teams', link: 'organizations/19/teams', id: 2 },
|
||||||
|
{ name: 'Notification', link: 'organizations/19/notification', id: 3 }
|
||||||
];
|
];
|
||||||
|
|
||||||
const history = createMemoryHistory({
|
|
||||||
history: {
|
|
||||||
location: {
|
|
||||||
pathname: '/organizations/19/details'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('<RoutedTabs />', () => {
|
describe('<RoutedTabs />', () => {
|
||||||
test('RoutedTabs renders successfully', () => {
|
test('RoutedTabs renders successfully', () => {
|
||||||
wrapper = mount(
|
wrapper = mount(
|
||||||
@@ -39,41 +36,34 @@ describe('<RoutedTabs />', () => {
|
|||||||
).find('RoutedTabs');
|
).find('RoutedTabs');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('the correct tab is rendered', async () => {
|
test('Given a URL the correct tab is displayed', async (done) => {
|
||||||
const currentTab = 'organizations/1/details';
|
|
||||||
wrapper = mount(
|
wrapper = mount(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<RoutedTabs
|
<RoutedTabs
|
||||||
tabsArray={tabs}
|
tabsArray={tabs}
|
||||||
location={currentTab}
|
|
||||||
/>
|
/>
|
||||||
</Router>
|
</Router>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
).find('RoutedTabs');
|
).find('RoutedTabs');
|
||||||
wrapper.find('button').at(2).simulate('click');
|
wrapper.find('Tabs').prop('onSelect')({}, 1);
|
||||||
wrapper.update();
|
|
||||||
expect(history.location.pathname).toEqual('/organizations/19/access');
|
expect(history.location.pathname).toEqual('/organizations/19/access');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Given a URL the correct tab is displayed', async (done) => {
|
test('the correct tab is rendered', async () => {
|
||||||
const currentTab = createMemoryHistory({
|
|
||||||
initialEntries: ['/organizations/19/teams'],
|
|
||||||
});
|
|
||||||
wrapper = mount(
|
wrapper = mount(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<Router history={currentTab}>
|
<Router history={history}>
|
||||||
<RoutedTabs
|
<RoutedTabs
|
||||||
tabsArray={tabs}
|
tabsArray={tabs}
|
||||||
/>
|
/>
|
||||||
</Router>
|
</Router>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
).find('RoutedTabs');
|
).find('RoutedTabs');
|
||||||
setImmediate(() => {
|
const selectedTab = wrapper.find('section').get(2).props.hidden;
|
||||||
wrapper.find('Tabs').prop('onSelect')({}, 2);
|
wrapper.find('button').at(2).simulate('click');
|
||||||
const selectedTab = wrapper.find('li').get(2).props.className;
|
expect(selectedTab).toBe(false);
|
||||||
expect(selectedTab).toBe('pf-c-tabs__item pf-m-current');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
13
src/app.scss
13
src/app.scss
@@ -283,19 +283,6 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.orgListAlert-actionBtn{
|
|
||||||
margin:0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.orgListDetete-progressBar{
|
|
||||||
padding-right: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.orgListDelete-progressBar-noShow{
|
|
||||||
display: none;
|
|
||||||
padding-right: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.OrgsTab-closeButton {
|
.OrgsTab-closeButton {
|
||||||
color: black;
|
color: black;
|
||||||
float:right;
|
float:right;
|
||||||
|
|||||||
@@ -1,55 +1,44 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {
|
|
||||||
withRouter
|
|
||||||
} from 'react-router-dom';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Tab,
|
Tab,
|
||||||
Tabs
|
Tabs
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
class RoutedTabs extends React.Component {
|
export default function RoutedTabs (props) {
|
||||||
constructor (props) {
|
const { history, tabsArray } = props;
|
||||||
super(props);
|
const getActiveTabId = () => {
|
||||||
|
if (history && history.location.pathname) {
|
||||||
|
const matchTab = tabsArray.find(selectedTab => selectedTab.link
|
||||||
|
=== history.location.pathname);
|
||||||
|
return matchTab.id;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
this.handleTabSelect = this.handleTabSelect.bind(this);
|
function handleTabSelect (event, eventKey) {
|
||||||
|
if (history && history.location.pathname) {
|
||||||
|
const tab = tabsArray.find(tabElement => tabElement.id === eventKey);
|
||||||
|
history.push(tab.link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getActiveTabId () {
|
return (
|
||||||
const { history, tabsArray } = this.props;
|
<Tabs
|
||||||
const matchTab = tabsArray.find(selectedTab => selectedTab.link === history.location.pathname);
|
activeKey={getActiveTabId()}
|
||||||
return matchTab ? matchTab.id : 0;
|
onSelect={handleTabSelect}
|
||||||
}
|
>
|
||||||
|
{tabsArray.map(tabElement => (
|
||||||
handleTabSelect (event, eventKey) {
|
<Tab
|
||||||
const { history, tabsArray } = this.props;
|
className={`${tabElement.name}`}
|
||||||
|
aria-label={`${tabElement.name}`}
|
||||||
const tab = tabsArray.find(tabElement => tabElement.id === eventKey);
|
eventKey={tabElement.id}
|
||||||
history.push(tab.link);
|
key={tabElement.id}
|
||||||
}
|
link={tabElement.link}
|
||||||
|
title={tabElement.name}
|
||||||
render () {
|
/>
|
||||||
const { tabsArray } = this.props;
|
))}
|
||||||
return (
|
</Tabs>
|
||||||
<Tabs
|
);
|
||||||
activeKey={this.getActiveTabId()}
|
|
||||||
onSelect={this.handleTabSelect}
|
|
||||||
>
|
|
||||||
{tabsArray.map(tabElement => (
|
|
||||||
<Tab
|
|
||||||
className={`${tabElement.name}`}
|
|
||||||
aria-label={`${tabElement.name}`}
|
|
||||||
eventKey={tabElement.id}
|
|
||||||
key={tabElement.id}
|
|
||||||
link={tabElement.link}
|
|
||||||
title={tabElement.name}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { RoutedTabs as _RoutedTabs };
|
|
||||||
export default withRouter(RoutedTabs);
|
|
||||||
|
|||||||
@@ -63,9 +63,6 @@ class Organization extends Component {
|
|||||||
this.setState({ organization: data, loading: false });
|
this.setState({ organization: data, loading: false });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleHttpError(error) || this.setState({ error: true, loading: false });
|
handleHttpError(error) || this.setState({ error: true, loading: false });
|
||||||
this.setState({ error: true });
|
|
||||||
} finally {
|
|
||||||
this.setState({ loading: false });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,35 +75,41 @@ class Organization extends Component {
|
|||||||
const {
|
const {
|
||||||
organization,
|
organization,
|
||||||
error,
|
error,
|
||||||
loading,
|
loading
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
let cardHeader = (
|
let cardHeader = (
|
||||||
<CardHeader>
|
loading ? ''
|
||||||
<I18n>
|
: (
|
||||||
{({ i18n }) => (
|
<CardHeader>
|
||||||
<React.Fragment>
|
<I18n>
|
||||||
<RoutedTabs
|
{({ i18n }) => (
|
||||||
labeltext={i18n._(t`Organization detail tabs`)}
|
<React.Fragment>
|
||||||
tabsArray={[
|
<RoutedTabs
|
||||||
{ name: i18nMark('Details'), link: `${match.url}/details`, id: 0 },
|
match={match}
|
||||||
{ name: i18nMark('Access'), link: `${match.url}/access`, id: 1 },
|
history={history}
|
||||||
{ name: i18nMark('Teams'), link: `${match.url}/teams`, id: 2 },
|
labeltext={i18n._(t`Organization detail tabs`)}
|
||||||
{ name: i18nMark('Notifications'), link: `${match.url}/notifications`, id: 3 },
|
tabsArray={[
|
||||||
]}
|
{ name: i18nMark('Details'), link: `${match.url}/details`, id: 0 },
|
||||||
/>
|
{ name: i18nMark('Access'), link: `${match.url}/access`, id: 1 },
|
||||||
<Link
|
{ name: i18nMark('Teams'), link: `${match.url}/teams`, id: 2 },
|
||||||
aria-label="Close"
|
{ name: i18nMark('Notifications'), link: `${match.url}/notifications`, id: 3 },
|
||||||
title="Close"
|
]}
|
||||||
to="/organizations"
|
/>
|
||||||
>
|
<Link
|
||||||
<TimesIcon className="OrgsTab-closeButton" />
|
aria-label="Close"
|
||||||
</Link>
|
title="Close"
|
||||||
</React.Fragment>
|
to="/organizations"
|
||||||
)}
|
>
|
||||||
</I18n>
|
<TimesIcon className="OrgsTab-closeButton" />
|
||||||
</CardHeader>
|
</Link>
|
||||||
);
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</I18n>
|
||||||
|
</CardHeader>
|
||||||
|
));
|
||||||
|
if (!match) {
|
||||||
|
cardHeader = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (location.pathname.endsWith('edit')) {
|
if (location.pathname.endsWith('edit')) {
|
||||||
cardHeader = null;
|
cardHeader = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user