pluginsStore.tsx 2.9 KB

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