{tableState.selectedCount > 0 && (
- <>
-
- {
- setConfirmationModal('deleteTopics');
- setConfirmationModalText(
- 'Are you sure you want to remove selected topics?'
- );
- }}
- >
- Delete selected topics
-
- {tableState.selectedCount === 1 && (
-
- Copy selected topic
-
- )}
-
- {
- setConfirmationModal('purgeMessages');
- setConfirmationModalText(
- 'Are you sure you want to purge messages of selected topics?'
- );
- }}
- >
- Purge messages of selected topics
-
-
-
+
- {confirmationModalText}
-
- >
+ Delete selected topics
+
+ {tableState.selectedCount === 1 && (
+
+ Copy selected topic
+
+ )}
+
+
+ Purge messages of selected topics
+
+
)}
{
)[buttonIndex];
userEvent.click(buttonClickedElement);
- const modal = screen.getByRole('dialog');
+ const modal = await screen.findByRole('dialog');
expect(within(modal).getByText(confirmationText)).toBeInTheDocument();
- userEvent.click(within(modal).getByRole('button', { name: 'Submit' }));
+ userEvent.click(within(modal).getByRole('button', { name: 'Confirm' }));
await waitFor(() => {
expect(screen.queryByTestId('delete-buttons')).not.toBeInTheDocument();
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx
index 9468f524b8..2fb13af8d1 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx
@@ -10,7 +10,6 @@ import {
clusterTopicSendMessageRelativePath,
} from 'lib/paths';
import ClusterContext from 'components/contexts/ClusterContext';
-import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
import PageHeading from 'components/common/PageHeading/PageHeading';
import { Button } from 'components/common/Button/Button';
import styled from 'styled-components';
@@ -60,42 +59,22 @@ const Details: React.FC = ({
clearTopicMessages,
}) => {
const { clusterName, topicName } = useAppParams();
-
const isInternal = useAppSelector((state) =>
getIsTopicInternal(state, topicName)
);
const isDeletePolicy = useAppSelector((state) =>
getIsTopicDeletePolicy(state, topicName)
);
-
const navigate = useNavigate();
+
const { isReadOnly, isTopicDeletionAllowed } =
React.useContext(ClusterContext);
- const [isDeleteTopicConfirmationVisible, setDeleteTopicConfirmationVisible] =
- React.useState(false);
- const [isClearTopicConfirmationVisible, setClearTopicConfirmationVisible] =
- React.useState(false);
- const [
- isRecreateTopicConfirmationVisible,
- setRecreateTopicConfirmationVisible,
- ] = React.useState(false);
const deleteTopicHandler = () => {
deleteTopic({ clusterName, topicName });
- setDeleteTopicConfirmationVisible(false);
navigate('../..');
};
- const clearTopicMessagesHandler = () => {
- clearTopicMessages({ clusterName, topicName });
- setClearTopicConfirmationVisible(false);
- };
-
- const recreateTopicHandler = () => {
- recreateTopic({ clusterName, topicName });
- setRecreateTopicConfirmationVisible(false);
- };
-
return (
@@ -131,26 +110,44 @@ const Details: React.FC = ({
especially important consequences.
+ {isDeletePolicy && (
+
+ clearTopicMessages({ clusterName, topicName })
+ }
+ confirm="Are you sure want to clear topic messages?"
+ danger
+ >
+ Clear messages
+
+ )}
setClearTopicConfirmationVisible(true)}
- danger
- >
- Clear messages
-
- setRecreateTopicConfirmationVisible(true)}
+ onClick={() => recreateTopic({ clusterName, topicName })}
+ confirm={
+ <>
+ Are you sure want to recreate {topicName} {' '}
+ topic?
+ >
+ }
danger
>
Recreate Topic
- setDeleteTopicConfirmationVisible(true)}
- danger
- >
- Remove Topic
-
+ {isTopicDeletionAllowed && (
+
+ Are you sure want to remove {topicName} {' '}
+ topic?
+ >
+ }
+ danger
+ >
+ Remove Topic
+
+ )}
}
/>
@@ -158,27 +155,6 @@ const Details: React.FC = ({
)}
-
setDeleteTopicConfirmationVisible(false)}
- onConfirm={deleteTopicHandler}
- >
- Are you sure want to remove {topicName} topic?
-
-
setClearTopicConfirmationVisible(false)}
- onConfirm={clearTopicMessagesHandler}
- >
- Are you sure want to clear topic messages?
-
-
setRecreateTopicConfirmationVisible(false)}
- onConfirm={recreateTopicHandler}
- >
- Are you sure want to recreate {topicName} topic?
-
theme.modal.deletionTextColor};
- font-size: 14px;
- line-height: 20px;
- padding: 16px 0;
-`;
-
export const MessageLoading = styled.div.attrs({
role: 'contentLoader',
})`
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx
index 1bfb5f096c..279ad24b3e 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx
@@ -1,8 +1,7 @@
import React, { FC } from 'react';
import { Button } from 'components/common/Button/Button';
-import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
-import useModal from 'lib/hooks/useModal';
import DeleteIcon from 'components/common/Icons/DeleteIcon';
+import { useConfirm } from 'lib/hooks/useConfirm';
import * as S from './Filters.styled';
import { MessageFilters } from './Filters';
@@ -24,9 +23,8 @@ const SavedFilters: FC = ({
closeModal,
onGoBack,
}) => {
- const { isOpen, setOpen, setClose } = useModal();
- const [deleteIndex, setDeleteIndex] = React.useState(-1);
const [selectedFilter, setSelectedFilter] = React.useState(-1);
+ const confirm = useConfirm();
const activeFilter = () => {
if (selectedFilter > -1) {
@@ -36,26 +34,13 @@ const SavedFilters: FC = ({
};
const deleteFilterHandler = (index: number) => {
- setOpen();
- setDeleteIndex(index);
+ confirm(<>Are you sure want to remove {filters[index]?.name}?>, () => {
+ deleteFilter(index);
+ });
};
return (
<>
- {
- deleteFilter(deleteIndex);
- setClose();
- }}
- onCancel={setClose}
- submitBtnText="Delete"
- >
-
- Are you sure want to remove {filters[deleteIndex]?.name}?
-
-
Back To custom filters
@@ -86,7 +71,6 @@ const SavedFilters: FC = ({
buttonType="secondary"
type="button"
onClick={closeModal}
- disabled={isOpen}
>
Cancel
@@ -95,7 +79,6 @@ const SavedFilters: FC = ({
buttonType="primary"
type="button"
onClick={activeFilter}
- disabled={isOpen}
>
Select filter
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx
index 1fa21b6e6c..862101f751 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx
@@ -3,7 +3,12 @@ import SavedFilters, {
Props,
} from 'components/Topics/Topic/Details/Messages/Filters/SavedFilters';
import { MessageFilters } from 'components/Topics/Topic/Details/Messages/Filters/Filters';
-import { screen, within } from '@testing-library/react';
+import {
+ screen,
+ waitFor,
+ waitForElementToBeRemoved,
+ within,
+} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from 'lib/testHelpers';
@@ -11,8 +16,8 @@ jest.mock('components/common/Icons/DeleteIcon', () => () => 'mock-DeleteIcon');
describe('SavedFilter Component', () => {
const mockFilters: MessageFilters[] = [
- { name: 'name', code: 'code' },
- { name: 'name1', code: 'code1' },
+ { name: 'My Filter', code: 'code' },
+ { name: 'One More Filter', code: 'code1' },
];
const setUpComponent = (props: Partial = {}) => {
@@ -125,11 +130,11 @@ describe('SavedFilter Component', () => {
const modelDialog = screen.getByRole('dialog');
expect(modelDialog).toBeInTheDocument();
expect(
- within(modelDialog).getByText(/Confirm deletion/i)
+ within(modelDialog).getByText('Are you sure want to remove My Filter?')
).toBeInTheDocument();
});
- it('Close Confirmations deletion modal with button', () => {
+ it('Close Confirmations deletion modal with button', async () => {
setUpComponent({ deleteFilter: deleteMock });
const savedFilters = getSavedFilters();
const deleteIcons = screen.getAllByText('mock-DeleteIcon');
@@ -142,11 +147,11 @@ describe('SavedFilter Component', () => {
const cancelButton = within(modelDialog).getByRole('button', {
name: /Cancel/i,
});
- userEvent.click(cancelButton);
+ await waitFor(() => userEvent.click(cancelButton));
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
- it('Delete the saved filter', () => {
+ it('Delete the saved filter', async () => {
setUpComponent({ deleteFilter: deleteMock });
const savedFilters = getSavedFilters();
const deleteIcons = screen.getAllByText('mock-DeleteIcon');
@@ -154,9 +159,11 @@ describe('SavedFilter Component', () => {
userEvent.hover(savedFilters[0]);
userEvent.click(deleteIcons[0]);
- userEvent.click(screen.getByRole('button', { name: /Delete/i }));
+ await waitFor(() =>
+ userEvent.click(screen.getByRole('button', { name: 'Confirm' }))
+ );
expect(deleteMock).toHaveBeenCalledTimes(1);
- expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
+ await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
});
});
});
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx
index c03f5b511a..5c1df4edf3 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/__test__/Details.spec.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { screen } from '@testing-library/react';
+import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ClusterContext from 'components/contexts/ClusterContext';
import Details from 'components/Topics/Topic/Details/Details';
@@ -97,9 +97,12 @@ describe('Details', () => {
userEvent.click(openModalButton);
});
- it('calls deleteTopic on confirm', () => {
- const submitButton = screen.getAllByText('Submit')[0];
- userEvent.click(submitButton);
+ it('calls deleteTopic on confirm', async () => {
+ const submitButton = screen.getAllByRole('button', {
+ name: 'Confirm',
+ })[0];
+
+ await waitFor(() => userEvent.click(submitButton));
expect(mockDelete).toHaveBeenCalledWith({
clusterName: mockClusterName,
@@ -107,10 +110,9 @@ describe('Details', () => {
});
});
- it('closes the modal when cancel button is clicked', () => {
+ it('closes the modal when cancel button is clicked', async () => {
const cancelButton = screen.getAllByText('Cancel')[0];
- userEvent.click(cancelButton);
-
+ await waitFor(() => userEvent.click(cancelButton));
expect(cancelButton).not.toBeInTheDocument();
});
});
@@ -123,9 +125,11 @@ describe('Details', () => {
userEvent.click(confirmButton);
});
- it('it calls clearTopicMessages on confirm', () => {
- const submitButton = screen.getAllByText('Submit')[0];
- userEvent.click(submitButton);
+ it('it calls clearTopicMessages on confirm', async () => {
+ const submitButton = screen.getAllByRole('button', {
+ name: 'Confirm',
+ })[0];
+ await waitFor(() => userEvent.click(submitButton));
expect(mockClearTopicMessages).toHaveBeenCalledWith({
clusterName: mockClusterName,
@@ -133,9 +137,9 @@ describe('Details', () => {
});
});
- it('closes the modal when cancel button is clicked', () => {
+ it('closes the modal when cancel button is clicked', async () => {
const cancelButton = screen.getAllByText('Cancel')[0];
- userEvent.click(cancelButton);
+ await waitFor(() => userEvent.click(cancelButton));
expect(cancelButton).not.toBeInTheDocument();
});
@@ -152,14 +156,14 @@ describe('Details', () => {
});
});
- it('redirects to the correct route if topic is deleted', () => {
+ it('redirects to the correct route if topic is deleted', async () => {
setupComponent();
const deleteTopicButton = screen.getByText(/Remove topic/i);
userEvent.click(deleteTopicButton);
- const submitDeleteButton = screen.getByText(/Submit/i);
- userEvent.click(submitDeleteButton);
+ const submitDeleteButton = screen.getByRole('button', { name: 'Confirm' });
+ await waitFor(() => userEvent.click(submitDeleteButton));
expect(mockNavigate).toHaveBeenCalledWith('../..');
});
@@ -184,12 +188,13 @@ describe('Details', () => {
).toBeInTheDocument();
});
- it('calling recreation function after click on Submit button', () => {
+ it('calling recreation function after click on Submit button', async () => {
setupComponent();
const recreateTopicButton = screen.getByText(/Recreate topic/i);
userEvent.click(recreateTopicButton);
- const confirmBtn = screen.getByRole('button', { name: /submit/i });
- userEvent.click(confirmBtn);
+ const confirmBtn = screen.getByRole('button', { name: /Confirm/i });
+
+ await waitFor(() => userEvent.click(confirmBtn));
expect(mockRecreateTopic).toBeCalledTimes(1);
});
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZone.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZone.tsx
index 3f7576d9f6..c84f43677c 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZone.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZone.tsx
@@ -1,6 +1,5 @@
import { ErrorMessage } from '@hookform/error-message';
import { Button } from 'components/common/Button/Button';
-import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
import Input from 'components/common/Input/Input';
import { FormError } from 'components/common/Input/Input.styled';
import { InputLabel } from 'components/common/Input/InputLabel.styled';
@@ -9,14 +8,13 @@ import { FormProvider, useForm } from 'react-hook-form';
import { RouteParamsClusterTopic } from 'lib/paths';
import { ClusterName, TopicName } from 'redux/interfaces';
import useAppParams from 'lib/hooks/useAppParams';
+import { useConfirm } from 'lib/hooks/useConfirm';
import * as S from './DangerZone.styled';
export interface Props {
defaultPartitions: number;
defaultReplicationFactor: number;
- partitionsCountIncreased: boolean;
- replicationFactorUpdated: boolean;
updateTopicPartitionsCount: (payload: {
clusterName: ClusterName;
topicName: TopicName;
@@ -32,19 +30,10 @@ export interface Props {
const DangerZone: React.FC = ({
defaultPartitions,
defaultReplicationFactor,
- partitionsCountIncreased,
- replicationFactorUpdated,
updateTopicPartitionsCount,
updateTopicReplicationFactor,
}) => {
const { clusterName, topicName } = useAppParams();
-
- const [isPartitionsConfirmationVisible, setIsPartitionsConfirmationVisible] =
- React.useState(false);
- const [
- isReplicationFactorConfirmationVisible,
- setIsReplicationFactorConfirmationVisible,
- ] = React.useState(false);
const [partitions, setPartitions] = React.useState(defaultPartitions);
const [replicationFactor, setReplicationFactor] = React.useState(
defaultReplicationFactor
@@ -62,6 +51,29 @@ const DangerZone: React.FC = ({
},
});
+ const confirm = useConfirm();
+
+ const confirmPartitionsChange = () =>
+ confirm(
+ `Are you sure you want to increase the number of partitions?
+ Do it only if you 100% know what you are doing!`,
+ () =>
+ updateTopicPartitionsCount({
+ clusterName,
+ topicName,
+ partitions: partitionsMethods.getValues('partitions'),
+ })
+ );
+ const confirmReplicationFactorChange = () =>
+ confirm('Are you sure you want to update the replication factor?', () =>
+ updateTopicReplicationFactor({
+ clusterName,
+ topicName,
+ replicationFactor:
+ replicationFactorMethods.getValues('replicationFactor'),
+ })
+ );
+
const validatePartitions = (data: { partitions: number }) => {
if (data.partitions < defaultPartitions) {
partitionsMethods.setError('partitions', {
@@ -70,42 +82,15 @@ const DangerZone: React.FC = ({
});
} else {
setPartitions(data.partitions);
- setIsPartitionsConfirmationVisible(true);
+ confirmPartitionsChange();
}
};
const validateReplicationFactor = (data: { replicationFactor: number }) => {
setReplicationFactor(data.replicationFactor);
- setIsReplicationFactorConfirmationVisible(true);
+ confirmReplicationFactorChange();
};
- React.useEffect(() => {
- if (partitionsCountIncreased) {
- setIsPartitionsConfirmationVisible(false);
- }
- }, [partitionsCountIncreased]);
-
- React.useEffect(() => {
- if (replicationFactorUpdated) {
- setIsReplicationFactorConfirmationVisible(false);
- }
- }, [replicationFactorUpdated]);
-
- const partitionsSubmit = () => {
- updateTopicPartitionsCount({
- clusterName,
- topicName,
- partitions: partitionsMethods.getValues('partitions'),
- });
- };
- const replicationFactorSubmit = () => {
- updateTopicReplicationFactor({
- clusterName,
- topicName,
- replicationFactor:
- replicationFactorMethods.getValues('replicationFactor'),
- });
- };
return (
Danger Zone
@@ -148,15 +133,6 @@ const DangerZone: React.FC = ({
name="partitions"
/>
- setIsPartitionsConfirmationVisible(false)}
- onConfirm={partitionsSubmit}
- >
- Are you sure you want to increase the number of partitions? Do it only
- if you 100% know what you are doing!
-
-
= ({
= ({
-
- setIsReplicationFactorConfirmationVisible(false)}
- onConfirm={replicationFactorSubmit}
- >
- Are you sure you want to update the replication factor?
-
);
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZoneContainer.ts b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZoneContainer.ts
index 722f5144db..f87ea03669 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZoneContainer.ts
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/DangerZoneContainer.ts
@@ -4,10 +4,6 @@ import {
updateTopicPartitionsCount,
updateTopicReplicationFactor,
} from 'redux/reducers/topics/topicsSlice';
-import {
- getTopicPartitionsCountIncreased,
- getTopicReplicationFactorUpdated,
-} from 'redux/reducers/topics/selectors';
import DangerZone from './DangerZone';
@@ -17,13 +13,11 @@ type OwnProps = {
};
const mapStateToProps = (
- state: RootState,
+ _: RootState,
{ defaultPartitions, defaultReplicationFactor }: OwnProps
) => ({
defaultPartitions,
defaultReplicationFactor,
- partitionsCountIncreased: getTopicPartitionsCountIncreased(state),
- replicationFactorUpdated: getTopicReplicationFactorUpdated(state),
});
const mapDispatchToProps = {
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/__test__/DangerZone.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/__test__/DangerZone.spec.tsx
index 2099f63305..32458bf565 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/__test__/DangerZone.spec.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Edit/DangerZone/__test__/DangerZone.spec.tsx
@@ -20,8 +20,6 @@ const renderComponent = (props?: Partial