resourcesAndPossibleSolutions.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {AiSuggestedSolution} from 'sentry/components/events/aiSuggestedSolution';
  4. import {Autofix} from 'sentry/components/events/autofix';
  5. import {EventDataSection} from 'sentry/components/events/eventDataSection';
  6. import {Resources} from 'sentry/components/events/interfaces/performance/resources';
  7. import {t} from 'sentry/locale';
  8. import {space} from 'sentry/styles/space';
  9. import {EntryType, type Event, type Group, type Project} from 'sentry/types';
  10. import {
  11. getConfigForIssueType,
  12. shouldShowCustomErrorResourceConfig,
  13. } from 'sentry/utils/issueTypeConfig';
  14. import {getRegionDataFromOrganization} from 'sentry/utils/regions';
  15. import useOrganization from 'sentry/utils/useOrganization';
  16. type Props = {
  17. event: Event;
  18. group: Group;
  19. project: Project;
  20. };
  21. // This section provides users with resources and possible solutions on how to resolve an issue
  22. export function ResourcesAndPossibleSolutions({event, project, group}: Props) {
  23. const organization = useOrganization();
  24. const config = getConfigForIssueType(group, project);
  25. const hasStacktrace = event.entries.some(
  26. entry =>
  27. entry.type === EntryType.EXCEPTION ||
  28. entry.type === EntryType.STACKTRACE ||
  29. entry.type === EntryType.THREADS
  30. );
  31. // NOTE: Autofix is for INTERNAL testing only for now.
  32. const displayAiAutofix =
  33. project.features.includes('ai-autofix') &&
  34. organization.features.includes('issue-details-autofix-ui') &&
  35. !shouldShowCustomErrorResourceConfig(group, project) &&
  36. config.autofix &&
  37. hasStacktrace;
  38. const displayAiSuggestedSolution =
  39. // Skip showing AI suggested solution if the issue has a custom resource
  40. organization.aiSuggestedSolution &&
  41. getRegionDataFromOrganization(organization)?.name !== 'de' &&
  42. !shouldShowCustomErrorResourceConfig(group, project) &&
  43. !displayAiAutofix;
  44. if (!config.resources && !(displayAiSuggestedSolution || displayAiAutofix)) {
  45. return null;
  46. }
  47. return (
  48. <Wrapper
  49. type="resources-and-possible-solutions"
  50. title={t('Resources and Possible Solutions')}
  51. configResources={!!config.resources}
  52. >
  53. <Content>
  54. {config.resources && (
  55. <Resources
  56. eventPlatform={event.platform}
  57. groupId={group.id}
  58. configResources={config.resources}
  59. />
  60. )}
  61. {displayAiSuggestedSolution && (
  62. <AiSuggestedSolution event={event} projectSlug={project.slug} />
  63. )}
  64. {displayAiAutofix && <Autofix event={event} group={group} />}
  65. </Content>
  66. </Wrapper>
  67. );
  68. }
  69. const Content = styled('div')`
  70. display: flex;
  71. flex-direction: column;
  72. gap: ${space(2)};
  73. `;
  74. const Wrapper = styled(EventDataSection)<{configResources: boolean}>`
  75. @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
  76. ${p =>
  77. !p.configResources &&
  78. css`
  79. && {
  80. padding-top: ${space(3)};
  81. }
  82. `}
  83. }
  84. `;