loadingError.tsx 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import * as React from 'react';
  2. import styled from '@emotion/styled';
  3. import Alert from 'app/components/alert';
  4. import Button from 'app/components/button';
  5. import {Panel} from 'app/components/panels';
  6. import {IconInfo} from 'app/icons';
  7. import {t} from 'app/locale';
  8. import space from 'app/styles/space';
  9. type DefaultProps = {
  10. message: React.ReactNode;
  11. };
  12. type Props = DefaultProps & {
  13. onRetry?: () => void;
  14. };
  15. /**
  16. * Renders an Alert box of type "error". Renders a "Retry" button only if a `onRetry` callback is defined.
  17. */
  18. class LoadingError extends React.Component<Props> {
  19. static defaultProps: DefaultProps = {
  20. message: t('There was an error loading data.'),
  21. };
  22. shouldComponentUpdate() {
  23. return false;
  24. }
  25. render() {
  26. const {message, onRetry} = this.props;
  27. return (
  28. <StyledAlert type="error">
  29. <Content>
  30. <IconInfo size="lg" />
  31. <div data-test-id="loading-error-message">{message}</div>
  32. {onRetry && (
  33. <Button onClick={onRetry} type="button" priority="default" size="small">
  34. {t('Retry')}
  35. </Button>
  36. )}
  37. </Content>
  38. </StyledAlert>
  39. );
  40. }
  41. }
  42. export default LoadingError;
  43. const StyledAlert = styled(Alert)`
  44. ${/* sc-selector */ Panel} & {
  45. border-radius: 0;
  46. border-width: 1px 0;
  47. }
  48. `;
  49. const Content = styled('div')`
  50. display: grid;
  51. grid-gap: ${space(1)};
  52. grid-template-columns: min-content auto max-content;
  53. align-items: center;
  54. `;