Quellcode durchsuchen

Dependabot/npm and yarn/kafka UI react app/eslint plugin react 7.30.1 (#2232)

* Bump eslint-plugin-react from 7.29.4 to 7.30.1 in /kafka-ui-react-app

Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.29.4 to 7.30.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.29.4...v7.30.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* taking ActionsCell out of List

* removing package-lock

* refactoring props

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Robert Azizbekyan vor 2 Jahren
Ursprung
Commit
30f836645d

+ 1 - 1
kafka-ui-react-app/package.json

@@ -104,7 +104,7 @@
     "eslint-plugin-jest-dom": "^4.0.2",
     "eslint-plugin-jsx-a11y": "^6.5.1",
     "eslint-plugin-prettier": "^4.0.0",
-    "eslint-plugin-react": "^7.29.4",
+    "eslint-plugin-react": "^7.30.1",
     "eslint-plugin-react-hooks": "^4.5.0",
     "fetch-mock-jest": "^1.5.1",
     "husky": "^8.0.1",

+ 11 - 11
kafka-ui-react-app/pnpm-lock.yaml

@@ -50,7 +50,7 @@ specifiers:
   eslint-plugin-jest-dom: ^4.0.2
   eslint-plugin-jsx-a11y: ^6.5.1
   eslint-plugin-prettier: ^4.0.0
-  eslint-plugin-react: ^7.29.4
+  eslint-plugin-react: ^7.30.1
   eslint-plugin-react-hooks: ^4.5.0
   fetch-mock: ^9.11.0
   fetch-mock-jest: ^1.5.1
@@ -155,7 +155,7 @@ devDependencies:
   '@typescript-eslint/parser': 5.29.0_vjep2yp2sits3sqnodefgcbnfi
   dotenv: 16.0.1
   eslint: 8.16.0
-  eslint-config-airbnb: 19.0.4_pamhosqcenlxoxj4ke2dmvzava
+  eslint-config-airbnb: 19.0.4_iayhaebzx3saen2ll7sn5gqmdq
   eslint-config-airbnb-typescript: 17.0.0_l6wia5brkiej5f4nhesunbzj5y
   eslint-config-prettier: 8.5.0_eslint@8.16.0
   eslint-config-react-app: 7.0.1_y3w6q4zxtal6gz5auqli3lo3ny
@@ -165,7 +165,7 @@ devDependencies:
   eslint-plugin-jest-dom: 4.0.2_eslint@8.16.0
   eslint-plugin-jsx-a11y: 6.5.1_eslint@8.16.0
   eslint-plugin-prettier: 4.0.0_q7a4ir2sdihdzpzdlnbgmzjlpq
-  eslint-plugin-react: 7.29.4_eslint@8.16.0
+  eslint-plugin-react: 7.30.1_eslint@8.16.0
   eslint-plugin-react-hooks: 4.5.0_eslint@8.16.0
   fetch-mock-jest: 1.5.1
   husky: 8.0.1
@@ -4208,7 +4208,7 @@ packages:
       eslint-plugin-import: 2.26.0_h5azci6ujakbaa2xblg2jlxooy
     dev: true
 
-  /eslint-config-airbnb/19.0.4_pamhosqcenlxoxj4ke2dmvzava:
+  /eslint-config-airbnb/19.0.4_iayhaebzx3saen2ll7sn5gqmdq:
     resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==}
     engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0}
     peerDependencies:
@@ -4222,7 +4222,7 @@ packages:
       eslint-config-airbnb-base: 15.0.0_btspkuwbqkl4adpiufzbathtpi
       eslint-plugin-import: 2.26.0_h5azci6ujakbaa2xblg2jlxooy
       eslint-plugin-jsx-a11y: 6.5.1_eslint@8.16.0
-      eslint-plugin-react: 7.29.4_eslint@8.16.0
+      eslint-plugin-react: 7.30.1_eslint@8.16.0
       eslint-plugin-react-hooks: 4.5.0_eslint@8.16.0
       object.assign: 4.1.2
       object.entries: 1.1.5
@@ -4259,7 +4259,7 @@ packages:
       eslint-plugin-import: 2.26.0_h5azci6ujakbaa2xblg2jlxooy
       eslint-plugin-jest: 25.7.0_lemdnf4suuyhpl5s2mhp2xyjqi
       eslint-plugin-jsx-a11y: 6.5.1_eslint@8.16.0
-      eslint-plugin-react: 7.29.4_eslint@8.16.0
+      eslint-plugin-react: 7.30.1_eslint@8.16.0
       eslint-plugin-react-hooks: 4.5.0_eslint@8.16.0
       eslint-plugin-testing-library: 5.5.0_vjep2yp2sits3sqnodefgcbnfi
       typescript: 4.7.4
@@ -4455,8 +4455,8 @@ packages:
       eslint: 8.16.0
     dev: true
 
-  /eslint-plugin-react/7.29.4_eslint@8.16.0:
-    resolution: {integrity: sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==}
+  /eslint-plugin-react/7.30.1_eslint@8.16.0:
+    resolution: {integrity: sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==}
     engines: {node: '>=4'}
     peerDependencies:
       eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
@@ -4475,7 +4475,7 @@ packages:
       prop-types: 15.8.1
       resolve: 2.0.0-next.3
       semver: 6.3.0
-      string.prototype.matchall: 4.0.6
+      string.prototype.matchall: 4.0.7
     dev: true
 
   /eslint-plugin-testing-library/5.5.0_vjep2yp2sits3sqnodefgcbnfi:
@@ -7206,8 +7206,8 @@ packages:
       strip-ansi: 7.0.1
     dev: true
 
-  /string.prototype.matchall/4.0.6:
-    resolution: {integrity: sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==}
+  /string.prototype.matchall/4.0.7:
+    resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==}
     dependencies:
       call-bind: 1.0.2
       define-properties: 1.1.4

+ 131 - 0
kafka-ui-react-app/src/components/Topics/List/ActionsCell/ActionsCell.tsx

@@ -0,0 +1,131 @@
+import React from 'react';
+import { useDispatch } from 'react-redux';
+import {
+  CleanUpPolicy,
+  SortOrder,
+  TopicColumnsToSort,
+} from 'generated-sources';
+import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
+import DropdownItem from 'components/common/Dropdown/DropdownItem';
+import { TableCellProps } from 'components/common/SmartTable/TableColumn';
+import { TopicWithDetailedInfo } from 'redux/interfaces';
+import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
+import Dropdown from 'components/common/Dropdown/Dropdown';
+import ClusterContext from 'components/contexts/ClusterContext';
+import * as S from 'components/Topics/List/List.styled';
+import { ClusterNameRoute } from 'lib/paths';
+import useModal from 'lib/hooks/useModal';
+import useAppParams from 'lib/hooks/useAppParams';
+import {
+  deleteTopic,
+  fetchTopicsList,
+  recreateTopic,
+} from 'redux/reducers/topics/topicsSlice';
+import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
+
+interface TopicsListParams {
+  clusterName: string;
+  page?: number;
+  perPage?: number;
+  showInternal?: boolean;
+  search?: string;
+  orderBy?: TopicColumnsToSort;
+  sortOrder?: SortOrder;
+}
+export interface ActionsCellProps {
+  topicsListParams: TopicsListParams;
+}
+
+const ActionsCell: React.FC<
+  TableCellProps<TopicWithDetailedInfo, string> & ActionsCellProps
+> = ({
+  hovered,
+  dataItem: { internal, cleanUpPolicy, name },
+  topicsListParams,
+}) => {
+  const { isReadOnly, isTopicDeletionAllowed } =
+    React.useContext(ClusterContext);
+  const dispatch = useDispatch();
+  const { clusterName } = useAppParams<ClusterNameRoute>();
+
+  const {
+    isOpen: isDeleteTopicModalOpen,
+    setClose: closeDeleteTopicModal,
+    setOpen: openDeleteTopicModal,
+  } = useModal(false);
+
+  const {
+    isOpen: isRecreateTopicModalOpen,
+    setClose: closeRecreateTopicModal,
+    setOpen: openRecreateTopicModal,
+  } = useModal(false);
+
+  const {
+    isOpen: isClearMessagesModalOpen,
+    setClose: closeClearMessagesModal,
+    setOpen: openClearMessagesModal,
+  } = useModal(false);
+
+  const isHidden = internal || isReadOnly || !hovered;
+
+  const deleteTopicHandler = () =>
+    dispatch(deleteTopic({ clusterName, topicName: name }));
+
+  const clearTopicMessagesHandler = () => {
+    dispatch(clearTopicMessages({ clusterName, topicName: name }));
+    dispatch(fetchTopicsList(topicsListParams));
+    closeClearMessagesModal();
+  };
+
+  const recreateTopicHandler = () => {
+    dispatch(recreateTopic({ clusterName, topicName: name }));
+    closeRecreateTopicModal();
+  };
+
+  return (
+    <>
+      <S.ActionsContainer>
+        {!isHidden && (
+          <Dropdown label={<VerticalElipsisIcon />} right>
+            {cleanUpPolicy === CleanUpPolicy.DELETE && (
+              <DropdownItem onClick={openClearMessagesModal} danger>
+                Clear Messages
+              </DropdownItem>
+            )}
+            {isTopicDeletionAllowed && (
+              <DropdownItem onClick={openDeleteTopicModal} danger>
+                Remove Topic
+              </DropdownItem>
+            )}
+            <DropdownItem onClick={openRecreateTopicModal} danger>
+              Recreate Topic
+            </DropdownItem>
+          </Dropdown>
+        )}
+      </S.ActionsContainer>
+      <ConfirmationModal
+        isOpen={isClearMessagesModalOpen}
+        onCancel={closeClearMessagesModal}
+        onConfirm={clearTopicMessagesHandler}
+      >
+        Are you sure want to clear topic messages?
+      </ConfirmationModal>
+      <ConfirmationModal
+        isOpen={isDeleteTopicModalOpen}
+        onCancel={closeDeleteTopicModal}
+        onConfirm={deleteTopicHandler}
+      >
+        Are you sure want to remove <b>{name}</b> topic?
+      </ConfirmationModal>
+      <ConfirmationModal
+        isOpen={isRecreateTopicModalOpen}
+        onCancel={closeRecreateTopicModal}
+        onConfirm={recreateTopicHandler}
+      >
+        Are you sure to recreate <b>{name}</b> topic?
+      </ConfirmationModal>
+    </>
+  );
+};
+
+export default React.memo(ActionsCell);

+ 3 - 101
kafka-ui-react-app/src/components/Topics/List/List.tsx

@@ -12,15 +12,11 @@ import {
   clusterTopicNewRelativePath,
 } from 'lib/paths';
 import usePagination from 'lib/hooks/usePagination';
-import useModal from 'lib/hooks/useModal';
 import ClusterContext from 'components/contexts/ClusterContext';
 import PageLoader from 'components/common/PageLoader/PageLoader';
 import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
 import {
-  CleanUpPolicy,
-  DeleteTopicRequest,
   GetTopicsRequest,
-  RecreateTopicRequest,
   SortOrder,
   TopicColumnsToSort,
 } from 'generated-sources';
@@ -31,14 +27,8 @@ import PageHeading from 'components/common/PageHeading/PageHeading';
 import { ControlPanelWrapper } from 'components/common/ControlPanel/ControlPanel.styled';
 import Switch from 'components/common/Switch/Switch';
 import { SmartTable } from 'components/common/SmartTable/SmartTable';
-import {
-  TableCellProps,
-  TableColumn,
-} from 'components/common/SmartTable/TableColumn';
+import { TableColumn } from 'components/common/SmartTable/TableColumn';
 import { useTableState } from 'lib/hooks/useTableState';
-import Dropdown from 'components/common/Dropdown/Dropdown';
-import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
-import DropdownItem from 'components/common/Dropdown/DropdownItem';
 
 import {
   MessagesCell,
@@ -47,18 +37,17 @@ import {
   TopicSizeCell,
 } from './TopicsTableCells';
 import * as S from './List.styled';
+import ActionsCell from './ActionsCell/ActionsCell';
 
 export interface TopicsListProps {
   areTopicsFetching: boolean;
   topics: TopicWithDetailedInfo[];
   totalPages: number;
   fetchTopicsList(payload: GetTopicsRequest): void;
-  deleteTopic(payload: DeleteTopicRequest): void;
   deleteTopics(payload: {
     clusterName: ClusterName;
     topicNames: TopicName[];
   }): void;
-  recreateTopic(payload: RecreateTopicRequest): void;
   clearTopicsMessages(payload: {
     clusterName: ClusterName;
     topicNames: TopicName[];
@@ -80,10 +69,7 @@ const List: React.FC<TopicsListProps> = ({
   topics,
   totalPages,
   fetchTopicsList,
-  deleteTopic,
   deleteTopics,
-  recreateTopic,
-  clearTopicMessages,
   clearTopicsMessages,
   search,
   orderBy,
@@ -91,8 +77,7 @@ const List: React.FC<TopicsListProps> = ({
   setTopicsSearch,
   setTopicsOrderBy,
 }) => {
-  const { isReadOnly, isTopicDeletionAllowed } =
-    React.useContext(ClusterContext);
+  const { isReadOnly } = React.useContext(ClusterContext);
   const { clusterName } = useAppParams<ClusterNameRoute>();
   const { page, perPage } = usePagination();
   const [showInternal, setShowInternal] = React.useState<boolean>(
@@ -197,89 +182,6 @@ const List: React.FC<TopicsListProps> = ({
     fetchTopicsList(topicsListParams);
   };
 
-  const ActionsCell = React.memo<TableCellProps<TopicWithDetailedInfo, string>>(
-    ({ hovered, dataItem: { internal, cleanUpPolicy, name } }) => {
-      const {
-        isOpen: isDeleteTopicModalOpen,
-        setClose: closeDeleteTopicModal,
-        setOpen: openDeleteTopicModal,
-      } = useModal(false);
-
-      const {
-        isOpen: isRecreateTopicModalOpen,
-        setClose: closeRecreateTopicModal,
-        setOpen: openRecreateTopicModal,
-      } = useModal(false);
-
-      const {
-        isOpen: isClearMessagesModalOpen,
-        setClose: closeClearMessagesModal,
-        setOpen: openClearMessagesModal,
-      } = useModal(false);
-
-      const isHidden = internal || isReadOnly || !hovered;
-
-      const deleteTopicHandler = () =>
-        deleteTopic({ clusterName, topicName: name });
-
-      const clearTopicMessagesHandler = () => {
-        clearTopicMessages({ clusterName, topicName: name });
-        fetchTopicsList(topicsListParams);
-        closeClearMessagesModal();
-      };
-
-      const recreateTopicHandler = () => {
-        recreateTopic({ clusterName, topicName: name });
-        closeRecreateTopicModal();
-      };
-
-      return (
-        <>
-          <S.ActionsContainer>
-            {!isHidden && (
-              <Dropdown label={<VerticalElipsisIcon />} right>
-                {cleanUpPolicy === CleanUpPolicy.DELETE && (
-                  <DropdownItem onClick={openClearMessagesModal} danger>
-                    Clear Messages
-                  </DropdownItem>
-                )}
-                {isTopicDeletionAllowed && (
-                  <DropdownItem onClick={openDeleteTopicModal} danger>
-                    Remove Topic
-                  </DropdownItem>
-                )}
-                <DropdownItem onClick={openRecreateTopicModal} danger>
-                  Recreate Topic
-                </DropdownItem>
-              </Dropdown>
-            )}
-          </S.ActionsContainer>
-          <ConfirmationModal
-            isOpen={isClearMessagesModalOpen}
-            onCancel={closeClearMessagesModal}
-            onConfirm={clearTopicMessagesHandler}
-          >
-            Are you sure want to clear topic messages?
-          </ConfirmationModal>
-          <ConfirmationModal
-            isOpen={isDeleteTopicModalOpen}
-            onCancel={closeDeleteTopicModal}
-            onConfirm={deleteTopicHandler}
-          >
-            Are you sure want to remove <b>{name}</b> topic?
-          </ConfirmationModal>
-          <ConfirmationModal
-            isOpen={isRecreateTopicModalOpen}
-            onCancel={closeRecreateTopicModal}
-            onConfirm={recreateTopicHandler}
-          >
-            Are you sure to recreate <b>{name}</b> topic?
-          </ConfirmationModal>
-        </>
-      );
-    }
-  );
-
   return (
     <div>
       <div>

+ 0 - 4
kafka-ui-react-app/src/components/Topics/List/ListContainer.ts

@@ -3,8 +3,6 @@ import { RootState } from 'redux/interfaces';
 import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
 import {
   fetchTopicsList,
-  deleteTopic,
-  recreateTopic,
   setTopicsSearch,
   setTopicsOrderBy,
   deleteTopics,
@@ -32,9 +30,7 @@ const mapStateToProps = (state: RootState) => ({
 
 const mapDispatchToProps = {
   fetchTopicsList,
-  deleteTopic,
   deleteTopics,
-  recreateTopic,
   clearTopicsMessages,
   clearTopicMessages,
   setTopicsSearch,

+ 0 - 66
kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx

@@ -27,11 +27,9 @@ describe('List', () => {
       topics={[]}
       totalPages={1}
       fetchTopicsList={jest.fn()}
-      deleteTopic={jest.fn()}
       deleteTopics={jest.fn()}
       clearTopicsMessages={jest.fn()}
       clearTopicMessages={jest.fn()}
-      recreateTopic={jest.fn()}
       search=""
       orderBy={null}
       sortOrder={SortOrder.ASC}
@@ -174,10 +172,8 @@ describe('List', () => {
 
   describe('when some list items are selected', () => {
     const mockDeleteTopics = jest.fn();
-    const mockDeleteTopic = jest.fn();
     const mockClearTopic = jest.fn();
     const mockClearTopicsMessages = jest.fn();
-    const mockRecreate = jest.fn();
     const fetchTopicsList = jest.fn();
 
     jest.useFakeTimers();
@@ -204,8 +200,6 @@ describe('List', () => {
               ],
               deleteTopics: mockDeleteTopics,
               clearTopicsMessages: mockClearTopicsMessages,
-              recreateTopic: mockRecreate,
-              deleteTopic: mockDeleteTopic,
               clearTopicMessages: mockClearTopic,
               fetchTopicsList,
             })}
@@ -218,8 +212,6 @@ describe('List', () => {
     afterEach(() => {
       mockDeleteTopics.mockClear();
       mockClearTopicsMessages.mockClear();
-      mockRecreate.mockClear();
-      mockDeleteTopic.mockClear();
     });
 
     const getCheckboxInput = (at: number) => {
@@ -335,63 +327,5 @@ describe('List', () => {
 
       expect(mockDeleteTopics).not.toHaveBeenCalled();
     });
-
-    const tableRowActionClickAndCheck = async (
-      action: 'deleteTopics' | 'clearTopicsMessages' | 'recreate'
-    ) => {
-      const row = screen.getAllByRole('row')[1];
-      userEvent.hover(row);
-      const actionBtn = within(row).getByRole('menu', { hidden: true });
-
-      userEvent.click(actionBtn);
-
-      let textBtn;
-      let mock: jest.Mock;
-
-      if (action === 'clearTopicsMessages') {
-        textBtn = 'Clear Messages';
-        mock = mockClearTopic;
-      } else if (action === 'deleteTopics') {
-        textBtn = 'Remove Topic';
-        mock = mockDeleteTopic;
-      } else {
-        textBtn = 'Recreate Topic';
-        mock = mockRecreate;
-      }
-
-      const ourAction = screen.getByText(textBtn);
-
-      userEvent.click(ourAction);
-
-      let dialog = screen.getByRole('dialog');
-      expect(dialog).toBeInTheDocument();
-      userEvent.click(within(dialog).getByRole('button', { name: 'Submit' }));
-
-      await waitFor(() => {
-        expect(mock).toHaveBeenCalled();
-        if (action === 'clearTopicsMessages') {
-          expect(fetchTopicsList).toHaveBeenCalled();
-        }
-      });
-
-      userEvent.click(ourAction);
-      dialog = screen.getByRole('dialog');
-      expect(dialog).toBeInTheDocument();
-      userEvent.click(within(dialog).getByRole('button', { name: 'Cancel' }));
-      expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
-      expect(mock).toHaveBeenCalledTimes(1);
-    };
-
-    it('should test the actions of the row and their modal and fetching for removing', async () => {
-      await tableRowActionClickAndCheck('deleteTopics');
-    });
-
-    it('should test the actions of the row and their modal and fetching for clear', async () => {
-      await tableRowActionClickAndCheck('clearTopicsMessages');
-    });
-
-    it('should test the actions of the row and their modal and fetching for recreate', async () => {
-      await tableRowActionClickAndCheck('recreate');
-    });
   });
 });

+ 2 - 1
kafka-ui-react-app/src/components/common/SmartTable/TableColumn.tsx

@@ -3,6 +3,7 @@ import { TableState } from 'lib/hooks/useTableState';
 import { SortOrder } from 'generated-sources';
 import * as S from 'components/common/table/TableHeaderCell/TableHeaderCell.styled';
 import { DefaultTheme, StyledComponent } from 'styled-components';
+import { ActionsCellProps } from 'components/Topics/List/ActionsCell/ActionsCell';
 
 export interface OrderableProps {
   orderBy: string | null;
@@ -28,7 +29,7 @@ export interface TableCellProps<T, TId extends IdType>
 }
 
 interface TableColumnProps<T, TId extends IdType> {
-  cell?: React.FC<TableCellProps<T, TId>>;
+  cell?: React.FC<TableCellProps<T, TId> & ActionsCellProps>;
   children?: React.ReactElement;
   headerCell?: React.FC<TableHeaderCellProps<T, TId>>;
   field?: string;