landingWidgetSelector.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import {useCallback, useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import omit from 'lodash/omit';
  4. import {CompactSelect, SelectOption} from 'sentry/components/compactSelect';
  5. import {t} from 'sentry/locale';
  6. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  7. import useRouter from 'sentry/utils/useRouter';
  8. import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
  9. import {FunctionTrendsWidget} from './functionTrendsWidget';
  10. import {SlowestFunctionsWidget} from './slowestFunctionsWidget';
  11. export type WidgetOption =
  12. | 'slowest functions'
  13. | 'regressed functions'
  14. | 'improved functions';
  15. interface LandingWidgetSelectorProps {
  16. cursorName: string;
  17. defaultWidget: WidgetOption;
  18. query: string;
  19. storageKey: string;
  20. widgetHeight?: string;
  21. }
  22. export function LandingWidgetSelector({
  23. cursorName,
  24. defaultWidget,
  25. storageKey,
  26. widgetHeight,
  27. }: LandingWidgetSelectorProps) {
  28. const router = useRouter();
  29. const [selectedWidget, setSelectedWidget] = useSyncedLocalStorageState<WidgetOption>(
  30. storageKey,
  31. defaultWidget
  32. );
  33. const onWidgetChange = useCallback(
  34. opt => {
  35. const newQuery = omit(router.location.query, [cursorName]);
  36. router.push({
  37. pathname: router.location.pathname,
  38. query: newQuery,
  39. });
  40. setSelectedWidget(opt.value);
  41. },
  42. [cursorName, router, setSelectedWidget]
  43. );
  44. const functionQuery = useMemo(() => {
  45. const conditions = new MutableSearch('');
  46. conditions.setFilterValues('is_application', ['1']);
  47. return conditions.formatString();
  48. }, []);
  49. const header = (
  50. <StyledCompactSelect
  51. value={selectedWidget}
  52. options={WIDGET_OPTIONS}
  53. onChange={onWidgetChange}
  54. triggerProps={{borderless: true, size: 'zero'}}
  55. offset={4}
  56. />
  57. );
  58. switch (selectedWidget) {
  59. case 'slowest functions':
  60. return (
  61. <SlowestFunctionsWidget
  62. cursorName={cursorName}
  63. header={header}
  64. userQuery={functionQuery}
  65. widgetHeight={widgetHeight}
  66. />
  67. );
  68. case 'regressed functions':
  69. return (
  70. <FunctionTrendsWidget
  71. cursorName={cursorName}
  72. header={header}
  73. trendFunction="p95()"
  74. trendType="regression"
  75. userQuery={functionQuery}
  76. widgetHeight={widgetHeight}
  77. />
  78. );
  79. case 'improved functions':
  80. return (
  81. <FunctionTrendsWidget
  82. cursorName={cursorName}
  83. header={header}
  84. trendFunction="p95()"
  85. trendType="improvement"
  86. userQuery={functionQuery}
  87. widgetHeight={widgetHeight}
  88. />
  89. );
  90. default:
  91. throw new Error('unknown widget type');
  92. }
  93. }
  94. const WIDGET_OPTIONS: SelectOption<WidgetOption>[] = [
  95. {
  96. label: t('Suspect Functions'),
  97. value: 'slowest functions' as const,
  98. },
  99. {
  100. label: t('Most Regressed Functions'),
  101. value: 'regressed functions' as const,
  102. },
  103. {
  104. label: t('Most Improved Functions'),
  105. value: 'improved functions' as const,
  106. },
  107. ];
  108. const StyledCompactSelect = styled(CompactSelect)`
  109. > button {
  110. border: None;
  111. padding: 0;
  112. }
  113. `;