dataSetStep.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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/datasetSelector';
  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. hasReleaseHealthFeature: boolean;
  47. onChange: (dataSet: DataSet) => void;
  48. source?: DatasetSource;
  49. splitDecision?: WidgetType;
  50. }
  51. export function DataSetStep({
  52. dataSet,
  53. onChange,
  54. hasReleaseHealthFeature,
  55. displayType,
  56. splitDecision,
  57. source,
  58. }: Props) {
  59. const [showSplitAlert, setShowSplitAlert] = useState<boolean>(
  60. source === DatasetSource.FORCED
  61. );
  62. const organization = useOrganization();
  63. const disabledChoices: RadioGroupProps<string>['disabledChoices'] = [];
  64. const hasDatasetSelectorFeature = hasDatasetSelector(organization);
  65. useEffect(() => {
  66. setShowSplitAlert(!!splitDecision);
  67. }, [splitDecision]);
  68. if (displayType !== DisplayType.TABLE) {
  69. disabledChoices.push([
  70. DataSet.ISSUES,
  71. t('This dataset is restricted to tabular visualization.'),
  72. ]);
  73. }
  74. const datasetChoices = new Map<string, string>();
  75. if (hasDatasetSelectorFeature) {
  76. // TODO: Finalize description copy
  77. datasetChoices.set(DataSet.ERRORS, t('Errors (TypeError, InvalidSearchQuery, etc)'));
  78. datasetChoices.set(DataSet.TRANSACTIONS, t('Transactions'));
  79. }
  80. if (!hasDatasetSelectorFeature) {
  81. datasetChoices.set(DataSet.EVENTS, t('Errors and Transactions'));
  82. }
  83. datasetChoices.set(DataSet.ISSUES, t('Issues (States, Assignment, Time, etc.)'));
  84. if (hasReleaseHealthFeature) {
  85. datasetChoices.set(DataSet.RELEASES, t('Releases (Sessions, Crash rates)'));
  86. }
  87. return (
  88. <BuildStep
  89. title={t('Choose your dataset')}
  90. description={tct(
  91. `This reflects the type of information you want to use. To learn more, [link: read the docs].`,
  92. {
  93. link: (
  94. <ExternalLink href="https://docs.sentry.io/product/dashboards/widget-builder/#choose-your-dataset" />
  95. ),
  96. }
  97. )}
  98. >
  99. {showSplitAlert && hasDatasetSelectorFeature && (
  100. <DiscoverSplitAlert
  101. onDismiss={() => setShowSplitAlert(false)}
  102. splitDecision={splitDecision}
  103. />
  104. )}
  105. <DataSetChoices
  106. label="dataSet"
  107. value={dataSet}
  108. choices={[...datasetChoices.entries()]}
  109. disabledChoices={disabledChoices}
  110. onChange={newDataSet => {
  111. onChange(newDataSet as DataSet);
  112. }}
  113. orientInline
  114. />
  115. </BuildStep>
  116. );
  117. }
  118. const DataSetChoices = styled(RadioGroup)`
  119. display: flex;
  120. flex-wrap: wrap;
  121. gap: ${space(2)};
  122. `;
  123. const StyledCloseButton = styled(Button)`
  124. background-color: transparent;
  125. transition: opacity 0.1s linear;
  126. &:hover,
  127. &:focus {
  128. background-color: transparent;
  129. opacity: 1;
  130. }
  131. `;