import {useEffect} from 'react'; import type {RouteComponentProps} from 'react-router'; import type {Theme} from '@emotion/react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; import {fetchOrganizationDetails} from 'sentry/actionCreators/organizations'; import DemoModeGate from 'sentry/components/acl/demoModeGate'; import OrganizationAvatar from 'sentry/components/avatar/organizationAvatar'; import UserAvatar from 'sentry/components/avatar/userAvatar'; import ExternalLink from 'sentry/components/links/externalLink'; import type {LinkProps} from 'sentry/components/links/link'; import Link from 'sentry/components/links/link'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {IconDocs, IconLock, IconStack, IconSupport} from 'sentry/icons'; import {t} from 'sentry/locale'; import ConfigStore from 'sentry/stores/configStore'; import {space} from 'sentry/styles/space'; import type {Organization} from 'sentry/types'; import useApi from 'sentry/utils/useApi'; import withLatestContext from 'sentry/utils/withLatestContext'; import SettingsLayout from 'sentry/views/settings/components/settingsLayout'; const LINKS = { DOCUMENTATION: 'https://docs.sentry.io/', DOCUMENTATION_PLATFORMS: 'https://docs.sentry.io/platforms/', DOCUMENTATION_QUICKSTART: 'https://docs.sentry.io/platform-redirect/?next=/', DOCUMENTATION_CLI: 'https://docs.sentry.io/product/cli/', DOCUMENTATION_API: 'https://docs.sentry.io/api/', API: '/settings/account/api/', MANAGE: '/manage/', FORUM: 'https://forum.sentry.io/', GITHUB_ISSUES: 'https://github.com/getsentry/sentry/issues', SERVICE_STATUS: 'https://status.sentry.io/', }; const HOME_ICON_SIZE = 56; interface SettingsIndexProps extends RouteComponentProps<{}, {}> { organization: Organization; } function SettingsIndex({organization, ...props}: SettingsIndexProps) { const api = useApi(); useEffect(() => { // if there is no org in context, SidebarDropdown uses an org from `withLatestContext` // (which queries the org index endpoint instead of org details) // and does not have `access` info if (organization && typeof organization.access === 'undefined') { fetchOrganizationDetails(api, organization.slug, { setActive: true, loadProjects: true, }); } }, [api, organization]); const user = ConfigStore.get('user'); const isSelfHosted = ConfigStore.get('isSelfHosted'); const organizationSettingsUrl = (organization && `/settings/${organization.slug}/`) || ''; const supportLinkProps = { isSelfHosted, organizationSettingsUrl, }; const myAccount = ( {t('My Account')}

{t('Quick links')}:

); const orgSettings = ( {!organization && } {organization ? ( ) : ( )} {organization ? organization.slug : t('No Organization')}

{t('Quick links')}:

  • {t('Projects')}
  • {t('Teams')}
  • {t('Members')}
); const documentation = ( {t('Documentation')}

{t('Quick links')}:

); const support = ( {t('Support')}

{t('Quick links')}:

); const apiKeys = ( {t('API Keys')}

{t('Quick links')}:

); return ( {myAccount} {orgSettings} {documentation} {support} {apiKeys} ); } export default withLatestContext(SettingsIndex); const GridLayout = styled('div')` display: grid; grid-template-columns: 1fr 1fr 1fr; gap: ${space(2)}; `; const GridPanel = styled(Panel)` margin-bottom: 0; `; const HomePanelHeader = styled(PanelHeader)` background: ${p => p.theme.background}; font-size: ${p => p.theme.fontSizeExtraLarge}; align-items: center; text-transform: unset; padding: ${space(4)}; `; const HomePanelBody = styled(PanelBody)` padding: 30px; h3 { font-size: 14px; } ul { margin: 0; li { line-height: 1.6; /* Bullet color */ color: ${p => p.theme.gray200}; } } `; const HomeIconContainer = styled('div')<{color?: string}>` background: ${p => p.theme[p.color || 'gray300']}; color: ${p => p.theme.white}; width: ${HOME_ICON_SIZE}px; height: ${HOME_ICON_SIZE}px; border-radius: ${HOME_ICON_SIZE}px; display: flex; justify-content: center; align-items: center; `; const linkCss = ({theme}: {theme: Theme}) => css` color: ${theme.activeText}; &:hover { color: ${theme.activeText}; } `; const linkIconCss = css` overflow: hidden; width: 100%; display: grid; grid-template-rows: max-content max-content; gap: ${space(1.5)}; align-items: center; justify-items: center; justify-content: center; `; const HomeLink = styled(Link)` ${linkCss} `; const ExternalHomeLink = styled(ExternalLink)` ${linkCss} `; const HomeLinkIcon = styled(HomeLink)` ${linkIconCss} `; const ExternalHomeLinkIcon = styled(ExternalLink)` ${linkIconCss} `; interface SupportLinkProps extends Omit { isSelfHosted: boolean; organizationSettingsUrl: string; icon?: boolean; } function SupportLink({ isSelfHosted, icon, organizationSettingsUrl, ...props }: SupportLinkProps) { if (isSelfHosted) { const SelfHostedLink = icon ? ExternalHomeLinkIcon : ExternalHomeLink; return ; } const SelfHostedLink = icon ? HomeLinkIcon : HomeLink; return ; } const OrganizationName = styled('div')` line-height: 1.1em; ${p => p.theme.overflowEllipsis}; `;