PromExploreExtraField.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { css, cx } from '@emotion/css';
  2. import { isEqual } from 'lodash';
  3. import React, { memo, useCallback } from 'react';
  4. import { usePrevious } from 'react-use';
  5. import { InlineFormLabel, RadioButtonGroup } from '@grafana/ui';
  6. import { PrometheusDatasource } from '../datasource';
  7. import { PromQuery } from '../types';
  8. import { PromExemplarField } from './PromExemplarField';
  9. export interface PromExploreExtraFieldProps {
  10. query: PromQuery;
  11. onChange: (value: PromQuery) => void;
  12. onRunQuery: () => void;
  13. datasource: PrometheusDatasource;
  14. }
  15. export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
  16. ({ query, datasource, onChange, onRunQuery }) => {
  17. const rangeOptions = getQueryTypeOptions(true);
  18. const prevQuery = usePrevious(query);
  19. const onExemplarChange = useCallback(
  20. (exemplar: boolean) => {
  21. if (!isEqual(query, prevQuery) || exemplar !== query.exemplar) {
  22. onChange({ ...query, exemplar });
  23. }
  24. },
  25. [prevQuery, query, onChange]
  26. );
  27. function onChangeQueryStep(interval: string) {
  28. onChange({ ...query, interval });
  29. }
  30. function onStepChange(e: React.SyntheticEvent<HTMLInputElement>) {
  31. if (e.currentTarget.value !== query.interval) {
  32. onChangeQueryStep(e.currentTarget.value);
  33. }
  34. }
  35. function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
  36. if (e.key === 'Enter' && e.shiftKey) {
  37. onRunQuery();
  38. }
  39. }
  40. const onQueryTypeChange = getQueryTypeChangeHandler(query, onChange);
  41. return (
  42. <div aria-label="Prometheus extra field" className="gf-form-inline" data-testid={testIds.extraFieldEditor}>
  43. {/*Query type field*/}
  44. <div
  45. data-testid={testIds.queryTypeField}
  46. className={cx(
  47. 'gf-form explore-input-margin',
  48. css`
  49. flex-wrap: nowrap;
  50. `
  51. )}
  52. aria-label="Query type field"
  53. >
  54. <InlineFormLabel width="auto">Query type</InlineFormLabel>
  55. <RadioButtonGroup
  56. options={rangeOptions}
  57. value={query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range'}
  58. onChange={onQueryTypeChange}
  59. />
  60. </div>
  61. {/*Step field*/}
  62. <div
  63. data-testid={testIds.stepField}
  64. className={cx(
  65. 'gf-form',
  66. css`
  67. flex-wrap: nowrap;
  68. `
  69. )}
  70. aria-label="Step field"
  71. >
  72. <InlineFormLabel
  73. width={6}
  74. tooltip={
  75. 'Time units and built-in variables can be used here, for example: $__interval, $__rate_interval, 5s, 1m, 3h, 1d, 1y (Default if no unit is specified: s)'
  76. }
  77. >
  78. Min step
  79. </InlineFormLabel>
  80. <input
  81. type={'text'}
  82. className="gf-form-input width-4"
  83. placeholder={'auto'}
  84. onChange={onStepChange}
  85. onKeyDown={onReturnKeyDown}
  86. value={query.interval ?? ''}
  87. />
  88. </div>
  89. <PromExemplarField onChange={onExemplarChange} datasource={datasource} query={query} />
  90. </div>
  91. );
  92. }
  93. );
  94. PromExploreExtraField.displayName = 'PromExploreExtraField';
  95. export function getQueryTypeOptions(includeBoth: boolean) {
  96. const rangeOptions = [
  97. { value: 'range', label: 'Range', description: 'Run query over a range of time' },
  98. {
  99. value: 'instant',
  100. label: 'Instant',
  101. description: 'Run query against a single point in time. For this query, the "To" time is used',
  102. },
  103. ];
  104. if (includeBoth) {
  105. rangeOptions.push({ value: 'both', label: 'Both', description: 'Run an Instant query and a Range query' });
  106. }
  107. return rangeOptions;
  108. }
  109. export function getQueryTypeChangeHandler(query: PromQuery, onChange: (update: PromQuery) => void) {
  110. return (queryType: string) => {
  111. if (queryType === 'instant') {
  112. onChange({ ...query, instant: true, range: false, exemplar: false });
  113. } else if (queryType === 'range') {
  114. onChange({ ...query, instant: false, range: true });
  115. } else {
  116. onChange({ ...query, instant: true, range: true });
  117. }
  118. };
  119. }
  120. export const testIds = {
  121. extraFieldEditor: 'prom-editor-extra-field',
  122. stepField: 'prom-editor-extra-field-step',
  123. queryTypeField: 'prom-editor-extra-field-query-type',
  124. };