123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
- import {resetPageFilters} from 'sentry/actionCreators/pageFilters';
- import type {Client} from 'sentry/api';
- import {USING_CUSTOMER_DOMAIN} from 'sentry/constants';
- import ConfigStore from 'sentry/stores/configStore';
- import GuideStore from 'sentry/stores/guideStore';
- import LatestContextStore from 'sentry/stores/latestContextStore';
- import OrganizationsStore from 'sentry/stores/organizationsStore';
- import OrganizationStore from 'sentry/stores/organizationStore';
- import ProjectsStore from 'sentry/stores/projectsStore';
- import TeamStore from 'sentry/stores/teamStore';
- import type {Organization} from 'sentry/types/organization';
- import {browserHistory} from 'sentry/utils/browserHistory';
- import normalizeUrl from 'sentry/utils/url/normalizeUrl';
- type RedirectRemainingOrganizationParams = {
- /**
- * The organization slug
- */
- orgId: string;
- /**
- * Should remove org?
- */
- removeOrg?: boolean;
- };
- /**
- * After removing an organization, this will redirect to a remaining active organization or
- * the screen to create a new organization.
- *
- * Can optionally remove organization from organizations store.
- */
- export function redirectToRemainingOrganization({
- orgId,
- removeOrg,
- }: RedirectRemainingOrganizationParams) {
- // Remove queued, should redirect
- const allOrgs = OrganizationsStore.getAll().filter(
- org => org.status.id === 'active' && org.slug !== orgId
- );
- if (!allOrgs.length) {
- browserHistory.push('/organizations/new/');
- return;
- }
- // Let's be smart and select the best org to redirect to
- const firstRemainingOrg = allOrgs[0];
- const route = `/organizations/${firstRemainingOrg.slug}/issues/`;
- if (USING_CUSTOMER_DOMAIN) {
- const {organizationUrl} = firstRemainingOrg.links;
- window.location.assign(`${organizationUrl}${normalizeUrl(route)}`);
- return;
- }
- browserHistory.push(route);
- // Remove org from SidebarDropdown
- if (removeOrg) {
- OrganizationsStore.remove(orgId);
- }
- }
- type RemoveParams = {
- /**
- * The organization slug
- */
- orgId: string;
- /**
- * An optional error message to be used in a toast, if remove fails
- */
- errorMessage?: string;
- /**
- * An optional success message to be used in a toast, if remove succeeds
- */
- successMessage?: string;
- };
- export function remove(api: Client, {successMessage, errorMessage, orgId}: RemoveParams) {
- const endpoint = `/organizations/${orgId}/`;
- return api
- .requestPromise(endpoint, {
- method: 'DELETE',
- })
- .then(() => {
- OrganizationsStore.onRemoveSuccess(orgId);
- if (successMessage) {
- addSuccessMessage(successMessage);
- }
- })
- .catch(() => {
- if (errorMessage) {
- addErrorMessage(errorMessage);
- }
- });
- }
- export function switchOrganization() {
- resetPageFilters();
- }
- export function removeAndRedirectToRemainingOrganization(
- api: Client,
- params: RedirectRemainingOrganizationParams & RemoveParams
- ) {
- remove(api, params).then(() => redirectToRemainingOrganization(params));
- }
- /**
- * Set active organization
- */
- export function setActiveOrganization(org: Organization) {
- GuideStore.setActiveOrganization(org);
- LatestContextStore.onSetActiveOrganization(org);
- }
- export function changeOrganizationSlug(
- prev: Organization,
- next: Partial<Organization> & Pick<Organization, 'slug'>
- ) {
- OrganizationsStore.onChangeSlug(prev, next);
- }
- /**
- * Updates an organization for the store
- *
- * Accepts a partial organization as it will merge will existing organization
- */
- export function updateOrganization(org: Partial<Organization>) {
- OrganizationsStore.onUpdate(org);
- OrganizationStore.onUpdate(org);
- }
- type FetchOrganizationByMemberParams = {
- addOrg?: boolean;
- fetchOrgDetails?: boolean;
- };
- export async function fetchOrganizationByMember(
- api: Client,
- memberId: string,
- {addOrg, fetchOrgDetails}: FetchOrganizationByMemberParams
- ) {
- const data = await api.requestPromise(`/organizations/?query=member_id:${memberId}`);
- if (!data.length) {
- return null;
- }
- const org = data[0];
- if (addOrg) {
- // add org to SwitchOrganization dropdown
- OrganizationsStore.addOrReplace(org);
- }
- if (fetchOrgDetails) {
- // load SidebarDropdown with org details including `access`
- await fetchOrganizationDetails(api, org.slug, {setActive: true, loadProjects: true});
- }
- return org;
- }
- type FetchOrganizationDetailsParams = {
- /**
- * Should load projects in ProjectsStore
- */
- loadProjects?: boolean;
- /**
- * Should load teams in TeamStore?
- */
- loadTeam?: boolean;
- /**
- * Should set as active organization?
- */
- setActive?: boolean;
- };
- export async function fetchOrganizationDetails(
- api: Client,
- orgId: string,
- {setActive, loadProjects, loadTeam}: FetchOrganizationDetailsParams
- ) {
- const data = await api.requestPromise(`/organizations/${orgId}/`, {
- query: {
- include_feature_flags: 1,
- },
- });
- if (setActive) {
- setActiveOrganization(data);
- }
- if (loadTeam) {
- TeamStore.loadInitialData(data.teams, false, null);
- }
- if (loadProjects) {
- ProjectsStore.loadInitialData(data.projects || []);
- }
- return data;
- }
- /**
- * Get all organizations for the current user.
- *
- * Will perform a fan-out across all multi-tenant regions,
- * and single-tenant regions the user has membership in.
- *
- * This function is challenging to type as the structure of the response
- * from /organizations can vary based on query parameters
- */
- export async function fetchOrganizations(api: Client, query?: Record<string, any>) {
- const regions = ConfigStore.get('memberRegions');
- const results = await Promise.all(
- regions.map(region =>
- api.requestPromise(`/organizations/`, {
- host: region.url,
- query,
- // Authentication errors can happen as we span regions.
- allowAuthError: true,
- })
- )
- );
- return results.reduce((acc, response) => {
- // Don't append error results to the org list.
- if (response[0]) {
- acc = acc.concat(response);
- }
- return acc;
- }, []);
- }
|