pluginsStore.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import {createStore, StoreDefinition} from 'reflux';
  2. import {Plugin} from 'sentry/types';
  3. interface InternalDefinition {
  4. plugins: Map<string, Plugin> | null;
  5. state: {
  6. error: Error | null;
  7. loading: boolean;
  8. pageLinks: string | null;
  9. plugins: Plugin[];
  10. };
  11. updating: Map<string, Plugin>;
  12. }
  13. interface PluginStoreDefinition extends StoreDefinition, InternalDefinition {
  14. onFetchAll: (options?: {resetLoading?: boolean}) => void;
  15. onFetchAllError: (err) => void;
  16. onFetchAllSuccess: (data: Plugin[], links: {pageLinks?: string}) => void;
  17. onUpdate: (id: string, updateObj: Partial<Plugin>) => void;
  18. onUpdateError: (id: string, _updateObj: Partial<Plugin>, err) => void;
  19. onUpdateSuccess: (id: string, _updateObj: Partial<Plugin>) => void;
  20. }
  21. const defaultState = {
  22. loading: true,
  23. plugins: [],
  24. error: null,
  25. pageLinks: null,
  26. };
  27. const storeConfig: PluginStoreDefinition = {
  28. plugins: null,
  29. state: {...defaultState},
  30. updating: new Map(),
  31. reset() {
  32. // reset our state
  33. this.plugins = null;
  34. this.state = {...defaultState};
  35. this.updating = new Map();
  36. return this.state;
  37. },
  38. getInitialState() {
  39. return this.getState();
  40. },
  41. getState() {
  42. const {plugins: _plugins, ...state} = this.state;
  43. return {
  44. ...state,
  45. plugins: this.plugins ? Array.from(this.plugins.values()) : [],
  46. };
  47. },
  48. init() {
  49. // XXX: Do not use `this.listenTo` in this store. We avoid usage of reflux
  50. // listeners due to their leaky nature in tests.
  51. this.reset();
  52. },
  53. triggerState() {
  54. this.trigger(this.getState());
  55. },
  56. onFetchAll({resetLoading} = {}) {
  57. if (resetLoading) {
  58. this.state.loading = true;
  59. this.state.error = null;
  60. this.plugins = null;
  61. }
  62. this.triggerState();
  63. },
  64. onFetchAllSuccess(data, {pageLinks}) {
  65. this.plugins = new Map(data.map(plugin => [plugin.id, plugin]));
  66. this.state.pageLinks = pageLinks || null;
  67. this.state.loading = false;
  68. this.triggerState();
  69. },
  70. onFetchAllError(err) {
  71. this.plugins = null;
  72. this.state.loading = false;
  73. this.state.error = err;
  74. this.triggerState();
  75. },
  76. onUpdate(id: string, updateObj: Partial<Plugin>) {
  77. if (!this.plugins) {
  78. return;
  79. }
  80. const plugin = this.plugins.get(id);
  81. if (!plugin) {
  82. return;
  83. }
  84. const newPlugin = {
  85. ...plugin,
  86. ...updateObj,
  87. };
  88. this.plugins.set(id, newPlugin);
  89. this.updating.set(id, plugin);
  90. this.triggerState();
  91. },
  92. onUpdateSuccess(id: string, _updateObj: Partial<Plugin>) {
  93. this.updating.delete(id);
  94. },
  95. onUpdateError(id: string, _updateObj: Partial<Plugin>, err) {
  96. const origPlugin = this.updating.get(id);
  97. if (!origPlugin || !this.plugins) {
  98. return;
  99. }
  100. this.plugins.set(id, origPlugin);
  101. this.updating.delete(id);
  102. this.state.error = err;
  103. this.triggerState();
  104. },
  105. };
  106. const PluginStore = createStore(storeConfig);
  107. export default PluginStore;