import {Fragment, useState} from 'react'; import type {WithRouterProps} from 'react-router'; import {components} from 'react-select'; import styled from '@emotion/styled'; import {Button} from 'sentry/components/button'; import SelectControl from 'sentry/components/forms/controls/selectControl'; import JsonForm from 'sentry/components/forms/jsonForm'; import IdBadge from 'sentry/components/idBadge'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import {IconAdd, IconDelete} from 'sentry/icons'; import {t} from 'sentry/locale'; import ConfigStore from 'sentry/stores/configStore'; import {space} from 'sentry/styles/space'; import {Organization, Project} from 'sentry/types'; import {useApiQuery} from 'sentry/utils/queryClient'; import withSentryRouter from 'sentry/utils/withSentryRouter'; import {NotificationOptionsObject} from 'sentry/views/settings/account/notifications/constants'; import {NOTIFICATION_SETTING_FIELDS_V2} from 'sentry/views/settings/account/notifications/fields2'; import {OrganizationSelectHeader} from 'sentry/views/settings/account/notifications/organizationSelectHeader'; type Value = 'always' | 'never' | 'subscribe_only' | 'committed_only'; const getLabelForValue = (value: Value) => { switch (value) { case 'always': return t('On'); case 'never': return t('Off'); case 'subscribe_only': return t('Subscribed Only'); case 'committed_only': return t('Committed Only'); default: return ''; } }; export type NotificationSettingsByProjectsBaseProps = { entityType: 'project' | 'organization'; handleAddNotificationOption: ( notificationOption: Omit ) => void; handleRemoveNotificationOption: (id: string) => void; notificationOptions: NotificationOptionsObject[]; notificationType: string; }; type Props = { organizations: Organization[]; } & NotificationSettingsByProjectsBaseProps & WithRouterProps; function NotificationSettingsByEntity(props: Props) { const { entityType, handleAddNotificationOption, handleRemoveNotificationOption, notificationOptions, notificationType, organizations, router, location, } = props; const [selectedEntityId, setSelectedEntityId] = useState(null); const [selectedValue, setSelectedValue] = useState(null); const customerDomain = ConfigStore.get('customerDomain'); const orgFromSubdomain = organizations.find( ({slug}) => slug === customerDomain?.subdomain )?.id; const orgId = location?.query?.organizationId ?? orgFromSubdomain ?? organizations[0]?.id; const orgSlug = organizations.find(({id}) => id === orgId)?.slug || organizations[0]?.slug; // loads all the projects for an org const {data: projects} = useApiQuery( [ `/organizations/${orgSlug}/projects/`, { query: { all_projects: '1', collapse: 'latestDeploys', }, }, ], {staleTime: Infinity} ); // always loading all projects even though we only need it sometimes const entities = entityType === 'project' ? projects || [] : organizations; const handleOrgChange = (organizationId: string) => { router.replace({ ...location, query: {organizationId}, }); }; const handleAdd = () => { // should never happen if (!selectedEntityId || !selectedValue) { return; } const data = { type: notificationType, scopeType: entityType, scopeIdentifier: selectedEntityId, value: selectedValue, }; setSelectedEntityId(null); setSelectedValue(null); handleAddNotificationOption(data); }; const renderOverrides = () => { const matchedOptions = notificationOptions.filter( option => option.type === notificationType && option.scopeType === entityType ); return matchedOptions.map(option => { const entity = (entities as any[]).find( ({id}) => id.toString() === option.scopeIdentifier.toString() ); if (!entity) { return null; } const handleDelete = async (id: string) => { await handleRemoveNotificationOption(id); }; const idBadgeProps = entityType === 'project' ? {project: entity as Project} : { organization: entity as Organization, }; return ( {getLabelForValue(option.value)}