import {useEffect} from 'react';
import {RouteComponentProps} from 'react-router';
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 Link, {LinkProps} from 'sentry/components/links/link';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
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 {Organization} from 'sentry/types';
import {Theme} from 'sentry/utils/theme';
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')}:
-
{t('Change my password')}
-
{t('Notification Preferences')}
-
{t('Change my avatar')}
);
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')}:
-
{t('Quickstart Guide')}
-
{t('Platforms & Frameworks')}
-
{t('Sentry CLI')}
);
const support = (
{t('Support')}
{t('Quick links')}:
-
{isSelfHosted ? t('Community Forums') : t('Contact Support')}
-
{t('Sentry on GitHub')}
-
{t('Service Status')}
);
const apiKeys = (
{t('API Keys')}
{t('Quick links')}:
-
{t('Auth Tokens')}
-
{t('Your Integrations')}
-
{t('Documentation')}
);
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.purple300};
&:hover {
color: ${theme.purple300};
}
`;
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};
`;