diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 01097ccc4afac57321e5534348b7e7426f608d49..1241f9a0f005442ae9bbde401b66e4bd83529adb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -2930,6 +2930,11 @@ "resolved": "https://registry.npmjs.org/bulma/-/bulma-0.8.0.tgz", "integrity": "sha512-nhf3rGyiZh/VM7FrSJ/5KeLlfaFkXz0nYcXriynfPH4vVpnxnqyEwaNGdNCVzHyyCA3cHgkQAMpdF/SFbFGZfA==" }, + "bulma-switch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bulma-switch/-/bulma-switch-2.0.0.tgz", + "integrity": "sha512-myD38zeUfjmdduq+pXabhJEe3x2hQP48l/OI+Y0fO3HdDynZUY/VJygucvEAJKRjr4HxD5DnEm4yx+oDOBXpAA==" + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index ab89b19943a3e90275f75d4ebcaafe2cd059d0ef..e1fd95695c634754c37c0d5ddd5608f70770c5f6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "@types/redux": "^3.6.0", "@types/redux-thunk": "^2.1.0", "bulma": "^0.8.0", + "bulma-switch": "^2.0.0", "classnames": "^2.2.6", "node-sass": "^4.13.0", "react": "^16.12.0", diff --git a/frontend/src/components/Topics/List/List.tsx b/frontend/src/components/Topics/List/List.tsx index 544ab7468b95973636d5f229d74d3b9567b59325..96fefe5ef27b561bcdc91571f4a20fdaca574740 100644 --- a/frontend/src/components/Topics/List/List.tsx +++ b/frontend/src/components/Topics/List/List.tsx @@ -4,14 +4,37 @@ import ListItem from './ListItem'; interface Props { topics: Topic[]; + externalTopics: Topic[]; } const List: React.FC = ({ topics, + externalTopics, }) => { + const [showInternal, setShowInternal] = React.useState(true); + + const handleSwitch = () => setShowInternal(!showInternal); + + const items = showInternal ? topics : externalTopics; + return ( <>
+
+
+ + +
+
@@ -22,7 +45,7 @@ const List: React.FC = ({ - {topics.map((topic) => ( + {items.map((topic) => ( ({ topics: getTopicList(state), - totalBrokers: getTotalBrokers(state), + externalTopics: getExternalTopicList(state), }); diff --git a/frontend/src/components/Topics/TopicsContainer.ts b/frontend/src/components/Topics/TopicsContainer.ts index 0982639210b5d5b15536af12a9250f409d028886..b7d4a167ea1c21f50471b373a4690d4daaf2faff 100644 --- a/frontend/src/components/Topics/TopicsContainer.ts +++ b/frontend/src/components/Topics/TopicsContainer.ts @@ -1,8 +1,6 @@ import { connect } from 'react-redux'; -import { - fetchTopicList, - fetchBrokers, -} from 'redux/reducers/topics/thunks'; +import { fetchTopicList } from 'redux/reducers/topics/thunks'; +import { fetchBrokers } from 'redux/reducers/brokers/thunks'; import Topics from './Topics'; import { getIsTopicListFetched } from 'redux/reducers/topics/selectors'; import { RootState, ClusterId } from 'types'; diff --git a/frontend/src/redux/reducers/actionType.ts b/frontend/src/redux/reducers/actionType.ts index 981f2da3f1b52ba9a80f03b795127702fc813868..33006ca457550e38dc0f2fbc626e70973c642d6f 100644 --- a/frontend/src/redux/reducers/actionType.ts +++ b/frontend/src/redux/reducers/actionType.ts @@ -1,7 +1,9 @@ import topicsActionType from './topics/actionType'; import clustersActionType from './clusters/actionType'; +import brokersActionType from './brokers/actionType'; export default { ...topicsActionType, ...clustersActionType, + ...brokersActionType, }; diff --git a/frontend/src/redux/reducers/brokers/actionType.ts b/frontend/src/redux/reducers/brokers/actionType.ts new file mode 100644 index 0000000000000000000000000000000000000000..85c501c67739698bfd6f017e8ffec8bcbe2f9c8b --- /dev/null +++ b/frontend/src/redux/reducers/brokers/actionType.ts @@ -0,0 +1,7 @@ +enum ActionType { + GET_BROKERS__REQUEST = 'GET_BROKERS__REQUEST', + GET_BROKERS__SUCCESS = 'GET_BROKERS__SUCCESS', + GET_BROKERS__FAILURE = 'GET_BROKERS__FAILURE', +} + +export default ActionType; diff --git a/frontend/src/redux/reducers/brokers/actions.ts b/frontend/src/redux/reducers/brokers/actions.ts new file mode 100644 index 0000000000000000000000000000000000000000..3163a5bd57176e859fc1c6a17c224174313ff4b8 --- /dev/null +++ b/frontend/src/redux/reducers/brokers/actions.ts @@ -0,0 +1,9 @@ +import { createAsyncAction} from 'typesafe-actions'; +import ActionType from './actionType'; +import { Broker } from 'types'; + +export const fetchBrokersAction = createAsyncAction( + ActionType.GET_BROKERS__REQUEST, + ActionType.GET_BROKERS__SUCCESS, + ActionType.GET_BROKERS__FAILURE, +)(); diff --git a/frontend/src/redux/reducers/brokers/reducer.ts b/frontend/src/redux/reducers/brokers/reducer.ts new file mode 100644 index 0000000000000000000000000000000000000000..a44771accfbf006c843332d3cc2e56e64fba077e --- /dev/null +++ b/frontend/src/redux/reducers/brokers/reducer.ts @@ -0,0 +1,15 @@ +import { Broker, Action } from 'types'; +import actionType from 'redux/reducers/actionType'; + +export const initialState: Broker[] = []; + +const reducer = (state = initialState, action: Action): Broker[] => { + switch (action.type) { + case actionType.GET_BROKERS__SUCCESS: + return action.payload; + default: + return state; + } +}; + +export default reducer; diff --git a/frontend/src/redux/reducers/brokers/selectors.ts b/frontend/src/redux/reducers/brokers/selectors.ts new file mode 100644 index 0000000000000000000000000000000000000000..4dbb6cd08971ce7c69dc8d9f880c41ab29327f10 --- /dev/null +++ b/frontend/src/redux/reducers/brokers/selectors.ts @@ -0,0 +1,20 @@ +import { createSelector } from 'reselect'; +import { RootState, FetchStatus, Broker } from 'types'; +import { createFetchingSelector } from 'redux/reducers/loader/selectors'; + +const brokersState = ({ brokers }: RootState): Broker[] => brokers; + +const getBrokerListFetchingStatus = createFetchingSelector('GET_BROKERS'); + +export const getIsBrokerListFetched = createSelector( + getBrokerListFetchingStatus, + (status) => status === FetchStatus.fetched, +); + +const getBrokerList = createSelector(brokersState, (brokers) => brokers); + +export const getTotalBrokers = createSelector( + getIsBrokerListFetched, + getBrokerList, + (isFetched, brokers) => (isFetched && brokers !== undefined ? brokers.length : undefined), +); diff --git a/frontend/src/redux/reducers/brokers/thunks.ts b/frontend/src/redux/reducers/brokers/thunks.ts new file mode 100644 index 0000000000000000000000000000000000000000..c2cee03a7af8e90d9f1aa837812076b269db636e --- /dev/null +++ b/frontend/src/redux/reducers/brokers/thunks.ts @@ -0,0 +1,14 @@ +import { getBrokers } from 'lib/api'; +import { fetchBrokersAction } from './actions'; +import { PromiseThunk, ClusterId } from 'types'; + + +export const fetchBrokers = (clusterId: ClusterId): PromiseThunk => async (dispatch) => { + dispatch(fetchBrokersAction.request()); + try { + const { brokers } = await getBrokers(clusterId); + dispatch(fetchBrokersAction.success(brokers)); + } catch (e) { + dispatch(fetchBrokersAction.failure()); + } +} diff --git a/frontend/src/redux/reducers/clusters/reducer.ts b/frontend/src/redux/reducers/clusters/reducer.ts index 0e8fa376b6cf53b88e074bcae9e609e6f47056a3..dd1431e2e59f880794d296afb94ce8c9a83596d0 100644 --- a/frontend/src/redux/reducers/clusters/reducer.ts +++ b/frontend/src/redux/reducers/clusters/reducer.ts @@ -1,9 +1,9 @@ -import { ClustersState, Action } from 'types'; +import { Cluster, Action } from 'types'; import actionType from 'redux/reducers/actionType'; -export const initialState: ClustersState = []; +export const initialState: Cluster[] = []; -const reducer = (state = initialState, action: Action): ClustersState => { +const reducer = (state = initialState, action: Action): Cluster[] => { switch (action.type) { case actionType.GET_CLUSTERS__SUCCESS: return action.payload; diff --git a/frontend/src/redux/reducers/clusters/selectors.ts b/frontend/src/redux/reducers/clusters/selectors.ts index 6808c60450d7e872102e765adf34b9621731c78d..e631378493c314b2f2c34ba81bd32f0796fb6254 100644 --- a/frontend/src/redux/reducers/clusters/selectors.ts +++ b/frontend/src/redux/reducers/clusters/selectors.ts @@ -1,11 +1,14 @@ import { createSelector } from 'reselect'; -import { ClustersState, RootState, FetchStatus } from 'types'; +import { Cluster, RootState, FetchStatus } from 'types'; import { createFetchingSelector } from 'redux/reducers/loader/selectors'; -const clustersState = ({ clusters }: RootState): ClustersState => clusters; +const clustersState = ({ clusters }: RootState): Cluster[] => clusters; const getClusterListFetchingStatus = createFetchingSelector('GET_CLUSTERS'); -export const getIsClusterListFetched = createSelector(getClusterListFetchingStatus, (status) => status === FetchStatus.fetched); +export const getIsClusterListFetched = createSelector( + getClusterListFetchingStatus, + (status) => status === FetchStatus.fetched, +); -export const getClusterList = createSelector(clustersState, (items) => items); +export const getClusterList = createSelector(clustersState, (clusters) => clusters); diff --git a/frontend/src/redux/reducers/index.ts b/frontend/src/redux/reducers/index.ts index 5245a7959d0456c8d6f187be4329a0a59865d3e4..77437dc5c8782fe9cb1e208e9e6640e84f9cd6ee 100644 --- a/frontend/src/redux/reducers/index.ts +++ b/frontend/src/redux/reducers/index.ts @@ -1,11 +1,13 @@ import { combineReducers } from 'redux'; import topics from './topics/reducer'; import clusters from './clusters/reducer'; +import brokers from './brokers/reducer'; import loader from './loader/reducer'; import { RootState } from 'types'; export default combineReducers({ topics, clusters, + brokers, loader, }); diff --git a/frontend/src/redux/reducers/topics/actionType.ts b/frontend/src/redux/reducers/topics/actionType.ts index bdbc41070a51a9882f1dc2a1a18afc9914d23286..27ce978a99597dd4c45e02c86c220cb749175141 100644 --- a/frontend/src/redux/reducers/topics/actionType.ts +++ b/frontend/src/redux/reducers/topics/actionType.ts @@ -1,11 +1,7 @@ enum ActionType { - TOPICS__FETCH_REQUEST = 'TOPICS__FETCH_REQUEST', - TOPICS__FETCH_SUCCESS = 'TOPICS__FETCH_SUCCESS', - TOPICS__FETCH_FAILURE = 'TOPICS__FETCH_FAILURE', - - BROKERS__FETCH_REQUEST = 'BROKERS__FETCH_REQUEST', - BROKERS__FETCH_SUCCESS = 'BROKERS__FETCH_SUCCESS', - BROKERS__FETCH_FAILURE = 'BROKERS__FETCH_FAILURE', + GET_TOPICS__REQUEST = 'GET_TOPICS__REQUEST', + GET_TOPICS__SUCCESS = 'GET_TOPICS__SUCCESS', + GET_TOPICS__FAILURE = 'GET_TOPICS__FAILURE', } export default ActionType; diff --git a/frontend/src/redux/reducers/topics/actions.ts b/frontend/src/redux/reducers/topics/actions.ts index 46bc047108bcd6d73dacd247ffe6688f061094bc..b98f1d953c2d593cd4a2d731ac9a81ff1399090f 100644 --- a/frontend/src/redux/reducers/topics/actions.ts +++ b/frontend/src/redux/reducers/topics/actions.ts @@ -1,15 +1,9 @@ import { createAsyncAction} from 'typesafe-actions'; import ActionType from './actionType'; -import { Topic, Broker } from 'types'; +import { Topic} from 'types'; export const fetchTopicListAction = createAsyncAction( - ActionType.TOPICS__FETCH_REQUEST, - ActionType.TOPICS__FETCH_SUCCESS, - ActionType.TOPICS__FETCH_FAILURE, + ActionType.GET_TOPICS__REQUEST, + ActionType.GET_TOPICS__SUCCESS, + ActionType.GET_TOPICS__FAILURE, )(); - -export const fetchBrokersAction = createAsyncAction( - ActionType.BROKERS__FETCH_REQUEST, - ActionType.BROKERS__FETCH_SUCCESS, - ActionType.BROKERS__FETCH_FAILURE, -)(); diff --git a/frontend/src/redux/reducers/topics/reducer.ts b/frontend/src/redux/reducers/topics/reducer.ts index 736c06904d394835b10d69b399bc1855b4eff55d..804e612eee9ee69a4ea9e090ebd34f5014868612 100644 --- a/frontend/src/redux/reducers/topics/reducer.ts +++ b/frontend/src/redux/reducers/topics/reducer.ts @@ -1,46 +1,12 @@ -import { TopicsState, FetchStatus, Action } from 'types'; +import { Topic, Action } from 'types'; import actionType from 'redux/reducers/actionType'; -export const initialState: TopicsState = { - fetchStatus: FetchStatus.notFetched, - items: [], - brokers: undefined, -}; +export const initialState: Topic[] = []; -const reducer = (state = initialState, action: Action): TopicsState => { +const reducer = (state = initialState, action: Action): Topic[] => { switch (action.type) { - case actionType.TOPICS__FETCH_REQUEST: - return { - ...state, - fetchStatus: FetchStatus.fetching, - }; - case actionType.TOPICS__FETCH_SUCCESS: - return { - ...state, - fetchStatus: FetchStatus.fetched, - items: action.payload, - }; - case actionType.TOPICS__FETCH_FAILURE: - return { - ...state, - fetchStatus: FetchStatus.errorFetching, - }; - - case actionType.BROKERS__FETCH_REQUEST: - return { - ...state, - brokers: undefined, - }; - case actionType.BROKERS__FETCH_SUCCESS: - return { - ...state, - brokers: action.payload, - }; - case actionType.BROKERS__FETCH_FAILURE: - return { - ...state, - brokers: undefined, - }; + case actionType.GET_TOPICS__SUCCESS: + return action.payload; default: return state; } diff --git a/frontend/src/redux/reducers/topics/selectors.ts b/frontend/src/redux/reducers/topics/selectors.ts index bfa5565bb613c2161bcaeb7e8cdfb30ad9596d4e..de7b4143e55c76cd36524f98e34c1d9ae2943872 100644 --- a/frontend/src/redux/reducers/topics/selectors.ts +++ b/frontend/src/redux/reducers/topics/selectors.ts @@ -1,15 +1,25 @@ import { createSelector } from 'reselect'; -import { TopicsState, RootState, Topic, TopicName, FetchStatus } from 'types'; +import { RootState, Topic, TopicName, FetchStatus } from 'types'; +import { createFetchingSelector } from 'redux/reducers/loader/selectors'; -const topicsState = ({ topics }: RootState): TopicsState => topics; +const topicsState = ({ topics }: RootState): Topic[] => topics; -export const getIsTopicListFetched = createSelector(topicsState, ({ fetchStatus }) => fetchStatus === FetchStatus.fetched); +const getTopicListFetchingStatus = createFetchingSelector('GET_TOPICS'); -export const getTopicList = createSelector(topicsState, ({ items }) => items); +export const getIsTopicListFetched = createSelector( + getTopicListFetchingStatus, + (status) => status === FetchStatus.fetched, +); -export const getTotalBrokers = createSelector( +export const getTopicList = createSelector( + getIsTopicListFetched, topicsState, - ({ brokers }) => (brokers !== undefined ? brokers.length : undefined), + (isFetched, topics) => isFetched ? topics : [], +); + +export const getExternalTopicList = createSelector( + getTopicList, + (topics) => topics.filter(({ internal }) => !internal), ); interface TopicMap {[key: string]: Topic}; diff --git a/frontend/src/redux/reducers/topics/thunks.ts b/frontend/src/redux/reducers/topics/thunks.ts index aa6d9ec1fa3bb6e83d161ac3641c2878909c7095..3af05f4e8f36ac58a74a9b8aca93fc705bfcac74 100644 --- a/frontend/src/redux/reducers/topics/thunks.ts +++ b/frontend/src/redux/reducers/topics/thunks.ts @@ -1,14 +1,6 @@ -import { - getTopics, - getTopic, - getBrokers, -} from 'lib/api'; -import { - fetchTopicListAction, - fetchBrokersAction, -} from './actions'; -import { Topic, TopicName, PromiseThunk, ClusterId } from 'types'; - +import { getTopics } from 'lib/api'; +import { fetchTopicListAction } from './actions'; +import { PromiseThunk, ClusterId } from 'types'; export const fetchTopicList = (clusterId: ClusterId): PromiseThunk => async (dispatch) => { dispatch(fetchTopicListAction.request()); @@ -21,13 +13,3 @@ export const fetchTopicList = (clusterId: ClusterId): PromiseThunk => asyn dispatch(fetchTopicListAction.failure()); } } - -export const fetchBrokers = (clusterId: ClusterId): PromiseThunk => async (dispatch) => { - dispatch(fetchBrokersAction.request()); - try { - 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 edc607ddeccf6905d8cd4f1b09c691d12d4ceb2b..484343687bb820ee13d5c4530bdcde121801e9d9 100644 --- a/frontend/src/theme/bulma_overrides.scss +++ b/frontend/src/theme/bulma_overrides.scss @@ -5,3 +5,4 @@ @import "../../node_modules/bulma/sass/components/_all.sass"; @import "../../node_modules/bulma/sass/grid/_all.sass"; @import "../../node_modules/bulma/sass/layout/_all.sass"; +@import "../../node_modules/bulma-switch/src/sass/index.sass"; diff --git a/frontend/src/types/broker.ts b/frontend/src/types/broker.ts new file mode 100644 index 0000000000000000000000000000000000000000..29698732d3ff874b71481f96e91d22c9de4dfd6b --- /dev/null +++ b/frontend/src/types/broker.ts @@ -0,0 +1,4 @@ +export interface Broker { + id: string, + host: "broker", +}; diff --git a/frontend/src/types/cluster.ts b/frontend/src/types/cluster.ts index fcaa4b0726cffb7fbf09f66a581d70bff76dc005..b80bacaa0f426062dab3e71d5afe999a02776633 100644 --- a/frontend/src/types/cluster.ts +++ b/frontend/src/types/cluster.ts @@ -14,5 +14,3 @@ export interface Cluster { onlinePartitionCount: number; topicCount: number; } - -export type ClustersState = Cluster[]; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index e687b779df45a58cebeef5127b3c4749511f9af5..20b02263a8cf5dbc3fbe421899d8459257e88506 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -1,14 +1,19 @@ +import { AnyAction } from 'redux'; import { ActionType } from 'typesafe-actions'; +import { ThunkAction } from 'redux-thunk'; + 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'; +import * as brokersActions from 'redux/reducers/brokers/actions'; + +import { Topic } from './topic'; +import { Cluster } from './cluster'; +import { Broker } from './broker'; import { LoaderState } from './loader'; export * from './topic'; export * from './cluster'; +export * from './broker'; export * from './loader'; export enum FetchStatus { @@ -19,11 +24,12 @@ export enum FetchStatus { } export interface RootState { - topics: TopicsState; - clusters: ClustersState; + topics: Topic[]; + clusters: Cluster[]; + brokers: Broker[]; loader: LoaderState; } -export type Action = ActionType; +export type Action = ActionType; export type PromiseThunk = ThunkAction, RootState, undefined, AnyAction>; diff --git a/frontend/src/types/topic.ts b/frontend/src/types/topic.ts index 4a2eb5f83d8d7ce162af81a7e8fe9f331b165c74..070cca8bae134a0b88ed74db58c44f0964d2d4df 100644 --- a/frontend/src/types/topic.ts +++ b/frontend/src/types/topic.ts @@ -1,5 +1,3 @@ -import { FetchStatus } from 'types'; - export type TopicName = string; export interface TopicConfigs { [key: string]: string; @@ -22,14 +20,3 @@ export interface Topic { internal: boolean; partitions: TopicPartition[]; } - -export interface TopicsState { - fetchStatus: FetchStatus; - items: Topic[]; - brokers?: Broker[]; -} - -export interface Broker { - id: 1, - host: "broker", -};