Refactor TopicMessages's store to redux/toolkit (#1902)
* Refactor TopicMessages's store to redux/toolkit * adding test cases to improve coverage * fixing eslint error * removing extra code * Transform redux connect reducer and actions into toolkit slice. (#1883) * integrate redux toolkit for connects * uncomment test case * remove unnecessary comment * reduce duplication * Implement code highlighting for smart filters (#1868) * Implement code highlighting for smart filters * delete unnecessary code * fixing eslint problem * fixing sonar code smells (#1826) * fixing sonar code smells * removing unnecessary change * fixing some sonar code smell issues * making requested changes * Fix sonar badges in readme (#1906) * fixing merge conflicts Co-authored-by: Oleg Shur <workshur@gmail.com> * Add positive notifications after some successful actions. (#1830) * add some positive notifications after successful actions * some improvements * improve alerts reducer tests * Fix test warnings (#1908) * fix fetch mock warnings in brokers.spec.tsx * use separate waitFor-s for fetch-mock call expects * Persist show internal topics switch state (#1832) * persist show internal topics switch state * minor improvements in topics list tests * prevent duplication in topic list test file * fix seek type select border-radius and user-select (#1904) * Refetch topics list to display the updated data (#1900) * refetch topics list to display the updated data * fixing sonar code smells (#1826) * fixing sonar code smells * removing unnecessary change * fixing some sonar code smell issues * making requested changes * Fix sonar badges in readme (#1906) Co-authored-by: Robert Azizbekyan <103438454+rAzizbekyan@users.noreply.github.com> Co-authored-by: Oleg Shur <workshur@gmail.com> * Show confirmation modal when clear messages is clicked in topics list (#1899) * show confirmation modal when clear messages is clicked in topics list * change variable name * add missing dependencies * use useModal hook for topics list modals * display a human-readable error message for topic custom parameers value field (#1896) * modify dependencies to fix partitions filter bug (#1901) Co-authored-by: Arsen Simonyan <103444767+simonyandev@users.noreply.github.com> Co-authored-by: Oleg Shur <workshur@gmail.com>
This commit is contained in:
parent
fa6f587f97
commit
81d1e955da
20 changed files with 463 additions and 376 deletions
470
kafka-ui-react-app/package-lock.json
generated
470
kafka-ui-react-app/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -50,11 +50,11 @@ export interface TopicsListProps {
|
|||
deleteTopics(topicName: TopicName, clusterNames: ClusterName[]): void;
|
||||
recreateTopic(topicName: TopicName, clusterName: ClusterName): void;
|
||||
clearTopicsMessages(topicName: TopicName, clusterNames: ClusterName[]): void;
|
||||
clearTopicMessages(
|
||||
topicName: TopicName,
|
||||
clusterName: ClusterName,
|
||||
partitions?: number[]
|
||||
): void;
|
||||
clearTopicMessages(params: {
|
||||
topicName: TopicName;
|
||||
clusterName: ClusterName;
|
||||
partitions?: number[];
|
||||
}): void;
|
||||
search: string;
|
||||
orderBy: TopicColumnsToSort | null;
|
||||
sortOrder: SortOrder;
|
||||
|
@ -225,7 +225,7 @@ const List: React.FC<TopicsListProps> = ({
|
|||
}, [name]);
|
||||
|
||||
const clearTopicMessagesHandler = React.useCallback(() => {
|
||||
clearTopicMessages(clusterName, name);
|
||||
clearTopicMessages({ clusterName, topicName: name });
|
||||
fetchTopicsList(topicsListParams);
|
||||
closeClearMessagesModal();
|
||||
}, [name, fetchTopicsList, topicsListParams]);
|
||||
|
|
|
@ -6,10 +6,10 @@ import {
|
|||
deleteTopics,
|
||||
recreateTopic,
|
||||
clearTopicsMessages,
|
||||
clearTopicMessages,
|
||||
setTopicsSearchAction,
|
||||
setTopicsOrderByAction,
|
||||
} from 'redux/actions';
|
||||
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import {
|
||||
getTopicList,
|
||||
getAreTopicsFetching,
|
||||
|
|
|
@ -298,10 +298,12 @@ describe('List', () => {
|
|||
|
||||
it('triggers the deleteTopics when clicked on the delete button', async () => {
|
||||
await checkActionButtonClick('deleteTopics');
|
||||
expect(mockDeleteTopics).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('triggers the clearTopicsMessages when clicked on the clear button', async () => {
|
||||
await checkActionButtonClick('clearTopicsMessages');
|
||||
expect(mockClearTopicsMessages).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('closes ConfirmationModal when clicked on the cancel button', async () => {
|
||||
|
|
|
@ -37,7 +37,10 @@ interface Props extends Topic, TopicDetails {
|
|||
isDeletePolicy: boolean;
|
||||
deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
|
||||
recreateTopic: (clusterName: ClusterName, topicName: TopicName) => void;
|
||||
clearTopicMessages(clusterName: ClusterName, topicName: TopicName): void;
|
||||
clearTopicMessages(params: {
|
||||
clusterName: ClusterName;
|
||||
topicName: TopicName;
|
||||
}): void;
|
||||
}
|
||||
|
||||
const HeaderControlsWrapper = styled.div`
|
||||
|
@ -81,7 +84,7 @@ const Details: React.FC<Props> = ({
|
|||
}, [isDeleted, clusterName, dispatch, history]);
|
||||
|
||||
const clearTopicMessagesHandler = React.useCallback(() => {
|
||||
clearTopicMessages(clusterName, topicName);
|
||||
clearTopicMessages({ clusterName, topicName });
|
||||
setClearTopicConfirmationVisible(false);
|
||||
}, [clusterName, topicName, clearTopicMessages]);
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { ClusterName, RootState, TopicName } from 'redux/interfaces';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { deleteTopic, clearTopicMessages, recreateTopic } from 'redux/actions';
|
||||
import { deleteTopic, recreateTopic } from 'redux/actions';
|
||||
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import {
|
||||
getIsTopicDeleted,
|
||||
getIsTopicDeletePolicy,
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
updateTopicMessagesMeta,
|
||||
updateTopicMessagesPhase,
|
||||
setTopicMessagesFetchingStatus,
|
||||
} from 'redux/actions';
|
||||
} from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import {
|
||||
getTopicMessgesMeta,
|
||||
getTopicMessgesPhase,
|
||||
|
|
|
@ -14,11 +14,11 @@ import { Tag } from 'components/common/Tag/Tag.styled';
|
|||
export interface Props extends Topic, TopicDetails {
|
||||
clusterName: ClusterName;
|
||||
topicName: TopicName;
|
||||
clearTopicMessages(
|
||||
clusterName: ClusterName,
|
||||
topicName: TopicName,
|
||||
partitions?: number[]
|
||||
): void;
|
||||
clearTopicMessages(params: {
|
||||
clusterName: ClusterName;
|
||||
topicName: TopicName;
|
||||
partitions?: number[];
|
||||
}): void;
|
||||
}
|
||||
|
||||
const Overview: React.FC<Props> = ({
|
||||
|
@ -120,9 +120,11 @@ const Overview: React.FC<Props> = ({
|
|||
<Dropdown label={<VerticalElipsisIcon />} right>
|
||||
<DropdownItem
|
||||
onClick={() =>
|
||||
clearTopicMessages(clusterName, topicName, [
|
||||
partition,
|
||||
])
|
||||
clearTopicMessages({
|
||||
clusterName,
|
||||
topicName,
|
||||
partitions: [partition],
|
||||
})
|
||||
}
|
||||
danger
|
||||
>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
|||
import { RootState, TopicName, ClusterName } from 'redux/interfaces';
|
||||
import { getTopicByName } from 'redux/reducers/topics/selectors';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { clearTopicMessages } from 'redux/actions';
|
||||
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import Overview from 'components/Topics/Topic/Details/Overview/Overview';
|
||||
|
||||
interface RouteProps {
|
||||
|
|
|
@ -127,10 +127,10 @@ describe('Details', () => {
|
|||
const submitButton = screen.getAllByText('Submit')[0];
|
||||
userEvent.click(submitButton);
|
||||
|
||||
expect(mockClearTopicMessages).toHaveBeenCalledWith(
|
||||
mockClusterName,
|
||||
internalTopicPayload.name
|
||||
);
|
||||
expect(mockClearTopicMessages).toHaveBeenCalledWith({
|
||||
clusterName: mockClusterName,
|
||||
topicName: internalTopicPayload.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('closes the modal when cancel button is clicked', () => {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { RootState } from 'redux/interfaces';
|
||||
import { fetchTopicDetails, resetTopicMessages } from 'redux/actions';
|
||||
import { fetchTopicDetails } from 'redux/actions';
|
||||
import { resetTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import { getIsTopicDetailsFetching } from 'redux/reducers/topics/selectors';
|
||||
|
||||
import Topic from './Topic';
|
||||
|
|
|
@ -5,10 +5,6 @@ import {
|
|||
TopicMessageSchema,
|
||||
} from 'generated-sources';
|
||||
import { FailurePayload } from 'redux/interfaces';
|
||||
import {
|
||||
topicMessagePayload,
|
||||
topicMessagesMetaPayload,
|
||||
} from 'redux/reducers/topicMessages/__test__/fixtures';
|
||||
|
||||
import { mockTopicsState } from './fixtures';
|
||||
|
||||
|
@ -85,39 +81,6 @@ describe('Actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('topic messages', () => {
|
||||
it('creates ADD_TOPIC_MESSAGE', () => {
|
||||
expect(actions.addTopicMessage({ message: topicMessagePayload })).toEqual(
|
||||
{
|
||||
type: 'ADD_TOPIC_MESSAGE',
|
||||
payload: { message: topicMessagePayload },
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('creates RESET_TOPIC_MESSAGES', () => {
|
||||
expect(actions.resetTopicMessages()).toEqual({
|
||||
type: 'RESET_TOPIC_MESSAGES',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates UPDATE_TOPIC_MESSAGES_PHASE', () => {
|
||||
expect(actions.updateTopicMessagesPhase('Polling')).toEqual({
|
||||
type: 'UPDATE_TOPIC_MESSAGES_PHASE',
|
||||
payload: 'Polling',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates UPDATE_TOPIC_MESSAGES_META', () => {
|
||||
expect(actions.updateTopicMessagesMeta(topicMessagesMetaPayload)).toEqual(
|
||||
{
|
||||
type: 'UPDATE_TOPIC_MESSAGES_META',
|
||||
payload: topicMessagesMetaPayload,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sending messages', () => {
|
||||
describe('fetchTopicMessageSchemaAction', () => {
|
||||
it('creates GET_TOPIC_SCHEMA__REQUEST', () => {
|
||||
|
|
|
@ -83,38 +83,6 @@ describe('Thunks', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('clearTopicMessages', () => {
|
||||
it('creates CLEAR_TOPIC_MESSAGES__SUCCESS when deleting existing messages', async () => {
|
||||
fetchMock.deleteOnce(
|
||||
`/api/clusters/${clusterName}/topics/${topicName}/messages`,
|
||||
200
|
||||
);
|
||||
await store.dispatch(thunks.clearTopicMessages(clusterName, topicName));
|
||||
expect(getTypeAndPayload(store)).toEqual([
|
||||
actions.clearMessagesTopicAction.request(),
|
||||
actions.clearMessagesTopicAction.success(),
|
||||
...getAlertActions(store),
|
||||
]);
|
||||
});
|
||||
|
||||
it('creates CLEAR_TOPIC_MESSAGES__FAILURE when deleting existing messages', async () => {
|
||||
fetchMock.deleteOnce(
|
||||
`/api/clusters/${clusterName}/topics/${topicName}/messages`,
|
||||
404
|
||||
);
|
||||
try {
|
||||
await store.dispatch(thunks.clearTopicMessages(clusterName, topicName));
|
||||
} catch (error) {
|
||||
const err = error as Response;
|
||||
expect(err.status).toEqual(404);
|
||||
expect(store.getActions()).toEqual([
|
||||
actions.clearMessagesTopicAction.request(),
|
||||
actions.clearMessagesTopicAction.failure({}),
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchTopicConsumerGroups', () => {
|
||||
it('GET_TOPIC_CONSUMER_GROUPS__FAILURE', async () => {
|
||||
fetchMock.getOnce(
|
||||
|
|
|
@ -3,8 +3,6 @@ import { FailurePayload, TopicName, TopicsState } from 'redux/interfaces';
|
|||
import {
|
||||
TopicColumnsToSort,
|
||||
Topic,
|
||||
TopicMessage,
|
||||
TopicMessageConsuming,
|
||||
TopicMessageSchema,
|
||||
} from 'generated-sources';
|
||||
|
||||
|
@ -73,25 +71,6 @@ export const fetchTopicConsumerGroupsAction = createAsyncAction(
|
|||
'GET_TOPIC_CONSUMER_GROUPS__FAILURE'
|
||||
)<undefined, TopicsState, undefined>();
|
||||
|
||||
export const addTopicMessage = createAction('ADD_TOPIC_MESSAGE')<{
|
||||
message: TopicMessage;
|
||||
prepend?: boolean;
|
||||
}>();
|
||||
|
||||
export const resetTopicMessages = createAction('RESET_TOPIC_MESSAGES')();
|
||||
|
||||
export const setTopicMessagesFetchingStatus = createAction(
|
||||
'SET_TOPIC_MESSAGES_FETCHING_STATUS'
|
||||
)<boolean>();
|
||||
|
||||
export const updateTopicMessagesPhase = createAction(
|
||||
'UPDATE_TOPIC_MESSAGES_PHASE'
|
||||
)<string>();
|
||||
|
||||
export const updateTopicMessagesMeta = createAction(
|
||||
'UPDATE_TOPIC_MESSAGES_META'
|
||||
)<TopicMessageConsuming>();
|
||||
|
||||
export const fetchTopicMessageSchemaAction = createAsyncAction(
|
||||
'GET_TOPIC_SCHEMA__REQUEST',
|
||||
'GET_TOPIC_SCHEMA__SUCCESS',
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
TopicFormData,
|
||||
AppDispatch,
|
||||
} from 'redux/interfaces';
|
||||
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
import { BASE_PARAMS } from 'lib/constants';
|
||||
import * as actions from 'redux/actions/actions';
|
||||
import { getResponse } from 'lib/errorHandling';
|
||||
|
@ -63,44 +64,12 @@ export const fetchTopicsList =
|
|||
dispatch(actions.fetchTopicsListAction.failure());
|
||||
}
|
||||
};
|
||||
export const clearTopicMessages =
|
||||
(
|
||||
clusterName: ClusterName,
|
||||
topicName: TopicName,
|
||||
partitions?: number[]
|
||||
): PromiseThunkResult =>
|
||||
async (dispatch) => {
|
||||
dispatch(actions.clearMessagesTopicAction.request());
|
||||
try {
|
||||
await messagesApiClient.deleteTopicMessages({
|
||||
clusterName,
|
||||
topicName,
|
||||
partitions,
|
||||
});
|
||||
dispatch(actions.clearMessagesTopicAction.success());
|
||||
|
||||
(dispatch as AppDispatch)(
|
||||
showSuccessAlert({
|
||||
id: `message-${topicName}-${clusterName}-${partitions}`,
|
||||
message: 'Messages successfully cleared!',
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
const response = await getResponse(e);
|
||||
const alert: FailurePayload = {
|
||||
subject: [clusterName, topicName, partitions].join('-'),
|
||||
title: `Clear Topic Messages`,
|
||||
response,
|
||||
};
|
||||
dispatch(actions.clearMessagesTopicAction.failure({ alert }));
|
||||
}
|
||||
};
|
||||
|
||||
export const clearTopicsMessages =
|
||||
(clusterName: ClusterName, topicsName: TopicName[]): PromiseThunkResult =>
|
||||
async (dispatch) => {
|
||||
topicsName.forEach((topicName) => {
|
||||
dispatch(clearTopicMessages(clusterName, topicName));
|
||||
dispatch(clearTopicMessages({ clusterName, topicName }));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import schemas from 'redux/reducers/schemas/schemasSlice';
|
|||
import connect from 'redux/reducers/connect/connectSlice';
|
||||
|
||||
import topics from './topics/reducer';
|
||||
import topicMessages from './topicMessages/reducer';
|
||||
import topicMessages from './topicMessages/topicMessagesSlice';
|
||||
import consumerGroups from './consumerGroups/consumerGroupsSlice';
|
||||
import ksqlDb from './ksqlDb/ksqlDbSlice';
|
||||
import legacyLoader from './loader/reducer';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
import reducer, {
|
||||
addTopicMessage,
|
||||
clearTopicMessages,
|
||||
resetTopicMessages,
|
||||
updateTopicMessagesMeta,
|
||||
updateTopicMessagesPhase,
|
||||
} from 'redux/actions';
|
||||
import reducer from 'redux/reducers/topicMessages/reducer';
|
||||
} from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
|
||||
import {
|
||||
topicMessagePayload,
|
||||
|
@ -12,6 +12,9 @@ import {
|
|||
topicMessagesMetaPayload,
|
||||
} from './fixtures';
|
||||
|
||||
const clusterName = 'local';
|
||||
const topicName = 'localTopic';
|
||||
|
||||
describe('TopicMessages reducer', () => {
|
||||
it('Adds new message', () => {
|
||||
const state = reducer(
|
||||
|
@ -53,7 +56,7 @@ describe('TopicMessages reducer', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('Clears messages', () => {
|
||||
it('reset messages', () => {
|
||||
const state = reducer(
|
||||
undefined,
|
||||
addTopicMessage({ message: topicMessagePayload })
|
||||
|
@ -63,6 +66,25 @@ describe('TopicMessages reducer', () => {
|
|||
const newState = reducer(state, resetTopicMessages());
|
||||
expect(newState.messages.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('clear messages', () => {
|
||||
const state = reducer(
|
||||
undefined,
|
||||
addTopicMessage({ message: topicMessagePayload })
|
||||
);
|
||||
expect(state.messages.length).toEqual(1);
|
||||
|
||||
expect(
|
||||
reducer(state, {
|
||||
type: clearTopicMessages.fulfilled,
|
||||
payload: { clusterName, topicName },
|
||||
})
|
||||
).toEqual({
|
||||
...state,
|
||||
messages: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('Updates Topic Messages Phase', () => {
|
||||
const phase = 'Polling';
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { store } from 'redux/store';
|
||||
import * as selectors from 'redux/reducers/topicMessages/selectors';
|
||||
import { initialState } from 'redux/reducers/topicMessages/reducer';
|
||||
import {
|
||||
initialState,
|
||||
addTopicMessage,
|
||||
updateTopicMessagesMeta,
|
||||
updateTopicMessagesPhase,
|
||||
} from 'redux/actions';
|
||||
} from 'redux/reducers/topicMessages/topicMessagesSlice';
|
||||
|
||||
import { topicMessagePayload, topicMessagesMetaPayload } from './fixtures';
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import { Action, TopicMessagesState } from 'redux/interfaces';
|
||||
import { getType } from 'typesafe-actions';
|
||||
import * as actions from 'redux/actions';
|
||||
import { TopicMessage } from 'generated-sources';
|
||||
|
||||
export const initialState: TopicMessagesState = {
|
||||
messages: [],
|
||||
meta: {
|
||||
bytesConsumed: 0,
|
||||
elapsedMs: 0,
|
||||
messagesConsumed: 0,
|
||||
isCancelled: false,
|
||||
},
|
||||
isFetching: false,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/default-param-last
|
||||
const reducer = (state = initialState, action: Action): TopicMessagesState => {
|
||||
switch (action.type) {
|
||||
case getType(actions.addTopicMessage): {
|
||||
const messages: TopicMessage[] = action.payload.prepend
|
||||
? [action.payload.message, ...state.messages]
|
||||
: [...state.messages, action.payload.message];
|
||||
|
||||
return {
|
||||
...state,
|
||||
messages,
|
||||
};
|
||||
}
|
||||
case getType(actions.resetTopicMessages):
|
||||
return initialState;
|
||||
case getType(actions.updateTopicMessagesPhase):
|
||||
return {
|
||||
...state,
|
||||
phase: action.payload,
|
||||
};
|
||||
case getType(actions.updateTopicMessagesMeta):
|
||||
return {
|
||||
...state,
|
||||
meta: action.payload,
|
||||
};
|
||||
case getType(actions.setTopicMessagesFetchingStatus):
|
||||
return {
|
||||
...state,
|
||||
isFetching: action.payload,
|
||||
};
|
||||
case getType(actions.clearMessagesTopicAction.success):
|
||||
return {
|
||||
...state,
|
||||
messages: [],
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default reducer;
|
|
@ -0,0 +1,92 @@
|
|||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
||||
import { TopicMessagesState, ClusterName, TopicName } from 'redux/interfaces';
|
||||
import { TopicMessage, Configuration, MessagesApi } from 'generated-sources';
|
||||
import { BASE_PARAMS } from 'lib/constants';
|
||||
import { getResponse } from 'lib/errorHandling';
|
||||
import { showSuccessAlert } from 'redux/reducers/alerts/alertsSlice';
|
||||
|
||||
const apiClientConf = new Configuration(BASE_PARAMS);
|
||||
export const messagesApiClient = new MessagesApi(apiClientConf);
|
||||
|
||||
export const clearTopicMessages = createAsyncThunk<
|
||||
undefined,
|
||||
{ clusterName: ClusterName; topicName: TopicName; partitions?: number[] }
|
||||
>(
|
||||
'topicMessages/clearTopicMessages',
|
||||
async (
|
||||
{ clusterName, topicName, partitions },
|
||||
{ rejectWithValue, dispatch }
|
||||
) => {
|
||||
try {
|
||||
await messagesApiClient.deleteTopicMessages({
|
||||
clusterName,
|
||||
topicName,
|
||||
partitions,
|
||||
});
|
||||
|
||||
dispatch(
|
||||
showSuccessAlert({
|
||||
id: `message-${topicName}-${clusterName}-${partitions}`,
|
||||
message: 'Messages successfully cleared!',
|
||||
})
|
||||
);
|
||||
|
||||
return undefined;
|
||||
} catch (err) {
|
||||
return rejectWithValue(await getResponse(err as Response));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const initialState: TopicMessagesState = {
|
||||
messages: [],
|
||||
meta: {
|
||||
bytesConsumed: 0,
|
||||
elapsedMs: 0,
|
||||
messagesConsumed: 0,
|
||||
isCancelled: false,
|
||||
},
|
||||
isFetching: false,
|
||||
};
|
||||
|
||||
export const topicMessagesSlice = createSlice({
|
||||
name: 'topicMessages',
|
||||
initialState,
|
||||
reducers: {
|
||||
addTopicMessage: (state, action) => {
|
||||
const messages: TopicMessage[] = action.payload.prepend
|
||||
? [action.payload.message, ...state.messages]
|
||||
: [...state.messages, action.payload.message];
|
||||
|
||||
return {
|
||||
...state,
|
||||
messages,
|
||||
};
|
||||
},
|
||||
resetTopicMessages: () => initialState,
|
||||
updateTopicMessagesPhase: (state, action) => {
|
||||
state.phase = action.payload;
|
||||
},
|
||||
updateTopicMessagesMeta: (state, action) => {
|
||||
state.meta = action.payload;
|
||||
},
|
||||
setTopicMessagesFetchingStatus: (state, action) => {
|
||||
state.isFetching = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(clearTopicMessages.fulfilled, (state) => {
|
||||
state.messages = [];
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
addTopicMessage,
|
||||
resetTopicMessages,
|
||||
updateTopicMessagesPhase,
|
||||
updateTopicMessagesMeta,
|
||||
setTopicMessagesFetchingStatus,
|
||||
} = topicMessagesSlice.actions;
|
||||
|
||||
export default topicMessagesSlice.reducer;
|
Loading…
Add table
Reference in a new issue