123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import * as Sentry from '@sentry/react';
- import {addErrorMessage} from 'app/actionCreators/indicator';
- import {setActiveOrganization} from 'app/actionCreators/organizations';
- import GlobalSelectionActions from 'app/actions/globalSelectionActions';
- import OrganizationActions from 'app/actions/organizationActions';
- import ProjectActions from 'app/actions/projectActions';
- import TeamActions from 'app/actions/teamActions';
- import {Client} from 'app/api';
- import ProjectsStore from 'app/stores/projectsStore';
- import TeamStore from 'app/stores/teamStore';
- import {Organization, Project, Team} from 'app/types';
- import {getPreloadedDataPromise} from 'app/utils/getPreloadedData';
- async function fetchOrg(
- api: Client,
- slug: string,
- detailed: boolean,
- isInitialFetch?: boolean
- ): Promise<Organization> {
- const detailedQueryParam = detailed ? 1 : 0;
- const org = await getPreloadedDataPromise(
- `organization?detailed=${detailedQueryParam}`,
- slug,
- () =>
- // This data should get preloaded in static/sentry/index.ejs
- // If this url changes make sure to update the preload
- api.requestPromise(`/organizations/${slug}/`, {
- query: {detailed: detailedQueryParam},
- }),
- isInitialFetch
- );
- if (!org) {
- throw new Error('retrieved organization is falsey');
- }
- OrganizationActions.update(org, {replace: true});
- setActiveOrganization(org);
- return org;
- }
- async function fetchProjectsAndTeams(
- slug: string,
- isInitialFetch?: boolean
- ): Promise<[Project[], Team[]]> {
- // Create a new client so the request is not cancelled
- const uncancelableApi = new Client();
- try {
- const [projects, teams] = await Promise.all([
- getPreloadedDataPromise(
- 'projects',
- slug,
- () =>
- // This data should get preloaded in static/sentry/index.ejs
- // If this url changes make sure to update the preload
- uncancelableApi.requestPromise(`/organizations/${slug}/projects/`, {
- query: {
- all_projects: 1,
- collapse: 'latestDeploys',
- },
- }),
- isInitialFetch
- ),
- getPreloadedDataPromise(
- 'teams',
- slug,
- // This data should get preloaded in static/sentry/index.ejs
- // If this url changes make sure to update the preload
- () => uncancelableApi.requestPromise(`/organizations/${slug}/teams/`),
- isInitialFetch
- ),
- ]);
- return [projects, teams];
- } catch (err) {
- // It's possible these requests fail with a 403 if the user has a role with insufficient access
- // to projects and teams, but *can* access org details (e.g. billing).
- // An example of this is in org settings.
- //
- // Ignore 403s and bubble up other API errors
- if (err.status !== 403) {
- throw err;
- }
- }
- return [[], []];
- }
- /**
- * Fetches an organization's details with an option for the detailed representation
- * with teams and projects
- *
- * @param api A reference to the api client
- * @param slug The organization slug
- * @param detailed Whether or not the detailed org details should be retrieved
- * @param silent Should we silently update the organization (do not clear the
- * current organization in the store)
- */
- export async function fetchOrganizationDetails(
- api: Client,
- slug: string,
- detailed: boolean,
- silent: boolean,
- isInitialFetch?: boolean
- ) {
- if (!silent) {
- OrganizationActions.fetchOrg();
- ProjectActions.reset();
- GlobalSelectionActions.reset();
- }
- try {
- const promises: Array<Promise<any>> = [fetchOrg(api, slug, detailed, isInitialFetch)];
- if (!detailed) {
- promises.push(fetchProjectsAndTeams(slug, isInitialFetch));
- }
- const [org, projectsAndTeams] = await Promise.all(promises);
- if (!detailed) {
- const [projects, teams] = projectsAndTeams as [Project[], Team[]];
- ProjectActions.loadProjects(projects);
- TeamActions.loadTeams(teams);
- }
- if (org && detailed) {
- // TODO(davidenwang): Change these to actions after organization.projects
- // and organization.teams no longer exists. Currently if they were changed
- // to actions it would cause OrganizationContext to rerender many times
- TeamStore.loadInitialData(org.teams);
- ProjectsStore.loadInitialData(org.projects);
- }
- } catch (err) {
- if (!err) {
- return;
- }
- OrganizationActions.fetchOrgError(err);
- if (err.status === 403 || err.status === 401) {
- const errMessage =
- typeof err.responseJSON?.detail === 'string'
- ? err.responseJSON?.detail
- : typeof err.responseJSON?.detail?.message === 'string'
- ? err.responseJSON?.detail.message
- : null;
- if (errMessage) {
- addErrorMessage(errMessage);
- }
- return;
- }
- Sentry.captureException(err);
- }
- }
|