reducers.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import { AnyAction, createAction } from '@reduxjs/toolkit';
  2. import { DataSourcePluginMeta, DataSourceSettings, LayoutMode, LayoutModes } from '@grafana/data';
  3. import { DataSourcesState, DataSourceSettingsState, TestingStatus } from 'app/types';
  4. import { GenericDataSourcePlugin } from '../settings/PluginSettings';
  5. import { DataSourceTypesLoadedPayload } from './actions';
  6. export const initialState: DataSourcesState = {
  7. dataSources: [],
  8. plugins: [],
  9. categories: [],
  10. dataSource: {} as DataSourceSettings,
  11. layoutMode: LayoutModes.List,
  12. searchQuery: '',
  13. dataSourcesCount: 0,
  14. dataSourceTypeSearchQuery: '',
  15. hasFetched: false,
  16. isLoadingDataSources: false,
  17. dataSourceMeta: {} as DataSourcePluginMeta,
  18. };
  19. export const dataSourceLoaded = createAction<DataSourceSettings>('dataSources/dataSourceLoaded');
  20. export const dataSourcesLoaded = createAction<DataSourceSettings[]>('dataSources/dataSourcesLoaded');
  21. export const dataSourceMetaLoaded = createAction<DataSourcePluginMeta>('dataSources/dataSourceMetaLoaded');
  22. export const dataSourcePluginsLoad = createAction('dataSources/dataSourcePluginsLoad');
  23. export const dataSourcePluginsLoaded = createAction<DataSourceTypesLoadedPayload>(
  24. 'dataSources/dataSourcePluginsLoaded'
  25. );
  26. export const setDataSourcesSearchQuery = createAction<string>('dataSources/setDataSourcesSearchQuery');
  27. export const setDataSourcesLayoutMode = createAction<LayoutMode>('dataSources/setDataSourcesLayoutMode');
  28. export const setDataSourceTypeSearchQuery = createAction<string>('dataSources/setDataSourceTypeSearchQuery');
  29. export const setDataSourceName = createAction<string>('dataSources/setDataSourceName');
  30. export const setIsDefault = createAction<boolean>('dataSources/setIsDefault');
  31. // Redux Toolkit uses ImmerJs as part of their solution to ensure that state objects are not mutated.
  32. // ImmerJs has an autoFreeze option that freezes objects from change which means this reducer can't be migrated to createSlice
  33. // because the state would become frozen and during run time we would get errors because Angular would try to mutate
  34. // the frozen state.
  35. // https://github.com/reduxjs/redux-toolkit/issues/242
  36. export const dataSourcesReducer = (state: DataSourcesState = initialState, action: AnyAction): DataSourcesState => {
  37. if (dataSourcesLoaded.match(action)) {
  38. return {
  39. ...state,
  40. hasFetched: true,
  41. dataSources: action.payload,
  42. dataSourcesCount: action.payload.length,
  43. };
  44. }
  45. if (dataSourceLoaded.match(action)) {
  46. return { ...state, dataSource: action.payload };
  47. }
  48. if (setDataSourcesSearchQuery.match(action)) {
  49. return { ...state, searchQuery: action.payload };
  50. }
  51. if (setDataSourcesLayoutMode.match(action)) {
  52. return { ...state, layoutMode: action.payload };
  53. }
  54. if (dataSourcePluginsLoad.match(action)) {
  55. return { ...state, plugins: [], isLoadingDataSources: true };
  56. }
  57. if (dataSourcePluginsLoaded.match(action)) {
  58. return {
  59. ...state,
  60. plugins: action.payload.plugins,
  61. categories: action.payload.categories,
  62. isLoadingDataSources: false,
  63. };
  64. }
  65. if (setDataSourceTypeSearchQuery.match(action)) {
  66. return { ...state, dataSourceTypeSearchQuery: action.payload };
  67. }
  68. if (dataSourceMetaLoaded.match(action)) {
  69. return { ...state, dataSourceMeta: action.payload };
  70. }
  71. if (setDataSourceName.match(action)) {
  72. return { ...state, dataSource: { ...state.dataSource, name: action.payload } };
  73. }
  74. if (setIsDefault.match(action)) {
  75. return {
  76. ...state,
  77. dataSource: { ...state.dataSource, isDefault: action.payload },
  78. };
  79. }
  80. return state;
  81. };
  82. export const initialDataSourceSettingsState: DataSourceSettingsState = {
  83. testingStatus: {},
  84. loadError: null,
  85. loading: true,
  86. plugin: null,
  87. };
  88. export const initDataSourceSettingsSucceeded = createAction<GenericDataSourcePlugin>(
  89. 'dataSourceSettings/initDataSourceSettingsSucceeded'
  90. );
  91. export const initDataSourceSettingsFailed = createAction<Error>('dataSourceSettings/initDataSourceSettingsFailed');
  92. export const testDataSourceStarting = createAction<undefined>('dataSourceSettings/testDataSourceStarting');
  93. export const testDataSourceSucceeded = createAction<TestingStatus>('dataSourceSettings/testDataSourceSucceeded');
  94. export const testDataSourceFailed = createAction<TestingStatus>('dataSourceSettings/testDataSourceFailed');
  95. export const dataSourceSettingsReducer = (
  96. state: DataSourceSettingsState = initialDataSourceSettingsState,
  97. action: AnyAction
  98. ): DataSourceSettingsState => {
  99. if (initDataSourceSettingsSucceeded.match(action)) {
  100. return { ...state, plugin: action.payload, loadError: null, loading: false };
  101. }
  102. if (initDataSourceSettingsFailed.match(action)) {
  103. return { ...state, plugin: null, loadError: action.payload.message, loading: false };
  104. }
  105. if (testDataSourceStarting.match(action)) {
  106. return {
  107. ...state,
  108. testingStatus: {
  109. message: 'Testing...',
  110. status: 'info',
  111. },
  112. };
  113. }
  114. if (testDataSourceSucceeded.match(action)) {
  115. return {
  116. ...state,
  117. testingStatus: {
  118. status: action.payload?.status,
  119. message: action.payload?.message,
  120. details: action.payload?.details,
  121. },
  122. };
  123. }
  124. if (testDataSourceFailed.match(action)) {
  125. return {
  126. ...state,
  127. testingStatus: {
  128. status: 'error',
  129. message: action.payload?.message,
  130. details: action.payload?.details,
  131. },
  132. };
  133. }
  134. return state;
  135. };
  136. export default {
  137. dataSources: dataSourcesReducer,
  138. dataSourceSettings: dataSourceSettingsReducer,
  139. };