organizations.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import {browserHistory} from 'react-router';
  2. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  3. import {resetPageFilters} from 'sentry/actionCreators/pageFilters';
  4. import OrganizationActions from 'sentry/actions/organizationActions';
  5. import OrganizationsActions from 'sentry/actions/organizationsActions';
  6. import {Client} from 'sentry/api';
  7. import OrganizationsStore from 'sentry/stores/organizationsStore';
  8. import ProjectsStore from 'sentry/stores/projectsStore';
  9. import TeamStore from 'sentry/stores/teamStore';
  10. import {Organization} from 'sentry/types';
  11. type RedirectRemainingOrganizationParams = {
  12. /**
  13. * The organization slug
  14. */
  15. orgId: string;
  16. /**
  17. * Should remove org?
  18. */
  19. removeOrg?: boolean;
  20. };
  21. /**
  22. * After removing an organization, this will redirect to a remaining active organization or
  23. * the screen to create a new organization.
  24. *
  25. * Can optionally remove organization from organizations store.
  26. */
  27. export function redirectToRemainingOrganization({
  28. orgId,
  29. removeOrg,
  30. }: RedirectRemainingOrganizationParams) {
  31. // Remove queued, should redirect
  32. const allOrgs = OrganizationsStore.getAll().filter(
  33. org => org.status.id === 'active' && org.slug !== orgId
  34. );
  35. if (!allOrgs.length) {
  36. browserHistory.push('/organizations/new/');
  37. return;
  38. }
  39. // Let's be smart and select the best org to redirect to
  40. const firstRemainingOrg = allOrgs[0];
  41. browserHistory.push(`/${firstRemainingOrg.slug}/`);
  42. // Remove org from SidebarDropdown
  43. if (removeOrg) {
  44. OrganizationsStore.remove(orgId);
  45. }
  46. }
  47. type RemoveParams = {
  48. /**
  49. * The organization slug
  50. */
  51. orgId: string;
  52. /**
  53. * An optional error message to be used in a toast, if remove fails
  54. */
  55. errorMessage?: string;
  56. /**
  57. * An optional success message to be used in a toast, if remove succeeds
  58. */
  59. successMessage?: string;
  60. };
  61. export function remove(api: Client, {successMessage, errorMessage, orgId}: RemoveParams) {
  62. const endpoint = `/organizations/${orgId}/`;
  63. return api
  64. .requestPromise(endpoint, {
  65. method: 'DELETE',
  66. })
  67. .then(() => {
  68. OrganizationsActions.removeSuccess(orgId);
  69. if (successMessage) {
  70. addSuccessMessage(successMessage);
  71. }
  72. })
  73. .catch(() => {
  74. OrganizationsActions.removeError();
  75. if (errorMessage) {
  76. addErrorMessage(errorMessage);
  77. }
  78. });
  79. }
  80. export function switchOrganization() {
  81. resetPageFilters();
  82. }
  83. export function removeAndRedirectToRemainingOrganization(
  84. api: Client,
  85. params: RedirectRemainingOrganizationParams & RemoveParams
  86. ) {
  87. remove(api, params).then(() => redirectToRemainingOrganization(params));
  88. }
  89. /**
  90. * Set active organization
  91. */
  92. export function setActiveOrganization(org: Organization) {
  93. OrganizationsActions.setActive(org);
  94. }
  95. export function changeOrganizationSlug(
  96. prev: Organization,
  97. next: Partial<Organization> & Pick<Organization, 'slug'>
  98. ) {
  99. OrganizationsActions.changeSlug(prev, next);
  100. }
  101. /**
  102. * Updates an organization for the store
  103. *
  104. * Accepts a partial organization as it will merge will existing organization
  105. */
  106. export function updateOrganization(org: Partial<Organization>) {
  107. OrganizationsActions.update(org);
  108. OrganizationActions.update(org);
  109. }
  110. type FetchOrganizationByMemberParams = {
  111. addOrg?: boolean;
  112. fetchOrgDetails?: boolean;
  113. };
  114. export async function fetchOrganizationByMember(
  115. memberId: string,
  116. {addOrg, fetchOrgDetails}: FetchOrganizationByMemberParams
  117. ) {
  118. const api = new Client();
  119. const data = await api.requestPromise(`/organizations/?query=member_id:${memberId}`);
  120. if (!data.length) {
  121. return null;
  122. }
  123. const org = data[0];
  124. if (addOrg) {
  125. // add org to SwitchOrganization dropdown
  126. OrganizationsStore.add(org);
  127. }
  128. if (fetchOrgDetails) {
  129. // load SidebarDropdown with org details including `access`
  130. await fetchOrganizationDetails(org.slug, {setActive: true, loadProjects: true});
  131. }
  132. return org;
  133. }
  134. type FetchOrganizationDetailsParams = {
  135. /**
  136. * Should load projects in ProjectsStore
  137. */
  138. loadProjects?: boolean;
  139. /**
  140. * Should load teams in TeamStore?
  141. */
  142. loadTeam?: boolean;
  143. /**
  144. * Should set as active organization?
  145. */
  146. setActive?: boolean;
  147. };
  148. export async function fetchOrganizationDetails(
  149. orgId: string,
  150. {setActive, loadProjects, loadTeam}: FetchOrganizationDetailsParams
  151. ) {
  152. const api = new Client();
  153. const data = await api.requestPromise(`/organizations/${orgId}/`);
  154. if (setActive) {
  155. setActiveOrganization(data);
  156. }
  157. if (loadTeam) {
  158. TeamStore.loadInitialData(data.teams, false, null);
  159. }
  160. if (loadProjects) {
  161. ProjectsStore.loadInitialData(data.projects || []);
  162. }
  163. return data;
  164. }