visualizes.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import type {Location} from 'history';
  2. import {defined} from 'sentry/utils';
  3. import {parseFunction} from 'sentry/utils/discover/fields';
  4. import {
  5. ALLOWED_EXPLORE_VISUALIZE_AGGREGATES,
  6. ALLOWED_EXPLORE_VISUALIZE_FIELDS,
  7. } from 'sentry/utils/fields';
  8. import {decodeList} from 'sentry/utils/queryString';
  9. import {ChartType} from 'sentry/views/insights/common/components/chart';
  10. export const MAX_VISUALIZES = 4;
  11. export const DEFAULT_VISUALIZATION_AGGREGATE = ALLOWED_EXPLORE_VISUALIZE_AGGREGATES[0];
  12. export const DEFAULT_VISUALIZATION_FIELD = ALLOWED_EXPLORE_VISUALIZE_FIELDS[0];
  13. export const DEFAULT_VISUALIZATION = `${DEFAULT_VISUALIZATION_AGGREGATE}(${DEFAULT_VISUALIZATION_FIELD})`;
  14. export function defaultVisualizes(): Visualize[] {
  15. return [
  16. {
  17. chartType: ChartType.LINE,
  18. yAxes: [DEFAULT_VISUALIZATION],
  19. label: 'A',
  20. },
  21. ];
  22. }
  23. export interface BaseVisualize {
  24. chartType: ChartType;
  25. yAxes: string[];
  26. }
  27. export interface Visualize extends BaseVisualize {
  28. label: string;
  29. }
  30. export function getVisualizesFromLocation(location: Location): Visualize[] {
  31. const rawVisualizes = decodeList(location.query.visualize);
  32. const result: Visualize[] = rawVisualizes
  33. .map(parseVisualizes)
  34. .filter(defined)
  35. .filter(parsed => parsed.yAxes.length > 0)
  36. .map((parsed, i) => {
  37. return {
  38. chartType: parsed.chartType,
  39. yAxes: parsed.yAxes,
  40. label: String.fromCharCode(65 + i), // starts from 'A'
  41. };
  42. });
  43. return result.length ? result : defaultVisualizes();
  44. }
  45. function parseVisualizes(raw: string): Omit<Visualize, 'label'> | null {
  46. try {
  47. const parsed = JSON.parse(raw);
  48. if (!defined(parsed) || !Array.isArray(parsed.yAxes)) {
  49. return null;
  50. }
  51. const yAxes = parsed.yAxes.filter(parseFunction);
  52. if (yAxes.length <= 0) {
  53. return null;
  54. }
  55. let chartType = Number(parsed.chartType);
  56. if (isNaN(chartType) || !Object.values(ChartType).includes(chartType)) {
  57. chartType = ChartType.LINE;
  58. }
  59. return {yAxes, chartType};
  60. } catch (error) {
  61. return null;
  62. }
  63. }
  64. export function updateLocationWithVisualizes(
  65. location: Location,
  66. visualizes: BaseVisualize[] | null | undefined
  67. ) {
  68. if (defined(visualizes)) {
  69. location.query.visualize = visualizes.map(visualize =>
  70. JSON.stringify({
  71. chartType: visualize.chartType,
  72. yAxes: visualize.yAxes,
  73. })
  74. );
  75. } else if (visualizes === null) {
  76. delete location.query.visualize;
  77. }
  78. }