mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
229 lines
5.7 KiB
TypeScript
229 lines
5.7 KiB
TypeScript
import {browserHistory} from 'react-router';
|
|
|
|
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';
|
|
import {normalizeUrl} from 'sentry/utils/withDomainRequired';
|
|
|
|
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}/`);
|
|
|
|
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('regions');
|
|
const results = await Promise.all(
|
|
regions.map(region =>
|
|
api.requestPromise(`/organizations/`, {
|
|
host: region.url,
|
|
query,
|
|
})
|
|
)
|
|
);
|
|
return results.reduce((acc, response) => acc.concat(response), []);
|
|
}
|