Commit d3815beb by Hugo Häggmark

Refactored Datasources as POC

parent 2236a1a3
import { actionCreatorFactory } from './actionCreatorFactory';
import { reducerFactory } from './reducerFactory';
export { actionCreatorFactory, reducerFactory };
......@@ -28,7 +28,7 @@ const dummyActionCreator = actionCreatorFactory<DummyReducerState>('dummy').crea
const dummyReducer = reducerFactory(dummyReducerIntialState)
.addHandler({
filter: dummyActionCreator,
handler: (state, action) => ({ ...state, ...action.payload }),
mapper: (state, action) => ({ ...state, ...action.payload }),
})
.create();
......@@ -78,7 +78,7 @@ describe('reducerFactory', () => {
it('then is should throw', () => {
const faultyReducer = reducerFactory(dummyReducerIntialState).addHandler({
filter: dummyActionCreator,
handler: (state, action) => {
mapper: (state, action) => {
return { ...state, ...action.payload };
},
});
......@@ -86,7 +86,7 @@ describe('reducerFactory', () => {
expect(() => {
faultyReducer.addHandler({
filter: dummyActionCreator,
handler: state => {
mapper: state => {
return state;
},
});
......
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> {
filter: ActionCreator<Payload>;
handler: (state: State, action: ActionOf<Payload>) => State;
mapper: Mapper<State, Payload>;
}
export interface AddHandler<State> {
......@@ -11,7 +12,7 @@ export interface AddHandler<State> {
}
export interface CreateReducer<State> extends AddHandler<State> {
create: () => Reducer<State, ActionOf<any>>;
create: () => Mapper<State, any>;
}
export const reducerFactory = <State>(initialState: State): AddHandler<State> => {
......@@ -27,18 +28,14 @@ export const reducerFactory = <State>(initialState: State): AddHandler<State> =>
return instance;
};
const create = (): Reducer<State, ActionOf<any>> => {
const reducer: Reducer<State, ActionOf<any>> = (state: State = initialState, action: ActionOf<any>) => {
const validHandlers = allHandlerConfigs
.filter(config => config.filter.type === action.type)
.map(config => config.handler);
const create = () => (state: State = initialState, action: ActionOf<any>): State => {
const handlerConfig = allHandlerConfigs.filter(config => config.filter.type === action.type)[0];
return validHandlers.reduce((currentState, handler) => {
return handler(currentState, action);
}, state || initialState);
};
if (handlerConfig) {
return handlerConfig.mapper(state, action);
}
return reducer;
return state;
};
const instance: CreateReducer<State> = {
......
......@@ -5,6 +5,7 @@ import { NavModel } from 'app/types';
import { DataSourceSettings } from '@grafana/ui/src/types';
import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector';
import { getMockDataSources } from './__mocks__/dataSourcesMocks';
import { setDataSourcesSearchQuery, setDataSourcesLayoutMode } from './state/actions';
const setup = (propOverrides?: object) => {
const props: Props = {
......@@ -13,16 +14,16 @@ const setup = (propOverrides?: object) => {
loadDataSources: jest.fn(),
navModel: {
main: {
text: 'Configuration'
text: 'Configuration',
},
node: {
text: 'Data Sources'
}
text: 'Data Sources',
},
} as NavModel,
dataSourcesCount: 0,
searchQuery: '',
setDataSourcesSearchQuery: jest.fn(),
setDataSourcesLayoutMode: jest.fn(),
setDataSourcesSearchQuery,
setDataSourcesLayoutMode,
hasFetched: false,
};
......
......@@ -5,6 +5,7 @@ import { NavModel } from 'app/types';
import { DataSourceSettings } from '@grafana/ui';
import { getMockDataSource } from '../__mocks__/dataSourcesMocks';
import { getMockPlugin } from '../../plugins/__mocks__/pluginMocks';
import { setDataSourceName, setIsDefault } from '../state/actions';
const setup = (propOverrides?: object) => {
const props: Props = {
......@@ -14,9 +15,9 @@ const setup = (propOverrides?: object) => {
pageId: 1,
deleteDataSource: jest.fn(),
loadDataSource: jest.fn(),
setDataSourceName: jest.fn(),
setDataSourceName,
updateDataSource: jest.fn(),
setIsDefault: jest.fn(),
setIsDefault,
};
Object.assign(props, propOverrides);
......
......@@ -8,6 +8,8 @@ import { UpdateLocationAction } from 'app/core/actions/location';
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';
export enum ActionTypes {
LoadDataSources = 'LOAD_DATA_SOURCES',
......@@ -22,124 +24,36 @@ export enum ActionTypes {
SetIsDefault = 'SET_IS_DEFAULT',
}
interface LoadDataSourcesAction {
type: ActionTypes.LoadDataSources;
payload: DataSourceSettings[];
}
export const dataSourceLoaded = actionCreatorFactory<DataSourceSettings>(ActionTypes.LoadDataSource).create();
interface SetDataSourcesSearchQueryAction {
type: ActionTypes.SetDataSourcesSearchQuery;
payload: string;
}
export const dataSourcesLoaded = actionCreatorFactory<DataSourceSettings[]>(ActionTypes.LoadDataSources).create();
interface SetDataSourcesLayoutModeAction {
type: ActionTypes.SetDataSourcesLayoutMode;
payload: LayoutMode;
}
export const dataSourceMetaLoaded = actionCreatorFactory<Plugin>(ActionTypes.LoadDataSourceMeta).create();
interface LoadDataSourceTypesAction {
type: ActionTypes.LoadDataSourceTypes;
}
export const dataSourceTypesLoad = actionCreatorFactory(ActionTypes.LoadDataSourceTypes).create();
interface LoadedDataSourceTypesAction {
type: ActionTypes.LoadedDataSourceTypes;
payload: Plugin[];
}
export const dataSourceTypesLoaded = actionCreatorFactory<Plugin[]>(ActionTypes.LoadedDataSourceTypes).create();
interface SetDataSourceTypeSearchQueryAction {
type: ActionTypes.SetDataSourceTypeSearchQuery;
payload: string;
}
export const setDataSourcesSearchQuery = actionCreatorFactory<string>(ActionTypes.SetDataSourcesSearchQuery).create();
interface LoadDataSourceAction {
type: ActionTypes.LoadDataSource;
payload: DataSourceSettings;
}
export const setDataSourcesLayoutMode = actionCreatorFactory<LayoutMode>(ActionTypes.SetDataSourcesLayoutMode).create();
interface LoadDataSourceMetaAction {
type: ActionTypes.LoadDataSourceMeta;
payload: Plugin;
}
export const setDataSourceTypeSearchQuery = actionCreatorFactory<string>(
ActionTypes.SetDataSourceTypeSearchQuery
).create();
interface SetDataSourceNameAction {
type: ActionTypes.SetDataSourceName;
payload: string;
}
export const setDataSourceName = actionCreatorFactory<string>(ActionTypes.SetDataSourceName).create();
interface SetIsDefaultAction {
type: ActionTypes.SetIsDefault;
payload: boolean;
}
export const setIsDefault = actionCreatorFactory<boolean>(ActionTypes.SetIsDefault).create();
const dataSourcesLoaded = (dataSources: DataSourceSettings[]): LoadDataSourcesAction => ({
type: ActionTypes.LoadDataSources,
payload: dataSources,
});
const dataSourceLoaded = (dataSource: DataSourceSettings): LoadDataSourceAction => ({
type: ActionTypes.LoadDataSource,
payload: dataSource,
});
const dataSourceMetaLoaded = (dataSourceMeta: Plugin): LoadDataSourceMetaAction => ({
type: ActionTypes.LoadDataSourceMeta,
payload: dataSourceMeta,
});
const dataSourceTypesLoad = (): LoadDataSourceTypesAction => ({
type: ActionTypes.LoadDataSourceTypes,
});
const dataSourceTypesLoaded = (dataSourceTypes: Plugin[]): LoadedDataSourceTypesAction => ({
type: ActionTypes.LoadedDataSourceTypes,
payload: dataSourceTypes,
});
export const setDataSourcesSearchQuery = (searchQuery: string): SetDataSourcesSearchQueryAction => ({
type: ActionTypes.SetDataSourcesSearchQuery,
payload: searchQuery,
});
export const setDataSourcesLayoutMode = (layoutMode: LayoutMode): SetDataSourcesLayoutModeAction => ({
type: ActionTypes.SetDataSourcesLayoutMode,
payload: layoutMode,
});
export const setDataSourceTypeSearchQuery = (query: string): SetDataSourceTypeSearchQueryAction => ({
type: ActionTypes.SetDataSourceTypeSearchQuery,
payload: query,
});
export const setDataSourceName = (name: string) => ({
type: ActionTypes.SetDataSourceName,
payload: name,
});
export const setIsDefault = (state: boolean) => ({
type: ActionTypes.SetIsDefault,
payload: state,
});
export type Action =
| LoadDataSourcesAction
| SetDataSourcesSearchQueryAction
| SetDataSourcesLayoutModeAction
| UpdateLocationAction
| LoadDataSourceTypesAction
| LoadedDataSourceTypesAction
| SetDataSourceTypeSearchQueryAction
| LoadDataSourceAction
| UpdateNavIndexAction
| LoadDataSourceMetaAction
| SetDataSourceNameAction
| SetIsDefaultAction;
export type Action = UpdateLocationAction | UpdateNavIndexAction | ActionOf<any>;
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
export function loadDataSources(): ThunkResult<void> {
return async dispatch => {
const response = await getBackendSrv().get('/api/datasources');
dispatch(dataSourcesLoaded(response));
dataSourcesLoaded(response);
};
}
......@@ -177,7 +91,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));
};
......
import { DataSourcesState, Plugin } from 'app/types';
import { DataSourceSettings } from '@grafana/ui/src/types';
import { Action, ActionTypes } from './actions';
import {
dataSourceLoaded,
dataSourcesLoaded,
setDataSourcesSearchQuery,
setDataSourcesLayoutMode,
dataSourceTypesLoad,
dataSourceTypesLoaded,
setDataSourceTypeSearchQuery,
dataSourceMetaLoaded,
setDataSourceName,
setIsDefault,
} from './actions';
import { LayoutModes } from 'app/core/components/LayoutSelector/LayoutSelector';
import { reducerFactory } from 'app/core/redux';
const initialState: DataSourcesState = {
dataSources: [] as DataSourceSettings[],
dataSources: [],
dataSource: {} as DataSourceSettings,
layoutMode: LayoutModes.List,
searchQuery: '',
dataSourcesCount: 0,
dataSourceTypes: [] as Plugin[],
dataSourceTypes: [],
dataSourceTypeSearchQuery: '',
hasFetched: false,
isLoadingDataSources: false,
dataSourceMeta: {} as Plugin,
};
export const dataSourcesReducer = (state = initialState, action: Action): DataSourcesState => {
switch (action.type) {
case ActionTypes.LoadDataSources:
return { ...state, hasFetched: true, dataSources: action.payload, dataSourcesCount: action.payload.length };
case ActionTypes.LoadDataSource:
return { ...state, dataSource: action.payload };
case ActionTypes.SetDataSourcesSearchQuery:
return { ...state, searchQuery: action.payload };
case ActionTypes.SetDataSourcesLayoutMode:
return { ...state, layoutMode: action.payload };
case ActionTypes.LoadDataSourceTypes:
return { ...state, dataSourceTypes: [], isLoadingDataSources: true };
case ActionTypes.LoadedDataSourceTypes:
return { ...state, dataSourceTypes: action.payload, isLoadingDataSources: false };
case ActionTypes.SetDataSourceTypeSearchQuery:
return { ...state, dataSourceTypeSearchQuery: action.payload };
case ActionTypes.LoadDataSourceMeta:
return { ...state, dataSourceMeta: action.payload };
case ActionTypes.SetDataSourceName:
return { ...state, dataSource: { ...state.dataSource, name: action.payload } };
case ActionTypes.SetIsDefault:
return { ...state, dataSource: { ...state.dataSource, isDefault: action.payload } };
}
return state;
};
export const dataSourcesReducer = reducerFactory(initialState)
.addHandler({
filter: dataSourcesLoaded,
mapper: (state, action) => ({
...state,
hasFetched: true,
dataSources: action.payload,
dataSourcesCount: action.payload.length,
}),
})
.addHandler({
filter: dataSourceLoaded,
mapper: (state, action) => ({ ...state, dataSource: action.payload }),
})
.addHandler({
filter: setDataSourcesSearchQuery,
mapper: (state, action) => ({ ...state, searchQuery: action.payload }),
})
.addHandler({
filter: setDataSourcesLayoutMode,
mapper: (state, action) => ({ ...state, layoutMode: action.payload }),
})
.addHandler({
filter: dataSourceTypesLoad,
mapper: state => ({ ...state, dataSourceTypes: [], isLoadingDataSources: true }),
})
.addHandler({
filter: dataSourceTypesLoaded,
mapper: (state, action) => ({
...state,
dataSourceTypes: action.payload,
isLoadingDataSources: false,
}),
})
.addHandler({
filter: setDataSourceTypeSearchQuery,
mapper: (state, action) => ({ ...state, dataSourceTypeSearchQuery: action.payload }),
})
.addHandler({
filter: dataSourceMetaLoaded,
mapper: (state, action) => ({ ...state, dataSourceMeta: action.payload }),
})
.addHandler({
filter: setDataSourceName,
mapper: (state, action) => ({ ...state, dataSource: { ...state.dataSource, name: action.payload } }),
})
.addHandler({
filter: setIsDefault,
mapper: (state, action) => ({
...state,
dataSource: { ...state.dataSource, isDefault: action.payload },
}),
})
.create();
export default {
dataSources: dataSourcesReducer,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment