commitLink.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import {LinkButton} from 'sentry/components/button';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import {IconBitbucket, IconGithub, IconGitlab, IconVsts} from 'sentry/icons';
  4. import type {SVGIconProps} from 'sentry/icons/svgIcon';
  5. import {t} from 'sentry/locale';
  6. import type {Repository} from 'sentry/types/integrations';
  7. import {getShortCommitHash} from 'sentry/utils';
  8. type CommitFormatterParameters = {
  9. baseUrl: string;
  10. commitId: string;
  11. };
  12. type CommitProvider = {
  13. commitUrl: (opts: CommitFormatterParameters) => string;
  14. icon: React.ComponentType<SVGIconProps>;
  15. providerIds: string[];
  16. };
  17. // TODO(epurkhiser, jess): This should be moved into plugins.
  18. const SUPPORTED_PROVIDERS: Readonly<CommitProvider[]> = [
  19. {
  20. icon: IconGithub,
  21. providerIds: ['github', 'integrations:github', 'integrations:github_enterprise'],
  22. commitUrl: ({baseUrl, commitId}) => `${baseUrl}/commit/${commitId}`,
  23. },
  24. {
  25. icon: IconBitbucket,
  26. providerIds: ['bitbucket', 'integrations:bitbucket'],
  27. commitUrl: ({baseUrl, commitId}) => `${baseUrl}/commits/${commitId}`,
  28. },
  29. {
  30. icon: IconVsts,
  31. providerIds: ['visualstudio', 'integrations:vsts'],
  32. commitUrl: ({baseUrl, commitId}) => `${baseUrl}/commit/${commitId}`,
  33. },
  34. {
  35. icon: IconGitlab,
  36. providerIds: ['gitlab', 'integrations:gitlab'],
  37. commitUrl: ({baseUrl, commitId}) => `${baseUrl}/commit/${commitId}`,
  38. },
  39. ];
  40. type Props = {
  41. commitId?: string;
  42. commitTitle?: string;
  43. inline?: boolean;
  44. onClick?: () => void;
  45. repository?: Repository;
  46. showIcon?: boolean;
  47. };
  48. function CommitLink({
  49. inline,
  50. commitId,
  51. repository,
  52. showIcon = true,
  53. onClick,
  54. commitTitle,
  55. }: Props) {
  56. if (!commitId || !repository) {
  57. return <span>{t('Unknown Commit')}</span>;
  58. }
  59. let label: string;
  60. if (commitTitle) {
  61. label = commitTitle;
  62. } else {
  63. label = getShortCommitHash(commitId);
  64. }
  65. const providerData = SUPPORTED_PROVIDERS.find(provider => {
  66. if (!repository.provider) {
  67. return false;
  68. }
  69. return provider.providerIds.includes(repository.provider.id);
  70. });
  71. if (providerData === undefined) {
  72. return <span>{label}</span>;
  73. }
  74. const commitUrl =
  75. repository.url &&
  76. providerData.commitUrl({
  77. commitId,
  78. baseUrl: repository.url,
  79. });
  80. const Icon = providerData.icon;
  81. return !inline ? (
  82. <LinkButton
  83. external
  84. href={commitUrl}
  85. size="sm"
  86. icon={showIcon ? <Icon size="sm" /> : null}
  87. onClick={onClick}
  88. >
  89. {label}
  90. </LinkButton>
  91. ) : (
  92. <ExternalLink href={commitUrl} onClick={onClick}>
  93. {showIcon ? <Icon size="xs" /> : null}
  94. {' ' + label}
  95. </ExternalLink>
  96. );
  97. }
  98. export default CommitLink;