widgetContainer.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import {useEffect, useState} from 'react';
  2. import pick from 'lodash/pick';
  3. import DropdownButtonV2 from 'sentry/components/dropdownButtonV2';
  4. import CompactSelect from 'sentry/components/forms/compactSelect';
  5. import {IconEllipsis} from 'sentry/icons/iconEllipsis';
  6. import {t} from 'sentry/locale';
  7. import {Organization} from 'sentry/types';
  8. import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
  9. import EventView from 'sentry/utils/discover/eventView';
  10. import {usePerformanceDisplayType} from 'sentry/utils/performance/contexts/performanceDisplayContext';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import withOrganization from 'sentry/utils/withOrganization';
  13. import {GenericPerformanceWidgetDataType} from '../types';
  14. import {_setChartSetting, getChartSetting} from '../utils';
  15. import {PerformanceWidgetSetting, WIDGET_DEFINITIONS} from '../widgetDefinitions';
  16. import {HistogramWidget} from '../widgets/histogramWidget';
  17. import {LineChartListWidget} from '../widgets/lineChartListWidget';
  18. import {SingleFieldAreaWidget} from '../widgets/singleFieldAreaWidget';
  19. import {TrendsWidget} from '../widgets/trendsWidget';
  20. import {VitalWidget} from '../widgets/vitalWidget';
  21. import {ChartRowProps} from './widgetChartRow';
  22. type Props = {
  23. allowedCharts: PerformanceWidgetSetting[];
  24. chartHeight: number;
  25. defaultChartSetting: PerformanceWidgetSetting;
  26. eventView: EventView;
  27. index: number;
  28. organization: Organization;
  29. rowChartSettings: PerformanceWidgetSetting[];
  30. setRowChartSettings: (settings: PerformanceWidgetSetting[]) => void;
  31. withStaticFilters: boolean;
  32. chartColor?: string;
  33. forceDefaultChartSetting?: boolean;
  34. } & ChartRowProps;
  35. function trackChartSettingChange(
  36. previousChartSetting: PerformanceWidgetSetting,
  37. chartSetting: PerformanceWidgetSetting,
  38. fromDefault: boolean,
  39. organization: Organization
  40. ) {
  41. trackAdvancedAnalyticsEvent('performance_views.landingv3.widget.switch', {
  42. organization,
  43. from_widget: previousChartSetting,
  44. to_widget: chartSetting,
  45. from_default: fromDefault,
  46. });
  47. }
  48. const _WidgetContainer = (props: Props) => {
  49. const {
  50. organization,
  51. index,
  52. chartHeight,
  53. allowedCharts,
  54. rowChartSettings,
  55. setRowChartSettings,
  56. ...rest
  57. } = props;
  58. const performanceType = usePerformanceDisplayType();
  59. let _chartSetting = getChartSetting(
  60. index,
  61. chartHeight,
  62. performanceType,
  63. rest.defaultChartSetting,
  64. rest.forceDefaultChartSetting
  65. );
  66. if (!allowedCharts.includes(_chartSetting)) {
  67. _chartSetting = rest.defaultChartSetting;
  68. }
  69. const [chartSetting, setChartSettingState] = useState(_chartSetting);
  70. const setChartSetting = (setting: PerformanceWidgetSetting) => {
  71. if (!props.forceDefaultChartSetting) {
  72. _setChartSetting(index, chartHeight, performanceType, setting);
  73. }
  74. setChartSettingState(setting);
  75. const newSettings = [...rowChartSettings];
  76. newSettings[index] = setting;
  77. setRowChartSettings(newSettings);
  78. trackChartSettingChange(
  79. chartSetting,
  80. setting,
  81. rest.defaultChartSetting === chartSetting,
  82. organization
  83. );
  84. };
  85. useEffect(() => {
  86. setChartSettingState(_chartSetting);
  87. }, [rest.defaultChartSetting]);
  88. const chartDefinition = WIDGET_DEFINITIONS({organization})[chartSetting];
  89. const widgetProps = {
  90. ...chartDefinition,
  91. chartSetting,
  92. chartDefinition,
  93. ContainerActions: containerProps => (
  94. <WidgetContainerActions
  95. {...containerProps}
  96. allowedCharts={props.allowedCharts}
  97. chartSetting={chartSetting}
  98. setChartSetting={setChartSetting}
  99. rowChartSettings={rowChartSettings}
  100. />
  101. ),
  102. };
  103. const passedProps = pick(props, [
  104. 'eventView',
  105. 'location',
  106. 'organization',
  107. 'chartHeight',
  108. 'withStaticFilters',
  109. ]);
  110. switch (widgetProps.dataType) {
  111. case GenericPerformanceWidgetDataType.trends:
  112. return <TrendsWidget {...passedProps} {...widgetProps} />;
  113. case GenericPerformanceWidgetDataType.area:
  114. return <SingleFieldAreaWidget {...passedProps} {...widgetProps} />;
  115. case GenericPerformanceWidgetDataType.vitals:
  116. return <VitalWidget {...passedProps} {...widgetProps} />;
  117. case GenericPerformanceWidgetDataType.line_list:
  118. return <LineChartListWidget {...passedProps} {...widgetProps} />;
  119. case GenericPerformanceWidgetDataType.histogram:
  120. return <HistogramWidget {...passedProps} {...widgetProps} />;
  121. default:
  122. throw new Error(`Widget type "${widgetProps.dataType}" has no implementation.`);
  123. }
  124. };
  125. export const WidgetContainerActions = ({
  126. chartSetting,
  127. setChartSetting,
  128. allowedCharts,
  129. rowChartSettings,
  130. }: {
  131. allowedCharts: PerformanceWidgetSetting[];
  132. chartSetting: PerformanceWidgetSetting;
  133. rowChartSettings: PerformanceWidgetSetting[];
  134. setChartSetting: (setting: PerformanceWidgetSetting) => void;
  135. }) => {
  136. const organization = useOrganization();
  137. const menuOptions: React.ComponentProps<typeof CompactSelect>['options'] = [];
  138. const settingsMap = WIDGET_DEFINITIONS({organization});
  139. for (const setting of allowedCharts) {
  140. const options = settingsMap[setting];
  141. menuOptions.push({
  142. value: setting,
  143. label: options.title,
  144. disabled: setting !== chartSetting && rowChartSettings.includes(setting),
  145. });
  146. }
  147. function trigger({props, ref}) {
  148. return (
  149. <DropdownButtonV2
  150. ref={ref}
  151. {...props}
  152. size="xs"
  153. borderless
  154. showChevron={false}
  155. icon={<IconEllipsis aria-label={t('More')} />}
  156. />
  157. );
  158. }
  159. return (
  160. <CompactSelect
  161. onChange={opt => setChartSetting(opt.value)}
  162. options={menuOptions}
  163. isOptionDisabled={opt => opt.disabled}
  164. value={chartSetting}
  165. trigger={trigger}
  166. placement="bottom right"
  167. />
  168. );
  169. };
  170. const WidgetContainer = withOrganization(_WidgetContainer);
  171. export default WidgetContainer;