From 1468adbc454096deaac9cc048360324db77fc203 Mon Sep 17 00:00:00 2001 From: Oleg Shuralev Date: Wed, 25 Dec 2019 09:33:17 +0300 Subject: [PATCH] Add Cluster --- frontend/src/components/App.scss | 101 ++++-------------- frontend/src/components/App.tsx | 77 ++++++------- frontend/src/components/AppContainer.tsx | 17 +++ frontend/src/components/Nav/ClusterMenu.tsx | 42 ++++++++ frontend/src/components/Nav/Nav.tsx | 38 +++++++ frontend/src/components/Nav/NavConatiner.ts | 11 ++ .../src/components/Topics/Details/Details.tsx | 1 - frontend/src/components/Topics/Topics.tsx | 11 +- .../src/components/Topics/TopicsContainer.ts | 16 ++- frontend/src/index.tsx | 4 +- frontend/src/lib/api/clusters.ts | 11 ++ frontend/src/lib/api/index.ts | 1 + frontend/src/lib/api/topics.ts | 24 ++--- frontend/src/lib/constants.ts | 9 ++ frontend/src/redux/reducers/actionType.ts | 6 +- .../src/redux/reducers/clusters/actionType.ts | 7 ++ .../src/redux/reducers/clusters/actions.ts | 9 ++ .../src/redux/reducers/clusters/reducer.ts | 33 ++++++ .../src/redux/reducers/clusters/selectors.ts | 8 ++ .../src/redux/reducers/clusters/thunks.ts | 19 ++++ frontend/src/redux/reducers/index.ts | 2 + frontend/src/redux/reducers/topics/thunks.ts | 10 +- frontend/src/theme/bulma_overrides.scss | 9 -- frontend/src/theme/index.scss | 23 ++++ frontend/src/types/cluster.ts | 23 ++++ frontend/src/types/index.ts | 7 +- 26 files changed, 350 insertions(+), 169 deletions(-) create mode 100644 frontend/src/components/AppContainer.tsx create mode 100644 frontend/src/components/Nav/ClusterMenu.tsx create mode 100644 frontend/src/components/Nav/Nav.tsx create mode 100644 frontend/src/components/Nav/NavConatiner.ts create mode 100644 frontend/src/lib/api/clusters.ts create mode 100644 frontend/src/lib/constants.ts create mode 100644 frontend/src/redux/reducers/clusters/actionType.ts create mode 100644 frontend/src/redux/reducers/clusters/actions.ts create mode 100644 frontend/src/redux/reducers/clusters/reducer.ts create mode 100644 frontend/src/redux/reducers/clusters/selectors.ts create mode 100644 frontend/src/redux/reducers/clusters/thunks.ts create mode 100644 frontend/src/types/cluster.ts diff --git a/frontend/src/components/App.scss b/frontend/src/components/App.scss index b5358fe5e8..2922058d3b 100644 --- a/frontend/src/components/App.scss +++ b/frontend/src/components/App.scss @@ -1,92 +1,29 @@ -$navbar-width: 64px; +$header-height: 52px; +$navbar-width: 250px; .Layout { - width: 100%; - height: 100%; - display: flex; - overflow: hidden; - position: relative; - background-color: #F7F7F7; - - &__navbar { - display: flex; - z-index: 4; - flex-direction: column; - width: $navbar-width; - margin-left: 0; - background-color: #192d3e; - box-shadow: 0 0 0 0 rgba(0,0,0,0.2), 0 0 0 0 rgba(0,0,0,0.12), 0px 2px 7px 0px rgba(0,0,0,0.2); - text-align: center; - - &Text { - display: none; - } - - &--expanded { - margin-left: 0; - width: 280px; - text-align: left; - - .Layout__navbar { - &Icon { - margin-right: 20px; - } - - &Text { - display: inline; - } - } - } - } - - &__logo { - height: 52px; - color: #fff; - text-align: center; - line-height: 52px; + &__header { + box-shadow: 0 0.46875rem 2.1875rem rgba(4,9,20,0.03), + 0 0.9375rem 1.40625rem rgba(4,9,20,0.03), + 0 0.25rem 0.53125rem rgba(4,9,20,0.05), + 0 0.125rem 0.1875rem rgba(4,9,20,0.03); } &__container { - flex: 1 1 auto; - overflow: auto; - z-index: 2; + margin-top: $header-height; + margin-left: $navbar-width; } - &__content { - margin-top: 52px; - } - - &__header { + &__navbar { + width: $navbar-width; + display: flex; + flex-direction: column; + box-shadow: 7px 0 60px rgba(0,0,0,0.05); position: fixed; - top: 0; - background-color: #F7F7F7; - width: 100%; - z-index: 3; - transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; - box-shadow: 0 0 0 0 rgba(0,0,0,0.2), 0px 3px 5px 0px rgba(0,0,0,0.1), 0 0 0 0 rgba(0,0,0,0.12); - } -} - -@media screen and (max-width: 1200px) { - .Layout__navbar { - margin-left: -$navbar-width; - - &--expanded { - margin-left: 0; - } - } -} - -@media screen and (max-width: 800px) { - .Layout__navbar { - margin-left: -$navbar-width; - - &--expanded { - margin-left: 0; - position: fixed; - top: 52px; - left: 0; - bottom: 0; - } + top: $header-height; + left: 0; + bottom: 0; + padding: 20px 20px; + } } diff --git a/frontend/src/components/App.tsx b/frontend/src/components/App.tsx index ba33b6c189..067a1b408a 100644 --- a/frontend/src/components/App.tsx +++ b/frontend/src/components/App.tsx @@ -2,60 +2,47 @@ import React from 'react'; import { Switch, Route, - NavLink, } from 'react-router-dom'; import './App.scss'; import TopicsContainer from './Topics/TopicsContainer'; +import NavConatiner from './Nav/NavConatiner'; +import PageLoader from './common/PageLoader/PageLoader'; -const App: React.FC = () => { - const [expandedNavbar, setExpandedNavbar] = React.useState(false); - const toggleNavbar = () => setExpandedNavbar(!expandedNavbar); +interface AppProps { + isClusterListFetched: boolean; + fetchClustersList: () => void; +} + +const App: React.FC = ({ + isClusterListFetched, + fetchClustersList, +}) => { + React.useEffect(() => { fetchClustersList() }, [fetchClustersList]); return (
- +
- -
- - - - Dashboard - - -
+ + {isClusterListFetched ? ( +
+ + + + Dashboard + + +
+ ) : ( + + )} +
); diff --git a/frontend/src/components/AppContainer.tsx b/frontend/src/components/AppContainer.tsx new file mode 100644 index 0000000000..b7cc2fd68b --- /dev/null +++ b/frontend/src/components/AppContainer.tsx @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { + fetchClustersList, +} from 'redux/reducers/clusters/thunks'; +import App from './App'; +import { getIsClusterListFetched } from 'redux/reducers/clusters/selectors'; +import { RootState } from 'types'; + +const mapStateToProps = (state: RootState) => ({ + isClusterListFetched: getIsClusterListFetched(state), +}); + +const mapDispatchToProps = { + fetchClustersList, +} + +export default connect(mapStateToProps, mapDispatchToProps)(App); diff --git a/frontend/src/components/Nav/ClusterMenu.tsx b/frontend/src/components/Nav/ClusterMenu.tsx new file mode 100644 index 0000000000..63a2ffbcb9 --- /dev/null +++ b/frontend/src/components/Nav/ClusterMenu.tsx @@ -0,0 +1,42 @@ +import React, { CSSProperties } from 'react'; +import { Cluster } from 'types'; +import { NavLink } from 'react-router-dom'; + +interface Props extends Cluster {} + +const DefaultIcon: React.FC = () => { + const style: CSSProperties = { + width: '.6rem', + left: '-8px', + top: '-4px', + position: 'relative', + }; + + return ( + + + + ) +}; + +const ClusterMenu: React.FC = ({ + id, + name, + defaultCluster, +}) => ( +
    +
  • + + {defaultCluster && } + {name} + +
      + + Topics + +
    +
  • +
+); + +export default ClusterMenu; diff --git a/frontend/src/components/Nav/Nav.tsx b/frontend/src/components/Nav/Nav.tsx new file mode 100644 index 0000000000..b84c025120 --- /dev/null +++ b/frontend/src/components/Nav/Nav.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { Cluster } from 'types'; +import { NavLink } from 'react-router-dom'; +import cx from 'classnames'; +import ClusterMenu from './ClusterMenu'; + +interface Props { + isClusterListFetched: boolean, + clusters: Cluster[]; + className?: string; +} + +const Nav: React.FC = ({ + isClusterListFetched, + clusters, + className, +}) => ( + +); + +export default Nav; diff --git a/frontend/src/components/Nav/NavConatiner.ts b/frontend/src/components/Nav/NavConatiner.ts new file mode 100644 index 0000000000..b18df8f0af --- /dev/null +++ b/frontend/src/components/Nav/NavConatiner.ts @@ -0,0 +1,11 @@ +import { connect } from 'react-redux'; +import Nav from './Nav'; +import { getIsClusterListFetched, getClusterList } from 'redux/reducers/clusters/selectors'; +import { RootState } from 'types'; + +const mapStateToProps = (state: RootState) => ({ + isClusterListFetched: getIsClusterListFetched(state), + clusters: getClusterList(state), +}); + +export default connect(mapStateToProps)(Nav); diff --git a/frontend/src/components/Topics/Details/Details.tsx b/frontend/src/components/Topics/Details/Details.tsx index b1d4b6ff4c..a39be081cd 100644 --- a/frontend/src/components/Topics/Details/Details.tsx +++ b/frontend/src/components/Topics/Details/Details.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { Topic } from 'types'; import ConfigRow from './ConfigRow'; import Partition from './Partition'; -import { NavLink } from 'react-router-dom'; const Details: React.FC<{ topic: Topic }> = ({ topic: { diff --git a/frontend/src/components/Topics/Topics.tsx b/frontend/src/components/Topics/Topics.tsx index e483e45ca8..700727b50a 100644 --- a/frontend/src/components/Topics/Topics.tsx +++ b/frontend/src/components/Topics/Topics.tsx @@ -6,20 +6,23 @@ import { import ListContainer from './List/ListContainer'; import DetailsContainer from './Details/DetailsContainer'; import PageLoader from 'components/common/PageLoader/PageLoader'; +import { ClusterId } from 'types'; interface Props { + clusterId: string; isFetched: boolean; - fetchBrokers: () => void; - fetchTopicList: () => void; + fetchBrokers: (clusterId: ClusterId) => void; + fetchTopicList: (clusterId: ClusterId) => void; } const Topics: React.FC = ({ + clusterId, isFetched, fetchBrokers, fetchTopicList, }) => { - React.useEffect(() => { fetchTopicList(); }, [fetchTopicList]); - React.useEffect(() => { fetchBrokers(); }, [fetchBrokers]); + React.useEffect(() => { fetchTopicList(clusterId); }, [fetchTopicList, clusterId]); + React.useEffect(() => { fetchBrokers(clusterId); }, [fetchBrokers, clusterId]); if (isFetched) { return ( diff --git a/frontend/src/components/Topics/TopicsContainer.ts b/frontend/src/components/Topics/TopicsContainer.ts index 751281b514..0982639210 100644 --- a/frontend/src/components/Topics/TopicsContainer.ts +++ b/frontend/src/components/Topics/TopicsContainer.ts @@ -5,15 +5,23 @@ import { } from 'redux/reducers/topics/thunks'; import Topics from './Topics'; import { getIsTopicListFetched } from 'redux/reducers/topics/selectors'; -import { RootState } from 'types'; +import { RootState, ClusterId } from 'types'; +import { RouteComponentProps } from 'react-router-dom'; -const mapStateToProps = (state: RootState) => ({ +interface RouteProps { + clusterId: string; +} + +interface OwnProps extends RouteComponentProps { } + +const mapStateToProps = (state: RootState, { match: { params: { clusterId } }}: OwnProps) => ({ isFetched: getIsTopicListFetched(state), + clusterId, }); const mapDispatchToProps = { - fetchTopicList, - fetchBrokers, + fetchTopicList: (clusterId: ClusterId) => fetchTopicList(clusterId), + fetchBrokers: (clusterId: ClusterId) => fetchBrokers(clusterId), } export default connect(mapStateToProps, mapDispatchToProps)(Topics); diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index e07a1043e1..bdf547a04d 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import './theme/index.scss'; -import App from './components/App'; +import AppContainer from './components/AppContainer'; import * as serviceWorker from './serviceWorker'; import configureStore from './redux/store/configureStore'; @@ -13,7 +13,7 @@ const store = configureStore(); ReactDOM.render( - + , document.getElementById('root'), diff --git a/frontend/src/lib/api/clusters.ts b/frontend/src/lib/api/clusters.ts new file mode 100644 index 0000000000..d68197beb5 --- /dev/null +++ b/frontend/src/lib/api/clusters.ts @@ -0,0 +1,11 @@ +import { + Cluster, +} from 'types'; +import { + BASE_URL, + BASE_PARAMS, +} from 'lib/constants'; + +export const getClusters = (): Promise => + fetch(`${BASE_URL}/clusters`, { ...BASE_PARAMS }) + .then(res => res.json()); diff --git a/frontend/src/lib/api/index.ts b/frontend/src/lib/api/index.ts index 7319ef7359..3f345a2ab7 100644 --- a/frontend/src/lib/api/index.ts +++ b/frontend/src/lib/api/index.ts @@ -1 +1,2 @@ export * from './topics'; +export * from './clusters'; diff --git a/frontend/src/lib/api/topics.ts b/frontend/src/lib/api/topics.ts index 9003c0fa4d..9507410b2e 100644 --- a/frontend/src/lib/api/topics.ts +++ b/frontend/src/lib/api/topics.ts @@ -2,27 +2,21 @@ import { TopicName, Topic, Broker, + ClusterId, } from 'types'; - -const BASE_PARAMS: RequestInit = { - credentials: 'include', - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/vnd.kafka.v2+json', - }, -}; - -const BASE_URL = 'http://localhost:8082'; +import { + BASE_URL, + BASE_PARAMS, +} from 'lib/constants'; export const getTopic = (name: TopicName): Promise => fetch(`${BASE_URL}/topics/${name}`, { ...BASE_PARAMS }) .then(res => res.json()); -export const getTopics = (): Promise => - fetch(`${BASE_URL}/topics`, { ...BASE_PARAMS }) +export const getTopics = (clusterId: ClusterId): Promise => + fetch(`${BASE_URL}/clusters/${clusterId}/topics`, { ...BASE_PARAMS }) .then(res => res.json()); -export const getBrokers = (): Promise<{ brokers: Broker[] }> => - fetch(`${BASE_URL}/brokers`, { ...BASE_PARAMS }) +export const getBrokers = (clusterId: ClusterId): Promise<{ brokers: Broker[] }> => + fetch(`${BASE_URL}/clusters/${clusterId}/brokers`, { ...BASE_PARAMS }) .then(res => res.json()); diff --git a/frontend/src/lib/constants.ts b/frontend/src/lib/constants.ts new file mode 100644 index 0000000000..56e9cfd1f8 --- /dev/null +++ b/frontend/src/lib/constants.ts @@ -0,0 +1,9 @@ +export const BASE_PARAMS: RequestInit = { + credentials: 'include', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, +}; + +export const BASE_URL = 'http://localhost:3004'; diff --git a/frontend/src/redux/reducers/actionType.ts b/frontend/src/redux/reducers/actionType.ts index 55cb5c49b0..981f2da3f1 100644 --- a/frontend/src/redux/reducers/actionType.ts +++ b/frontend/src/redux/reducers/actionType.ts @@ -1,3 +1,7 @@ import topicsActionType from './topics/actionType'; +import clustersActionType from './clusters/actionType'; -export default { ...topicsActionType }; +export default { + ...topicsActionType, + ...clustersActionType, +}; diff --git a/frontend/src/redux/reducers/clusters/actionType.ts b/frontend/src/redux/reducers/clusters/actionType.ts new file mode 100644 index 0000000000..aef471b378 --- /dev/null +++ b/frontend/src/redux/reducers/clusters/actionType.ts @@ -0,0 +1,7 @@ +enum ActionType { + CLUSTERS__FETCH_REQUEST = 'CLUSTERS__FETCH_REQUEST', + CLUSTERS__FETCH_SUCCESS = 'CLUSTERS__FETCH_SUCCESS', + CLUSTERS__FETCH_FAILURE = 'CLUSTERS__FETCH_FAILURE', +} + +export default ActionType; diff --git a/frontend/src/redux/reducers/clusters/actions.ts b/frontend/src/redux/reducers/clusters/actions.ts new file mode 100644 index 0000000000..8c68473752 --- /dev/null +++ b/frontend/src/redux/reducers/clusters/actions.ts @@ -0,0 +1,9 @@ +import { createAsyncAction} from 'typesafe-actions'; +import ActionType from './actionType'; +import { Cluster } from 'types'; + +export const fetchClusterListAction = createAsyncAction( + ActionType.CLUSTERS__FETCH_REQUEST, + ActionType.CLUSTERS__FETCH_SUCCESS, + ActionType.CLUSTERS__FETCH_FAILURE, +)(); diff --git a/frontend/src/redux/reducers/clusters/reducer.ts b/frontend/src/redux/reducers/clusters/reducer.ts new file mode 100644 index 0000000000..52aee789b0 --- /dev/null +++ b/frontend/src/redux/reducers/clusters/reducer.ts @@ -0,0 +1,33 @@ +import { ClustersState, FetchStatus, Action } from 'types'; +import actionType from 'redux/reducers/actionType'; + +export const initialState: ClustersState = { + fetchStatus: FetchStatus.notFetched, + items: [], +}; + +const reducer = (state = initialState, action: Action): ClustersState => { + switch (action.type) { + case actionType.CLUSTERS__FETCH_REQUEST: + return { + ...state, + fetchStatus: FetchStatus.fetching, + }; + case actionType.CLUSTERS__FETCH_SUCCESS: + return { + ...state, + fetchStatus: FetchStatus.fetched, + items: action.payload, + }; + case actionType.CLUSTERS__FETCH_FAILURE: + return { + ...state, + fetchStatus: FetchStatus.errorFetching, + }; + + default: + return state; + } +}; + +export default reducer; diff --git a/frontend/src/redux/reducers/clusters/selectors.ts b/frontend/src/redux/reducers/clusters/selectors.ts new file mode 100644 index 0000000000..a6b84c6337 --- /dev/null +++ b/frontend/src/redux/reducers/clusters/selectors.ts @@ -0,0 +1,8 @@ +import { createSelector } from 'reselect'; +import { ClustersState, RootState, FetchStatus } from 'types'; + +const clustersState = ({ clusters }: RootState): ClustersState => clusters; + +export const getIsClusterListFetched = createSelector(clustersState, ({ fetchStatus }) => fetchStatus === FetchStatus.fetched); + +export const getClusterList = createSelector(clustersState, ({ items }) => items); diff --git a/frontend/src/redux/reducers/clusters/thunks.ts b/frontend/src/redux/reducers/clusters/thunks.ts new file mode 100644 index 0000000000..78e11664fd --- /dev/null +++ b/frontend/src/redux/reducers/clusters/thunks.ts @@ -0,0 +1,19 @@ +import { + getClusters, +} from 'lib/api'; +import { + fetchClusterListAction, +} from './actions'; +import { Cluster, PromiseThunk } from 'types'; + +export const fetchClustersList = (): PromiseThunk => async (dispatch) => { + dispatch(fetchClusterListAction.request()); + + try { + const clusters: Cluster[] = await getClusters(); + + dispatch(fetchClusterListAction.success(clusters)); + } catch (e) { + dispatch(fetchClusterListAction.failure()); + } +} diff --git a/frontend/src/redux/reducers/index.ts b/frontend/src/redux/reducers/index.ts index aebf462d11..7cda17c601 100644 --- a/frontend/src/redux/reducers/index.ts +++ b/frontend/src/redux/reducers/index.ts @@ -1,7 +1,9 @@ import { combineReducers } from 'redux'; import topics from './topics/reducer'; +import clusters from './clusters/reducer'; import { RootState } from 'types'; export default combineReducers({ topics, + clusters, }); diff --git a/frontend/src/redux/reducers/topics/thunks.ts b/frontend/src/redux/reducers/topics/thunks.ts index b9c385b646..bdaf5e39c4 100644 --- a/frontend/src/redux/reducers/topics/thunks.ts +++ b/frontend/src/redux/reducers/topics/thunks.ts @@ -7,14 +7,14 @@ import { fetchTopicListAction, fetchBrokersAction, } from './actions'; -import { Topic, TopicName, PromiseThunk } from 'types'; +import { Topic, TopicName, PromiseThunk, ClusterId } from 'types'; -export const fetchTopicList = (): PromiseThunk => async (dispatch, getState) => { +export const fetchTopicList = (clusterId: ClusterId): PromiseThunk => async (dispatch) => { dispatch(fetchTopicListAction.request()); try { - const topics = await getTopics(); + const topics = await getTopics(clusterId); const detailedList = await Promise.all(topics.map((topic: TopicName): Promise => getTopic(topic))); dispatch(fetchTopicListAction.success(detailedList)); @@ -23,10 +23,10 @@ export const fetchTopicList = (): PromiseThunk => async (dispatch, getStat } } -export const fetchBrokers = (): PromiseThunk => async (dispatch, getState) => { +export const fetchBrokers = (clusterId: ClusterId): PromiseThunk => async (dispatch) => { dispatch(fetchBrokersAction.request()); try { - const { brokers } = await getBrokers(); + const { brokers } = await getBrokers(clusterId); dispatch(fetchBrokersAction.success(brokers)); } catch (e) { dispatch(fetchBrokersAction.failure()); diff --git a/frontend/src/theme/bulma_overrides.scss b/frontend/src/theme/bulma_overrides.scss index e8577deae0..edc607ddec 100644 --- a/frontend/src/theme/bulma_overrides.scss +++ b/frontend/src/theme/bulma_overrides.scss @@ -1,13 +1,4 @@ @import "../../node_modules/bulma/sass/utilities/_all.sass"; - -$menu-item-color: $white; -$menu-item-radius: 0; -$menu-item-hover-color: $white; -$menu-item-hover-background-color: transparent; -$menu-item-active-color: $text-strong; -$menu-item-active-background-color: $background; -$menu-list-border-left: 1px solid $border-light; - @import "../../node_modules/bulma/sass/base/_all.sass"; @import "../../node_modules/bulma/sass/elements/_all.sass"; @import "../../node_modules/bulma/sass/form/_all.sass"; diff --git a/frontend/src/theme/index.scss b/frontend/src/theme/index.scss index fb71b9cdd5..8941cef626 100644 --- a/frontend/src/theme/index.scss +++ b/frontend/src/theme/index.scss @@ -11,9 +11,32 @@ sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + background: repeating-linear-gradient( + 145deg, + rgba(0,0,0,.003), + rgba(0,0,0,.005) 5px, + rgba(0,0,0,0) 5px, + rgba(0,0,0,0) 10px + ), + repeating-linear-gradient( + -145deg, + rgba(0,0,0,.003), + rgba(0,0,0,.005) 5px, + rgba(0,0,0,0) 5px, + rgba(0,0,0,0) 10px + ); + background-color: $light; + } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +.has-text-overflow-ellipsis { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/frontend/src/types/cluster.ts b/frontend/src/types/cluster.ts new file mode 100644 index 0000000000..0780cbe189 --- /dev/null +++ b/frontend/src/types/cluster.ts @@ -0,0 +1,23 @@ +import { FetchStatus } from "types"; + +export enum ClusterStatus { + Online = 'online', + Offline = 'offline', +} + +export type ClusterId = string; + +export interface Cluster { + id: ClusterId; + name: string; + defaultCluster: boolean; + status: ClusterStatus; + brokerCount: number; + onlinePartitionCount: number; + topicCount: number; +} + +export interface ClustersState { + fetchStatus: FetchStatus; + items: Cluster[]; +} diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index a74ac5a4df..612d0f087e 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -1,9 +1,13 @@ import { ActionType } from 'typesafe-actions'; import * as topicsActions from 'redux/reducers/topics/actions'; +import * as clustersActions from 'redux/reducers/clusters/actions'; import { ThunkAction } from 'redux-thunk'; import { TopicsState } from './topic'; import { AnyAction } from 'redux'; +import { ClustersState } from './cluster'; + export * from './topic'; +export * from './cluster'; export enum FetchStatus { notFetched = 'notFetched', @@ -14,8 +18,9 @@ export enum FetchStatus { export interface RootState { topics: TopicsState; + clusters: ClustersState; } -export type Action = ActionType; +export type Action = ActionType; export type PromiseThunk = ThunkAction, RootState, undefined, AnyAction>;