mirror of
https://github.com/ansible/awx.git
synced 2026-03-05 10:41:05 -03:30
Merge pull request #7444 from AlexSCorey/7412-OrganizationEditButton
Adds edit icon to the OrganizationTeams list Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -6,6 +6,7 @@ import { t } from '@lingui/macro';
|
|||||||
import { OrganizationsAPI } from '../../../api';
|
import { OrganizationsAPI } from '../../../api';
|
||||||
import PaginatedDataList from '../../../components/PaginatedDataList';
|
import PaginatedDataList from '../../../components/PaginatedDataList';
|
||||||
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
import { getQSConfig, parseQueryString } from '../../../util/qs';
|
||||||
|
import OrganizationTeamListItem from './OrganizationTeamListItem';
|
||||||
|
|
||||||
const QS_CONFIG = getQSConfig('team', {
|
const QS_CONFIG = getQSConfig('team', {
|
||||||
page: 1,
|
page: 1,
|
||||||
@@ -13,7 +14,7 @@ const QS_CONFIG = getQSConfig('team', {
|
|||||||
order_by: 'name',
|
order_by: 'name',
|
||||||
});
|
});
|
||||||
|
|
||||||
function OrganizationTeams({ id, i18n }) {
|
function OrganizationTeamList({ id, i18n }) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(false);
|
const [hasContentLoading, setHasContentLoading] = useState(false);
|
||||||
@@ -70,13 +71,21 @@ function OrganizationTeams({ id, i18n }) {
|
|||||||
key: 'name',
|
key: 'name',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
renderItem={item => (
|
||||||
|
<OrganizationTeamListItem
|
||||||
|
key={item.id}
|
||||||
|
value={item.name}
|
||||||
|
team={item}
|
||||||
|
detailUrl={`/teams/${item.id}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OrganizationTeams.propTypes = {
|
OrganizationTeamList.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { OrganizationTeams as _OrganizationTeams };
|
export { OrganizationTeamList as _OrganizationTeamList };
|
||||||
export default withI18n()(OrganizationTeams);
|
export default withI18n()(OrganizationTeamList);
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '../../../../testUtils/enzymeHelpers';
|
} from '../../../../testUtils/enzymeHelpers';
|
||||||
import { sleep } from '../../../../testUtils/testUtils';
|
import { sleep } from '../../../../testUtils/testUtils';
|
||||||
|
|
||||||
import OrganizationTeams from './OrganizationTeams';
|
import OrganizationTeamList from './OrganizationTeamList';
|
||||||
|
|
||||||
jest.mock('../../../api');
|
jest.mock('../../../api');
|
||||||
|
|
||||||
@@ -16,16 +16,41 @@ const listData = {
|
|||||||
data: {
|
data: {
|
||||||
count: 7,
|
count: 7,
|
||||||
results: [
|
results: [
|
||||||
{ id: 1, name: 'one', url: '/org/team/1' },
|
{
|
||||||
{ id: 2, name: 'two', url: '/org/team/2' },
|
id: 1,
|
||||||
{ id: 3, name: 'three', url: '/org/team/3' },
|
name: 'one',
|
||||||
{ id: 4, name: 'four', url: '/org/team/4' },
|
url: '/org/team/1',
|
||||||
{ id: 5, name: 'five', url: '/org/team/5' },
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'two',
|
||||||
|
url: '/org/team/2',
|
||||||
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'three',
|
||||||
|
url: '/org/team/3',
|
||||||
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'four',
|
||||||
|
url: '/org/team/4',
|
||||||
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: 'five',
|
||||||
|
url: '/org/team/5',
|
||||||
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('<OrganizationTeams />', () => {
|
describe('<OrganizationTeamList />', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
OrganizationsAPI.readTeams.mockResolvedValue(listData);
|
OrganizationsAPI.readTeams.mockResolvedValue(listData);
|
||||||
});
|
});
|
||||||
@@ -37,7 +62,7 @@ describe('<OrganizationTeams />', () => {
|
|||||||
test('renders succesfully', async () => {
|
test('renders succesfully', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
mountWithContexts(
|
mountWithContexts(
|
||||||
<OrganizationTeams
|
<OrganizationTeamList
|
||||||
id={1}
|
id={1}
|
||||||
searchString=""
|
searchString=""
|
||||||
location={{ search: '', pathname: '/organizations/1/teams' }}
|
location={{ search: '', pathname: '/organizations/1/teams' }}
|
||||||
@@ -48,8 +73,8 @@ describe('<OrganizationTeams />', () => {
|
|||||||
|
|
||||||
test('should load teams on mount', async () => {
|
test('should load teams on mount', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
mountWithContexts(<OrganizationTeams id={1} searchString="" />).find(
|
mountWithContexts(<OrganizationTeamList id={1} searchString="" />).find(
|
||||||
'OrganizationTeams'
|
'OrganizationTeamList'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(OrganizationsAPI.readTeams).toHaveBeenCalledWith(1, {
|
expect(OrganizationsAPI.readTeams).toHaveBeenCalledWith(1, {
|
||||||
@@ -62,7 +87,9 @@ describe('<OrganizationTeams />', () => {
|
|||||||
test('should pass fetched teams to PaginatedDatalist', async () => {
|
test('should pass fetched teams to PaginatedDatalist', async () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(<OrganizationTeams id={1} searchString="" />);
|
wrapper = mountWithContexts(
|
||||||
|
<OrganizationTeamList id={1} searchString="" />
|
||||||
|
);
|
||||||
});
|
});
|
||||||
await sleep(0);
|
await sleep(0);
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
@@ -90,7 +117,7 @@ describe('<OrganizationTeams />', () => {
|
|||||||
);
|
);
|
||||||
let wrapper;
|
let wrapper;
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(<OrganizationTeams id={1} />);
|
wrapper = mountWithContexts(<OrganizationTeamList id={1} />);
|
||||||
});
|
});
|
||||||
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
|
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
DataListAction,
|
||||||
|
DataListItem,
|
||||||
|
DataListItemRow,
|
||||||
|
DataListItemCells,
|
||||||
|
Tooltip,
|
||||||
|
} from '@patternfly/react-core';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||||
|
import DataListCell from '../../../components/DataListCell';
|
||||||
|
|
||||||
|
function OrganizationTeamListItem({ i18n, team, detailUrl }) {
|
||||||
|
const labelId = `check-action-${team.id}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataListItem aria-labelledby={labelId} id={`${team.id}`}>
|
||||||
|
<DataListItemRow>
|
||||||
|
<DataListItemCells
|
||||||
|
dataListCells={[
|
||||||
|
<DataListCell key="divider">
|
||||||
|
<span>
|
||||||
|
<Link to={`${detailUrl}/details`}>
|
||||||
|
<b aria-label={i18n._(t`team name`)}>{team.name}</b>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
</DataListCell>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<DataListAction
|
||||||
|
aria-label="actions"
|
||||||
|
aria-labelledby={labelId}
|
||||||
|
id={labelId}
|
||||||
|
>
|
||||||
|
{team.summary_fields.user_capabilities.edit && (
|
||||||
|
<Tooltip content={i18n._(t`Edit Team`)} position="top">
|
||||||
|
<Button
|
||||||
|
aria-label={i18n._(t`Edit Team`)}
|
||||||
|
css="grid-column: 2"
|
||||||
|
variant="plain"
|
||||||
|
component={Link}
|
||||||
|
to={`${detailUrl}/edit`}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</DataListAction>
|
||||||
|
</DataListItemRow>
|
||||||
|
</DataListItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
OrganizationTeamListItem.propTypes = {
|
||||||
|
team: PropTypes.shape({ id: PropTypes.number, name: PropTypes.string })
|
||||||
|
.isRequired,
|
||||||
|
detailUrl: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withI18n()(OrganizationTeamListItem);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
|
||||||
|
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||||
|
|
||||||
|
import OrganizationTeamListItem from './OrganizationTeamListItem';
|
||||||
|
|
||||||
|
const team = {
|
||||||
|
id: 1,
|
||||||
|
name: 'one',
|
||||||
|
url: '/org/team/1',
|
||||||
|
summary_fields: { user_capabilities: { edit: true, delete: true } },
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('<OrganizationTeamListItem />', () => {
|
||||||
|
let wrapper;
|
||||||
|
test('should mount properly', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<OrganizationTeamListItem team={team} detailUrl="/teams/1" />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(wrapper.find('OrganizationTeamListItem').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render proper data', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<OrganizationTeamListItem team={team} detailUrl="/teams/1" />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(wrapper.find(`b[aria-label="team name"]`).text()).toBe('one');
|
||||||
|
expect(wrapper.find('PencilAltIcon').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render edit button', async () => {
|
||||||
|
team.summary_fields.user_capabilities.edit = false;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<OrganizationTeamListItem team={team} detailUrl="/teams/1" />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(wrapper.find('PencilAltIcon').length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1 +1 @@
|
|||||||
export { default } from './OrganizationTeams';
|
export { default } from './OrganizationTeamList';
|
||||||
|
|||||||
Reference in New Issue
Block a user