mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -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 {
|
interface Dummy {
|
||||||
n: number;
|
n: number;
|
||||||
@ -11,15 +15,14 @@ interface Dummy {
|
|||||||
b: boolean;
|
b: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setup = (payload: Dummy) => {
|
const setup = (payload?: Dummy) => {
|
||||||
resetAllActionCreatorTypes();
|
resetAllActionCreatorTypes();
|
||||||
const actionCreator = actionCreatorFactory<Dummy>('dummy').create();
|
const actionCreator = actionCreatorFactory<Dummy>('dummy').create();
|
||||||
|
const noPayloadactionCreator = noPayloadActionCreatorFactory('NoPayload').create();
|
||||||
const result = actionCreator(payload);
|
const result = actionCreator(payload);
|
||||||
|
const noPayloadResult = noPayloadactionCreator();
|
||||||
|
|
||||||
return {
|
return { actionCreator, noPayloadactionCreator, result, noPayloadResult };
|
||||||
actionCreator,
|
|
||||||
result,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('actionCreatorFactory', () => {
|
describe('actionCreatorFactory', () => {
|
||||||
@ -46,7 +49,34 @@ describe('actionCreatorFactory', () => {
|
|||||||
setup(payload);
|
setup(payload);
|
||||||
|
|
||||||
expect(() => {
|
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();
|
}).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,10 +12,19 @@ export interface ActionCreator<Payload> {
|
|||||||
(payload: Payload): ActionOf<Payload>;
|
(payload: Payload): ActionOf<Payload>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NoPayloadActionCreator {
|
||||||
|
readonly type: string;
|
||||||
|
(): ActionOf<undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ActionCreatorFactory<Payload> {
|
export interface ActionCreatorFactory<Payload> {
|
||||||
create: () => ActionCreator<Payload>;
|
create: () => ActionCreator<Payload>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NoPayloadActionCreatorFactory {
|
||||||
|
create: () => NoPayloadActionCreator;
|
||||||
|
}
|
||||||
|
|
||||||
export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactory<Payload> => {
|
export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactory<Payload> => {
|
||||||
const create = (): ActionCreator<Payload> => {
|
const create = (): ActionCreator<Payload> => {
|
||||||
return Object.assign((payload: Payload): ActionOf<Payload> => ({ type, payload }), { type });
|
return Object.assign((payload: Payload): ActionOf<Payload> => ({ type, payload }), { type });
|
||||||
@ -30,5 +39,19 @@ export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactor
|
|||||||
return { create };
|
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
|
// Should only be used by tests
|
||||||
export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);
|
export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);
|
||||||
|
@ -26,7 +26,7 @@ const dummyReducerIntialState: DummyReducerState = {
|
|||||||
const dummyActionCreator = actionCreatorFactory<DummyReducerState>('dummy').create();
|
const dummyActionCreator = actionCreatorFactory<DummyReducerState>('dummy').create();
|
||||||
|
|
||||||
const dummyReducer = reducerFactory(dummyReducerIntialState)
|
const dummyReducer = reducerFactory(dummyReducerIntialState)
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dummyActionCreator,
|
filter: dummyActionCreator,
|
||||||
mapper: (state, action) => ({ ...state, ...action.payload }),
|
mapper: (state, action) => ({ ...state, ...action.payload }),
|
||||||
})
|
})
|
||||||
@ -76,7 +76,7 @@ describe('reducerFactory', () => {
|
|||||||
describe('given a handler is added', () => {
|
describe('given a handler is added', () => {
|
||||||
describe('when a handler with the same creator is added', () => {
|
describe('when a handler with the same creator is added', () => {
|
||||||
it('then is should throw', () => {
|
it('then is should throw', () => {
|
||||||
const faultyReducer = reducerFactory(dummyReducerIntialState).addHandler({
|
const faultyReducer = reducerFactory(dummyReducerIntialState).addMapper({
|
||||||
filter: dummyActionCreator,
|
filter: dummyActionCreator,
|
||||||
mapper: (state, action) => {
|
mapper: (state, action) => {
|
||||||
return { ...state, ...action.payload };
|
return { ...state, ...action.payload };
|
||||||
@ -84,7 +84,7 @@ describe('reducerFactory', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
faultyReducer.addHandler({
|
faultyReducer.addMapper({
|
||||||
filter: dummyActionCreator,
|
filter: dummyActionCreator,
|
||||||
mapper: state => {
|
mapper: state => {
|
||||||
return state;
|
return state;
|
||||||
|
@ -1,47 +1,45 @@
|
|||||||
import { ActionOf, ActionCreator } from './actionCreatorFactory';
|
import { ActionOf, ActionCreator } from './actionCreatorFactory';
|
||||||
|
import { Reducer } from 'redux';
|
||||||
|
|
||||||
export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
|
export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
|
||||||
|
|
||||||
export interface HandlerConfig<State, Payload> {
|
export interface MapperConfig<State, Payload> {
|
||||||
filter: ActionCreator<Payload>;
|
filter: ActionCreator<Payload>;
|
||||||
mapper: Mapper<State, Payload>;
|
mapper: Mapper<State, Payload>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddHandler<State> {
|
export interface AddMapper<State> {
|
||||||
addHandler: <Payload>(config: HandlerConfig<State, Payload>) => CreateReducer<State>;
|
addMapper: <Payload>(config: MapperConfig<State, Payload>) => CreateReducer<State>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateReducer<State> extends AddHandler<State> {
|
export interface CreateReducer<State> extends AddMapper<State> {
|
||||||
create: () => Mapper<State, any>;
|
create: () => Reducer<State, ActionOf<any>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const reducerFactory = <State>(initialState: State): AddHandler<State> => {
|
export const reducerFactory = <State>(initialState: State): AddMapper<State> => {
|
||||||
const allHandlerConfigs: Array<HandlerConfig<State, any>> = [];
|
const allMapperConfigs: Array<MapperConfig<State, any>> = [];
|
||||||
|
|
||||||
const addHandler = <Payload>(config: HandlerConfig<State, Payload>): CreateReducer<State> => {
|
const addMapper = <Payload>(config: MapperConfig<State, Payload>): CreateReducer<State> => {
|
||||||
if (allHandlerConfigs.some(c => c.filter.type === config.filter.type)) {
|
if (allMapperConfigs.some(c => c.filter.type === config.filter.type)) {
|
||||||
throw new Error(`There is already a handlers defined with the 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;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = () => (state: State = initialState, action: ActionOf<any>): State => {
|
const create = (): Reducer<State, ActionOf<any>> => (state: State = initialState, action: ActionOf<any>): State => {
|
||||||
const handlerConfig = allHandlerConfigs.filter(config => config.filter.type === action.type)[0];
|
const mapperConfig = allMapperConfigs.filter(config => config.filter.type === action.type)[0];
|
||||||
|
|
||||||
if (handlerConfig) {
|
if (mapperConfig) {
|
||||||
return handlerConfig.mapper(state, action);
|
return mapperConfig.mapper(state, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance: CreateReducer<State> = {
|
const instance: CreateReducer<State> = { addMapper, create };
|
||||||
addHandler,
|
|
||||||
create,
|
|
||||||
};
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
@ -9,51 +9,42 @@ import { buildNavModel } from './navModel';
|
|||||||
import { DataSourceSettings } from '@grafana/ui/src/types';
|
import { DataSourceSettings } from '@grafana/ui/src/types';
|
||||||
import { Plugin, StoreState } from 'app/types';
|
import { Plugin, StoreState } from 'app/types';
|
||||||
import { actionCreatorFactory } from 'app/core/redux';
|
import { actionCreatorFactory } from 'app/core/redux';
|
||||||
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
|
import { ActionOf, noPayloadActionCreatorFactory } from 'app/core/redux/actionCreatorFactory';
|
||||||
|
|
||||||
export enum ActionTypes {
|
export const dataSourceLoaded = actionCreatorFactory<DataSourceSettings>('LOAD_DATA_SOURCE').create();
|
||||||
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>(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>(
|
export const setDataSourceName = actionCreatorFactory<string>('SET_DATA_SOURCE_NAME').create();
|
||||||
ActionTypes.SetDataSourceTypeSearchQuery
|
|
||||||
).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
|
||||||
export type Action = UpdateLocationAction | UpdateNavIndexAction | ActionOf<any>;
|
| UpdateNavIndexAction
|
||||||
|
| ActionOf<DataSourceSettings>
|
||||||
|
| ActionOf<DataSourceSettings[]>
|
||||||
|
| ActionOf<Plugin>
|
||||||
|
| ActionOf<Plugin[]>;
|
||||||
|
|
||||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
||||||
|
|
||||||
export function loadDataSources(): ThunkResult<void> {
|
export function loadDataSources(): ThunkResult<void> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const response = await getBackendSrv().get('/api/datasources');
|
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> {
|
export function loadDataSourceTypes(): ThunkResult<void> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
dispatch(dataSourceTypesLoad({}));
|
dispatch(dataSourceTypesLoad());
|
||||||
const result = await getBackendSrv().get('/api/plugins', { enabled: 1, type: 'datasource' });
|
const result = await getBackendSrv().get('/api/plugins', { enabled: 1, type: 'datasource' });
|
||||||
dispatch(dataSourceTypesLoaded(result));
|
dispatch(dataSourceTypesLoaded(result));
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@ const initialState: DataSourcesState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const dataSourcesReducer = reducerFactory(initialState)
|
export const dataSourcesReducer = reducerFactory(initialState)
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dataSourcesLoaded,
|
filter: dataSourcesLoaded,
|
||||||
mapper: (state, action) => ({
|
mapper: (state, action) => ({
|
||||||
...state,
|
...state,
|
||||||
@ -38,23 +38,23 @@ export const dataSourcesReducer = reducerFactory(initialState)
|
|||||||
dataSourcesCount: action.payload.length,
|
dataSourcesCount: action.payload.length,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dataSourceLoaded,
|
filter: dataSourceLoaded,
|
||||||
mapper: (state, action) => ({ ...state, dataSource: action.payload }),
|
mapper: (state, action) => ({ ...state, dataSource: action.payload }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: setDataSourcesSearchQuery,
|
filter: setDataSourcesSearchQuery,
|
||||||
mapper: (state, action) => ({ ...state, searchQuery: action.payload }),
|
mapper: (state, action) => ({ ...state, searchQuery: action.payload }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: setDataSourcesLayoutMode,
|
filter: setDataSourcesLayoutMode,
|
||||||
mapper: (state, action) => ({ ...state, layoutMode: action.payload }),
|
mapper: (state, action) => ({ ...state, layoutMode: action.payload }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dataSourceTypesLoad,
|
filter: dataSourceTypesLoad,
|
||||||
mapper: state => ({ ...state, dataSourceTypes: [], isLoadingDataSources: true }),
|
mapper: state => ({ ...state, dataSourceTypes: [], isLoadingDataSources: true }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dataSourceTypesLoaded,
|
filter: dataSourceTypesLoaded,
|
||||||
mapper: (state, action) => ({
|
mapper: (state, action) => ({
|
||||||
...state,
|
...state,
|
||||||
@ -62,19 +62,19 @@ export const dataSourcesReducer = reducerFactory(initialState)
|
|||||||
isLoadingDataSources: false,
|
isLoadingDataSources: false,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: setDataSourceTypeSearchQuery,
|
filter: setDataSourceTypeSearchQuery,
|
||||||
mapper: (state, action) => ({ ...state, dataSourceTypeSearchQuery: action.payload }),
|
mapper: (state, action) => ({ ...state, dataSourceTypeSearchQuery: action.payload }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: dataSourceMetaLoaded,
|
filter: dataSourceMetaLoaded,
|
||||||
mapper: (state, action) => ({ ...state, dataSourceMeta: action.payload }),
|
mapper: (state, action) => ({ ...state, dataSourceMeta: action.payload }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: setDataSourceName,
|
filter: setDataSourceName,
|
||||||
mapper: (state, action) => ({ ...state, dataSource: { ...state.dataSource, name: action.payload } }),
|
mapper: (state, action) => ({ ...state, dataSource: { ...state.dataSource, name: action.payload } }),
|
||||||
})
|
})
|
||||||
.addHandler({
|
.addMapper({
|
||||||
filter: setIsDefault,
|
filter: setIsDefault,
|
||||||
mapper: (state, action) => ({
|
mapper: (state, action) => ({
|
||||||
...state,
|
...state,
|
||||||
|
Loading…
Reference in New Issue
Block a user