diff --git a/kafka-ui-react-app/src/components/Connect/List/List.tsx b/kafka-ui-react-app/src/components/Connect/List/List.tsx index 1958ac200a..0f1ab074b0 100644 --- a/kafka-ui-react-app/src/components/Connect/List/List.tsx +++ b/kafka-ui-react-app/src/components/Connect/List/List.tsx @@ -21,6 +21,7 @@ export interface ListProps { connectors: FullConnectorInfo[]; connects: Connect[]; failedConnectors: FullConnectorInfo[]; + failedTasks: number | undefined; fetchConnects(clusterName: ClusterName): void; fetchConnectors({ clusterName }: { clusterName: ClusterName }): void; search: string; @@ -32,6 +33,7 @@ const List: React.FC = ({ areConnectsFetching, areConnectorsFetching, failedConnectors, + failedTasks, fetchConnects, fetchConnectors, search, @@ -75,12 +77,19 @@ const List: React.FC = ({ {connectors.length} {failedConnectors?.length} + + {failedTasks} + diff --git a/kafka-ui-react-app/src/components/Connect/List/ListContainer.ts b/kafka-ui-react-app/src/components/Connect/List/ListContainer.ts index b1180738b4..c3e939a2db 100644 --- a/kafka-ui-react-app/src/components/Connect/List/ListContainer.ts +++ b/kafka-ui-react-app/src/components/Connect/List/ListContainer.ts @@ -12,6 +12,7 @@ import { getAreConnectorsFetching, getConnectorSearch, getFailedConnectors, + getFailedTasks, } from 'redux/reducers/connect/selectors'; import List from 'components/Connect/List/List'; @@ -20,6 +21,7 @@ const mapStateToProps = (state: RootState) => ({ areConnectorsFetching: getAreConnectorsFetching(state), connects: getConnects(state), failedConnectors: getFailedConnectors(state), + failedTasks: getFailedTasks(state), connectors: getConnectors(state), search: getConnectorSearch(state), }); diff --git a/kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx b/kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx index a1edf8ce47..bb8fb3cfa6 100644 --- a/kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx @@ -37,6 +37,7 @@ describe('Connectors List', () => { areConnectsFetching connectors={[]} failedConnectors={[]} + failedTasks={0} connects={[]} fetchConnects={fetchConnects} fetchConnectors={fetchConnectors} diff --git a/kafka-ui-react-app/src/redux/reducers/connect/__test__/selectors.spec.ts b/kafka-ui-react-app/src/redux/reducers/connect/__test__/selectors.spec.ts index bf1d5e946f..0ca9e2fdd0 100644 --- a/kafka-ui-react-app/src/redux/reducers/connect/__test__/selectors.spec.ts +++ b/kafka-ui-react-app/src/redux/reducers/connect/__test__/selectors.spec.ts @@ -20,6 +20,7 @@ describe('Connect selectors', () => { ); expect(selectors.getConnectors(store.getState())).toEqual([]); expect(selectors.getFailedConnectors(store.getState())).toEqual([]); + expect(selectors.getFailedTasks(store.getState())).toEqual(0); expect(selectors.getIsConnectorFetching(store.getState())).toEqual(false); expect(selectors.getConnector(store.getState())).toEqual(null); expect(selectors.getConnectorStatus(store.getState())).toEqual(undefined); @@ -74,6 +75,14 @@ describe('Connect selectors', () => { expect(selectors.getFailedConnectors(store.getState()).length).toEqual(1); }); + it('returns failed tasks', () => { + store.dispatch({ + type: fetchConnectors.fulfilled.type, + payload: { connectors }, + }); + expect(selectors.getFailedTasks(store.getState())).toEqual(1); + }); + it('returns connector', () => { store.dispatch({ type: fetchConnector.fulfilled.type, diff --git a/kafka-ui-react-app/src/redux/reducers/connect/selectors.ts b/kafka-ui-react-app/src/redux/reducers/connect/selectors.ts index 107bc843ab..2e029a7f9e 100644 --- a/kafka-ui-react-app/src/redux/reducers/connect/selectors.ts +++ b/kafka-ui-react-app/src/redux/reducers/connect/selectors.ts @@ -1,7 +1,11 @@ import { createSelector } from '@reduxjs/toolkit'; import { ConnectState, RootState } from 'redux/interfaces'; import { createFetchingSelector } from 'redux/reducers/loader/selectors'; -import { ConnectorTaskStatus, ConnectorState } from 'generated-sources'; +import { + ConnectorTaskStatus, + ConnectorState, + FullConnectorInfo, +} from 'generated-sources'; import { deleteConnector, @@ -47,11 +51,18 @@ export const getFailedConnectors = createSelector( connectState, ({ connectors }) => { return connectors.filter( - (connector) => connector.status.state === ConnectorState.FAILED + (connector: FullConnectorInfo) => + connector.status.state === ConnectorState.FAILED ); } ); +export const getFailedTasks = createSelector(connectState, ({ connectors }) => { + return connectors + .map((connector: FullConnectorInfo) => connector.failedTasksCount || 0) + .reduce((acc: number, value: number) => acc + value, 0); +}); + const getConnectorFetchingStatus = createFetchingSelector( fetchConnector.typePrefix );