mirror of
https://github.com/ansible/awx.git
synced 2026-05-10 02:47:36 -02:30
Addresses PR issues
Adds Delete Modal for deleting from Details view Adds test for delete modal Addresses styling for Variables label Removes X close button from form
This commit is contained in:
@@ -51,14 +51,24 @@ function InventoryGroups({ i18n, match, setBreadcrumb, inventory }) {
|
|||||||
key="edit"
|
key="edit"
|
||||||
path="/inventories/inventory/:id/groups/:groupId/edit"
|
path="/inventories/inventory/:id/groups/:groupId/edit"
|
||||||
render={() => {
|
render={() => {
|
||||||
return <InventoryGroupEdit inventoryGroup={inventoryGroup} />;
|
return (
|
||||||
|
<InventoryGroupEdit
|
||||||
|
inventory={inventory}
|
||||||
|
inventoryGroup={inventoryGroup}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
<Route
|
<Route
|
||||||
key="details"
|
key="details"
|
||||||
path="/inventories/inventory/:id/groups/:groupId/details"
|
path="/inventories/inventory/:id/groups/:groupId/details"
|
||||||
render={() => {
|
render={() => {
|
||||||
return <InventoryGroupDetail inventoryGroup={inventoryGroup} />;
|
return (
|
||||||
|
<InventoryGroupDetail
|
||||||
|
inventory={inventory}
|
||||||
|
inventoryGroup={inventoryGroup}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import { t } from '@lingui/macro';
|
|||||||
|
|
||||||
import { CardBody, Button } from '@patternfly/react-core';
|
import { CardBody, Button } from '@patternfly/react-core';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter, Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { VariablesInput } from '@components/CodeMirrorInput';
|
import { VariablesInput } from '@components/CodeMirrorInput';
|
||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
|
import AlertModal from '@components/AlertModal';
|
||||||
|
import { formatDateString } from '@util/dates';
|
||||||
|
|
||||||
import { GroupsAPI } from '@api';
|
import { GroupsAPI } from '@api';
|
||||||
import { DetailList, Detail } from '@components/DetailList';
|
import { DetailList, Detail } from '@components/DetailList';
|
||||||
@@ -21,6 +23,8 @@ const ActionButtonWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
try {
|
try {
|
||||||
await GroupsAPI.destroy(inventoryGroup.id);
|
await GroupsAPI.destroy(inventoryGroup.id);
|
||||||
@@ -29,10 +33,42 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
setError(err);
|
setError(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <ContentError />;
|
return <ContentError />;
|
||||||
}
|
}
|
||||||
|
if (isDeleteModalOpen) {
|
||||||
|
return (
|
||||||
|
<AlertModal
|
||||||
|
variant="danger"
|
||||||
|
title={i18n._(t`Delete Inventory Group`)}
|
||||||
|
isOpen={isDeleteModalOpen}
|
||||||
|
onClose={() => setIsDeleteModalOpen(false)}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
key="delete"
|
||||||
|
variant="danger"
|
||||||
|
aria-label={i18n._(t`confirm delete`)}
|
||||||
|
onClick={handleDelete}
|
||||||
|
>
|
||||||
|
{i18n._(t`Delete`)}
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
key="cancel"
|
||||||
|
variant="secondary"
|
||||||
|
aria-label={i18n._(t`cancel delete`)}
|
||||||
|
onClick={() => setIsDeleteModalOpen(false)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Cancel`)}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{i18n._(t`Are you sure you want to delete:`)}
|
||||||
|
<br />
|
||||||
|
<strong>{inventoryGroup.name}</strong>
|
||||||
|
<br />
|
||||||
|
</AlertModal>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<CardBody style={{ paddingTop: '20px' }}>
|
<CardBody style={{ paddingTop: '20px' }}>
|
||||||
<DetailList gutter="sm">
|
<DetailList gutter="sm">
|
||||||
@@ -41,23 +77,47 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
label={i18n._(t`Description`)}
|
label={i18n._(t`Description`)}
|
||||||
value={inventoryGroup.description}
|
value={inventoryGroup.description}
|
||||||
/>
|
/>
|
||||||
|
<Detail
|
||||||
|
fullWidth
|
||||||
|
label={i18n._(t`Variables`)}
|
||||||
|
value={
|
||||||
|
<VariablesInput
|
||||||
|
css="margin: 20px 0"
|
||||||
|
id="inventoryGroup-variables"
|
||||||
|
readOnly
|
||||||
|
value={inventoryGroup.variables}
|
||||||
|
rows={4}
|
||||||
|
label=""
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</DetailList>
|
</DetailList>
|
||||||
<VariablesInput
|
|
||||||
css="margin: 20px 0"
|
|
||||||
id="inventoryGroup-variables"
|
|
||||||
readOnly
|
|
||||||
value={inventoryGroup.variables}
|
|
||||||
rows={4}
|
|
||||||
label={i18n._(t`Variables`)}
|
|
||||||
/>
|
|
||||||
<DetailList>
|
<DetailList>
|
||||||
<Detail
|
<Detail
|
||||||
label={i18n._(t`Created`)}
|
label={i18n._(t`Created`)}
|
||||||
value={`${inventoryGroup.created} by ${inventoryGroup.summary_fields.created_by.username}`}
|
value={
|
||||||
|
<span>
|
||||||
|
{i18n._(t`${formatDateString(inventoryGroup.created)} by`)}{' '}
|
||||||
|
<Link
|
||||||
|
to={`/users/${inventoryGroup.summary_fields.created_by.id}`}
|
||||||
|
>
|
||||||
|
{inventoryGroup.summary_fields.created_by.username}
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Detail
|
<Detail
|
||||||
label={i18n._(t`Modified`)}
|
label={i18n._(t`Modified`)}
|
||||||
value={`${inventoryGroup.modified} by ${inventoryGroup.summary_fields.modified_by.username}`}
|
value={
|
||||||
|
<span>
|
||||||
|
{i18n._(t`${formatDateString(inventoryGroup.modified)} by`)}{' '}
|
||||||
|
<Link
|
||||||
|
to={`/users/${inventoryGroup.summary_fields.modified_by.id}`}
|
||||||
|
>
|
||||||
|
{inventoryGroup.summary_fields.modified_by.username}
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</DetailList>
|
</DetailList>
|
||||||
<ActionButtonWrapper>
|
<ActionButtonWrapper>
|
||||||
@@ -75,7 +135,7 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
<Button
|
<Button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
aria-label={i18n._(t`Delete`)}
|
aria-label={i18n._(t`Delete`)}
|
||||||
onClick={handleDelete}
|
onClick={() => setIsDeleteModalOpen(true)}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -13,14 +13,16 @@ const inventoryGroup = {
|
|||||||
description: 'Bar',
|
description: 'Bar',
|
||||||
variables: 'bizz: buzz',
|
variables: 'bizz: buzz',
|
||||||
id: 1,
|
id: 1,
|
||||||
created: '10:00',
|
created: '2019-12-02T15:58:16.276813Z',
|
||||||
modified: '12:00',
|
modified: '2019-12-03T20:33:46.207654Z',
|
||||||
summary_fields: {
|
summary_fields: {
|
||||||
created_by: {
|
created_by: {
|
||||||
username: 'James',
|
username: 'James',
|
||||||
|
id: 13,
|
||||||
},
|
},
|
||||||
modified_by: {
|
modified_by: {
|
||||||
username: 'Bond',
|
username: 'Bond',
|
||||||
|
id: 14,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -49,8 +51,10 @@ describe('<InventoryGroupDetail />', () => {
|
|||||||
test('InventoryGroupDetail renders successfully', () => {
|
test('InventoryGroupDetail renders successfully', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
});
|
});
|
||||||
test('should call api to delete the group', () => {
|
test('should open delete modal and then call api to delete the group', () => {
|
||||||
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
||||||
|
expect(wrapper.find('Modal').length).toBe(1);
|
||||||
|
wrapper.find('button[aria-label="confirm delete"]').simulate('click');
|
||||||
expect(GroupsAPI.destroy).toBeCalledWith(1);
|
expect(GroupsAPI.destroy).toBeCalledWith(1);
|
||||||
});
|
});
|
||||||
test('should navigate user to edit form on edit button click', async () => {
|
test('should navigate user to edit form on edit button click', async () => {
|
||||||
@@ -67,12 +71,8 @@ describe('<InventoryGroupDetail />', () => {
|
|||||||
expect(wrapper.find('Detail[label="Description"]').prop('value')).toBe(
|
expect(wrapper.find('Detail[label="Description"]').prop('value')).toBe(
|
||||||
'Bar'
|
'Bar'
|
||||||
);
|
);
|
||||||
expect(wrapper.find('Detail[label="Created"]').prop('value')).toBe(
|
expect(wrapper.find('Detail[label="Created"]').length).toBe(1);
|
||||||
'10:00 by James'
|
expect(wrapper.find('Detail[label="Modified"]').length).toBe(1);
|
||||||
);
|
|
||||||
expect(wrapper.find('Detail[label="Modified"]').prop('value')).toBe(
|
|
||||||
'12:00 by Bond'
|
|
||||||
);
|
|
||||||
expect(wrapper.find('VariablesInput').prop('value')).toBe('bizz: buzz');
|
expect(wrapper.find('VariablesInput').prop('value')).toBe('bizz: buzz');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ import React from 'react';
|
|||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { Form, Card, CardBody, CardHeader } from '@patternfly/react-core';
|
import { Form, Card, CardBody } from '@patternfly/react-core';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
import CardCloseButton from '@components/CardCloseButton';
|
|
||||||
import FormRow from '@components/FormRow';
|
import FormRow from '@components/FormRow';
|
||||||
import FormField from '@components/FormField';
|
import FormField from '@components/FormField';
|
||||||
import FormActionGroup from '@components/FormActionGroup/FormActionGroup';
|
import FormActionGroup from '@components/FormActionGroup/FormActionGroup';
|
||||||
@@ -18,7 +17,6 @@ function InventoryGroupForm({
|
|||||||
group = {},
|
group = {},
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
handleCancel,
|
handleCancel,
|
||||||
match,
|
|
||||||
}) {
|
}) {
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
name: group.name || '',
|
name: group.name || '',
|
||||||
@@ -28,11 +26,6 @@ function InventoryGroupForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="awx-c-card">
|
<Card className="awx-c-card">
|
||||||
<CardHeader>
|
|
||||||
<CardCloseButton
|
|
||||||
linkTo={`/inventories/inventory/${match.params.id}/groups`}
|
|
||||||
/>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
|
|||||||
Reference in New Issue
Block a user