diff --git a/frontend/src/redux/reducers/clusters/actionType.ts b/frontend/src/redux/reducers/clusters/actionType.ts index aef471b378..e4856edcea 100644 --- a/frontend/src/redux/reducers/clusters/actionType.ts +++ b/frontend/src/redux/reducers/clusters/actionType.ts @@ -1,7 +1,7 @@ enum ActionType { - CLUSTERS__FETCH_REQUEST = 'CLUSTERS__FETCH_REQUEST', - CLUSTERS__FETCH_SUCCESS = 'CLUSTERS__FETCH_SUCCESS', - CLUSTERS__FETCH_FAILURE = 'CLUSTERS__FETCH_FAILURE', + GET_CLUSTERS__REQUEST = 'GET_CLUSTERS__REQUEST', + GET_CLUSTERS__SUCCESS = 'GET_CLUSTERS__SUCCESS', + GET_CLUSTERS__FAILURE = 'GET_CLUSTERS__FAILURE', } export default ActionType; diff --git a/frontend/src/redux/reducers/clusters/actions.ts b/frontend/src/redux/reducers/clusters/actions.ts index 8c68473752..ffb704304b 100644 --- a/frontend/src/redux/reducers/clusters/actions.ts +++ b/frontend/src/redux/reducers/clusters/actions.ts @@ -3,7 +3,7 @@ import ActionType from './actionType'; import { Cluster } from 'types'; export const fetchClusterListAction = createAsyncAction( - ActionType.CLUSTERS__FETCH_REQUEST, - ActionType.CLUSTERS__FETCH_SUCCESS, - ActionType.CLUSTERS__FETCH_FAILURE, + ActionType.GET_CLUSTERS__REQUEST, + ActionType.GET_CLUSTERS__SUCCESS, + ActionType.GET_CLUSTERS__FAILURE, )(); diff --git a/frontend/src/redux/reducers/clusters/reducer.ts b/frontend/src/redux/reducers/clusters/reducer.ts index 52aee789b0..0e8fa376b6 100644 --- a/frontend/src/redux/reducers/clusters/reducer.ts +++ b/frontend/src/redux/reducers/clusters/reducer.ts @@ -1,30 +1,12 @@ -import { ClustersState, FetchStatus, Action } from 'types'; +import { ClustersState, Action } from 'types'; import actionType from 'redux/reducers/actionType'; -export const initialState: ClustersState = { - fetchStatus: FetchStatus.notFetched, - items: [], -}; +export const initialState: ClustersState = []; 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, - }; - + case actionType.GET_CLUSTERS__SUCCESS: + return action.payload; default: return state; } diff --git a/frontend/src/redux/reducers/clusters/selectors.ts b/frontend/src/redux/reducers/clusters/selectors.ts index a6b84c6337..6808c60450 100644 --- a/frontend/src/redux/reducers/clusters/selectors.ts +++ b/frontend/src/redux/reducers/clusters/selectors.ts @@ -1,8 +1,11 @@ import { createSelector } from 'reselect'; import { ClustersState, RootState, FetchStatus } from 'types'; +import { createFetchingSelector } from 'redux/reducers/loader/selectors'; const clustersState = ({ clusters }: RootState): ClustersState => clusters; -export const getIsClusterListFetched = createSelector(clustersState, ({ fetchStatus }) => fetchStatus === FetchStatus.fetched); +const getClusterListFetchingStatus = createFetchingSelector('GET_CLUSTERS'); -export const getClusterList = createSelector(clustersState, ({ items }) => items); +export const getIsClusterListFetched = createSelector(getClusterListFetchingStatus, (status) => status === FetchStatus.fetched); + +export const getClusterList = createSelector(clustersState, (items) => items); diff --git a/frontend/src/redux/reducers/index.ts b/frontend/src/redux/reducers/index.ts index 7cda17c601..5245a7959d 100644 --- a/frontend/src/redux/reducers/index.ts +++ b/frontend/src/redux/reducers/index.ts @@ -1,9 +1,11 @@ import { combineReducers } from 'redux'; import topics from './topics/reducer'; import clusters from './clusters/reducer'; +import loader from './loader/reducer'; import { RootState } from 'types'; export default combineReducers({ topics, clusters, + loader, }); diff --git a/frontend/src/redux/reducers/loader/reducer.ts b/frontend/src/redux/reducers/loader/reducer.ts new file mode 100644 index 0000000000..166273257f --- /dev/null +++ b/frontend/src/redux/reducers/loader/reducer.ts @@ -0,0 +1,35 @@ +import { FetchStatus, Action, LoaderState } from 'types'; + +export const initialState: LoaderState = {}; + +const reducer = (state = initialState, action: Action): LoaderState => { + const { type } = action; + const matches = /(.*)__(REQUEST|SUCCESS|FAILURE)/.exec(type); + + // not a *__REQUEST / *__SUCCESS / *__FAILURE actions, so we ignore them + if (!matches) return state; + + const [, requestName, requestState] = matches; + + switch (requestState) { + case 'REQUEST': + return { + ...state, + [requestName]: FetchStatus.fetching, + }; + case 'SUCCESS': + return { + ...state, + [requestName]: FetchStatus.fetched, + }; + case 'FAILURE': + return { + ...state, + [requestName]: FetchStatus.errorFetching, + }; + default: + return state; + } +}; + +export default reducer; diff --git a/frontend/src/redux/reducers/loader/selectors.ts b/frontend/src/redux/reducers/loader/selectors.ts new file mode 100644 index 0000000000..df32a2c9a6 --- /dev/null +++ b/frontend/src/redux/reducers/loader/selectors.ts @@ -0,0 +1,4 @@ +import { RootState, FetchStatus } from 'types'; + +export const createFetchingSelector = (action: string) => + (state: RootState) => (state.loader[action] || FetchStatus.notFetched); diff --git a/frontend/src/types/cluster.ts b/frontend/src/types/cluster.ts index 0780cbe189..fcaa4b0726 100644 --- a/frontend/src/types/cluster.ts +++ b/frontend/src/types/cluster.ts @@ -1,5 +1,3 @@ -import { FetchStatus } from "types"; - export enum ClusterStatus { Online = 'online', Offline = 'offline', @@ -17,7 +15,4 @@ export interface Cluster { topicCount: number; } -export interface ClustersState { - fetchStatus: FetchStatus; - items: Cluster[]; -} +export type ClustersState = Cluster[]; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 612d0f087e..e687b779df 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -5,9 +5,11 @@ import { ThunkAction } from 'redux-thunk'; import { TopicsState } from './topic'; import { AnyAction } from 'redux'; import { ClustersState } from './cluster'; +import { LoaderState } from './loader'; export * from './topic'; export * from './cluster'; +export * from './loader'; export enum FetchStatus { notFetched = 'notFetched', @@ -19,6 +21,7 @@ export enum FetchStatus { export interface RootState { topics: TopicsState; clusters: ClustersState; + loader: LoaderState; } export type Action = ActionType; diff --git a/frontend/src/types/loader.ts b/frontend/src/types/loader.ts new file mode 100644 index 0000000000..00213c15a3 --- /dev/null +++ b/frontend/src/types/loader.ts @@ -0,0 +1,5 @@ +import { FetchStatus } from "types"; + +export interface LoaderState { + [key: string]: FetchStatus; +}