diff --git a/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.scss b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.scss new file mode 100644 index 0000000..acd9576 --- /dev/null +++ b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.scss @@ -0,0 +1 @@ +@import '~@redhat-cloud-services/frontend-components-utilities/styles/variables'; diff --git a/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.test.tsx b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.test.tsx new file mode 100644 index 0000000..e3b7371 --- /dev/null +++ b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.test.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import ConfirmDeleteDomain from './ConfirmDeleteDomain'; +import '@testing-library/jest-dom'; +import { Domain } from '../../Api'; + +const domain: Domain = { + domain_name: 'mydomain.test', +} as unknown as Domain; + +test('expect empty when isOpen is false', () => { + const root = render(); + expect(root.container).toBeEmptyDOMElement(); +}); + +test('expect modal displayed', () => { + render(); + expect(screen.getByRole('heading')).toHaveTextContent(/^Warning alert:Delete identity domain registration\?$/); + expect(screen.getByRole('button', { name: 'Close' })).toHaveTextContent(/^$/); + expect(screen.getByRole('button', { name: 'Delete' })).toHaveTextContent(/^Delete$/); + expect(screen.getByRole('button', { name: 'Cancel' })).toHaveTextContent(/^Cancel$/); +}); + +test('expect handler onDelete to be called', () => { + // given + const confirmHandler = jest.fn(); + const cancelHandler = jest.fn(); + render(); + + // when the OK button is clicked + screen.getByRole('button', { name: 'Delete' }).click(); + + // then the confirmHandler should be called with the domain as argument and cancelHandler should not + expect(confirmHandler).toBeCalledWith(domain); + expect(cancelHandler).toBeCalledTimes(0); +}); + +test('expect handler onCancel to be called', () => { + // given + const confirmHandler = jest.fn(); + const cancelHandler = jest.fn(); + render(); + + // when the OK button is clicked + screen.getByRole('button', { name: 'Cancel' }).click(); + + // then the confirmHandler should be called with the domain as argument and cancelHandler should not + expect(cancelHandler).toBeCalledTimes(1); + expect(confirmHandler).toBeCalledTimes(0); +}); diff --git a/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.tsx b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.tsx new file mode 100644 index 0000000..c792177 --- /dev/null +++ b/src/Components/ConfirmDeleteDomain/ConfirmDeleteDomain.tsx @@ -0,0 +1,44 @@ +import { Button, Modal } from '@patternfly/react-core'; +import './ConfirmDeleteDomain.scss'; +import React from 'react'; +import { Domain } from '../../Api/api'; + +interface ConfirmDeleteDomainProps { + domain?: Domain; + isOpen?: boolean; + onDelete?: (domain?: Domain) => void; + onCancel?: () => void; +} + +/** + * Modal dialog to confirm a domain deletion. + * + * @param props the props given by the smart component. + */ +const ConfirmDeleteDomain: React.FC = (props) => { + const onDeleteWrapper = () => { + props.onDelete && props.onDelete(props.domain); + }; + return ( + + Delete + , + , + ]} + > + No new host enrollment from HCC will be allowed on {props.domain?.title || ''} domain after registration deletion. + + ); +}; + +export default ConfirmDeleteDomain; diff --git a/src/Components/DomainList/DomainList.tsx b/src/Components/DomainList/DomainList.tsx index d3c9c6a..335083c 100644 --- a/src/Components/DomainList/DomainList.tsx +++ b/src/Components/DomainList/DomainList.tsx @@ -8,6 +8,7 @@ import { useNavigate } from 'react-router-dom'; import { AppContext, AppContextType } from '../../AppContext'; import { Button } from '@patternfly/react-core'; import AutoJoinChangeConfirmDialog from '../AutoJoinChangeConfirmDialog/AutoJoinChangeConfirmDialog'; +import ConfirmDeleteDomain from '../ConfirmDeleteDomain/ConfirmDeleteDomain'; export interface IColumnType { key: string; @@ -108,7 +109,9 @@ export const DomainList = () => { const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc'>('asc'); const domains = context?.domains || ([] as Domain[]); + const [isOpenAutoJoinChangeConfirm, setIsOpenAutoJoinChangeConfirm] = useState(false); + const [isOpenConfirmDelete, setIsOpenConfirmDelete] = useState(false); const [currentDomain, setCurrentDomain] = useState(); const enabledText = 'Enabled'; @@ -166,8 +169,18 @@ export const DomainList = () => { } }; - const onDelete = (domain: Domain) => { - if (domain.domain_id !== undefined) { + const OnShowConfirmDelete = (domain: Domain) => { + setIsOpenConfirmDelete(true); + setCurrentDomain(domain); + }; + + const onDismissConfirmDelete = () => { + setIsOpenConfirmDelete(false); + }; + + const onDelete = (domain?: Domain) => { + setIsOpenConfirmDelete(false); + if (domain?.domain_id !== undefined) { const domainId = domain.domain_id; resources_api .deleteDomain(domainId) @@ -198,7 +211,7 @@ export const DomainList = () => { }, { title: 'Delete', - onClick: () => onDelete(domain), + onClick: () => OnShowConfirmDelete(domain), ouiaId: 'ButtonActionDelete', }, ]; @@ -269,6 +282,7 @@ export const DomainList = () => { onConfirm={onConfirmAutoJoinChange} onCancel={() => setIsOpenAutoJoinChangeConfirm(false)} /> + ); }; diff --git a/src/Routes/DetailPage/DetailPage.tsx b/src/Routes/DetailPage/DetailPage.tsx index 3eb62e3..ac2aec0 100644 --- a/src/Routes/DetailPage/DetailPage.tsx +++ b/src/Routes/DetailPage/DetailPage.tsx @@ -22,6 +22,7 @@ import { Domain, ResourcesApiFactory } from '../../Api/api'; import { AppContext, AppContextType } from '../../AppContext'; import { DetailGeneral } from './Components/DetailGeneral/DetailGeneral'; import { DetailServers } from './Components/DetailServers/DetailServers'; +import ConfirmDeleteDomain from '../../Components/ConfirmDeleteDomain/ConfirmDeleteDomain'; /** * It represents the detail page to show the information about a @@ -40,6 +41,7 @@ const DetailPage = () => { // States const [domain, setDomain] = useState(appContext?.getDomain(domain_id || '')); + const [isOpenConfirmDelete, setIsOpenConfirmDelete] = useState(false); console.log('INFO:DetailPage render:domain_id=' + domain_id); @@ -82,26 +84,40 @@ const DetailPage = () => { setIsKebabOpen(!isKebabOpen); }; + const OnShowConfirmDelete = () => { + setIsOpenConfirmDelete(true); + }; + + const onDismissConfirmDelete = () => { + setIsOpenConfirmDelete(false); + }; + + const onDelete = (domain?: Domain) => { + if (domain?.domain_id !== undefined) { + const domainId = domain.domain_id; + resources_api + .deleteDomain(domainId) + .then((response) => { + if (response.status == 204) { + appContext?.deleteDomain(domainId); + navigate('/domains', { replace: true }); + } else { + // TODO show-up notification with error message + console.error(`response.status=${response.status}; response.data=${response.data}`); + } + }) + .catch((error) => { + // TODO show-up notification with error message + console.log('error onClose: ' + error); + }); + } + }; + const dropdownItems: JSX.Element[] = [ { - console.log('Deleting domain: ' + value); - if (domain_id !== undefined) { - resources_api - .deleteDomain(domain_id) - .then((res) => { - if (res.status === 204) { - console.info('Domain ' + value + ' was deleted'); - appContext?.deleteDomain(domain_id); - navigate('/domains', { replace: true }); - } - }) - .catch((reason) => { - // TODO Send error notification to chrome - console.log(reason); - }); - } + onClick={() => { + domain !== undefined && OnShowConfirmDelete(); }} ouiaId="ButtonDetailsDelete" > @@ -168,6 +184,7 @@ const DetailPage = () => { + ); };