integrationIcon.tsx 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import {Component} from 'react';
  2. import styled from '@emotion/styled';
  3. import PluginIcon, {DEFAULT_ICON, ICON_PATHS} from 'sentry/plugins/components/pluginIcon';
  4. import type {Integration} from 'sentry/types/integrations';
  5. type Props = {
  6. integration: Integration;
  7. size?: number;
  8. };
  9. type State = {
  10. imgSrc: Integration['icon'];
  11. };
  12. type IconProps = Pick<Props, 'size'>;
  13. const StyledIcon = styled('img')<IconProps>`
  14. height: ${p => p.size}px;
  15. width: ${p => p.size}px;
  16. border-radius: 2px;
  17. display: block;
  18. `;
  19. class Icon extends Component<Props, State> {
  20. state: State = {
  21. imgSrc: this.props.integration.icon,
  22. };
  23. render() {
  24. const {integration, size} = this.props;
  25. return (
  26. <StyledIcon
  27. size={size}
  28. src={this.state.imgSrc || undefined}
  29. onError={() => {
  30. // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
  31. this.setState({imgSrc: ICON_PATHS[integration.provider.key] || DEFAULT_ICON});
  32. }}
  33. />
  34. );
  35. }
  36. }
  37. function IntegrationIcon({integration, size = 32}: Props) {
  38. return integration.icon ? (
  39. <Icon size={size} integration={integration} />
  40. ) : (
  41. <PluginIcon size={size} pluginId={integration.provider.key} />
  42. );
  43. }
  44. export default IntegrationIcon;