releaseStore.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import type {StoreDefinition} from 'reflux';
  2. import {createStore} from 'reflux';
  3. import type {Deploy, Organization, Release} from 'sentry/types';
  4. type StoreRelease = Map<string, Release>;
  5. type StoreDeploys = Map<string, Array<Deploy>>;
  6. type StoreLoading = Map<string, boolean>;
  7. type StoreError = Map<string, Error>;
  8. interface ReleaseStoreDefinition extends StoreDefinition {
  9. get(
  10. projectSlug: string,
  11. releaseVersion: string
  12. ): {
  13. deploys: Array<Deploy> | undefined;
  14. deploysError: Error | undefined;
  15. deploysLoading: boolean | undefined;
  16. release: Release | undefined;
  17. releaseError: Error | undefined;
  18. releaseLoading: boolean | undefined;
  19. };
  20. loadDeploys(orgSlug: string, projectSlug: string, releaseVersion: string): void;
  21. loadDeploysError(projectSlug: string, releaseVersion: string, error: Error): void;
  22. loadDeploysSuccess(
  23. projectSlug: string,
  24. releaseVersion: string,
  25. data: Deploy[] | null
  26. ): void;
  27. loadRelease(orgSlug: string, projectSlug: string, releaseVersion: string): void;
  28. loadReleaseError(projectSlug: string, releaseVersion: string, error: Error): void;
  29. loadReleaseSuccess(
  30. projectSlug: string,
  31. releaseVersion: string,
  32. data: Release | null
  33. ): void;
  34. reset(): void;
  35. state: {
  36. deploys: StoreDeploys;
  37. deploysError: StoreError;
  38. deploysLoading: StoreLoading;
  39. orgSlug: string | undefined;
  40. release: StoreRelease;
  41. releaseError: StoreError;
  42. releaseLoading: StoreLoading;
  43. };
  44. updateOrganization(org: Organization): void;
  45. }
  46. export const getReleaseStoreKey = (projectSlug: string, releaseVersion: string) =>
  47. `${projectSlug}${releaseVersion}`;
  48. const storeConfig: ReleaseStoreDefinition = {
  49. state: {
  50. orgSlug: undefined,
  51. release: new Map() as StoreRelease,
  52. releaseLoading: new Map() as StoreLoading,
  53. releaseError: new Map() as StoreError,
  54. deploys: new Map() as StoreDeploys,
  55. deploysLoading: new Map() as StoreLoading,
  56. deploysError: new Map() as StoreError,
  57. },
  58. init() {
  59. // XXX: Do not use `this.listenTo` in this store. We avoid usage of reflux
  60. // listeners due to their leaky nature in tests.
  61. this.reset();
  62. },
  63. reset() {
  64. this.state = {
  65. orgSlug: undefined,
  66. release: new Map() as StoreRelease,
  67. releaseLoading: new Map() as StoreLoading,
  68. releaseError: new Map() as StoreError,
  69. deploys: new Map() as StoreDeploys,
  70. deploysLoading: new Map() as StoreLoading,
  71. deploysError: new Map() as StoreError,
  72. };
  73. this.trigger(this.state);
  74. },
  75. updateOrganization(org) {
  76. this.reset();
  77. this.state.orgSlug = org.slug;
  78. this.trigger(this.state);
  79. },
  80. loadRelease(orgSlug, projectSlug, releaseVersion) {
  81. // Wipe entire store if the user switched organizations
  82. if (!this.orgSlug || this.orgSlug !== orgSlug) {
  83. this.reset();
  84. this.orgSlug = orgSlug;
  85. }
  86. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  87. const {releaseLoading, releaseError, ...state} = this.state;
  88. this.state = {
  89. ...state,
  90. releaseLoading: {
  91. ...releaseLoading,
  92. [releaseKey]: true,
  93. },
  94. releaseError: {
  95. ...releaseError,
  96. [releaseKey]: undefined,
  97. },
  98. };
  99. this.trigger(this.state);
  100. },
  101. loadReleaseError(projectSlug, releaseVersion, error) {
  102. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  103. const {releaseLoading, releaseError, ...state} = this.state;
  104. this.state = {
  105. ...state,
  106. releaseLoading: {
  107. ...releaseLoading,
  108. [releaseKey]: false,
  109. },
  110. releaseError: {
  111. ...releaseError,
  112. [releaseKey]: error,
  113. },
  114. };
  115. this.trigger(this.state);
  116. },
  117. loadReleaseSuccess(projectSlug, releaseVersion, data) {
  118. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  119. const {release, releaseLoading, releaseError, ...state} = this.state;
  120. this.state = {
  121. ...state,
  122. release: {
  123. ...release,
  124. [releaseKey]: data,
  125. },
  126. releaseLoading: {
  127. ...releaseLoading,
  128. [releaseKey]: false,
  129. },
  130. releaseError: {
  131. ...releaseError,
  132. [releaseKey]: undefined,
  133. },
  134. };
  135. this.trigger(this.state);
  136. },
  137. loadDeploys(orgSlug, projectSlug, releaseVersion) {
  138. // Wipe entire store if the user switched organizations
  139. if (!this.orgSlug || this.orgSlug !== orgSlug) {
  140. this.reset();
  141. this.orgSlug = orgSlug;
  142. }
  143. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  144. const {deploysLoading, deploysError, ...state} = this.state;
  145. this.state = {
  146. ...state,
  147. deploysLoading: {
  148. ...deploysLoading,
  149. [releaseKey]: true,
  150. },
  151. deploysError: {
  152. ...deploysError,
  153. [releaseKey]: undefined,
  154. },
  155. };
  156. this.trigger(this.state);
  157. },
  158. loadDeploysError(projectSlug, releaseVersion, error) {
  159. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  160. const {deploysLoading, deploysError, ...state} = this.state;
  161. this.state = {
  162. ...state,
  163. deploysLoading: {
  164. ...deploysLoading,
  165. [releaseKey]: false,
  166. },
  167. deploysError: {
  168. ...deploysError,
  169. [releaseKey]: error,
  170. },
  171. };
  172. this.trigger(this.state);
  173. },
  174. loadDeploysSuccess(projectSlug, releaseVersion, data) {
  175. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  176. const {deploys, deploysLoading, deploysError, ...state} = this.state;
  177. this.state = {
  178. ...state,
  179. deploys: {
  180. ...deploys,
  181. [releaseKey]: data,
  182. },
  183. deploysLoading: {
  184. ...deploysLoading,
  185. [releaseKey]: false,
  186. },
  187. deploysError: {
  188. ...deploysError,
  189. [releaseKey]: undefined,
  190. },
  191. };
  192. this.trigger(this.state);
  193. },
  194. get(projectSlug, releaseVersion) {
  195. const releaseKey = getReleaseStoreKey(projectSlug, releaseVersion);
  196. return {
  197. release: this.state.release[releaseKey],
  198. releaseLoading: this.state.releaseLoading[releaseKey],
  199. releaseError: this.state.releaseError[releaseKey],
  200. deploys: this.state.deploys[releaseKey],
  201. deploysLoading: this.state.deploysLoading[releaseKey],
  202. deploysError: this.state.deploysError[releaseKey],
  203. };
  204. },
  205. };
  206. const ReleaseStore = createStore(storeConfig);
  207. export default ReleaseStore;