123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- import React, { Suspense } from 'react';
- import { NavLink, Route, Routes, useNavigate } from 'react-router-dom';
- import {
- clusterTopicConsumerGroupsRelativePath,
- clusterTopicEditRelativePath,
- clusterTopicMessagesRelativePath,
- clusterTopicSettingsRelativePath,
- clusterTopicsPath,
- clusterTopicStatisticsRelativePath,
- RouteParamsClusterTopic,
- } from 'lib/paths';
- import ClusterContext from 'components/contexts/ClusterContext';
- import PageHeading from 'components/common/PageHeading/PageHeading';
- import {
- ActionButton,
- ActionNavLink,
- ActionDropdownItem,
- } from 'components/common/ActionComponent';
- import Navbar from 'components/common/Navigation/Navbar.styled';
- import { useAppDispatch } from 'lib/hooks/redux';
- import useAppParams from 'lib/hooks/useAppParams';
- import { Dropdown, DropdownItemHint } from 'components/common/Dropdown';
- import {
- useClearTopicMessages,
- useDeleteTopic,
- useRecreateTopic,
- useTopicDetails,
- } from 'lib/hooks/api/topics';
- import { resetTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
- import { Action, CleanUpPolicy, ResourceType } from 'generated-sources';
- import PageLoader from 'components/common/PageLoader/PageLoader';
- import SlidingSidebar from 'components/common/SlidingSidebar';
- import useBoolean from 'lib/hooks/useBoolean';
- import Messages from './Messages/Messages';
- import Overview from './Overview/Overview';
- import Settings from './Settings/Settings';
- import TopicConsumerGroups from './ConsumerGroups/TopicConsumerGroups';
- import Statistics from './Statistics/Statistics';
- import Edit from './Edit/Edit';
- import SendMessage from './SendMessage/SendMessage';
- const Topic: React.FC = () => {
- const dispatch = useAppDispatch();
- const {
- value: isSidebarOpen,
- setFalse: closeSidebar,
- setTrue: openSidebar,
- } = useBoolean(false);
- const { clusterName, topicName } = useAppParams<RouteParamsClusterTopic>();
- const navigate = useNavigate();
- const deleteTopic = useDeleteTopic(clusterName);
- const recreateTopic = useRecreateTopic({ clusterName, topicName });
- const { data } = useTopicDetails({ clusterName, topicName });
- const { isReadOnly, isTopicDeletionAllowed } =
- React.useContext(ClusterContext);
- const deleteTopicHandler = async () => {
- await deleteTopic.mutateAsync(topicName);
- navigate(clusterTopicsPath(clusterName));
- };
- React.useEffect(() => {
- return () => {
- dispatch(resetTopicMessages());
- };
- }, []);
- const clearMessages = useClearTopicMessages(clusterName);
- const clearTopicMessagesHandler = async () => {
- await clearMessages.mutateAsync(topicName);
- };
- const canCleanup = data?.cleanUpPolicy === CleanUpPolicy.DELETE;
- return (
- <>
- <PageHeading
- text={topicName}
- backText="Topics"
- backTo={clusterTopicsPath(clusterName)}
- >
- <ActionButton
- buttonSize="M"
- buttonType="primary"
- onClick={openSidebar}
- disabled={isReadOnly}
- permission={{
- resource: ResourceType.TOPIC,
- action: Action.MESSAGES_PRODUCE,
- value: topicName,
- }}
- >
- Produce Message
- </ActionButton>
- <Dropdown disabled={isReadOnly || data?.internal}>
- <ActionDropdownItem
- onClick={() => navigate(clusterTopicEditRelativePath)}
- permission={{
- resource: ResourceType.TOPIC,
- action: Action.EDIT,
- value: topicName,
- }}
- >
- Edit settings
- <DropdownItemHint>
- Pay attention! This operation has
- <br />
- especially important consequences.
- </DropdownItemHint>
- </ActionDropdownItem>
- <ActionDropdownItem
- onClick={clearTopicMessagesHandler}
- confirm="Are you sure want to clear topic messages?"
- disabled={!canCleanup}
- danger
- permission={{
- resource: ResourceType.TOPIC,
- action: Action.MESSAGES_DELETE,
- value: topicName,
- }}
- >
- Clear messages
- <DropdownItemHint>
- Clearing messages is only allowed for topics
- <br />
- with DELETE policy
- </DropdownItemHint>
- </ActionDropdownItem>
- <ActionDropdownItem
- onClick={recreateTopic.mutateAsync}
- confirm={
- <>
- Are you sure want to recreate <b>{topicName}</b> topic?
- </>
- }
- danger
- permission={{
- resource: ResourceType.TOPIC,
- action: [Action.MESSAGES_READ, Action.CREATE, Action.DELETE],
- value: topicName,
- }}
- >
- Recreate Topic
- </ActionDropdownItem>
- <ActionDropdownItem
- onClick={deleteTopicHandler}
- confirm={
- <>
- Are you sure want to remove <b>{topicName}</b> topic?
- </>
- }
- disabled={!isTopicDeletionAllowed}
- danger
- permission={{
- resource: ResourceType.TOPIC,
- action: Action.DELETE,
- value: topicName,
- }}
- >
- Remove Topic
- {!isTopicDeletionAllowed && (
- <DropdownItemHint>
- The topic deletion is restricted at the application
- <br />
- configuration level
- </DropdownItemHint>
- )}
- </ActionDropdownItem>
- </Dropdown>
- </PageHeading>
- <Navbar role="navigation">
- <NavLink
- to="."
- className={({ isActive }) => (isActive ? 'is-active' : '')}
- end
- >
- Overview
- </NavLink>
- <ActionNavLink
- to={clusterTopicMessagesRelativePath}
- className={({ isActive }) => (isActive ? 'is-active' : '')}
- permission={{
- resource: ResourceType.TOPIC,
- action: Action.MESSAGES_READ,
- value: topicName,
- }}
- >
- Messages
- </ActionNavLink>
- <NavLink
- to={clusterTopicConsumerGroupsRelativePath}
- className={({ isActive }) => (isActive ? 'is-active' : '')}
- >
- Consumers
- </NavLink>
- <NavLink
- to={clusterTopicSettingsRelativePath}
- className={({ isActive }) => (isActive ? 'is-active' : '')}
- >
- Settings
- </NavLink>
- <NavLink
- to={clusterTopicStatisticsRelativePath}
- className={({ isActive }) => (isActive ? 'is-active' : '')}
- >
- Statistics
- </NavLink>
- </Navbar>
- <Suspense fallback={<PageLoader />}>
- <Routes>
- <Route index element={<Overview />} />
- <Route
- path={clusterTopicMessagesRelativePath}
- element={<Messages />}
- />
- <Route
- path={clusterTopicSettingsRelativePath}
- element={<Settings />}
- />
- <Route
- path={clusterTopicConsumerGroupsRelativePath}
- element={<TopicConsumerGroups />}
- />
- <Route
- path={clusterTopicStatisticsRelativePath}
- element={<Statistics />}
- />
- <Route path={clusterTopicEditRelativePath} element={<Edit />} />
- </Routes>
- </Suspense>
- <SlidingSidebar
- open={isSidebarOpen}
- onClose={closeSidebar}
- title="Produce Message"
- >
- <Suspense fallback={<PageLoader />}>
- <SendMessage closeSidebar={closeSidebar} />
- </Suspense>
- </SlidingSidebar>
- </>
- );
- };
- export default Topic;
|