widgetCard.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Panel, PanelBody} from 'sentry/components/panels';
  4. import {IconArrow, IconGlobe, IconGraph, IconMenu, IconNumber} from 'sentry/icons';
  5. import {IconGraphArea} from 'sentry/icons/iconGraphArea';
  6. import {IconGraphBar} from 'sentry/icons/iconGraphBar';
  7. import space from 'sentry/styles/space';
  8. import {DisplayType} from '../types';
  9. import {WidgetTemplate} from './data';
  10. type Props = {
  11. selectedWidgets: WidgetTemplate[];
  12. setErrored: (errored: boolean) => void;
  13. setSelectedWidgets: (widgets: WidgetTemplate[]) => void;
  14. widget: WidgetTemplate;
  15. ['data-test-id']?: string;
  16. };
  17. export function getWidgetIcon(displayType: DisplayType) {
  18. switch (displayType) {
  19. case DisplayType.TABLE:
  20. return IconMenu;
  21. case DisplayType.WORLD_MAP:
  22. return IconGlobe;
  23. case DisplayType.BIG_NUMBER:
  24. return IconNumber;
  25. case DisplayType.BAR:
  26. return IconGraphBar;
  27. case DisplayType.TOP_N:
  28. return IconArrow;
  29. case DisplayType.AREA:
  30. return IconGraphArea;
  31. case DisplayType.LINE:
  32. default:
  33. return IconGraph;
  34. }
  35. }
  36. function WidgetLibraryCard({
  37. selectedWidgets,
  38. widget,
  39. setSelectedWidgets,
  40. ['data-test-id']: dataTestId,
  41. }: Props) {
  42. const [selected, setSelected] = useState(selectedWidgets.includes(widget));
  43. const Icon = getWidgetIcon(widget.displayType);
  44. return (
  45. <StyledPanel
  46. data-test-id={dataTestId}
  47. selected={selected}
  48. onClick={() => {
  49. if (selected) {
  50. const updatedWidgets = selectedWidgets.filter(
  51. selectedWidget => widget !== selectedWidget
  52. );
  53. setSelectedWidgets(updatedWidgets);
  54. } else {
  55. const updatedWidgets = selectedWidgets.slice().concat(widget);
  56. setSelectedWidgets(updatedWidgets);
  57. }
  58. setSelected(!selected);
  59. }}
  60. >
  61. <PanelBody>
  62. <TitleContainer>
  63. <Icon size="xs" />
  64. <Title>{widget.title}</Title>
  65. </TitleContainer>
  66. <Description>{widget.description}</Description>
  67. </PanelBody>
  68. </StyledPanel>
  69. );
  70. }
  71. const Title = styled('div')`
  72. padding-left: ${space(1)};
  73. font-size: 16px;
  74. line-height: 140%;
  75. color: ${p => p.theme.gray500};
  76. `;
  77. const TitleContainer = styled('div')`
  78. padding: ${space(1.5)} ${space(2)};
  79. padding-bottom: ${space(0.5)};
  80. display: flex;
  81. align-items: center;
  82. `;
  83. const Description = styled('div')`
  84. padding: 0 ${space(1)} ${space(1.5)} 36px;
  85. font-size: 14px;
  86. line-height: 21px;
  87. color: ${p => p.theme.gray300};
  88. `;
  89. type PanelProps = {
  90. selected?: boolean;
  91. };
  92. const StyledPanel = styled(Panel)<PanelProps>`
  93. border: ${p =>
  94. p.selected ? `2px solid ${p.theme.active}` : `1px solid ${p.theme.border}`};
  95. margin: ${p => (p.selected ? '-1px' : 0)};
  96. box-sizing: border-box;
  97. box-shadow: 0px 2px 1px rgba(0, 0, 0, 0.08);
  98. cursor: pointer;
  99. `;
  100. export default WidgetLibraryCard;