diff --git a/frontend/src/redux/reducers/clusters/actionType.ts b/frontend/src/redux/reducers/clusters/actionType.ts index aef471b3786630627cb5de5b378dd6a83d4bf895..e4856edceadec05004a8445d5726df5112beb0fd 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 8c684737522e835f6b2bd567401a3f2ccae5beb6..ffb704304b7db43ef31c6e0b7f8ab284b421f3f6 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 52aee789b0523eeadd2227842b17597e7b875fa4..0e8fa376b6cf53b88e074bcae9e609e6f47056a3 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 a6b84c633799494ab924a92222979633fc547a9c..6808c60450d7e872102e765adf34b9621731c78d 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 7cda17c601654c35c1213df046f6f03488d8b3d3..5245a7959d0456c8d6f187be4329a0a59865d3e4 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 0000000000000000000000000000000000000000..166273257fdf9cc4dc1dc495abf2959863f3a588 --- /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 0000000000000000000000000000000000000000..df32a2c9a63c524d5ae3e5a6476e6463ca79a251 --- /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 0780cbe18945fea51558593660dbf4ddae06dd30..fcaa4b0726cffb7fbf09f66a581d70bff76dc005 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 612d0f087e0ca1d843eedd3cf37bc690c53e9242..e687b779df45a58cebeef5127b3c4749511f9af5 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 0000000000000000000000000000000000000000..00213c15a3a163f153bd6029251a3ed38d1f1cf2 --- /dev/null +++ b/frontend/src/types/loader.ts @@ -0,0 +1,5 @@ +import { FetchStatus } from "types"; + +export interface LoaderState { + [key: string]: FetchStatus; +}