getWidgetExploreUrl.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import type {PageFilters} from 'sentry/types/core';
  2. import type {Organization} from 'sentry/types/organization';
  3. import {defined} from 'sentry/utils';
  4. import {
  5. getAggregateAlias,
  6. isAggregateFieldOrEquation,
  7. } from 'sentry/utils/discover/fields';
  8. import {decodeBoolean, decodeList, decodeScalar} from 'sentry/utils/queryString';
  9. import {DisplayType, type Widget} from 'sentry/views/dashboards/types';
  10. import {
  11. eventViewFromWidget,
  12. getFieldsFromEquations,
  13. getWidgetInterval,
  14. } from 'sentry/views/dashboards/utils';
  15. import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode';
  16. import {getExploreUrl} from 'sentry/views/explore/utils';
  17. import {ChartType} from 'sentry/views/insights/common/components/chart';
  18. export function getWidgetExploreUrl(
  19. widget: Widget,
  20. selection: PageFilters,
  21. organization: Organization
  22. ) {
  23. const eventView = eventViewFromWidget(widget.title, widget.queries[0]!, selection);
  24. const {query: locationQueryParams} = eventView.getResultsViewUrlTarget(
  25. organization.slug,
  26. false,
  27. undefined
  28. );
  29. // Pull a max of 3 valid Y-Axis from the widget
  30. const yAxisOptions = eventView.getYAxisOptions().map(({value}) => value);
  31. locationQueryParams.yAxes = [
  32. ...new Set(
  33. widget.queries[0]!.aggregates.filter(aggregate => yAxisOptions.includes(aggregate))
  34. ),
  35. ].slice(0, 3);
  36. // Visualization specific transforms
  37. let exploreMode: Mode | undefined = undefined;
  38. let chartType: ChartType = ChartType.LINE;
  39. switch (widget.displayType) {
  40. case DisplayType.BAR:
  41. exploreMode = Mode.AGGREGATE;
  42. chartType = ChartType.BAR;
  43. break;
  44. case DisplayType.LINE:
  45. exploreMode = Mode.AGGREGATE;
  46. chartType = ChartType.LINE;
  47. break;
  48. case DisplayType.AREA:
  49. exploreMode = Mode.AGGREGATE;
  50. chartType = ChartType.AREA;
  51. break;
  52. case DisplayType.TABLE:
  53. case DisplayType.BIG_NUMBER:
  54. exploreMode = Mode.SAMPLES;
  55. break;
  56. default:
  57. break;
  58. }
  59. // Equation fields need to have their terms explicitly selected as columns in the discover table
  60. const fields =
  61. Array.isArray(locationQueryParams.field) || !defined(locationQueryParams.field)
  62. ? locationQueryParams.field
  63. : [locationQueryParams.field];
  64. const query = widget.queries[0]!;
  65. const queryFields = defined(query.fields)
  66. ? query.fields
  67. : [...query.columns, ...query.aggregates];
  68. // Updates fields by adding any individual terms from equation fields as a column
  69. getFieldsFromEquations(queryFields).forEach(term => {
  70. if (Array.isArray(fields) && !fields.includes(term)) {
  71. fields.unshift(term);
  72. }
  73. });
  74. locationQueryParams.field = fields;
  75. const datetime = {
  76. end: decodeScalar(locationQueryParams.end) ?? null,
  77. period: decodeScalar(locationQueryParams.statsPeriod) ?? null,
  78. start: decodeScalar(locationQueryParams.start) ?? null,
  79. utc: decodeBoolean(locationQueryParams.utc) ?? null,
  80. };
  81. const queryParams = {
  82. // Page filters should propagate
  83. selection: {
  84. ...selection,
  85. datetime,
  86. },
  87. orgSlug: organization.slug,
  88. mode: exploreMode,
  89. visualize: [
  90. {
  91. chartType,
  92. yAxes: locationQueryParams.yAxes,
  93. },
  94. ],
  95. groupBy: fields?.filter(field => !isAggregateFieldOrEquation(field)),
  96. field: decodeList(locationQueryParams.field),
  97. query: decodeScalar(locationQueryParams.query),
  98. sort:
  99. defined(fields) && defined(locationQueryParams.sort)
  100. ? _getSort(fields, locationQueryParams.sort as string)
  101. : undefined,
  102. interval:
  103. decodeScalar(locationQueryParams.interval) ??
  104. getWidgetInterval(widget.displayType, selection.datetime),
  105. };
  106. return getExploreUrl(queryParams);
  107. }
  108. function _getSort(fields: string[], sort: string) {
  109. const descending = sort.startsWith('-');
  110. const rawSort = descending ? sort.slice(1) : sort;
  111. const sortedField = fields?.find(field => getAggregateAlias(field) === rawSort);
  112. return descending ? `-${sortedField}` : sortedField;
  113. }