import {useCallback, useMemo} from 'react'; import {useSortable} from '@dnd-kit/sortable'; import styled from '@emotion/styled'; import Feature from 'sentry/components/acl/feature'; import FeatureBadge from 'sentry/components/badge/featureBadge'; import type {ButtonProps} from 'sentry/components/button'; import {Button} from 'sentry/components/button'; import DropdownButton from 'sentry/components/dropdownButton'; import type {MenuItemProps} from 'sentry/components/dropdownMenu'; import {DropdownMenu} from 'sentry/components/dropdownMenu'; import ExternalLink from 'sentry/components/links/externalLink'; import {IconAdd} from 'sentry/icons'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {trackAnalytics} from 'sentry/utils/analytics'; import {hasCustomMetrics} from 'sentry/utils/metrics/features'; import useOrganization from 'sentry/utils/useOrganization'; import {DataSet} from 'sentry/views/dashboards/widgetBuilder/utils'; import {DisplayType} from './types'; import WidgetWrapper from './widgetWrapper'; export const ADD_WIDGET_BUTTON_DRAG_ID = 'add-widget-button'; const initialStyles = { x: 0, y: 0, scaleX: 1, scaleY: 1, }; type Props = { onAddWidget: (dataset: DataSet) => void; }; function AddWidget({onAddWidget}: Props) { const {setNodeRef, transform} = useSortable({ disabled: true, id: ADD_WIDGET_BUTTON_DRAG_ID, transition: null, }); const organization = useOrganization(); const defaultDataset = organization.features.includes( 'performance-discover-dataset-selector' ) ? DataSet.ERRORS : DataSet.EVENTS; return ( {hasCustomMetrics(organization) ? ( ) : ( onAddWidget(defaultDataset)}> } aria-label={t('Add widget')} /> )} ); } const AddButton = styled(Button)` border: none; &, &:focus, &:active, &:hover { background: transparent; box-shadow: none; } `; export default AddWidget; export function AddWidgetButton({onAddWidget, ...buttonProps}: Props & ButtonProps) { const organization = useOrganization(); const handleAction = useCallback( (dataset: DataSet) => { trackAnalytics('dashboards_views.widget_library.opened', { organization, }); onAddWidget(dataset); }, [organization, onAddWidget] ); const items = useMemo(() => { const menuItems: MenuItemProps[] = []; if (organization.features.includes('performance-discover-dataset-selector')) { menuItems.push({ key: DataSet.ERRORS, label: t('Errors'), onAction: () => handleAction(DataSet.ERRORS), }); menuItems.push({ key: DataSet.TRANSACTIONS, label: t('Transactions'), onAction: () => handleAction(DataSet.TRANSACTIONS), }); } else { menuItems.push({ key: DataSet.EVENTS, label: t('Errors and Transactions'), onAction: () => handleAction(DataSet.EVENTS), }); } menuItems.push({ key: DataSet.ISSUES, label: t('Issues'), details: t('States, Assignment, Time, etc.'), onAction: () => handleAction(DataSet.ISSUES), }); menuItems.push({ key: DataSet.RELEASES, label: t('Releases'), details: t('Sessions, Crash rates, etc.'), onAction: () => handleAction(DataSet.RELEASES), }); if (hasCustomMetrics(organization)) { menuItems.push({ key: DataSet.METRICS, label: t('Metrics'), onAction: () => handleAction(DataSet.METRICS), trailingItems: ( ), }); } return menuItems; }, [handleAction, organization]); return ( ( } > {t('Add Widget')} )} menuTitle={ {t('Dataset')} {t('Learn more')} } /> ); } const InnerWrapper = styled('div')<{onClick?: () => void}>` width: 100%; height: 110px; border: 2px dashed ${p => p.theme.border}; border-radius: ${p => p.theme.borderRadius}; display: flex; align-items: center; justify-content: center; cursor: ${p => (p.onClick ? 'pointer' : '')}; `; const MenuTitle = styled('span')` display: flex; gap: ${space(1)}; & > a { font-weight: ${p => p.theme.fontWeightNormal}; } `;