actions.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { DataTransformerConfig, FieldConfigSource } from '@grafana/data';
  2. import { PanelModel } from 'app/features/dashboard/state/PanelModel';
  3. import { getPanelOptionsWithDefaults } from 'app/features/dashboard/state/getPanelOptionsWithDefaults';
  4. import { LibraryElementDTO } from 'app/features/library-panels/types';
  5. import { toPanelModelLibraryPanel } from 'app/features/library-panels/utils';
  6. import { getPanelPluginNotFound } from 'app/features/panel/components/PanelPluginError';
  7. import { loadPanelPlugin } from 'app/features/plugins/admin/state/actions';
  8. import { ThunkResult } from 'app/types';
  9. import { PanelOptionsChangedEvent, PanelQueriesChangedEvent } from 'app/types/events';
  10. import {
  11. changePanelKey,
  12. cleanUpAngularComponent,
  13. panelModelAndPluginReady,
  14. removePanel,
  15. removePanels,
  16. } from './reducers';
  17. export function initPanelState(panel: PanelModel): ThunkResult<void> {
  18. return async (dispatch, getStore) => {
  19. let pluginToLoad = panel.type;
  20. let plugin = getStore().plugins.panels[pluginToLoad];
  21. if (!plugin) {
  22. try {
  23. plugin = await dispatch(loadPanelPlugin(pluginToLoad));
  24. } catch (e) {
  25. // When plugin not found
  26. plugin = getPanelPluginNotFound(pluginToLoad, pluginToLoad === 'row');
  27. }
  28. }
  29. if (!panel.plugin) {
  30. panel.pluginLoaded(plugin);
  31. }
  32. dispatch(panelModelAndPluginReady({ key: panel.key, plugin }));
  33. };
  34. }
  35. export function cleanUpPanelState(panelKey: string): ThunkResult<void> {
  36. return (dispatch, getStore) => {
  37. const store = getStore().panels;
  38. cleanUpAngularComponent(store[panelKey]);
  39. dispatch(removePanel({ key: panelKey }));
  40. };
  41. }
  42. export function cleanAndRemoveMany(panelKeys: string[]): ThunkResult<void> {
  43. return (dispatch, getStore) => {
  44. const store = getStore().panels;
  45. for (const key of panelKeys) {
  46. cleanUpAngularComponent(store[key]);
  47. }
  48. dispatch(removePanels({ keys: panelKeys }));
  49. };
  50. }
  51. export interface ChangePanelPluginAndOptionsArgs {
  52. panel: PanelModel;
  53. pluginId: string;
  54. options?: any;
  55. fieldConfig?: FieldConfigSource;
  56. transformations?: DataTransformerConfig[];
  57. }
  58. export function changePanelPlugin({
  59. panel,
  60. pluginId,
  61. options,
  62. fieldConfig,
  63. }: ChangePanelPluginAndOptionsArgs): ThunkResult<void> {
  64. return async (dispatch, getStore) => {
  65. // ignore action is no change
  66. if (panel.type === pluginId && !options && !fieldConfig) {
  67. return;
  68. }
  69. const store = getStore();
  70. let plugin = store.plugins.panels[pluginId];
  71. if (!plugin) {
  72. plugin = await dispatch(loadPanelPlugin(pluginId));
  73. }
  74. let cleanUpKey = panel.key;
  75. if (panel.type !== pluginId) {
  76. panel.changePlugin(plugin);
  77. }
  78. if (options || fieldConfig) {
  79. const newOptions = getPanelOptionsWithDefaults({
  80. plugin,
  81. currentOptions: options || panel.options,
  82. currentFieldConfig: fieldConfig || panel.fieldConfig,
  83. isAfterPluginChange: false,
  84. });
  85. panel.options = newOptions.options;
  86. panel.fieldConfig = newOptions.fieldConfig;
  87. panel.configRev++;
  88. }
  89. panel.generateNewKey();
  90. dispatch(panelModelAndPluginReady({ key: panel.key, plugin, cleanUpKey }));
  91. };
  92. }
  93. export function changeToLibraryPanel(panel: PanelModel, libraryPanel: LibraryElementDTO): ThunkResult<void> {
  94. return async (dispatch, getStore) => {
  95. const newPluginId = libraryPanel.model.type;
  96. const oldType = panel.type;
  97. // Update model but preserve gridPos & id
  98. panel.restoreModel({
  99. ...libraryPanel.model,
  100. gridPos: panel.gridPos,
  101. id: panel.id,
  102. libraryPanel: toPanelModelLibraryPanel(libraryPanel),
  103. });
  104. // a new library panel usually means new queries, clear any current result
  105. panel.getQueryRunner().clearLastResult();
  106. // Handle plugin change
  107. if (oldType !== newPluginId) {
  108. const store = getStore();
  109. let plugin = store.plugins.panels[newPluginId];
  110. if (!plugin) {
  111. plugin = await dispatch(loadPanelPlugin(newPluginId));
  112. }
  113. const oldKey = panel.key;
  114. panel.pluginLoaded(plugin);
  115. panel.generateNewKey();
  116. await dispatch(panelModelAndPluginReady({ key: panel.key, plugin, cleanUpKey: oldKey }));
  117. } else {
  118. // Even if the plugin is the same, we want to change the key
  119. // to force a rerender
  120. const oldKey = panel.key;
  121. panel.generateNewKey();
  122. dispatch(changePanelKey({ oldKey, newKey: panel.key }));
  123. }
  124. panel.configRev = 0;
  125. panel.refresh();
  126. panel.events.publish(PanelQueriesChangedEvent);
  127. panel.events.publish(PanelOptionsChangedEvent);
  128. };
  129. }