Update the file structure
This commit is contained in:
parent
7193af2b52
commit
83ce3f7f5b
56 changed files with 199 additions and 222 deletions
|
@ -1,10 +1,10 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchClustersList,
|
fetchClustersList,
|
||||||
} from 'redux/reducers/clusters/thunks';
|
} from 'redux/actions';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import { getIsClusterListFetched } from 'redux/reducers/clusters/selectors';
|
import { getIsClusterListFetched } from 'redux/reducers/clusters/selectors';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
|
|
||||||
const mapStateToProps = (state: RootState) => ({
|
const mapStateToProps = (state: RootState) => ({
|
||||||
isClusterListFetched: getIsClusterListFetched(state),
|
isClusterListFetched: getIsClusterListFetched(state),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, BrokerMetrics, ZooKeeperStatus } from 'lib/interfaces';
|
import { ClusterId, BrokerMetrics, ZooKeeperStatus } from 'redux/interfaces';
|
||||||
import useInterval from 'lib/hooks/useInterval';
|
import useInterval from 'lib/hooks/useInterval';
|
||||||
import formatBytes from 'lib/utils/formatBytes';
|
import formatBytes from 'lib/utils/formatBytes';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
|
|
|
@ -2,10 +2,10 @@ import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchBrokers,
|
fetchBrokers,
|
||||||
fetchBrokerMetrics,
|
fetchBrokerMetrics,
|
||||||
} from 'redux/reducers/brokers/thunks';
|
} from 'redux/actions';
|
||||||
import Brokers from './Brokers';
|
import Brokers from './Brokers';
|
||||||
import * as brokerSelectors from 'redux/reducers/brokers/selectors';
|
import * as brokerSelectors from 'redux/reducers/brokers/selectors';
|
||||||
import { RootState, ClusterId } from 'lib/interfaces';
|
import { RootState, ClusterId } from 'redux/interfaces';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Cluster, ClusterStatus } from 'lib/interfaces';
|
import { Cluster, ClusterStatus } from 'redux/interfaces';
|
||||||
import formatBytes from 'lib/utils/formatBytes';
|
import formatBytes from 'lib/utils/formatBytes';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { clusterBrokersPath } from 'lib/paths';
|
import { clusterBrokersPath } from 'lib/paths';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { chunk } from 'lodash';
|
import { chunk } from 'lodash';
|
||||||
import { Cluster } from 'lib/interfaces';
|
import { Cluster } from 'redux/interfaces';
|
||||||
import MetricsWrapper from 'components/common/Dashboard/MetricsWrapper';
|
import MetricsWrapper from 'components/common/Dashboard/MetricsWrapper';
|
||||||
import Indicator from 'components/common/Dashboard/Indicator';
|
import Indicator from 'components/common/Dashboard/Indicator';
|
||||||
import ClusterWidget from './ClusterWidget';
|
import ClusterWidget from './ClusterWidget';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
getOnlineClusters,
|
getOnlineClusters,
|
||||||
getOfflineClusters,
|
getOfflineClusters,
|
||||||
} from 'redux/reducers/clusters/selectors';
|
} from 'redux/reducers/clusters/selectors';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
|
|
||||||
const mapStateToProps = (state: RootState) => ({
|
const mapStateToProps = (state: RootState) => ({
|
||||||
clusters: getClusterList(state),
|
clusters: getClusterList(state),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { CSSProperties } from 'react';
|
import React, { CSSProperties } from 'react';
|
||||||
import { Cluster } from 'lib/interfaces';
|
import { Cluster } from 'redux/interfaces';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { clusterBrokersPath, clusterTopicsPath } from 'lib/paths';
|
import { clusterBrokersPath, clusterTopicsPath } from 'lib/paths';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Cluster } from 'lib/interfaces';
|
import { Cluster } from 'redux/interfaces';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import ClusterMenu from './ClusterMenu';
|
import ClusterMenu from './ClusterMenu';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Nav from './Nav';
|
import Nav from './Nav';
|
||||||
import { getIsClusterListFetched, getClusterList } from 'redux/reducers/clusters/selectors';
|
import { getIsClusterListFetched, getClusterList } from 'redux/reducers/clusters/selectors';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
|
|
||||||
const mapStateToProps = (state: RootState) => ({
|
const mapStateToProps = (state: RootState) => ({
|
||||||
isClusterListFetched: getIsClusterListFetched(state),
|
isClusterListFetched: getIsClusterListFetched(state),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, Topic, TopicDetails, TopicName } from 'lib/interfaces';
|
import { ClusterId, Topic, TopicDetails, TopicName } from 'redux/interfaces';
|
||||||
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
||||||
import { NavLink, Switch, Route } from 'react-router-dom';
|
import { NavLink, Switch, Route } from 'react-router-dom';
|
||||||
import { clusterTopicsPath, clusterTopicSettingsPath, clusterTopicPath, clusterTopicMessagesPath } from 'lib/paths';
|
import { clusterTopicsPath, clusterTopicSettingsPath, clusterTopicPath, clusterTopicMessagesPath } from 'lib/paths';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, TopicName } from 'lib/interfaces';
|
import { ClusterId, TopicName } from 'redux/interfaces';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
clusterId: ClusterId;
|
clusterId: ClusterId;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Messages from './Messages';
|
import Messages from './Messages';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, Topic, TopicDetails, TopicName } from 'lib/interfaces';
|
import { ClusterId, Topic, TopicDetails, TopicName } from 'redux/interfaces';
|
||||||
import MetricsWrapper from 'components/common/Dashboard/MetricsWrapper';
|
import MetricsWrapper from 'components/common/Dashboard/MetricsWrapper';
|
||||||
import Indicator from 'components/common/Dashboard/Indicator';
|
import Indicator from 'components/common/Dashboard/Indicator';
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchTopicDetails,
|
fetchTopicDetails,
|
||||||
} from 'redux/reducers/topics/thunks';
|
} from 'redux/actions';
|
||||||
import Overview from './Overview';
|
import Overview from './Overview';
|
||||||
import { RootState, TopicName, ClusterId } from 'lib/interfaces';
|
import { RootState, TopicName, ClusterId } from 'redux/interfaces';
|
||||||
import { getTopicByName, getIsTopicDetailsFetched } from 'redux/reducers/topics/selectors';
|
import { getTopicByName, getIsTopicDetailsFetched } from 'redux/reducers/topics/selectors';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, TopicName, TopicConfig } from 'lib/interfaces';
|
import { ClusterId, TopicName, TopicConfig } from 'redux/interfaces';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
clusterId: ClusterId;
|
clusterId: ClusterId;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RootState, ClusterId, TopicName } from 'lib/interfaces';
|
import { RootState, ClusterId, TopicName } from 'redux/interfaces';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
fetchTopicConfig,
|
fetchTopicConfig,
|
||||||
} from 'redux/reducers/topics/thunks';
|
} from 'redux/actions';
|
||||||
import Settings from './Settings';
|
import Settings from './Settings';
|
||||||
import {
|
import {
|
||||||
getTopicConfig,
|
getTopicConfig,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TopicWithDetailedInfo, ClusterId } from 'lib/interfaces';
|
import { TopicWithDetailedInfo, ClusterId } from 'redux/interfaces';
|
||||||
import ListItem from './ListItem';
|
import ListItem from './ListItem';
|
||||||
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
import { getTopicList, getExternalTopicList } from 'redux/reducers/topics/selectors';
|
import { getTopicList, getExternalTopicList } from 'redux/reducers/topics/selectors';
|
||||||
import List from './List';
|
import List from './List';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { TopicWithDetailedInfo } from 'lib/interfaces';
|
import { TopicWithDetailedInfo } from 'redux/interfaces';
|
||||||
|
|
||||||
const ListItem: React.FC<TopicWithDetailedInfo> = ({
|
const ListItem: React.FC<TopicWithDetailedInfo> = ({
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId, CleanupPolicy, TopicFormData, TopicName } from 'lib/interfaces';
|
import { ClusterId, CleanupPolicy, TopicFormData, TopicName } from 'redux/interfaces';
|
||||||
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
|
||||||
import { clusterTopicsPath } from 'lib/paths';
|
import { clusterTopicsPath } from 'lib/paths';
|
||||||
import { useForm, ErrorMessage } from 'react-hook-form';
|
import { useForm, ErrorMessage } from 'react-hook-form';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RootState, ClusterId, TopicFormData, TopicName, Action } from 'lib/interfaces';
|
import { RootState, ClusterId, TopicFormData, TopicName, Action } from 'redux/interfaces';
|
||||||
import New from './New';
|
import New from './New';
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
import { createTopic } from 'redux/reducers/topics/thunks';
|
import { createTopic } from 'redux/actions';
|
||||||
import { getTopicCreated } from 'redux/reducers/topics/selectors';
|
import { getTopicCreated } from 'redux/reducers/topics/selectors';
|
||||||
import { clusterTopicPath } from 'lib/paths';
|
import { clusterTopicPath } from 'lib/paths';
|
||||||
import { ThunkDispatch } from 'redux-thunk';
|
import { ThunkDispatch } from 'redux-thunk';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterId } from 'lib/interfaces';
|
import { ClusterId } from 'redux/interfaces';
|
||||||
import {
|
import {
|
||||||
Switch,
|
Switch,
|
||||||
Route,
|
Route,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { fetchTopicList } from 'redux/reducers/topics/thunks';
|
import { fetchTopicList } from 'redux/actions';
|
||||||
import Topics from './Topics';
|
import Topics from './Topics';
|
||||||
import { getIsTopicListFetched } from 'redux/reducers/topics/selectors';
|
import { getIsTopicListFetched } from 'redux/reducers/topics/selectors';
|
||||||
import { RootState, ClusterId } from 'lib/interfaces';
|
import { RootState, ClusterId } from 'redux/interfaces';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
|
|
|
@ -9,5 +9,7 @@ export const BASE_PARAMS: RequestInit = {
|
||||||
export const BASE_URL = process.env.REACT_APP_API_URL;
|
export const BASE_URL = process.env.REACT_APP_API_URL;
|
||||||
|
|
||||||
export const TOPIC_NAME_VALIDATION_PATTERN = RegExp(/^[.,A-Za-z0-9_-]+$/);
|
export const TOPIC_NAME_VALIDATION_PATTERN = RegExp(/^[.,A-Za-z0-9_-]+$/);
|
||||||
|
|
||||||
export const MILLISECONDS_IN_DAY = 86_400_000;
|
export const MILLISECONDS_IN_DAY = 86_400_000;
|
||||||
|
|
||||||
export const BYTES_IN_GB = 1_073_741_824;
|
export const BYTES_IN_GB = 1_073_741_824;
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { ClusterId, TopicName } from 'lib/interfaces';
|
import {
|
||||||
|
ClusterId,
|
||||||
|
TopicName,
|
||||||
|
} from 'redux/interfaces';
|
||||||
|
|
||||||
const clusterPath = (clusterId: ClusterId) => `/clusters/${clusterId}`;
|
const clusterPath = (clusterId: ClusterId) => `/clusters/${clusterId}`;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,16 @@
|
||||||
enum ActionType {
|
export enum ActionType {
|
||||||
|
GET_CLUSTERS__REQUEST = 'GET_CLUSTERS__REQUEST',
|
||||||
|
GET_CLUSTERS__SUCCESS = 'GET_CLUSTERS__SUCCESS',
|
||||||
|
GET_CLUSTERS__FAILURE = 'GET_CLUSTERS__FAILURE',
|
||||||
|
|
||||||
|
GET_BROKERS__REQUEST = 'GET_BROKERS__REQUEST',
|
||||||
|
GET_BROKERS__SUCCESS = 'GET_BROKERS__SUCCESS',
|
||||||
|
GET_BROKERS__FAILURE = 'GET_BROKERS__FAILURE',
|
||||||
|
|
||||||
|
GET_BROKER_METRICS__REQUEST = 'GET_BROKER_METRICS__REQUEST',
|
||||||
|
GET_BROKER_METRICS__SUCCESS = 'GET_BROKER_METRICS__SUCCESS',
|
||||||
|
GET_BROKER_METRICS__FAILURE = 'GET_BROKER_METRICS__FAILURE',
|
||||||
|
|
||||||
GET_TOPICS__REQUEST = 'GET_TOPICS__REQUEST',
|
GET_TOPICS__REQUEST = 'GET_TOPICS__REQUEST',
|
||||||
GET_TOPICS__SUCCESS = 'GET_TOPICS__SUCCESS',
|
GET_TOPICS__SUCCESS = 'GET_TOPICS__SUCCESS',
|
||||||
GET_TOPICS__FAILURE = 'GET_TOPICS__FAILURE',
|
GET_TOPICS__FAILURE = 'GET_TOPICS__FAILURE',
|
||||||
|
@ -14,6 +26,4 @@ enum ActionType {
|
||||||
POST_TOPIC__REQUEST = 'POST_TOPIC__REQUEST',
|
POST_TOPIC__REQUEST = 'POST_TOPIC__REQUEST',
|
||||||
POST_TOPIC__SUCCESS = 'POST_TOPIC__SUCCESS',
|
POST_TOPIC__SUCCESS = 'POST_TOPIC__SUCCESS',
|
||||||
POST_TOPIC__FAILURE = 'POST_TOPIC__FAILURE',
|
POST_TOPIC__FAILURE = 'POST_TOPIC__FAILURE',
|
||||||
}
|
};
|
||||||
|
|
||||||
export default ActionType;
|
|
|
@ -1,6 +1,32 @@
|
||||||
import { createAsyncAction} from 'typesafe-actions';
|
import { createAsyncAction} from 'typesafe-actions';
|
||||||
import ActionType from './actionType';
|
import { ActionType } from 'redux/actionType';
|
||||||
import { Topic, TopicDetails, TopicName, TopicConfig} from 'lib/interfaces';
|
import {
|
||||||
|
Broker,
|
||||||
|
BrokerMetrics,
|
||||||
|
Cluster,
|
||||||
|
Topic,
|
||||||
|
TopicConfig,
|
||||||
|
TopicDetails,
|
||||||
|
TopicName,
|
||||||
|
} from 'redux/interfaces';
|
||||||
|
|
||||||
|
export const fetchBrokersAction = createAsyncAction(
|
||||||
|
ActionType.GET_BROKERS__REQUEST,
|
||||||
|
ActionType.GET_BROKERS__SUCCESS,
|
||||||
|
ActionType.GET_BROKERS__FAILURE,
|
||||||
|
)<undefined, Broker[], undefined>();
|
||||||
|
|
||||||
|
export const fetchBrokerMetricsAction = createAsyncAction(
|
||||||
|
ActionType.GET_BROKER_METRICS__REQUEST,
|
||||||
|
ActionType.GET_BROKER_METRICS__SUCCESS,
|
||||||
|
ActionType.GET_BROKER_METRICS__FAILURE,
|
||||||
|
)<undefined, BrokerMetrics, undefined>();
|
||||||
|
|
||||||
|
export const fetchClusterListAction = createAsyncAction(
|
||||||
|
ActionType.GET_CLUSTERS__REQUEST,
|
||||||
|
ActionType.GET_CLUSTERS__SUCCESS,
|
||||||
|
ActionType.GET_CLUSTERS__FAILURE,
|
||||||
|
)<undefined, Cluster[], undefined>();
|
||||||
|
|
||||||
export const fetchTopicListAction = createAsyncAction(
|
export const fetchTopicListAction = createAsyncAction(
|
||||||
ActionType.GET_TOPICS__REQUEST,
|
ActionType.GET_TOPICS__REQUEST,
|
2
src/redux/actions/index.ts
Normal file
2
src/redux/actions/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actions';
|
||||||
|
export * from './thunks';
|
79
src/redux/actions/thunks.ts
Normal file
79
src/redux/actions/thunks.ts
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import * as api from 'redux/api';
|
||||||
|
import * as actions from './actions';
|
||||||
|
import {
|
||||||
|
PromiseThunk,
|
||||||
|
Cluster,
|
||||||
|
ClusterId,
|
||||||
|
TopicFormData,
|
||||||
|
TopicName,
|
||||||
|
} from 'redux/interfaces';
|
||||||
|
|
||||||
|
export const fetchBrokers = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchBrokersAction.request());
|
||||||
|
try {
|
||||||
|
const payload = await api.getBrokers(clusterId);
|
||||||
|
dispatch(actions.fetchBrokersAction.success(payload));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchBrokersAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchBrokerMetrics = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchBrokerMetricsAction.request());
|
||||||
|
try {
|
||||||
|
const payload = await api.getBrokerMetrics(clusterId);
|
||||||
|
dispatch(actions.fetchBrokerMetricsAction.success(payload));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchBrokerMetricsAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchClustersList = (): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchClusterListAction.request());
|
||||||
|
try {
|
||||||
|
const clusters: Cluster[] = await api.getClusters();
|
||||||
|
dispatch(actions.fetchClusterListAction.success(clusters));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchClusterListAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchTopicList = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchTopicListAction.request());
|
||||||
|
try {
|
||||||
|
const topics = await api.getTopics(clusterId);
|
||||||
|
dispatch(actions.fetchTopicListAction.success(topics));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchTopicListAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchTopicDetails = (clusterId: ClusterId, topicName: TopicName): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchTopicDetailsAction.request());
|
||||||
|
try {
|
||||||
|
const topicDetails = await api.getTopicDetails(clusterId, topicName);
|
||||||
|
dispatch(actions.fetchTopicDetailsAction.success({ topicName, details: topicDetails }));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchTopicDetailsAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchTopicConfig = (clusterId: ClusterId, topicName: TopicName): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchTopicConfigAction.request());
|
||||||
|
try {
|
||||||
|
const config = await api.getTopicConfig(clusterId, topicName);
|
||||||
|
dispatch(actions.fetchTopicConfigAction.success({ topicName, config }));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchTopicConfigAction.failure());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createTopic = (clusterId: ClusterId, form: TopicFormData): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.createTopicAction.request());
|
||||||
|
try {
|
||||||
|
await api.postTopic(clusterId, form);
|
||||||
|
dispatch(actions.createTopicAction.success());
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.createTopicAction.failure());
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import {
|
||||||
Broker,
|
Broker,
|
||||||
ClusterId,
|
ClusterId,
|
||||||
BrokerMetrics,
|
BrokerMetrics,
|
||||||
} from 'lib/interfaces';
|
} from 'redux/interfaces';
|
||||||
import {
|
import {
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
BASE_PARAMS,
|
BASE_PARAMS,
|
|
@ -1,6 +1,6 @@
|
||||||
import {
|
import {
|
||||||
Cluster,
|
Cluster,
|
||||||
} from 'lib/interfaces';
|
} from 'redux/interfaces';
|
||||||
import {
|
import {
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
BASE_PARAMS,
|
BASE_PARAMS,
|
|
@ -5,7 +5,7 @@ import {
|
||||||
TopicDetails,
|
TopicDetails,
|
||||||
TopicConfig,
|
TopicConfig,
|
||||||
TopicFormData,
|
TopicFormData,
|
||||||
} from 'lib/interfaces';
|
} from 'redux/interfaces';
|
||||||
import {
|
import {
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
BASE_PARAMS,
|
BASE_PARAMS,
|
|
@ -2,9 +2,7 @@ import { AnyAction } from 'redux';
|
||||||
import { ActionType } from 'typesafe-actions';
|
import { ActionType } from 'typesafe-actions';
|
||||||
import { ThunkAction } from 'redux-thunk';
|
import { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
import * as topicsActions from 'redux/reducers/topics/actions';
|
import * as actions from 'redux/actions/actions';
|
||||||
import * as clustersActions from 'redux/reducers/clusters/actions';
|
|
||||||
import * as brokersActions from 'redux/reducers/brokers/actions';
|
|
||||||
|
|
||||||
import { TopicsState } from './topic';
|
import { TopicsState } from './topic';
|
||||||
import { Cluster } from './cluster';
|
import { Cluster } from './cluster';
|
||||||
|
@ -30,6 +28,6 @@ export interface RootState {
|
||||||
loader: LoaderState;
|
loader: LoaderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action = ActionType<typeof topicsActions | typeof clustersActions | typeof brokersActions>;
|
export type Action = ActionType<typeof actions>;
|
||||||
|
|
||||||
export type PromiseThunk<T> = ThunkAction<Promise<T>, RootState, undefined, AnyAction>;
|
export type PromiseThunk<T> = ThunkAction<Promise<T>, RootState, undefined, AnyAction>;
|
|
@ -1,4 +1,4 @@
|
||||||
import { FetchStatus } from 'lib/interfaces';
|
import { FetchStatus } from 'redux/interfaces';
|
||||||
|
|
||||||
export interface LoaderState {
|
export interface LoaderState {
|
||||||
[key: string]: FetchStatus;
|
[key: string]: FetchStatus;
|
|
@ -1,9 +0,0 @@
|
||||||
import topicsActionType from './topics/actionType';
|
|
||||||
import clustersActionType from './clusters/actionType';
|
|
||||||
import brokersActionType from './brokers/actionType';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
...topicsActionType,
|
|
||||||
...clustersActionType,
|
|
||||||
...brokersActionType,
|
|
||||||
};
|
|
|
@ -1,11 +0,0 @@
|
||||||
enum ActionType {
|
|
||||||
GET_BROKERS__REQUEST = 'GET_BROKERS__REQUEST',
|
|
||||||
GET_BROKERS__SUCCESS = 'GET_BROKERS__SUCCESS',
|
|
||||||
GET_BROKERS__FAILURE = 'GET_BROKERS__FAILURE',
|
|
||||||
|
|
||||||
GET_BROKER_METRICS__REQUEST = 'GET_BROKER_METRICS__REQUEST',
|
|
||||||
GET_BROKER_METRICS__SUCCESS = 'GET_BROKER_METRICS__SUCCESS',
|
|
||||||
GET_BROKER_METRICS__FAILURE = 'GET_BROKER_METRICS__FAILURE',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ActionType;
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { createAsyncAction} from 'typesafe-actions';
|
|
||||||
import ActionType from './actionType';
|
|
||||||
import { Broker, BrokerMetrics } from 'lib/interfaces';
|
|
||||||
|
|
||||||
export const fetchBrokersAction = createAsyncAction(
|
|
||||||
ActionType.GET_BROKERS__REQUEST,
|
|
||||||
ActionType.GET_BROKERS__SUCCESS,
|
|
||||||
ActionType.GET_BROKERS__FAILURE,
|
|
||||||
)<undefined, Broker[], undefined>();
|
|
||||||
|
|
||||||
export const fetchBrokerMetricsAction = createAsyncAction(
|
|
||||||
ActionType.GET_BROKER_METRICS__REQUEST,
|
|
||||||
ActionType.GET_BROKER_METRICS__SUCCESS,
|
|
||||||
ActionType.GET_BROKER_METRICS__FAILURE,
|
|
||||||
)<undefined, BrokerMetrics, undefined>();
|
|
|
@ -1,5 +1,12 @@
|
||||||
import { Action, BrokersState, ZooKeeperStatus, BrokerMetrics } from 'lib/interfaces';
|
import {
|
||||||
import actionType from 'redux/reducers/actionType';
|
Action,
|
||||||
|
BrokersState,
|
||||||
|
ZooKeeperStatus,
|
||||||
|
BrokerMetrics,
|
||||||
|
} from 'redux/interfaces';
|
||||||
|
import {
|
||||||
|
ActionType,
|
||||||
|
} from 'redux/actionType';
|
||||||
|
|
||||||
export const initialState: BrokersState = {
|
export const initialState: BrokersState = {
|
||||||
items: [],
|
items: [],
|
||||||
|
@ -32,14 +39,14 @@ const updateBrokerSegmentSize = (state: BrokersState, payload: BrokerMetrics) =>
|
||||||
|
|
||||||
const reducer = (state = initialState, action: Action): BrokersState => {
|
const reducer = (state = initialState, action: Action): BrokersState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case actionType.GET_BROKERS__REQUEST:
|
case ActionType.GET_BROKERS__REQUEST:
|
||||||
return initialState;
|
return initialState;
|
||||||
case actionType.GET_BROKERS__SUCCESS:
|
case ActionType.GET_BROKERS__SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
items: action.payload,
|
items: action.payload,
|
||||||
};
|
};
|
||||||
case actionType.GET_BROKER_METRICS__SUCCESS:
|
case ActionType.GET_BROKER_METRICS__SUCCESS:
|
||||||
return updateBrokerSegmentSize(state, action.payload);
|
return updateBrokerSegmentSize(state, action.payload);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { RootState, FetchStatus, BrokersState } from 'lib/interfaces';
|
import { RootState, FetchStatus, BrokersState } from 'redux/interfaces';
|
||||||
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
||||||
|
|
||||||
const brokersState = ({ brokers }: RootState): BrokersState => brokers;
|
const brokersState = ({ brokers }: RootState): BrokersState => brokers;
|
||||||
|
@ -29,7 +29,6 @@ export const getMinDiskUsage = createSelector(
|
||||||
if (brokers.length === 0) {
|
if (brokers.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(...brokers.map(({ segmentSize }) => segmentSize));
|
return Math.min(...brokers.map(({ segmentSize }) => segmentSize));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -40,7 +39,6 @@ export const getMaxDiskUsage = createSelector(
|
||||||
if (brokers.length === 0) {
|
if (brokers.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.max(...brokers.map(({ segmentSize }) => segmentSize));
|
return Math.max(...brokers.map(({ segmentSize }) => segmentSize));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { getBrokers, getBrokerMetrics } from 'lib/api';
|
|
||||||
import {
|
|
||||||
fetchBrokersAction,
|
|
||||||
fetchBrokerMetricsAction,
|
|
||||||
} from './actions';
|
|
||||||
import { PromiseThunk, ClusterId } from 'lib/interfaces';
|
|
||||||
|
|
||||||
|
|
||||||
export const fetchBrokers = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchBrokersAction.request());
|
|
||||||
try {
|
|
||||||
const payload = await getBrokers(clusterId);
|
|
||||||
dispatch(fetchBrokersAction.success(payload));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchBrokersAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchBrokerMetrics = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchBrokerMetricsAction.request());
|
|
||||||
try {
|
|
||||||
const payload = await getBrokerMetrics(clusterId);
|
|
||||||
dispatch(fetchBrokerMetricsAction.success(payload));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchBrokerMetricsAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
enum ActionType {
|
|
||||||
GET_CLUSTERS__REQUEST = 'GET_CLUSTERS__REQUEST',
|
|
||||||
GET_CLUSTERS__SUCCESS = 'GET_CLUSTERS__SUCCESS',
|
|
||||||
GET_CLUSTERS__FAILURE = 'GET_CLUSTERS__FAILURE',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ActionType;
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { createAsyncAction} from 'typesafe-actions';
|
|
||||||
import ActionType from './actionType';
|
|
||||||
import { Cluster } from 'lib/interfaces';
|
|
||||||
|
|
||||||
export const fetchClusterListAction = createAsyncAction(
|
|
||||||
ActionType.GET_CLUSTERS__REQUEST,
|
|
||||||
ActionType.GET_CLUSTERS__SUCCESS,
|
|
||||||
ActionType.GET_CLUSTERS__FAILURE,
|
|
||||||
)<undefined, Cluster[], undefined>();
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Cluster, Action } from 'lib/interfaces';
|
import { Cluster, Action } from 'redux/interfaces';
|
||||||
import actionType from 'redux/reducers/actionType';
|
import { ActionType } from 'redux/actionType';
|
||||||
|
|
||||||
export const initialState: Cluster[] = [];
|
export const initialState: Cluster[] = [];
|
||||||
|
|
||||||
const reducer = (state = initialState, action: Action): Cluster[] => {
|
const reducer = (state = initialState, action: Action): Cluster[] => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case actionType.GET_CLUSTERS__SUCCESS:
|
case ActionType.GET_CLUSTERS__SUCCESS:
|
||||||
return action.payload;
|
return action.payload;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { Cluster, RootState, FetchStatus, ClusterStatus } from 'lib/interfaces';
|
import { Cluster, RootState, FetchStatus, ClusterStatus } from 'redux/interfaces';
|
||||||
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
||||||
|
|
||||||
const clustersState = ({ clusters }: RootState): Cluster[] => clusters;
|
const clustersState = ({ clusters }: RootState): Cluster[] => clusters;
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import {
|
|
||||||
getClusters,
|
|
||||||
} from 'lib/api';
|
|
||||||
import {
|
|
||||||
fetchClusterListAction,
|
|
||||||
} from './actions';
|
|
||||||
import { Cluster, PromiseThunk } from 'lib/interfaces';
|
|
||||||
|
|
||||||
export const fetchClustersList = (): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchClusterListAction.request());
|
|
||||||
|
|
||||||
try {
|
|
||||||
const clusters: Cluster[] = await getClusters();
|
|
||||||
|
|
||||||
dispatch(fetchClusterListAction.success(clusters));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchClusterListAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ import topics from './topics/reducer';
|
||||||
import clusters from './clusters/reducer';
|
import clusters from './clusters/reducer';
|
||||||
import brokers from './brokers/reducer';
|
import brokers from './brokers/reducer';
|
||||||
import loader from './loader/reducer';
|
import loader from './loader/reducer';
|
||||||
import { RootState } from 'lib/interfaces';
|
import { RootState } from 'redux/interfaces';
|
||||||
|
|
||||||
export default combineReducers<RootState>({
|
export default combineReducers<RootState>({
|
||||||
topics,
|
topics,
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
import { FetchStatus, Action, LoaderState } from 'lib/interfaces';
|
import {
|
||||||
|
FetchStatus,
|
||||||
|
Action,
|
||||||
|
LoaderState,
|
||||||
|
} from 'redux/interfaces';
|
||||||
|
|
||||||
export const initialState: LoaderState = {};
|
export const initialState: LoaderState = {};
|
||||||
|
|
||||||
const reducer = (state = initialState, action: Action): LoaderState => {
|
const reducer = (state = initialState, action: Action): LoaderState => {
|
||||||
const { type } = action;
|
const { type } = action;
|
||||||
const matches = /(.*)__(REQUEST|SUCCESS|FAILURE)/.exec(type);
|
const matches = /(.*)__(REQUEST|SUCCESS|FAILURE)$/.exec(type);
|
||||||
|
|
||||||
// not a *__REQUEST / *__SUCCESS / *__FAILURE actions, so we ignore them
|
// not a *__REQUEST / *__SUCCESS / *__FAILURE actions, so we ignore them
|
||||||
if (!matches) return state;
|
if (!matches) return state;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { RootState, FetchStatus } from 'lib/interfaces';
|
import { RootState, FetchStatus } from 'redux/interfaces';
|
||||||
|
|
||||||
export const createFetchingSelector = (action: string) =>
|
export const createFetchingSelector = (action: string) =>
|
||||||
(state: RootState) => (state.loader[action] || FetchStatus.notFetched);
|
(state: RootState) => (state.loader[action] || FetchStatus.notFetched);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Action, TopicsState, Topic } from 'lib/interfaces';
|
import { Action, TopicsState, Topic } from 'redux/interfaces';
|
||||||
import actionType from 'redux/reducers/actionType';
|
import { ActionType } from 'redux/actionType';
|
||||||
|
|
||||||
export const initialState: TopicsState = {
|
export const initialState: TopicsState = {
|
||||||
byName: {},
|
byName: {},
|
||||||
|
@ -29,9 +29,9 @@ const updateTopicList = (state: TopicsState, payload: Topic[]) => {
|
||||||
|
|
||||||
const reducer = (state = initialState, action: Action): TopicsState => {
|
const reducer = (state = initialState, action: Action): TopicsState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case actionType.GET_TOPICS__SUCCESS:
|
case ActionType.GET_TOPICS__SUCCESS:
|
||||||
return updateTopicList(state, action.payload);
|
return updateTopicList(state, action.payload);
|
||||||
case actionType.GET_TOPIC_DETAILS__SUCCESS:
|
case ActionType.GET_TOPIC_DETAILS__SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
byName: {
|
byName: {
|
||||||
|
@ -42,7 +42,7 @@ const reducer = (state = initialState, action: Action): TopicsState => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case actionType.GET_TOPIC_CONFIG__SUCCESS:
|
case ActionType.GET_TOPIC_CONFIG__SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
byName: {
|
byName: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { RootState, TopicName, FetchStatus, TopicsState } from 'lib/interfaces';
|
import { RootState, TopicName, FetchStatus, TopicsState } from 'redux/interfaces';
|
||||||
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
import { createFetchingSelector } from 'redux/reducers/loader/selectors';
|
||||||
|
|
||||||
const topicsState = ({ topics }: RootState): TopicsState => topics;
|
const topicsState = ({ topics }: RootState): TopicsState => topics;
|
||||||
|
@ -37,11 +37,10 @@ export const getTopicList = createSelector(
|
||||||
getAllNames,
|
getAllNames,
|
||||||
getTopicMap,
|
getTopicMap,
|
||||||
(isFetched, allNames, byName) => {
|
(isFetched, allNames, byName) => {
|
||||||
if (isFetched) {
|
if (!isFetched) {
|
||||||
return allNames.map((name) => byName[name])
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
}
|
||||||
|
return allNames.map((name) => byName[name])
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
import {
|
|
||||||
getTopics,
|
|
||||||
getTopicDetails,
|
|
||||||
getTopicConfig,
|
|
||||||
postTopic,
|
|
||||||
} from 'lib/api';
|
|
||||||
import {
|
|
||||||
fetchTopicListAction,
|
|
||||||
fetchTopicDetailsAction,
|
|
||||||
fetchTopicConfigAction,
|
|
||||||
createTopicAction,
|
|
||||||
} from './actions';
|
|
||||||
import { PromiseThunk, ClusterId, TopicName, TopicFormData } from 'lib/interfaces';
|
|
||||||
|
|
||||||
export const fetchTopicList = (clusterId: ClusterId): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchTopicListAction.request());
|
|
||||||
try {
|
|
||||||
const topics = await getTopics(clusterId);
|
|
||||||
dispatch(fetchTopicListAction.success(topics));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchTopicListAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchTopicDetails = (clusterId: ClusterId, topicName: TopicName): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchTopicDetailsAction.request());
|
|
||||||
try {
|
|
||||||
const topicDetails = await getTopicDetails(clusterId, topicName);
|
|
||||||
dispatch(fetchTopicDetailsAction.success({ topicName, details: topicDetails }));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchTopicDetailsAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchTopicConfig = (clusterId: ClusterId, topicName: TopicName): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(fetchTopicConfigAction.request());
|
|
||||||
try {
|
|
||||||
const config = await getTopicConfig(clusterId, topicName);
|
|
||||||
dispatch(fetchTopicConfigAction.success({ topicName, config }));
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(fetchTopicConfigAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createTopic = (clusterId: ClusterId, form: TopicFormData): PromiseThunk<void> => async (dispatch) => {
|
|
||||||
dispatch(createTopicAction.request());
|
|
||||||
|
|
||||||
try {
|
|
||||||
await postTopic(clusterId, form);
|
|
||||||
dispatch(createTopicAction.success());
|
|
||||||
} catch (e) {
|
|
||||||
dispatch(createTopicAction.failure());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue