highlightsSettingsForm.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import {addSuccessMessage} from 'sentry/actionCreators/indicator';
  2. import {hasEveryAccess} from 'sentry/components/acl/access';
  3. import {CONTEXT_DOCS_LINK} from 'sentry/components/events/contexts/utils';
  4. import Form, {type FormProps} from 'sentry/components/forms/form';
  5. import JsonForm from 'sentry/components/forms/jsonForm';
  6. import ExternalLink from 'sentry/components/links/externalLink';
  7. import {t, tct} from 'sentry/locale';
  8. import type {Project} from 'sentry/types';
  9. import {convertMultilineFieldValue, extractMultilineFields} from 'sentry/utils';
  10. import {trackAnalytics} from 'sentry/utils/analytics';
  11. import {setApiQueryData, useQueryClient} from 'sentry/utils/queryClient';
  12. import {
  13. makeDetailedProjectQueryKey,
  14. useDetailedProject,
  15. } from 'sentry/utils/useDetailedProject';
  16. import useOrganization from 'sentry/utils/useOrganization';
  17. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  18. interface HighlightsSettingsFormProps {
  19. projectSlug;
  20. }
  21. export default function HighlightsSettingsForm({
  22. projectSlug,
  23. }: HighlightsSettingsFormProps) {
  24. const organization = useOrganization();
  25. const {data: project} = useDetailedProject({
  26. orgSlug: organization.slug,
  27. projectSlug,
  28. });
  29. const queryClient = useQueryClient();
  30. if (!project) {
  31. return null;
  32. }
  33. const access = new Set(organization.access.concat(project.access));
  34. const formProps: FormProps = {
  35. saveOnBlur: true,
  36. allowUndo: true,
  37. initialData: {
  38. highlightTags: project.highlightTags,
  39. highlightContext: project.highlightContext,
  40. },
  41. apiMethod: 'PUT',
  42. apiEndpoint: `/projects/${organization.slug}/${projectSlug}/`,
  43. onSubmitSuccess: (updatedProject: Project) => {
  44. setApiQueryData<Project>(
  45. queryClient,
  46. makeDetailedProjectQueryKey({
  47. orgSlug: organization.slug,
  48. projectSlug: project.slug,
  49. }),
  50. data => (updatedProject ? updatedProject : data)
  51. );
  52. trackAnalytics('highlights.project_settings.updated_manually', {organization});
  53. addSuccessMessage(`Successfully updated highlights for '${project.name}'`);
  54. },
  55. };
  56. return (
  57. <Form {...formProps}>
  58. <TextBlock>
  59. {t(
  60. `Setup Highlights to promote your event data to the top of the issue page for quicker debugging.`
  61. )}
  62. </TextBlock>
  63. <JsonForm
  64. access={access}
  65. disabled={!hasEveryAccess(['project:write'], {organization, project})}
  66. title={t('Highlights')}
  67. fields={[
  68. {
  69. name: 'highlightTags',
  70. type: 'string',
  71. multiline: true,
  72. autosize: true,
  73. rows: 1,
  74. placeholder: t('environment, release, my-tag'),
  75. label: t('Highlighted Tags'),
  76. help: t('Separate tag keys with a newline.'),
  77. getValue: val => extractMultilineFields(val),
  78. setValue: val => convertMultilineFieldValue(val),
  79. },
  80. {
  81. name: 'highlightContext',
  82. type: 'textarea',
  83. multiline: true,
  84. autosize: true,
  85. rows: 1,
  86. placeholder: t('{"browser": ["name"], "my-ctx": ["my-key"]}'),
  87. label: t('Highlighted Context'),
  88. help: tct(
  89. 'Enter a valid JSON entry for mapping [Structured Context] types, to their keys. E.g. [example]',
  90. {
  91. link: <ExternalLink openInNewTab href={CONTEXT_DOCS_LINK} />,
  92. example: '{"user": ["id", "email"]}',
  93. }
  94. ),
  95. getValue: (val: string) => (val === '' ? {} : JSON.parse(val)),
  96. setValue: (val: string) => {
  97. const schema = JSON.stringify(val, null, 2);
  98. if (schema === '{}') {
  99. return '';
  100. }
  101. return schema;
  102. },
  103. validate: ({id, form}) => {
  104. if (form.highlightContext) {
  105. try {
  106. JSON.parse(form.highlightContext);
  107. } catch (e) {
  108. return [[id, 'Invalid JSON']];
  109. }
  110. }
  111. return [];
  112. },
  113. },
  114. ]}
  115. />
  116. </Form>
  117. );
  118. }