organizationLayout.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Alert} from 'sentry/components/alert';
  4. import HookOrDefault from 'sentry/components/hookOrDefault';
  5. import LoadingError from 'sentry/components/loadingError';
  6. import LoadingTriangle from 'sentry/components/loadingTriangle';
  7. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  8. import Sidebar from 'sentry/components/sidebar';
  9. import {ORGANIZATION_FETCH_ERROR_TYPES} from 'sentry/constants';
  10. import {t} from 'sentry/locale';
  11. import OrganizationStore from 'sentry/stores/organizationStore';
  12. import {useLegacyStore} from 'sentry/stores/useLegacyStore';
  13. import {space} from 'sentry/styles/space';
  14. import {useEnsureOrganization} from './organizationContext';
  15. interface OrganizationLayoutProps {
  16. children: React.ReactNode;
  17. /**
  18. * Render the sidebar when possible if enabled
  19. */
  20. includeSidebar: boolean;
  21. }
  22. const OrganizationHeader = HookOrDefault({
  23. hookName: 'component:organization-header',
  24. });
  25. /**
  26. * Renders the organization page layout
  27. */
  28. function OrganizationLayout({includeSidebar, children}: OrganizationLayoutProps) {
  29. const {organization, loading, error, errorType} = useLegacyStore(OrganizationStore);
  30. useEnsureOrganization();
  31. if (loading) {
  32. return <LoadingTriangle>{t('Loading data for your organization.')}</LoadingTriangle>;
  33. }
  34. const mainBody = (
  35. <SentryDocumentTitle noSuffix title={organization?.name ?? 'Sentry'}>
  36. <div className="app">
  37. {organization && <OrganizationHeader organization={organization} />}
  38. {includeSidebar && <Sidebar organization={organization ?? undefined} />}
  39. {children}
  40. </div>
  41. </SentryDocumentTitle>
  42. );
  43. if (error) {
  44. const errorBody =
  45. errorType === ORGANIZATION_FETCH_ERROR_TYPES.ORG_NO_ACCESS ? (
  46. // We can still render when an org can't be loaded due to 401. The
  47. // backend will handle redirects when this is a problem.
  48. mainBody
  49. ) : errorType === ORGANIZATION_FETCH_ERROR_TYPES.ORG_NOT_FOUND ? (
  50. <Alert type="error" data-test-id="org-loading-error">
  51. {t('The organization you were looking for was not found.')}
  52. </Alert>
  53. ) : (
  54. <LoadingError />
  55. );
  56. return (
  57. <Fragment>
  58. {includeSidebar && <Sidebar organization={organization ?? undefined} />}
  59. <ErrorWrapper>{errorBody}</ErrorWrapper>
  60. </Fragment>
  61. );
  62. }
  63. return mainBody;
  64. }
  65. const ErrorWrapper = styled('div')`
  66. padding: ${space(3)};
  67. `;
  68. export default OrganizationLayout;