sentryApplicationRowButtons.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import Access from 'sentry/components/acl/access';
  2. import {t} from 'sentry/locale';
  3. import type {
  4. SentryApp,
  5. SentryAppAvatar,
  6. SentryAppAvatarPhotoType,
  7. SentryAppSchemaElement,
  8. } from 'sentry/types/integrations';
  9. import type {Organization} from 'sentry/types/organization';
  10. import ActionButtons from './actionButtons';
  11. type Props = {
  12. app: SentryApp;
  13. onClickRemove: (app: SentryApp) => void;
  14. organization: Organization;
  15. onClickPublish?: () => void;
  16. };
  17. const UI_COMPONENT_TYPES = ['stacktrace-link', 'issue-link'];
  18. const hasInvalidStatus = (app: SentryApp): boolean => {
  19. return app.status !== 'unpublished';
  20. };
  21. const hasUploadedSentryAppPhoto = (
  22. avatars: SentryAppAvatar[] | undefined,
  23. photoType: SentryAppAvatarPhotoType
  24. ): boolean => {
  25. return avatars
  26. ? avatars.some(
  27. avatar => avatar.avatarType === 'upload' && avatar.photoType === photoType
  28. )
  29. : false;
  30. };
  31. const hasUIComponent = (elements: SentryAppSchemaElement[] | undefined): boolean => {
  32. return elements
  33. ? elements.some(element => UI_COMPONENT_TYPES.includes(element.type))
  34. : false;
  35. };
  36. function SentryApplicationRowButtons({
  37. organization,
  38. app,
  39. onClickRemove,
  40. onClickPublish,
  41. }: Props) {
  42. const isInternal = app.status === 'internal';
  43. return (
  44. <Access access={['org:admin']}>
  45. {({hasAccess}) => {
  46. let disablePublishReason = '';
  47. let disableDeleteReason = '';
  48. // Publish & Delete buttons will always be disabled if the app is published
  49. if (app.status === 'published') {
  50. disablePublishReason = t('Published integrations cannot be re-published.');
  51. disableDeleteReason = t('Published integrations cannot be removed.');
  52. } else if (!hasAccess) {
  53. disablePublishReason = t(
  54. 'Organization owner permissions are required for this action.'
  55. );
  56. disableDeleteReason = t(
  57. 'Organization owner permissions are required for this action.'
  58. );
  59. } else if (app.status === 'publish_request_inprogress') {
  60. disablePublishReason = t(
  61. 'This integration has already been submitted for publishing'
  62. );
  63. } else if (hasInvalidStatus(app)) {
  64. disablePublishReason = t('Only unpublished integrations can be published');
  65. } else if (!hasUploadedSentryAppPhoto(app.avatars, 'logo')) {
  66. disablePublishReason = t('A logo is required to publish an integration');
  67. } else if (
  68. hasUIComponent(app.schema.elements) &&
  69. !hasUploadedSentryAppPhoto(app.avatars, 'icon')
  70. ) {
  71. disablePublishReason = t('Integrations with a UI component must have an icon');
  72. }
  73. return (
  74. <ActionButtons
  75. org={organization}
  76. app={app}
  77. showPublish={!isInternal}
  78. showDelete
  79. onPublish={onClickPublish}
  80. onDelete={onClickRemove}
  81. disablePublishReason={disablePublishReason}
  82. disableDeleteReason={disableDeleteReason}
  83. />
  84. );
  85. }}
  86. </Access>
  87. );
  88. }
  89. export default SentryApplicationRowButtons;