sentryApplication.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import {Field} from 'sentry/components/forms/type';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import {tct} from 'sentry/locale';
  4. import {extractMultilineFields} from 'sentry/utils';
  5. const getPublicFormFields = (): Field[] => [
  6. {
  7. name: 'name',
  8. type: 'string',
  9. required: true,
  10. placeholder: 'e.g. My Integration',
  11. label: 'Name',
  12. help: 'Human readable name of your Integration.',
  13. },
  14. {
  15. name: 'author',
  16. type: 'string',
  17. required: true,
  18. placeholder: 'e.g. Acme Software',
  19. label: 'Author',
  20. help: 'The company or person who built and maintains this Integration.',
  21. },
  22. {
  23. name: 'webhookUrl',
  24. type: 'string',
  25. required: true,
  26. label: 'Webhook URL',
  27. placeholder: 'e.g. https://example.com/sentry/webhook/',
  28. help: tct(
  29. 'All webhook requests for your integration will be sent to this URL. Visit the [webhook_docs:documentation] to see the different types and payloads.',
  30. {
  31. webhook_docs: (
  32. <ExternalLink href="https://docs.sentry.io/product/integrations/integration-platform/webhooks/" />
  33. ),
  34. }
  35. ),
  36. },
  37. {
  38. name: 'redirectUrl',
  39. type: 'string',
  40. label: 'Redirect URL',
  41. placeholder: 'e.g. https://example.com/sentry/setup/',
  42. help: 'The URL Sentry will redirect users to after installation.',
  43. },
  44. {
  45. name: 'verifyInstall',
  46. label: 'Verify Installation',
  47. type: 'boolean',
  48. help: 'If enabled, installations will need to be verified before becoming installed.',
  49. },
  50. {
  51. name: 'isAlertable',
  52. type: 'boolean',
  53. label: 'Alert Rule Action',
  54. disabled: ({webhookDisabled}) => webhookDisabled,
  55. disabledReason: 'Cannot enable alert rule action without a webhook url',
  56. help: tct(
  57. 'If enabled, this integration will be available in Issue Alert rules and Metric Alert rules in Sentry. The notification destination is the Webhook URL specified above. More on actions [learn_more:here].',
  58. {
  59. learn_more: (
  60. <ExternalLink href="https://docs.sentry.io/product/alerts-notifications/notifications/" />
  61. ),
  62. }
  63. ),
  64. },
  65. {
  66. name: 'schema',
  67. type: 'textarea',
  68. label: 'Schema',
  69. autosize: true,
  70. rows: 1,
  71. help: tct(
  72. 'Schema for your UI components. Click [schema_docs:here] for documentation.',
  73. {
  74. schema_docs: (
  75. <ExternalLink href="https://docs.sentry.io/product/integrations/integration-platform/ui-components/" />
  76. ),
  77. }
  78. ),
  79. getValue: (val: string) => (val === '' ? {} : JSON.parse(val)),
  80. setValue: (val: string) => {
  81. const schema = JSON.stringify(val, null, 2);
  82. if (schema === '{}') {
  83. return '';
  84. }
  85. return schema;
  86. },
  87. validate: ({id, form}) => {
  88. if (!form.schema) {
  89. return [];
  90. }
  91. try {
  92. JSON.parse(form.schema);
  93. } catch (e) {
  94. return [[id, 'Invalid JSON']];
  95. }
  96. return [];
  97. },
  98. },
  99. {
  100. name: 'overview',
  101. type: 'textarea',
  102. label: 'Overview',
  103. autosize: true,
  104. rows: 1,
  105. help: 'Description of your Integration and its functionality.',
  106. },
  107. {
  108. name: 'allowedOrigins',
  109. type: 'string',
  110. multiline: true,
  111. placeholder: 'e.g. example.com',
  112. label: 'Authorized JavaScript Origins',
  113. help: 'Separate multiple entries with a newline.',
  114. getValue: (val: string) => extractMultilineFields(val),
  115. setValue: (val: string[] | undefined | null) =>
  116. (val && typeof val.join === 'function' && val.join('\n')) || '',
  117. },
  118. ];
  119. export const publicIntegrationForms = [
  120. {
  121. title: 'Public Integration Details',
  122. fields: getPublicFormFields(),
  123. },
  124. ];
  125. const getInternalFormFields = () => {
  126. // Generate internal form fields copy copying the public form fields and
  127. // making adjustments:
  128. //
  129. // 1. remove fields not needed for internal integrations
  130. // 2. make webhookUrl optional
  131. const internalFormFields = getPublicFormFields().filter(
  132. formField =>
  133. !['redirectUrl', 'verifyInstall', 'author'].includes(formField.name || '')
  134. );
  135. const webhookField = internalFormFields.find(field => field.name === 'webhookUrl');
  136. if (webhookField) {
  137. webhookField.required = false;
  138. }
  139. return internalFormFields;
  140. };
  141. export const internalIntegrationForms = [
  142. {
  143. title: 'Internal Integration Details',
  144. fields: getInternalFormFields(),
  145. },
  146. ];