mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
Removed ActionTypes and fixed a noPayloadActionCreatorFactory
This commit is contained in:
parent
d3815beb1c
commit
2f47b225a0
@ -1,4 +1,8 @@
|
||||
import { actionCreatorFactory, resetAllActionCreatorTypes } from './actionCreatorFactory';
|
||||
import {
|
||||
actionCreatorFactory,
|
||||
resetAllActionCreatorTypes,
|
||||
noPayloadActionCreatorFactory,
|
||||
} from './actionCreatorFactory';
|
||||
|
||||
interface Dummy {
|
||||
n: number;
|
||||
@ -11,15 +15,14 @@ interface Dummy {
|
||||
b: boolean;
|
||||
}
|
||||
|
||||
const setup = (payload: Dummy) => {
|
||||
const setup = (payload?: Dummy) => {
|
||||
resetAllActionCreatorTypes();
|
||||
const actionCreator = actionCreatorFactory<Dummy>('dummy').create();
|
||||
const noPayloadactionCreator = noPayloadActionCreatorFactory('NoPayload').create();
|
||||
const result = actionCreator(payload);
|
||||
const noPayloadResult = noPayloadactionCreator();
|
||||
|
||||
return {
|
||||
actionCreator,
|
||||
result,
|
||||
};
|
||||
return { actionCreator, noPayloadactionCreator, result, noPayloadResult };
|
||||
};
|
||||
|
||||
describe('actionCreatorFactory', () => {
|
||||
@ -46,7 +49,34 @@ describe('actionCreatorFactory', () => {
|
||||
setup(payload);
|
||||
|
||||
expect(() => {
|
||||
actionCreatorFactory<Dummy>('DuMmY').create();
|
||||
noPayloadActionCreatorFactory('DuMmY').create();
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('noPayloadActionCreatorFactory', () => {
|
||||
describe('when calling create', () => {
|
||||
it('then it should create correct type string', () => {
|
||||
const { noPayloadResult, noPayloadactionCreator } = setup();
|
||||
|
||||
expect(noPayloadactionCreator.type).toEqual('NoPayload');
|
||||
expect(noPayloadResult.type).toEqual('NoPayload');
|
||||
});
|
||||
|
||||
it('then it should create correct payload', () => {
|
||||
const { noPayloadResult } = setup();
|
||||
|
||||
expect(noPayloadResult.payload).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling create with existing type', () => {
|
||||
it('then it should throw error', () => {
|
||||
setup();
|
||||
|
||||
expect(() => {
|
||||
actionCreatorFactory<Dummy>('nOpAyLoAd').create();
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
|
@ -12,10 +12,19 @@ export interface ActionCreator<Payload> {
|
||||
(payload: Payload): ActionOf<Payload>;
|
||||
}
|
||||
|
||||
export interface NoPayloadActionCreator {
|
||||
readonly type: string;
|
||||
(): ActionOf<undefined>;
|
||||
}
|
||||
|
||||
export interface ActionCreatorFactory<Payload> {
|
||||
create: () => ActionCreator<Payload>;
|
||||
}
|
||||
|
||||
export interface NoPayloadActionCreatorFactory {
|
||||
create: () => NoPayloadActionCreator;
|
||||
}
|
||||
|
||||
export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactory<Payload> => {
|
||||
const create = (): ActionCreator<Payload> => {
|
||||
return Object.assign((payload: Payload): ActionOf<Payload> => ({ type, payload }), { type });
|
||||
@ -30,5 +39,19 @@ export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactor
|
||||
return { create };
|
||||
};
|
||||
|
||||
export const noPayloadActionCreatorFactory = (type: string): NoPayloadActionCreatorFactory => {
|
||||
const create = (): NoPayloadActionCreator => {
|
||||
return Object.assign((): ActionOf<undefined> => ({ type, payload: undefined }), { type });
|
||||
};
|
||||
|
||||
if (allActionCreators.some(t => (t && type ? t.toLocaleUpperCase() === type.toLocaleUpperCase() : false))) {
|
||||
throw new Error(`There is already an actionCreator defined with the type ${type}`);
|
||||
}
|
||||
|
||||
allActionCreators.push(type);
|
||||
|
||||
return { create };
|
||||
};
|
||||
|
||||
// Should only be used by tests
|
||||
export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);
|
||||
|
@ -26,7 +26,7 @@ const dummyReducerIntialState: DummyReducerState = {
|
||||
const dummyActionCreator = actionCreatorFactory<DummyReducerState>('dummy').create();
|
||||
|
||||
const dummyReducer = reducerFactory(dummyReducerIntialState)
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dummyActionCreator,
|
||||
mapper: (state, action) => ({ ...state, ...action.payload }),
|
||||
})
|
||||
@ -76,7 +76,7 @@ describe('reducerFactory', () => {
|
||||
describe('given a handler is added', () => {
|
||||
describe('when a handler with the same creator is added', () => {
|
||||
it('then is should throw', () => {
|
||||
const faultyReducer = reducerFactory(dummyReducerIntialState).addHandler({
|
||||
const faultyReducer = reducerFactory(dummyReducerIntialState).addMapper({
|
||||
filter: dummyActionCreator,
|
||||
mapper: (state, action) => {
|
||||
return { ...state, ...action.payload };
|
||||
@ -84,7 +84,7 @@ describe('reducerFactory', () => {
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
faultyReducer.addHandler({
|
||||
faultyReducer.addMapper({
|
||||
filter: dummyActionCreator,
|
||||
mapper: state => {
|
||||
return state;
|
||||
|
@ -1,47 +1,45 @@
|
||||
import { ActionOf, ActionCreator } from './actionCreatorFactory';
|
||||
import { Reducer } from 'redux';
|
||||
|
||||
export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
|
||||
|
||||
export interface HandlerConfig<State, Payload> {
|
||||
export interface MapperConfig<State, Payload> {
|
||||
filter: ActionCreator<Payload>;
|
||||
mapper: Mapper<State, Payload>;
|
||||
}
|
||||
|
||||
export interface AddHandler<State> {
|
||||
addHandler: <Payload>(config: HandlerConfig<State, Payload>) => CreateReducer<State>;
|
||||
export interface AddMapper<State> {
|
||||
addMapper: <Payload>(config: MapperConfig<State, Payload>) => CreateReducer<State>;
|
||||
}
|
||||
|
||||
export interface CreateReducer<State> extends AddHandler<State> {
|
||||
create: () => Mapper<State, any>;
|
||||
export interface CreateReducer<State> extends AddMapper<State> {
|
||||
create: () => Reducer<State, ActionOf<any>>;
|
||||
}
|
||||
|
||||
export const reducerFactory = <State>(initialState: State): AddHandler<State> => {
|
||||
const allHandlerConfigs: Array<HandlerConfig<State, any>> = [];
|
||||
export const reducerFactory = <State>(initialState: State): AddMapper<State> => {
|
||||
const allMapperConfigs: Array<MapperConfig<State, any>> = [];
|
||||
|
||||
const addHandler = <Payload>(config: HandlerConfig<State, Payload>): CreateReducer<State> => {
|
||||
if (allHandlerConfigs.some(c => c.filter.type === config.filter.type)) {
|
||||
throw new Error(`There is already a handlers defined with the type ${config.filter.type}`);
|
||||
const addMapper = <Payload>(config: MapperConfig<State, Payload>): CreateReducer<State> => {
|
||||
if (allMapperConfigs.some(c => c.filter.type === config.filter.type)) {
|
||||
throw new Error(`There is already a Mappers defined with the type ${config.filter.type}`);
|
||||
}
|
||||
|
||||
allHandlerConfigs.push(config);
|
||||
allMapperConfigs.push(config);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const create = () => (state: State = initialState, action: ActionOf<any>): State => {
|
||||
const handlerConfig = allHandlerConfigs.filter(config => config.filter.type === action.type)[0];
|
||||
const create = (): Reducer<State, ActionOf<any>> => (state: State = initialState, action: ActionOf<any>): State => {
|
||||
const mapperConfig = allMapperConfigs.filter(config => config.filter.type === action.type)[0];
|
||||
|
||||
if (handlerConfig) {
|
||||
return handlerConfig.mapper(state, action);
|
||||
if (mapperConfig) {
|
||||
return mapperConfig.mapper(state, action);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const instance: CreateReducer<State> = {
|
||||
addHandler,
|
||||
create,
|
||||
};
|
||||
const instance: CreateReducer<State> = { addMapper, create };
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
@ -9,51 +9,42 @@ import { buildNavModel } from './navModel';
|
||||
import { DataSourceSettings } from '@grafana/ui/src/types';
|
||||
import { Plugin, StoreState } from 'app/types';
|
||||
import { actionCreatorFactory } from 'app/core/redux';
|
||||
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
|
||||
import { ActionOf, noPayloadActionCreatorFactory } from 'app/core/redux/actionCreatorFactory';
|
||||
|
||||
export enum ActionTypes {
|
||||
LoadDataSources = 'LOAD_DATA_SOURCES',
|
||||
LoadDataSourceTypes = 'LOAD_DATA_SOURCE_TYPES',
|
||||
LoadedDataSourceTypes = 'LOADED_DATA_SOURCE_TYPES',
|
||||
LoadDataSource = 'LOAD_DATA_SOURCE',
|
||||
LoadDataSourceMeta = 'LOAD_DATA_SOURCE_META',
|
||||
SetDataSourcesSearchQuery = 'SET_DATA_SOURCES_SEARCH_QUERY',
|
||||
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
|
||||
SetDataSourceTypeSearchQuery = 'SET_DATA_SOURCE_TYPE_SEARCH_QUERY',
|
||||
SetDataSourceName = 'SET_DATA_SOURCE_NAME',
|
||||
SetIsDefault = 'SET_IS_DEFAULT',
|
||||
}
|
||||
export const dataSourceLoaded = actionCreatorFactory<DataSourceSettings>('LOAD_DATA_SOURCE').create();
|
||||
|
||||
export const dataSourceLoaded = actionCreatorFactory<DataSourceSettings>(ActionTypes.LoadDataSource).create();
|
||||
export const dataSourcesLoaded = actionCreatorFactory<DataSourceSettings[]>('LOAD_DATA_SOURCES').create();
|
||||
|
||||
export const dataSourcesLoaded = actionCreatorFactory<DataSourceSettings[]>(ActionTypes.LoadDataSources).create();
|
||||
export const dataSourceMetaLoaded = actionCreatorFactory<Plugin>('LOAD_DATA_SOURCE_META').create();
|
||||
|
||||
export const dataSourceMetaLoaded = actionCreatorFactory<Plugin>(ActionTypes.LoadDataSourceMeta).create();
|
||||
export const dataSourceTypesLoad = noPayloadActionCreatorFactory('LOAD_DATA_SOURCE_TYPES').create();
|
||||
|
||||
export const dataSourceTypesLoad = actionCreatorFactory(ActionTypes.LoadDataSourceTypes).create();
|
||||
export const dataSourceTypesLoaded = actionCreatorFactory<Plugin[]>('LOADED_DATA_SOURCE_TYPES').create();
|
||||
|
||||
export const dataSourceTypesLoaded = actionCreatorFactory<Plugin[]>(ActionTypes.LoadedDataSourceTypes).create();
|
||||
export const setDataSourcesSearchQuery = actionCreatorFactory<string>('SET_DATA_SOURCES_SEARCH_QUERY').create();
|
||||
|
||||
export const setDataSourcesSearchQuery = actionCreatorFactory<string>(ActionTypes.SetDataSourcesSearchQuery).create();
|
||||
export const setDataSourcesLayoutMode = actionCreatorFactory<LayoutMode>('SET_DATA_SOURCES_LAYOUT_MODE').create();
|
||||
|
||||
export const setDataSourcesLayoutMode = actionCreatorFactory<LayoutMode>(ActionTypes.SetDataSourcesLayoutMode).create();
|
||||
export const setDataSourceTypeSearchQuery = actionCreatorFactory<string>('SET_DATA_SOURCE_TYPE_SEARCH_QUERY').create();
|
||||
|
||||
export const setDataSourceTypeSearchQuery = actionCreatorFactory<string>(
|
||||
ActionTypes.SetDataSourceTypeSearchQuery
|
||||
).create();
|
||||
export const setDataSourceName = actionCreatorFactory<string>('SET_DATA_SOURCE_NAME').create();
|
||||
|
||||
export const setDataSourceName = actionCreatorFactory<string>(ActionTypes.SetDataSourceName).create();
|
||||
export const setIsDefault = actionCreatorFactory<boolean>('SET_IS_DEFAULT').create();
|
||||
|
||||
export const setIsDefault = actionCreatorFactory<boolean>(ActionTypes.SetIsDefault).create();
|
||||
|
||||
export type Action = UpdateLocationAction | UpdateNavIndexAction | ActionOf<any>;
|
||||
export type Action =
|
||||
| UpdateLocationAction
|
||||
| UpdateNavIndexAction
|
||||
| ActionOf<DataSourceSettings>
|
||||
| ActionOf<DataSourceSettings[]>
|
||||
| ActionOf<Plugin>
|
||||
| ActionOf<Plugin[]>;
|
||||
|
||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
||||
|
||||
export function loadDataSources(): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
const response = await getBackendSrv().get('/api/datasources');
|
||||
dataSourcesLoaded(response);
|
||||
dispatch(dataSourcesLoaded(response));
|
||||
};
|
||||
}
|
||||
|
||||
@ -91,7 +82,7 @@ export function addDataSource(plugin: Plugin): ThunkResult<void> {
|
||||
|
||||
export function loadDataSourceTypes(): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
dispatch(dataSourceTypesLoad({}));
|
||||
dispatch(dataSourceTypesLoad());
|
||||
const result = await getBackendSrv().get('/api/plugins', { enabled: 1, type: 'datasource' });
|
||||
dispatch(dataSourceTypesLoaded(result));
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ const initialState: DataSourcesState = {
|
||||
};
|
||||
|
||||
export const dataSourcesReducer = reducerFactory(initialState)
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dataSourcesLoaded,
|
||||
mapper: (state, action) => ({
|
||||
...state,
|
||||
@ -38,23 +38,23 @@ export const dataSourcesReducer = reducerFactory(initialState)
|
||||
dataSourcesCount: action.payload.length,
|
||||
}),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dataSourceLoaded,
|
||||
mapper: (state, action) => ({ ...state, dataSource: action.payload }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: setDataSourcesSearchQuery,
|
||||
mapper: (state, action) => ({ ...state, searchQuery: action.payload }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: setDataSourcesLayoutMode,
|
||||
mapper: (state, action) => ({ ...state, layoutMode: action.payload }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dataSourceTypesLoad,
|
||||
mapper: state => ({ ...state, dataSourceTypes: [], isLoadingDataSources: true }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dataSourceTypesLoaded,
|
||||
mapper: (state, action) => ({
|
||||
...state,
|
||||
@ -62,19 +62,19 @@ export const dataSourcesReducer = reducerFactory(initialState)
|
||||
isLoadingDataSources: false,
|
||||
}),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: setDataSourceTypeSearchQuery,
|
||||
mapper: (state, action) => ({ ...state, dataSourceTypeSearchQuery: action.payload }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: dataSourceMetaLoaded,
|
||||
mapper: (state, action) => ({ ...state, dataSourceMeta: action.payload }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: setDataSourceName,
|
||||
mapper: (state, action) => ({ ...state, dataSource: { ...state.dataSource, name: action.payload } }),
|
||||
})
|
||||
.addHandler({
|
||||
.addMapper({
|
||||
filter: setIsDefault,
|
||||
mapper: (state, action) => ({
|
||||
...state,
|
||||
|
Loading…
Reference in New Issue
Block a user