dataSetStep.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import {useEffect, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import Alert from 'sentry/components/alert';
  4. import {Button} from 'sentry/components/button';
  5. import type {RadioGroupProps} from 'sentry/components/forms/controls/radioGroup';
  6. import RadioGroup from 'sentry/components/forms/controls/radioGroup';
  7. import ExternalLink from 'sentry/components/links/externalLink';
  8. import {IconClose} from 'sentry/icons';
  9. import {t, tct} from 'sentry/locale';
  10. import {space} from 'sentry/styles/space';
  11. import {DatasetSource} from 'sentry/utils/discover/types';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. import {DisplayType, type WidgetType} from 'sentry/views/dashboards/types';
  14. import {hasDatasetSelector} from 'sentry/views/dashboards/utils';
  15. import {DATASET_LABEL_MAP} from 'sentry/views/discover/savedQuery/datasetSelectorTabs';
  16. import {DataSet} from '../utils';
  17. import {BuildStep} from './buildStep';
  18. function DiscoverSplitAlert({onDismiss, splitDecision}) {
  19. const splitAlertMessage = splitDecision
  20. ? tct(
  21. "We're splitting our datasets up to make it a bit easier to digest. We defaulted this widget to [splitDecision]. Edit as you see fit.",
  22. {splitDecision: DATASET_LABEL_MAP[splitDecision]}
  23. )
  24. : null;
  25. return (
  26. <Alert
  27. type="warning"
  28. showIcon
  29. trailingItems={
  30. <StyledCloseButton
  31. icon={<IconClose size="sm" />}
  32. aria-label={t('Close')}
  33. onClick={onDismiss}
  34. size="zero"
  35. borderless
  36. />
  37. }
  38. >
  39. {splitAlertMessage}
  40. </Alert>
  41. );
  42. }
  43. interface Props {
  44. dataSet: DataSet;
  45. displayType: DisplayType;
  46. onChange: (dataSet: DataSet) => void;
  47. source?: DatasetSource;
  48. splitDecision?: WidgetType;
  49. }
  50. export function DataSetStep({
  51. dataSet,
  52. onChange,
  53. displayType,
  54. splitDecision,
  55. source,
  56. }: Props) {
  57. const [showSplitAlert, setShowSplitAlert] = useState<boolean>(
  58. source === DatasetSource.FORCED
  59. );
  60. const organization = useOrganization();
  61. const disabledChoices: RadioGroupProps<string>['disabledChoices'] = [];
  62. const hasDatasetSelectorFeature = hasDatasetSelector(organization);
  63. useEffect(() => {
  64. setShowSplitAlert(!!splitDecision);
  65. }, [splitDecision]);
  66. if (displayType !== DisplayType.TABLE) {
  67. disabledChoices.push([
  68. DataSet.ISSUES,
  69. t('This dataset is restricted to tabular visualization.'),
  70. ]);
  71. }
  72. const datasetChoices = new Map<string, string>();
  73. if (hasDatasetSelectorFeature) {
  74. // TODO: Finalize description copy
  75. datasetChoices.set(DataSet.ERRORS, t('Errors (TypeError, InvalidSearchQuery, etc)'));
  76. datasetChoices.set(DataSet.TRANSACTIONS, t('Transactions'));
  77. }
  78. if (!hasDatasetSelectorFeature) {
  79. datasetChoices.set(DataSet.EVENTS, t('Errors and Transactions'));
  80. }
  81. if (organization.features.includes('dashboards-eap')) {
  82. datasetChoices.set(DataSet.SPANS, t('Spans'));
  83. }
  84. datasetChoices.set(DataSet.ISSUES, t('Issues (States, Assignment, Time, etc.)'));
  85. datasetChoices.set(DataSet.RELEASES, t('Releases (Sessions, Crash rates)'));
  86. return (
  87. <BuildStep
  88. title={t('Choose your dataset')}
  89. description={tct(
  90. `This reflects the type of information you want to use. To learn more, [link: read the docs].`,
  91. {
  92. link: (
  93. <ExternalLink href="https://docs.sentry.io/product/dashboards/widget-builder/#choose-your-dataset" />
  94. ),
  95. }
  96. )}
  97. >
  98. {showSplitAlert && hasDatasetSelectorFeature && (
  99. <DiscoverSplitAlert
  100. onDismiss={() => setShowSplitAlert(false)}
  101. splitDecision={splitDecision}
  102. />
  103. )}
  104. <DataSetChoices
  105. label="dataSet"
  106. value={dataSet}
  107. choices={[...datasetChoices.entries()]}
  108. disabledChoices={disabledChoices}
  109. onChange={newDataSet => {
  110. onChange(newDataSet as DataSet);
  111. }}
  112. orientInline
  113. />
  114. </BuildStep>
  115. );
  116. }
  117. const DataSetChoices = styled(RadioGroup)`
  118. display: flex;
  119. flex-wrap: wrap;
  120. gap: ${space(2)};
  121. `;
  122. const StyledCloseButton = styled(Button)`
  123. background-color: transparent;
  124. transition: opacity 0.1s linear;
  125. &:hover,
  126. &:focus {
  127. background-color: transparent;
  128. opacity: 1;
  129. }
  130. `;