import {Fragment, useState} from 'react';
import styled from '@emotion/styled';
import starImage from 'sentry-images/spot/banner-star.svg';
import {SeerIcon} from 'sentry/components/ai/SeerIcon';
import ProjectAvatar from 'sentry/components/avatar/projectAvatar';
import FeatureBadge from 'sentry/components/badge/featureBadge';
import {Breadcrumbs as NavigationBreadcrumbs} from 'sentry/components/breadcrumbs';
import {Button} from 'sentry/components/button';
import ButtonBar from 'sentry/components/buttonBar';
import AutofixFeedback from 'sentry/components/events/autofix/autofixFeedback';
import {AutofixSetupContent} from 'sentry/components/events/autofix/autofixSetupModal';
import {AutofixSteps} from 'sentry/components/events/autofix/autofixSteps';
import {useAiAutofix} from 'sentry/components/events/autofix/useAutofix';
import {DrawerBody, DrawerHeader} from 'sentry/components/globalDrawer/components';
import {GroupSummary, useGroupSummary} from 'sentry/components/group/groupSummary';
import HookOrDefault from 'sentry/components/hookOrDefault';
import Input from 'sentry/components/input';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {IconDocs} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Event} from 'sentry/types/event';
import type {Group} from 'sentry/types/group';
import type {Project} from 'sentry/types/project';
import {getShortEventId} from 'sentry/utils/events';
import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
import {MIN_NAV_HEIGHT} from 'sentry/views/issueDetails/streamline/eventTitle';
import {useAiConfig} from 'sentry/views/issueDetails/streamline/hooks/useAiConfig';
import Resources from 'sentry/views/issueDetails/streamline/sidebar/resources';
interface AutofixStartBoxProps {
groupId: string;
onSend: (message: string) => void;
}
function AutofixStartBox({onSend, groupId}: AutofixStartBoxProps) {
const [message, setMessage] = useState('');
const stars = [
{size: 10, left: 20, top: 5, rotation: 30, opacity: 0.15},
{size: 12, left: 50, top: 8, rotation: 45, opacity: 0.2},
{size: 10, left: 80, top: 12, rotation: 15, opacity: 0.2},
{size: 14, left: 15, top: 20, rotation: 60, opacity: 0.3},
{size: 16, left: 45, top: 25, rotation: 30, opacity: 0.35},
{size: 14, left: 75, top: 22, rotation: 45, opacity: 0.3},
{size: 18, left: 25, top: 35, rotation: 20, opacity: 0.4},
{size: 20, left: 60, top: 38, rotation: 50, opacity: 0.45},
{size: 18, left: 85, top: 42, rotation: 35, opacity: 0.4},
{size: 22, left: 15, top: 55, rotation: 25, opacity: 0.5},
{size: 24, left: 40, top: 58, rotation: 40, opacity: 0.55},
{size: 22, left: 70, top: 52, rotation: 30, opacity: 0.5},
{size: 26, left: 30, top: 70, rotation: 35, opacity: 0.65},
{size: 28, left: 50, top: 75, rotation: 45, opacity: 0.7},
{size: 26, left: 80, top: 72, rotation: 25, opacity: 0.7},
];
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSend(message);
};
return (
{stars.map((star, i) => (
))}
Autofix
Work together with Autofix to find the root cause and fix the issue.
);
}
interface SolutionsHubDrawerProps {
event: Event;
group: Group;
project: Project;
}
const AiSetupDataConsent = HookOrDefault({
hookName: 'component:ai-setup-data-consent',
defaultComponent: () =>
,
});
export function SolutionsHubDrawer({group, project, event}: SolutionsHubDrawerProps) {
const {autofixData, triggerAutofix, reset} = useAiAutofix(group, event);
const {
data: summaryData,
isError,
isPending: isSummaryLoading,
} = useGroupSummary(group, event, project);
const aiConfig = useAiConfig(group, event, project);
useRouteAnalyticsParams({
autofix_status: autofixData?.status ?? 'none',
});
const config = getConfigForIssueType(group, project);
return (
{group.shortId}
),
},
{label: getShortEventId(event.id)},
{label: t('Solutions Hub')},
]}
/>
{config.resources && (
{t('Resources')}
)}
{t('Sentry AI')}
,
}
)}
/>
{autofixData && (
)}
{aiConfig.isAutofixSetupLoading ? (
) : aiConfig.needsGenAIConsent ? (
) : (
{aiConfig.hasSummary && (
)}
{aiConfig.hasAutofix && (
{aiConfig.needsAutofixSetup ? (
) : !autofixData ? (
) : (
)}
)}
)}
);
}
const ResourcesContainer = styled('div')``;
const ResourcesBody = styled('div')`
padding: 0 ${space(2)} ${space(2)} ${space(2)};
border-bottom: 1px solid ${p => p.theme.border};
margin-bottom: ${space(2)};
`;
const Row = styled('div')`
display: flex;
gap: ${space(1)};
`;
const StartBox = styled('div')`
padding: ${space(2)};
position: absolute;
bottom: ${space(2)};
left: ${space(2)};
right: ${space(2)};
`;
const ContentContainer = styled('div')`
position: relative;
z-index: 1;
margin-top: 80px;
`;
const SolutionsDrawerContainer = styled('div')`
height: 100%;
display: grid;
grid-template-rows: auto auto 1fr;
position: relative;
`;
const SolutionsDrawerHeader = styled(DrawerHeader)`
position: unset;
max-height: ${MIN_NAV_HEIGHT}px;
box-shadow: none;
border-bottom: 1px solid ${p => p.theme.border};
`;
const SolutionsDrawerNavigator = styled('div')`
display: grid;
grid-template-columns: 1fr;
align-items: center;
padding: ${space(0.75)} 24px;
background: ${p => p.theme.background};
z-index: 1;
min-height: ${MIN_NAV_HEIGHT}px;
box-shadow: ${p => p.theme.translucentBorder} 0 1px;
`;
const SolutionsDrawerBody = styled(DrawerBody)`
overflow: auto;
overscroll-behavior: contain;
/* Move the scrollbar to the left edge */
scroll-margin: 0 ${space(2)};
direction: rtl;
* {
direction: ltr;
}
`;
const Header = styled('h3')`
display: block;
font-size: ${p => p.theme.fontSizeExtraLarge};
font-weight: ${p => p.theme.fontWeightBold};
margin: 0;
`;
const NavigationCrumbs = styled(NavigationBreadcrumbs)`
margin: 0;
padding: 0;
`;
const CrumbContainer = styled('div')`
display: flex;
gap: ${space(1)};
align-items: center;
`;
const ShortId = styled('div')`
font-family: ${p => p.theme.text.family};
font-size: ${p => p.theme.fontSizeMedium};
line-height: 1;
`;
const ButtonWithStars = styled('div')`
position: relative;
display: flex;
align-items: center;
`;
const StarLarge = styled('img')`
position: absolute;
z-index: 0;
filter: sepia(1) saturate(3) hue-rotate(290deg);
`;
const StarLarge1 = styled(StarLarge)`
left: 45px;
bottom: -15px;
transform: rotate(90deg);
width: 16px;
height: 16px;
`;
const StarLarge2 = styled(StarLarge)`
left: -5px;
top: -15px;
transform: rotate(-30deg);
width: 24px;
height: 24px;
`;
const StarLarge3 = styled(StarLarge)`
right: -25px;
bottom: 0px;
transform: rotate(20deg);
width: 28px;
height: 28px;
`;
const StyledCard = styled('div')`
background: ${p => p.theme.backgroundElevated};
border-radius: ${p => p.theme.borderRadius};
border: 1px solid ${p => p.theme.border};
overflow: hidden;
box-shadow: ${p => p.theme.dropShadowMedium};
padding: ${space(1.5)} ${space(2)};
`;
const HeaderText = styled('div')`
font-weight: bold;
font-size: ${p => p.theme.fontSizeLarge};
display: flex;
align-items: center;
gap: ${space(0.5)};
padding-bottom: ${space(2)};
justify-content: space-between;
`;
const StyledFeatureBadge = styled(FeatureBadge)`
margin-left: ${space(0.25)};
padding-bottom: 3px;
`;
const ResourcesHeader = styled('div')`
gap: ${space(1)};
font-weight: bold;
font-size: ${p => p.theme.fontSizeLarge};
display: flex;
align-items: center;
padding-bottom: ${space(2)};
`;
const StarTrail = styled('div')`
height: 450px;
width: 100%;
position: absolute;
bottom: 5rem;
left: 0;
right: 0;
z-index: -1;
pointer-events: none;
overflow: hidden;
`;
const TrailStar = styled('img')`
position: absolute;
filter: sepia(1) saturate(3) hue-rotate(290deg);
transition: all 0.2s ease-in-out;
`;
const HeaderContainer = styled('div')`
display: flex;
align-items: center;
gap: ${space(0.5)};
`;