dataSetStep.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. 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. datasetChoices.set(DataSet.ISSUES, t('Issues (States, Assignment, Time, etc.)'));
  82. datasetChoices.set(DataSet.RELEASES, t('Releases (Sessions, Crash rates)'));
  83. return (
  84. <BuildStep
  85. title={t('Choose your dataset')}
  86. description={tct(
  87. `This reflects the type of information you want to use. To learn more, [link: read the docs].`,
  88. {
  89. link: (
  90. <ExternalLink href="https://docs.sentry.io/product/dashboards/widget-builder/#choose-your-dataset" />
  91. ),
  92. }
  93. )}
  94. >
  95. {showSplitAlert && hasDatasetSelectorFeature && (
  96. <DiscoverSplitAlert
  97. onDismiss={() => setShowSplitAlert(false)}
  98. splitDecision={splitDecision}
  99. />
  100. )}
  101. <DataSetChoices
  102. label="dataSet"
  103. value={dataSet}
  104. choices={[...datasetChoices.entries()]}
  105. disabledChoices={disabledChoices}
  106. onChange={newDataSet => {
  107. onChange(newDataSet as DataSet);
  108. }}
  109. orientInline
  110. />
  111. </BuildStep>
  112. );
  113. }
  114. const DataSetChoices = styled(RadioGroup)`
  115. display: flex;
  116. flex-wrap: wrap;
  117. gap: ${space(2)};
  118. `;
  119. const StyledCloseButton = styled(Button)`
  120. background-color: transparent;
  121. transition: opacity 0.1s linear;
  122. &:hover,
  123. &:focus {
  124. background-color: transparent;
  125. opacity: 1;
  126. }
  127. `;