TimeSeriesPanel.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import React, { useMemo } from 'react';
  2. import { Field, PanelProps } from '@grafana/data';
  3. import { PanelDataErrorView } from '@grafana/runtime';
  4. import { TooltipDisplayMode } from '@grafana/schema';
  5. import { usePanelContext, TimeSeries, TooltipPlugin, ZoomPlugin, KeyboardPlugin } from '@grafana/ui';
  6. import { config } from 'app/core/config';
  7. import { getFieldLinksForExplore } from 'app/features/explore/utils/links';
  8. import { AnnotationEditorPlugin } from './plugins/AnnotationEditorPlugin';
  9. import { AnnotationsPlugin } from './plugins/AnnotationsPlugin';
  10. import { ContextMenuPlugin } from './plugins/ContextMenuPlugin';
  11. import { ExemplarsPlugin } from './plugins/ExemplarsPlugin';
  12. import { OutsideRangePlugin } from './plugins/OutsideRangePlugin';
  13. import { ThresholdControlsPlugin } from './plugins/ThresholdControlsPlugin';
  14. import { TimeSeriesOptions } from './types';
  15. import { prepareGraphableFields } from './utils';
  16. interface TimeSeriesPanelProps extends PanelProps<TimeSeriesOptions> {}
  17. export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
  18. data,
  19. timeRange,
  20. timeZone,
  21. width,
  22. height,
  23. options,
  24. fieldConfig,
  25. onChangeTimeRange,
  26. replaceVariables,
  27. id,
  28. }) => {
  29. const { sync, canAddAnnotations, onThresholdsChange, canEditThresholds, onSplitOpen } = usePanelContext();
  30. const getFieldLinks = (field: Field, rowIndex: number) => {
  31. return getFieldLinksForExplore({ field, rowIndex, splitOpenFn: onSplitOpen, range: timeRange });
  32. };
  33. const frames = useMemo(() => prepareGraphableFields(data.series, config.theme2, timeRange), [data, timeRange]);
  34. if (!frames) {
  35. return (
  36. <PanelDataErrorView
  37. panelId={id}
  38. fieldConfig={fieldConfig}
  39. data={data}
  40. needsTimeField={true}
  41. needsNumberField={true}
  42. />
  43. );
  44. }
  45. const enableAnnotationCreation = Boolean(canAddAnnotations && canAddAnnotations());
  46. return (
  47. <TimeSeries
  48. frames={frames}
  49. structureRev={data.structureRev}
  50. timeRange={timeRange}
  51. timeZone={timeZone}
  52. width={width}
  53. height={height}
  54. legend={options.legend}
  55. >
  56. {(config, alignedDataFrame) => {
  57. return (
  58. <>
  59. <KeyboardPlugin config={config} />
  60. <ZoomPlugin config={config} onZoom={onChangeTimeRange} />
  61. {options.tooltip.mode === TooltipDisplayMode.None || (
  62. <TooltipPlugin
  63. data={alignedDataFrame}
  64. config={config}
  65. mode={options.tooltip.mode}
  66. sortOrder={options.tooltip.sort}
  67. sync={sync}
  68. timeZone={timeZone}
  69. />
  70. )}
  71. {/* Renders annotation markers*/}
  72. {data.annotations && (
  73. <AnnotationsPlugin annotations={data.annotations} config={config} timeZone={timeZone} />
  74. )}
  75. {/* Enables annotations creation*/}
  76. {enableAnnotationCreation ? (
  77. <AnnotationEditorPlugin data={alignedDataFrame} timeZone={timeZone} config={config}>
  78. {({ startAnnotating }) => {
  79. return (
  80. <ContextMenuPlugin
  81. data={alignedDataFrame}
  82. config={config}
  83. timeZone={timeZone}
  84. replaceVariables={replaceVariables}
  85. defaultItems={[
  86. {
  87. items: [
  88. {
  89. label: 'Add annotation',
  90. ariaLabel: 'Add annotation',
  91. icon: 'comment-alt',
  92. onClick: (e, p) => {
  93. if (!p) {
  94. return;
  95. }
  96. startAnnotating({ coords: p.coords });
  97. },
  98. },
  99. ],
  100. },
  101. ]}
  102. />
  103. );
  104. }}
  105. </AnnotationEditorPlugin>
  106. ) : (
  107. <ContextMenuPlugin
  108. data={alignedDataFrame}
  109. config={config}
  110. timeZone={timeZone}
  111. replaceVariables={replaceVariables}
  112. defaultItems={[]}
  113. />
  114. )}
  115. {data.annotations && (
  116. <ExemplarsPlugin
  117. config={config}
  118. exemplars={data.annotations}
  119. timeZone={timeZone}
  120. getFieldLinks={getFieldLinks}
  121. />
  122. )}
  123. {canEditThresholds && onThresholdsChange && (
  124. <ThresholdControlsPlugin
  125. config={config}
  126. fieldConfig={fieldConfig}
  127. onThresholdsChange={onThresholdsChange}
  128. />
  129. )}
  130. <OutsideRangePlugin config={config} onChangeTimeRange={onChangeTimeRange} />
  131. </>
  132. );
  133. }}
  134. </TimeSeries>
  135. );
  136. };