Confirmation modal for topic & schema delete actions (#384)
This commit is contained in:
parent
9d62670eef
commit
ca4b3f12f9
10 changed files with 216 additions and 52 deletions
|
@ -1,13 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
import { SchemaSubject } from 'generated-sources';
|
import { SchemaSubject } from 'generated-sources';
|
||||||
import { ClusterName, SchemaName } from 'redux/interfaces';
|
import { ClusterName, SchemaName } from 'redux/interfaces';
|
||||||
import { clusterSchemasPath } from 'lib/paths';
|
import { clusterSchemasPath } from 'lib/paths';
|
||||||
import ClusterContext from 'components/contexts/ClusterContext';
|
import ClusterContext from 'components/contexts/ClusterContext';
|
||||||
import { useHistory } from 'react-router';
|
import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
|
||||||
import Breadcrumb from '../../common/Breadcrumb/Breadcrumb';
|
import PageLoader from 'components/common/PageLoader/PageLoader';
|
||||||
|
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
||||||
import SchemaVersion from './SchemaVersion';
|
import SchemaVersion from './SchemaVersion';
|
||||||
import LatestVersionItem from './LatestVersionItem';
|
import LatestVersionItem from './LatestVersionItem';
|
||||||
import PageLoader from '../../common/PageLoader/PageLoader';
|
|
||||||
|
|
||||||
export interface DetailsProps {
|
export interface DetailsProps {
|
||||||
subject: SchemaName;
|
subject: SchemaName;
|
||||||
|
@ -32,15 +33,20 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
isFetched,
|
isFetched,
|
||||||
}) => {
|
}) => {
|
||||||
const { isReadOnly } = React.useContext(ClusterContext);
|
const { isReadOnly } = React.useContext(ClusterContext);
|
||||||
|
const [
|
||||||
|
isDeleteSchemaConfirmationVisible,
|
||||||
|
setDeleteSchemaConfirmationVisible,
|
||||||
|
] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchSchemaVersions(clusterName, subject);
|
fetchSchemaVersions(clusterName, subject);
|
||||||
}, [fetchSchemaVersions, clusterName]);
|
}, [fetchSchemaVersions, clusterName]);
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const onDelete = async () => {
|
const onDelete = React.useCallback(() => {
|
||||||
await deleteSchema(clusterName, subject);
|
deleteSchema(clusterName, subject);
|
||||||
history.push(clusterSchemasPath(clusterName));
|
history.push(clusterSchemasPath(clusterName));
|
||||||
};
|
}, [deleteSchema, clusterName, subject]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="section">
|
<div className="section">
|
||||||
|
@ -84,10 +90,17 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
className="button is-danger is-small level-item"
|
className="button is-danger is-small level-item"
|
||||||
type="button"
|
type="button"
|
||||||
title="in development"
|
title="in development"
|
||||||
onClick={onDelete}
|
onClick={() => setDeleteSchemaConfirmationVisible(true)}
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={isDeleteSchemaConfirmationVisible}
|
||||||
|
onCancel={() => setDeleteSchemaConfirmationVisible(false)}
|
||||||
|
onConfirm={onDelete}
|
||||||
|
>
|
||||||
|
Are you sure want to remove <b>{subject}</b> schema?
|
||||||
|
</ConfirmationModal>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { shallow, mount } from 'enzyme';
|
import { shallow, mount, ReactWrapper } from 'enzyme';
|
||||||
import configureStore from 'redux/store/configureStore';
|
import configureStore from 'redux/store/configureStore';
|
||||||
import { StaticRouter } from 'react-router';
|
import { StaticRouter } from 'react-router';
|
||||||
import ClusterContext from 'components/contexts/ClusterContext';
|
import ClusterContext from 'components/contexts/ClusterContext';
|
||||||
|
@ -11,6 +11,11 @@ import { schema, versions } from './fixtures';
|
||||||
const clusterName = 'testCluster';
|
const clusterName = 'testCluster';
|
||||||
const fetchSchemaVersionsMock = jest.fn();
|
const fetchSchemaVersionsMock = jest.fn();
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'components/common/ConfirmationModal/ConfirmationModal',
|
||||||
|
() => 'mock-ConfirmationModal'
|
||||||
|
);
|
||||||
|
|
||||||
describe('Details', () => {
|
describe('Details', () => {
|
||||||
describe('Container', () => {
|
describe('Container', () => {
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
@ -92,28 +97,52 @@ describe('Details', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when schema has versions', () => {
|
describe('when schema has versions', () => {
|
||||||
const wrapper = shallow(setupWrapper({ versions }));
|
|
||||||
|
|
||||||
it('renders table heading with SchemaVersion', () => {
|
it('renders table heading with SchemaVersion', () => {
|
||||||
|
const wrapper = shallow(setupWrapper({ versions }));
|
||||||
expect(wrapper.exists('LatestVersionItem')).toBeTruthy();
|
expect(wrapper.exists('LatestVersionItem')).toBeTruthy();
|
||||||
expect(wrapper.exists('button')).toBeTruthy();
|
expect(wrapper.exists('button')).toBeTruthy();
|
||||||
expect(wrapper.exists('thead')).toBeTruthy();
|
expect(wrapper.exists('thead')).toBeTruthy();
|
||||||
expect(wrapper.find('SchemaVersion').length).toEqual(2);
|
expect(wrapper.find('SchemaVersion').length).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls deleteSchema on button click', () => {
|
it('matches snapshot', () => {
|
||||||
|
expect(shallow(setupWrapper({ versions }))).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('confirmation', () => {
|
||||||
|
let wrapper: ReactWrapper;
|
||||||
|
let confirmationModal: ReactWrapper;
|
||||||
const mockDelete = jest.fn();
|
const mockDelete = jest.fn();
|
||||||
const component = mount(
|
|
||||||
|
const findConfirmationModal = () =>
|
||||||
|
wrapper.find('mock-ConfirmationModal');
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
<StaticRouter>
|
<StaticRouter>
|
||||||
{setupWrapper({ versions, deleteSchema: mockDelete })}
|
{setupWrapper({ versions, deleteSchema: mockDelete })}
|
||||||
</StaticRouter>
|
</StaticRouter>
|
||||||
);
|
);
|
||||||
component.find('button').at(1).simulate('click');
|
confirmationModal = findConfirmationModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls deleteSchema after confirmation', () => {
|
||||||
|
expect(confirmationModal.prop('isOpen')).toBeFalsy();
|
||||||
|
wrapper.find('button').at(1).simulate('click');
|
||||||
|
expect(findConfirmationModal().prop('isOpen')).toBeTruthy();
|
||||||
|
// @ts-expect-error lack of typing of enzyme#invoke
|
||||||
|
confirmationModal.invoke('onConfirm')();
|
||||||
expect(mockDelete).toHaveBeenCalledTimes(1);
|
expect(mockDelete).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('matches snapshot', () => {
|
it('calls deleteSchema after confirmation', () => {
|
||||||
expect(shallow(setupWrapper({ versions }))).toMatchSnapshot();
|
expect(confirmationModal.prop('isOpen')).toBeFalsy();
|
||||||
|
wrapper.find('button').at(1).simulate('click');
|
||||||
|
expect(findConfirmationModal().prop('isOpen')).toBeTruthy();
|
||||||
|
// @ts-expect-error lack of typing of enzyme#invoke
|
||||||
|
wrapper.find('mock-ConfirmationModal').invoke('onCancel')();
|
||||||
|
expect(findConfirmationModal().prop('isOpen')).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,17 @@ exports[`Details View Initial state matches snapshot 1`] = `
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
|
<mock-ConfirmationModal
|
||||||
|
isOpen={false}
|
||||||
|
onCancel={[Function]}
|
||||||
|
onConfirm={[Function]}
|
||||||
|
>
|
||||||
|
Are you sure want to remove
|
||||||
|
<b>
|
||||||
|
test
|
||||||
|
</b>
|
||||||
|
schema?
|
||||||
|
</mock-ConfirmationModal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LatestVersionItem
|
<LatestVersionItem
|
||||||
|
@ -202,6 +213,17 @@ exports[`Details View when page with schema versions loaded when schema has vers
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
|
<mock-ConfirmationModal
|
||||||
|
isOpen={false}
|
||||||
|
onCancel={[Function]}
|
||||||
|
onConfirm={[Function]}
|
||||||
|
>
|
||||||
|
Are you sure want to remove
|
||||||
|
<b>
|
||||||
|
test
|
||||||
|
</b>
|
||||||
|
schema?
|
||||||
|
</mock-ConfirmationModal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LatestVersionItem
|
<LatestVersionItem
|
||||||
|
@ -340,6 +362,17 @@ exports[`Details View when page with schema versions loaded when versions are em
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
|
<mock-ConfirmationModal
|
||||||
|
isOpen={false}
|
||||||
|
onCancel={[Function]}
|
||||||
|
onConfirm={[Function]}
|
||||||
|
>
|
||||||
|
Are you sure want to remove
|
||||||
|
<b>
|
||||||
|
test
|
||||||
|
</b>
|
||||||
|
schema?
|
||||||
|
</mock-ConfirmationModal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LatestVersionItem
|
<LatestVersionItem
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from 'redux/interfaces';
|
} from 'redux/interfaces';
|
||||||
import DropdownItem from 'components/common/Dropdown/DropdownItem';
|
import DropdownItem from 'components/common/Dropdown/DropdownItem';
|
||||||
import Dropdown from 'components/common/Dropdown/Dropdown';
|
import Dropdown from 'components/common/Dropdown/Dropdown';
|
||||||
|
import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
|
||||||
|
|
||||||
export interface ListItemProps {
|
export interface ListItemProps {
|
||||||
topic: TopicWithDetailedInfo;
|
topic: TopicWithDetailedInfo;
|
||||||
|
@ -20,6 +21,11 @@ const ListItem: React.FC<ListItemProps> = ({
|
||||||
deleteTopic,
|
deleteTopic,
|
||||||
clusterName,
|
clusterName,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [
|
||||||
|
isDeleteTopicConfirmationVisible,
|
||||||
|
setDeleteTopicConfirmationVisible,
|
||||||
|
] = React.useState(false);
|
||||||
|
|
||||||
const outOfSyncReplicas = React.useMemo(() => {
|
const outOfSyncReplicas = React.useMemo(() => {
|
||||||
if (partitions === undefined || partitions.length === 0) {
|
if (partitions === undefined || partitions.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -54,7 +60,8 @@ const ListItem: React.FC<ListItemProps> = ({
|
||||||
{internal ? 'Internal' : 'External'}
|
{internal ? 'Internal' : 'External'}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="has-text-right">
|
<td>
|
||||||
|
<div className="has-text-right">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
label={
|
label={
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
|
@ -63,10 +70,20 @@ const ListItem: React.FC<ListItemProps> = ({
|
||||||
}
|
}
|
||||||
right
|
right
|
||||||
>
|
>
|
||||||
<DropdownItem onClick={deleteTopicHandler}>
|
<DropdownItem
|
||||||
|
onClick={() => setDeleteTopicConfirmationVisible(true)}
|
||||||
|
>
|
||||||
<span className="has-text-danger">Remove Topic</span>
|
<span className="has-text-danger">Remove Topic</span>
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={isDeleteTopicConfirmationVisible}
|
||||||
|
onCancel={() => setDeleteTopicConfirmationVisible(false)}
|
||||||
|
onConfirm={deleteTopicHandler}
|
||||||
|
>
|
||||||
|
Are you sure want to remove <b>{name}</b> topic?
|
||||||
|
</ConfirmationModal>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,11 @@ import ListItem, { ListItemProps } from '../ListItem';
|
||||||
const mockDelete = jest.fn();
|
const mockDelete = jest.fn();
|
||||||
const clusterName = 'local';
|
const clusterName = 'local';
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'components/common/ConfirmationModal/ConfirmationModal',
|
||||||
|
() => 'mock-ConfirmationModal'
|
||||||
|
);
|
||||||
|
|
||||||
describe('ListItem', () => {
|
describe('ListItem', () => {
|
||||||
const setupComponent = (props: Partial<ListItemProps> = {}) => (
|
const setupComponent = (props: Partial<ListItemProps> = {}) => (
|
||||||
<ListItem
|
<ListItem
|
||||||
|
@ -22,11 +27,25 @@ describe('ListItem', () => {
|
||||||
|
|
||||||
it('triggers the deleteTopic when clicked on the delete button', () => {
|
it('triggers the deleteTopic when clicked on the delete button', () => {
|
||||||
const wrapper = shallow(setupComponent());
|
const wrapper = shallow(setupComponent());
|
||||||
wrapper.find('DropdownItem').simulate('click');
|
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy();
|
||||||
|
wrapper.find('DropdownItem').last().simulate('click');
|
||||||
|
const modal = wrapper.find('mock-ConfirmationModal');
|
||||||
|
expect(modal.prop('isOpen')).toBeTruthy();
|
||||||
|
modal.simulate('confirm');
|
||||||
expect(mockDelete).toBeCalledTimes(1);
|
expect(mockDelete).toBeCalledTimes(1);
|
||||||
expect(mockDelete).toBeCalledWith(clusterName, internalTopicPayload.name);
|
expect(mockDelete).toBeCalledWith(clusterName, internalTopicPayload.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('closes ConfirmationModal when clicked on the cancel button', () => {
|
||||||
|
const wrapper = shallow(setupComponent());
|
||||||
|
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy();
|
||||||
|
wrapper.find('DropdownItem').last().simulate('click');
|
||||||
|
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeTruthy();
|
||||||
|
wrapper.find('mock-ConfirmationModal').simulate('cancel');
|
||||||
|
expect(mockDelete).toBeCalledTimes(0);
|
||||||
|
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders correct tags for internal topic', () => {
|
it('renders correct tags for internal topic', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<StaticRouter>
|
<StaticRouter>
|
||||||
|
@ -50,4 +69,20 @@ describe('ListItem', () => {
|
||||||
|
|
||||||
expect(wrapper.find('.tag.is-primary').text()).toEqual('External');
|
expect(wrapper.find('.tag.is-primary').text()).toEqual('External');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders correct out of sync replicas number', () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
<StaticRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{setupComponent({
|
||||||
|
topic: { ...externalTopicPayload, partitions: undefined },
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</StaticRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.find('td').at(2).text()).toEqual('0');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterName, TopicName } from 'redux/interfaces';
|
import { ClusterName, TopicName } from 'redux/interfaces';
|
||||||
import { Topic, TopicDetails } from 'generated-sources';
|
import { Topic, TopicDetails } from 'generated-sources';
|
||||||
import { NavLink, Switch, Route, Link } from 'react-router-dom';
|
import { NavLink, Switch, Route, Link, useHistory } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
clusterTopicSettingsPath,
|
clusterTopicSettingsPath,
|
||||||
clusterTopicPath,
|
clusterTopicPath,
|
||||||
clusterTopicMessagesPath,
|
clusterTopicMessagesPath,
|
||||||
clusterTopicsTopicEditPath,
|
clusterTopicsPath,
|
||||||
|
clusterTopicEditPath,
|
||||||
} from 'lib/paths';
|
} from 'lib/paths';
|
||||||
import ClusterContext from 'components/contexts/ClusterContext';
|
import ClusterContext from 'components/contexts/ClusterContext';
|
||||||
|
import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
|
||||||
import OverviewContainer from './Overview/OverviewContainer';
|
import OverviewContainer from './Overview/OverviewContainer';
|
||||||
import MessagesContainer from './Messages/MessagesContainer';
|
import MessagesContainer from './Messages/MessagesContainer';
|
||||||
import SettingsContainer from './Settings/SettingsContainer';
|
import SettingsContainer from './Settings/SettingsContainer';
|
||||||
|
@ -16,10 +18,20 @@ import SettingsContainer from './Settings/SettingsContainer';
|
||||||
interface Props extends Topic, TopicDetails {
|
interface Props extends Topic, TopicDetails {
|
||||||
clusterName: ClusterName;
|
clusterName: ClusterName;
|
||||||
topicName: TopicName;
|
topicName: TopicName;
|
||||||
|
deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Details: React.FC<Props> = ({ clusterName, topicName }) => {
|
const Details: React.FC<Props> = ({ clusterName, topicName, deleteTopic }) => {
|
||||||
|
const history = useHistory();
|
||||||
const { isReadOnly } = React.useContext(ClusterContext);
|
const { isReadOnly } = React.useContext(ClusterContext);
|
||||||
|
const [
|
||||||
|
isDeleteTopicConfirmationVisible,
|
||||||
|
setDeleteTopicConfirmationVisible,
|
||||||
|
] = React.useState(false);
|
||||||
|
const deleteTopicHandler = React.useCallback(() => {
|
||||||
|
deleteTopic(clusterName, topicName);
|
||||||
|
history.push(clusterTopicsPath(clusterName));
|
||||||
|
}, [clusterName, topicName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="box">
|
<div className="box">
|
||||||
|
@ -51,15 +63,35 @@ const Details: React.FC<Props> = ({ clusterName, topicName }) => {
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
<div className="navbar-end">
|
<div className="navbar-end">
|
||||||
|
<div className="buttons">
|
||||||
{!isReadOnly && (
|
{!isReadOnly && (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className="button is-danger"
|
||||||
|
type="button"
|
||||||
|
onClick={() => setDeleteTopicConfirmationVisible(true)}
|
||||||
|
>
|
||||||
|
Delete Topic
|
||||||
|
</button>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
to={clusterTopicsTopicEditPath(clusterName, topicName)}
|
to={clusterTopicEditPath(clusterName, topicName)}
|
||||||
className="button"
|
className="button"
|
||||||
>
|
>
|
||||||
Edit settings
|
Edit settings
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={isDeleteTopicConfirmationVisible}
|
||||||
|
onCancel={() => setDeleteTopicConfirmationVisible(false)}
|
||||||
|
onConfirm={deleteTopicHandler}
|
||||||
|
>
|
||||||
|
Are you sure want to remove <b>{topicName}</b> topic?
|
||||||
|
</ConfirmationModal>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<br />
|
<br />
|
||||||
<Switch>
|
<Switch>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { ClusterName, RootState, TopicName } from 'redux/interfaces';
|
import { ClusterName, RootState, TopicName } from 'redux/interfaces';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
|
import { deleteTopic } from 'redux/actions';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
|
@ -22,4 +23,10 @@ const mapStateToProps = (
|
||||||
topicName,
|
topicName,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withRouter(connect(mapStateToProps)(Details));
|
const mapDispatchToProps = {
|
||||||
|
deleteTopic,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)(Details)
|
||||||
|
);
|
||||||
|
|
|
@ -30,8 +30,7 @@ const mapStateToProps = (
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchTopicConfig: (clusterName: ClusterName, topicName: TopicName) =>
|
fetchTopicConfig,
|
||||||
fetchTopicConfig(clusterName, topicName),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(
|
export default withRouter(
|
||||||
|
|
|
@ -61,12 +61,11 @@ describe('Paths', () => {
|
||||||
'/ui/clusters/local/topics/topic123/messages'
|
'/ui/clusters/local/topics/topic123/messages'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('clusterTopicsTopicEditPath', () => {
|
it('clusterTopicEditPath', () => {
|
||||||
expect(paths.clusterTopicsTopicEditPath('local', 'topic123')).toEqual(
|
expect(paths.clusterTopicEditPath('local', 'topic123')).toEqual(
|
||||||
'/ui/clusters/local/topics/topic123/edit'
|
'/ui/clusters/local/topics/topic123/edit'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clusterConnectorsPath', () => {
|
it('clusterConnectorsPath', () => {
|
||||||
expect(paths.clusterConnectorsPath('local')).toEqual(
|
expect(paths.clusterConnectorsPath('local')).toEqual(
|
||||||
'/ui/clusters/local/connectors'
|
'/ui/clusters/local/connectors'
|
|
@ -41,7 +41,7 @@ export const clusterTopicMessagesPath = (
|
||||||
clusterName: ClusterName,
|
clusterName: ClusterName,
|
||||||
topicName: TopicName
|
topicName: TopicName
|
||||||
) => `${clusterTopicsPath(clusterName)}/${topicName}/messages`;
|
) => `${clusterTopicsPath(clusterName)}/${topicName}/messages`;
|
||||||
export const clusterTopicsTopicEditPath = (
|
export const clusterTopicEditPath = (
|
||||||
clusterName: ClusterName,
|
clusterName: ClusterName,
|
||||||
topicName: TopicName
|
topicName: TopicName
|
||||||
) => `${clusterTopicsPath(clusterName)}/${topicName}/edit`;
|
) => `${clusterTopicsPath(clusterName)}/${topicName}/edit`;
|
||||||
|
|
Loading…
Add table
Reference in a new issue