import {Fragment, useState} from 'react'; import styled from '@emotion/styled'; import {removeSentryApp} from 'sentry/actionCreators/sentryApps'; import EmptyMessage from 'sentry/components/emptyMessage'; import ExternalLink from 'sentry/components/links/externalLink'; import LoadingError from 'sentry/components/loadingError'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import NavTabs from 'sentry/components/navTabs'; 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 {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {SentryApp} from 'sentry/types/integrations'; import { platformEventLinkMap, PlatformEvents, } from 'sentry/utils/analytics/integrations/platformAnalyticsEvents'; import {trackIntegrationAnalytics} from 'sentry/utils/integrationUtil'; import {useApiQuery} from 'sentry/utils/queryClient'; import useApi from 'sentry/utils/useApi'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader'; import SentryApplicationRow from 'sentry/views/settings/organizationDeveloperSettings/sentryApplicationRow'; import CreateIntegrationButton from 'sentry/views/settings/organizationIntegrations/createIntegrationButton'; import ExampleIntegrationButton from 'sentry/views/settings/organizationIntegrations/exampleIntegrationButton'; type Tab = 'public' | 'internal'; function OrganizationDeveloperSettings() { const location = useLocation(); const organization = useOrganization(); const api = useApi({persistInFlight: true}); const value = ['public', 'internal'].find(tab => tab === location?.query?.type) || 'internal'; const analyticsView = 'developer_settings'; const tabs: Array<[id: Tab, label: string]> = [ ['internal', t('Internal Integration')], ['public', t('Public Integration')], ]; const [tab, setTab] = useState(value as Tab); const [applicationsState, setApplicationsState] = useState( undefined ); const { data: fetchedApplications, isPending, isError, refetch, } = useApiQuery([`/organizations/${organization.slug}/sentry-apps/`], { staleTime: 0, }); if (isPending) { return ; } if (isError) { return ; } const applications = applicationsState ?? fetchedApplications; const removeApp = (app: SentryApp) => { const apps = applications.filter(a => a.slug !== app.slug); removeSentryApp(api, app).then( () => setApplicationsState(apps), () => {} ); }; const renderApplicationRow = (app: SentryApp) => { return ( ); }; const renderInternalIntegrations = () => { const integrations = applications.filter( (app: SentryApp) => app.status === 'internal' ); const isEmpty = integrations.length === 0; return ( {t('Internal Integrations')} {!isEmpty ? ( integrations.map(renderApplicationRow) ) : ( {t('No internal integrations have been created yet.')} )} ); }; const renderPublicIntegrations = () => { const integrations = applications.filter(app => app.status !== 'internal'); const isEmpty = integrations.length === 0; return ( {t('Public Integrations')} {!isEmpty ? ( integrations.map(renderApplicationRow) ) : ( {t('No public integrations have been created yet.')} )} ); }; const renderTabContent = () => { switch (tab) { case 'internal': return renderInternalIntegrations(); case 'public': default: return renderPublicIntegrations(); } }; return (
{t( 'Create integrations that interact with Sentry using the REST API and webhooks. ' )}
{tct('For more information [link: see our docs].', { link: ( { trackIntegrationAnalytics(PlatformEvents.DOCS, { organization, view: analyticsView, }); }} /> ), })} } action={ } /> {tabs.map(([type, label]) => (
  • setTab(type)} > {label}
  • ))}
    {renderTabContent()}
    ); } const ActionContainer = styled('div')` display: flex; `; export default OrganizationDeveloperSettings;