index.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import type {RouteComponentProps} from 'react-router';
  2. import {hasEveryAccess} from 'sentry/components/acl/access';
  3. import Feature from 'sentry/components/acl/feature';
  4. import Form from 'sentry/components/forms/form';
  5. import JsonForm from 'sentry/components/forms/jsonForm';
  6. import ExternalLink from 'sentry/components/links/externalLink';
  7. import LoadingError from 'sentry/components/loadingError';
  8. import LoadingIndicator from 'sentry/components/loadingIndicator';
  9. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  10. import {fields} from 'sentry/data/forms/projectIssueGrouping';
  11. import {t, tct} from 'sentry/locale';
  12. import ProjectsStore from 'sentry/stores/projectsStore';
  13. import type {EventGroupingConfig, Organization, Project} from 'sentry/types';
  14. import {useApiQuery} from 'sentry/utils/queryClient';
  15. import routeTitleGen from 'sentry/utils/routeTitle';
  16. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  17. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  18. import PermissionAlert from 'sentry/views/settings/project/permissionAlert';
  19. type Props = RouteComponentProps<{}, {projectId: string}> & {
  20. organization: Organization;
  21. project: Project;
  22. };
  23. export default function ProjectIssueGrouping({organization, project, params}: Props) {
  24. const queryKey = `/projects/${organization.slug}/${project.slug}/grouping-configs/`;
  25. const {
  26. data: groupingConfigs,
  27. isLoading,
  28. isError,
  29. refetch,
  30. } = useApiQuery<EventGroupingConfig[]>([queryKey], {staleTime: 0, cacheTime: 0});
  31. if (isLoading) {
  32. return <LoadingIndicator />;
  33. }
  34. if (isError) {
  35. return (
  36. <LoadingError message={t('Failed to load grouping configs')} onRetry={refetch} />
  37. );
  38. }
  39. const handleSubmit = (response: Project) => {
  40. // This will update our project context
  41. ProjectsStore.onUpdateSuccess(response);
  42. };
  43. const endpoint = `/projects/${organization.slug}/${project.slug}/`;
  44. const access = new Set(organization.access.concat(project.access));
  45. const hasAccess = hasEveryAccess(['project:write'], {organization, project});
  46. const jsonFormProps = {
  47. additionalFieldProps: {
  48. organization,
  49. groupingConfigs,
  50. },
  51. features: new Set(organization.features),
  52. access,
  53. disabled: !hasAccess,
  54. };
  55. return (
  56. <SentryDocumentTitle
  57. title={routeTitleGen(t('Issue Grouping'), params.projectId, false)}
  58. >
  59. <SettingsPageHeader title={t('Issue Grouping')} />
  60. <TextBlock>
  61. {tct(
  62. `All events have a fingerprint. Events with the same fingerprint are grouped together into an issue. To learn more about issue grouping, [link: read the docs].`,
  63. {
  64. link: (
  65. <ExternalLink href="https://docs.sentry.io/product/data-management-settings/event-grouping/" />
  66. ),
  67. }
  68. )}
  69. </TextBlock>
  70. <PermissionAlert project={project} />
  71. <Form
  72. saveOnBlur
  73. allowUndo
  74. initialData={project}
  75. apiMethod="PUT"
  76. apiEndpoint={endpoint}
  77. onSubmitSuccess={handleSubmit}
  78. >
  79. <JsonForm
  80. {...jsonFormProps}
  81. title={t('Fingerprint Rules')}
  82. fields={[fields.fingerprintingRules]}
  83. />
  84. <JsonForm
  85. {...jsonFormProps}
  86. title={t('Stack Trace Rules')}
  87. fields={[fields.groupingEnhancements]}
  88. />
  89. <Feature features="set-grouping-config" organization={organization}>
  90. <JsonForm
  91. {...jsonFormProps}
  92. title={t('Change defaults')}
  93. fields={[
  94. fields.groupingConfig,
  95. fields.secondaryGroupingConfig,
  96. fields.secondaryGroupingExpiry,
  97. ]}
  98. />
  99. </Feature>
  100. </Form>
  101. </SentryDocumentTitle>
  102. );
  103. }