[UI] Loader reducer

This commit is contained in:
Oleg Shuralev 2020-01-06 13:44:34 +03:00
parent 3bfa1a7d1e
commit a70a688b64
No known key found for this signature in database
GPG key ID: 0459DF80E1A2FD1B
10 changed files with 65 additions and 36 deletions

View file

@ -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;

View file

@ -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,
)<undefined, Cluster[], undefined>();

View file

@ -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;
}

View file

@ -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);

View file

@ -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<RootState>({
topics,
clusters,
loader,
});

View file

@ -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;

View file

@ -0,0 +1,4 @@
import { RootState, FetchStatus } from 'types';
export const createFetchingSelector = (action: string) =>
(state: RootState) => (state.loader[action] || FetchStatus.notFetched);

View file

@ -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[];

View file

@ -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<typeof topicsActions | typeof clustersActions>;

View file

@ -0,0 +1,5 @@
import { FetchStatus } from "types";
export interface LoaderState {
[key: string]: FetchStatus;
}